Depd provides a sophisticated deprecation warning system for Node.js modules that goes beyond simple one-time warnings. It tracks deprecation warnings per unique call site, providing detailed stack trace information including file names and line numbers for each deprecated function call.
npm install depdconst deprecate = require('depd')('my-module-name');ESM environments can use import:
import depd from 'depd';
const deprecate = depd('my-module-name');const deprecate = require('depd')('my-cool-module');
// Simple deprecation warning
deprecate('some feature is deprecated');
// Wrap a function to show deprecation warning on every call
exports.oldFunction = deprecate.function(function oldFunction() {
// implementation
}, 'oldFunction is deprecated');
// Wrap a property to show deprecation warning on access
exports.oldProperty = 'some value';
deprecate.property(exports, 'oldProperty', 'oldProperty is deprecated');Depd is built around several key components:
Creates a deprecation function for a specific namespace that tracks warnings per unique call site.
/**
* Create deprecate for namespace in caller
* @param {string} namespace - The namespace for deprecation warnings (typically module name)
* @returns {DeprecateFunction} Deprecation function with additional methods
* @throws {TypeError} If namespace is not provided
*/
function depd(namespace);
interface DeprecateFunction {
/**
* Display a deprecation message for the current call site
* @param {string} [message] - Custom deprecation message. If omitted, generates automatic message from call site
*/
(message?: string): void;
/** Properties for internal state tracking */
_file: string | undefined;
_ignored: boolean;
_namespace: string;
_traced: boolean;
_warned: object;
/** Wrap a function to show deprecation warnings */
function: typeof wrapFunction;
/** Wrap property access to show deprecation warnings */
property: typeof wrapProperty;
}Usage Examples:
const deprecate = require('depd')('my-module');
// Direct deprecation call
function someFunction(options) {
if (options.oldOption) {
deprecate('oldOption is deprecated, use newOption instead');
}
}
// Multiple deprecation warnings in same function
function flexibleFunction() {
if (arguments.length < 2) {
deprecate('calling with less than 2 arguments is deprecated');
} else if (typeof arguments[0] !== 'string') {
deprecate('non-string first argument is deprecated');
}
}Wraps a function to display deprecation warnings on each call while preserving the original function's behavior and arity.
/**
* Return a wrapped function in a deprecation message
* @param {Function} fn - Function to wrap
* @param {string} [message] - Custom deprecation message
* @returns {Function} Wrapped function that shows deprecation warning on each call
* @throws {TypeError} If fn is not a function
*/
function wrapFunction(fn, message);Usage Examples:
const deprecate = require('depd')('my-module');
// Automatic message from function name
exports.oldFunction = deprecate.function(function oldFunction() {
return 'old implementation';
});
// Custom deprecation message
exports.legacyApi = deprecate.function(function modernApi() {
return 'new implementation';
}, 'legacyApi is deprecated, use modernApi instead');
// Preserves function arity and behavior
function add(a, b, c) {
return a + b + c;
}
const deprecatedAdd = deprecate.function(add, 'add function will be removed');
console.log(deprecatedAdd.length); // 3 (same as original)Wraps object property access (both getting and setting) to display deprecation warnings while maintaining the original property behavior.
/**
* Wrap property in a deprecation message
* @param {Object} obj - Object containing the property
* @param {string} prop - Property name to wrap
* @param {string} [message] - Custom deprecation message
* @throws {TypeError} If obj is not an object
* @throws {TypeError} If property doesn't exist on object
* @throws {TypeError} If property is not configurable
*/
function wrapProperty(obj, prop, message);Usage Examples:
const deprecate = require('depd')('my-module');
// Basic property deprecation
exports.oldProperty = 'legacy value';
deprecate.property(exports, 'oldProperty');
// Custom deprecation message
exports.config = { timeout: 5000 };
deprecate.property(exports.config, 'timeout', 'timeout option is deprecated, use requestTimeout instead');
// Works with both getters and setters
const state = { _value: 42 };
Object.defineProperty(state, 'value', {
get() { return this._value; },
set(val) { this._value = val; },
configurable: true
});
deprecate.property(state, 'value', 'direct value access is deprecated');
// Advanced property wrapping scenarios
const apiObject = {
current: 'v2',
deprecated: 'v1'
};
// Wrap multiple properties
['deprecated', 'legacy', 'old'].forEach(prop => {
if (prop in apiObject) {
deprecate.property(apiObject, prop, `${prop} property will be removed`);
}
});
// Dynamic property deprecation
function addDeprecatedProperty(obj, propName, value, message) {
obj[propName] = value;
deprecate.property(obj, propName, message || `${propName} is deprecated`);
}
addDeprecatedProperty(apiObject, 'temporaryFeature', true, 'temporaryFeature will be removed in v3.0');
// Property deprecation with data descriptors (converts to accessor)
const config = { timeout: 5000 };
deprecate.property(config, 'timeout'); // Converts data descriptor to accessor
console.log(Object.getOwnPropertyDescriptor(config, 'timeout')); // Now has get/set functionsDeprecation warnings can be captured programmatically using Node.js process events instead of being written to STDERR.
/**
* Process event emitted when deprecation occurs (if listeners are present)
* @param {DeprecationError} error - Deprecation error object
*/
process.on('deprecation', function(error));
/**
* DeprecationError constructor function (used internally by depd)
* @param {string} namespace - The namespace the deprecation came from
* @param {string} message - The deprecation message
* @param {Array} stack - Stack trace array from the deprecated call
* @returns {DeprecationError} Error object with deprecation properties
*/
function DeprecationError(namespace, message, stack);
interface DeprecationError extends Error {
/** Always 'DeprecationError' */
name: 'DeprecationError';
/** The deprecation message */
message: string;
/** The namespace the deprecation came from */
namespace: string;
/** Stack trace of the deprecated call */
stack: string;
}Usage Examples:
// Capture deprecation warnings programmatically
process.on('deprecation', function(err) {
console.log('Deprecation in namespace:', err.namespace);
console.log('Message:', err.message);
console.log('Stack:', err.stack);
});
const deprecate = require('depd')('my-module');
deprecate('something is deprecated'); // Will emit 'deprecation' event instead of STDERR
// Advanced error handling - logging to file
const fs = require('fs');
process.on('deprecation', function(err) {
const logEntry = {
timestamp: new Date().toISOString(),
namespace: err.namespace,
message: err.message,
stack: err.stack.split('\n')
};
fs.appendFileSync('deprecations.log', JSON.stringify(logEntry) + '\n');
});
// Conditional error handling based on namespace
process.on('deprecation', function(err) {
if (err.namespace === 'critical-module') {
// Log critical deprecations with full stack trace
console.error('CRITICAL DEPRECATION:', err);
} else {
// Just log message for other modules
console.warn(`${err.namespace}: ${err.message}`);
}
});
// Creating custom DeprecationError instances (advanced usage)
function myCustomFunction() {
// This would normally be done internally by depd, but shows the structure
const deprecate = require('depd')('my-module');
// Force emit a deprecation event with custom details
if (process.listenerCount('deprecation') > 0) {
const customError = new Error();
customError.name = 'DeprecationError';
customError.message = 'custom deprecation message';
customError.namespace = 'my-module';
customError.stack = 'CustomError: custom message\n at myCustomFunction (file.js:1:1)';
process.emit('deprecation', customError);
}
}Controls which deprecation namespaces should be suppressed from output.
# Suppress specific namespaces
NO_DEPRECATION=my-module,other-module node app.js
# Suppress all deprecation warnings
NO_DEPRECATION=* node app.js
# Complex namespace patterns
NO_DEPRECATION=express,connect,body-parser node app.js
# Using with npm scripts
npm start --no-deprecation # Also suppresses all deprecationsThe --no-deprecation Node.js flag also suppresses all deprecation output.
Advanced Environment Usage:
// Check if deprecations are suppressed for your module
const deprecate = require('depd')('my-module');
console.log('Deprecations ignored:', deprecate._ignored);
// Programmatically check environment
function shouldShowDeprecation(namespace) {
const noDeprecation = process.env.NO_DEPRECATION || '';
return !noDeprecation.split(/[ ,]+/).some(ns =>
ns === '*' || ns.toLowerCase() === namespace.toLowerCase()
);
}
// Conditional deprecation based on environment
if (process.env.NODE_ENV !== 'production') {
const deprecate = require('depd')('dev-module');
deprecate('this feature is deprecated in development');
}Controls which deprecation namespaces should show full stack traces instead of just call site location.
# Show full stack traces for specific namespaces
TRACE_DEPRECATION=my-module,other-module node app.js
# Show full stack traces for all deprecations
TRACE_DEPRECATION=* node app.jsThe --trace-deprecation Node.js flag shows stack traces for all deprecations.
When bundled for browser environments (e.g., with Browserify or webpack), depd automatically provides a no-op implementation to avoid browser incompatibilities.
/**
* Browser version of depd function (no-op implementation)
* @param {string} namespace - The namespace (still required for validation)
* @returns {DeprecateFunction} No-op deprecation function
*/
function depd(namespace);
interface DeprecateFunction {
/** No-op function that does nothing in browser */
(message?: string): void;
/** Browser-specific properties */
_file: undefined;
_ignored: true;
_namespace: string;
_traced: false;
_warned: object;
/** Function wrapper that validates but doesn't warn */
function: (fn: Function, message?: string) => Function;
/** Property wrapper that validates but doesn't wrap */
property: (obj: object, prop: string, message?: string) => void;
}Browser Behavior:
deprecate(message) becomes a no-op (does nothing)deprecate.function(fn, message) validates parameters but returns original function unchangeddeprecate.property(obj, prop, message) validates parameters but doesn't modify property behaviorUsage Examples:
// In browser environments - all these work but produce no warnings
const deprecate = require('depd')('my-module');
// No-op call
deprecate('this will not show in browser');
// Function wrapper validates but doesn't warn
const wrappedFn = deprecate.function(function test() {
return 'result';
}, 'test is deprecated');
console.log(wrappedFn()); // 'result' - no warning shown
// Property wrapper validates but doesn't wrap
const obj = { value: 42 };
deprecate.property(obj, 'value', 'value is deprecated');
console.log(obj.value); // 42 - no warning shown
// Validation errors still thrown
try {
deprecate.function('not a function'); // TypeError: argument fn must be a function
} catch (err) {
console.log(err.message);
}/**
* Main depd function signature
* @param {string} namespace - Required namespace string for deprecation tracking
* @returns {DeprecateFunction} Configured deprecation function with methods
* @throws {TypeError} If namespace is not provided or not a string
*/
function depd(namespace: string): DeprecateFunction;
/**
* Deprecation function interface with additional methods and properties
*/
interface DeprecateFunction {
/**
* Display deprecation warning for current call site
* @param {string} [message] - Optional custom message, auto-generated if omitted
*/
(message?: string): void;
/** Internal properties for state tracking */
_file: string | undefined;
_ignored: boolean;
_namespace: string;
_traced: boolean;
_warned: Record<string, boolean>;
/**
* Wrap function to show deprecation on each call
* @param {Function} fn - Function to wrap (required)
* @param {string} [message] - Optional custom deprecation message
* @returns {Function} Wrapped function that preserves original behavior
* @throws {TypeError} If fn is not a function
*/
function: (fn: Function, message?: string) => Function;
/**
* Wrap property access to show deprecation warnings
* @param {object} obj - Object containing the property (required)
* @param {string} prop - Property name to wrap (required)
* @param {string} [message] - Optional custom deprecation message
* @throws {TypeError} If obj is not an object
* @throws {TypeError} If property doesn't exist on object
* @throws {TypeError} If property is not configurable
*/
property: (obj: object, prop: string, message?: string) => void;
}
/**
* Error object emitted by process 'deprecation' event
*/
interface DeprecationError extends Error {
/** Always 'DeprecationError' */
name: 'DeprecationError';
/** The deprecation message */
message: string;
/** The namespace the deprecation came from */
namespace: string;
/** Full stack trace of the deprecated call */
stack: string;
}
/**
* Browser-specific type differences
*/
interface BrowserDeprecateFunction {
/** No-op function in browser environments */
(message?: string): void;
/** Browser-specific property values */
_file: undefined;
_ignored: true;
_namespace: string;
_traced: false;
_warned: Record<string, boolean>;
/** Validates but returns original function unchanged */
function: (fn: Function, message?: string) => Function;
/** Validates but doesn't modify property behavior */
property: (obj: object, prop: string, message?: string) => void;
}