CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-depd

Deprecate all the things - sophisticated deprecation warning system for Node.js modules

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Depd

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.

Package Information

  • Package Name: depd
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install depd

Core Imports

const deprecate = require('depd')('my-module-name');

ESM environments can use import:

import depd from 'depd';
const deprecate = depd('my-module-name');

Basic Usage

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');

Architecture

Depd is built around several key components:

  • Namespace System: Each deprecation instance is associated with a namespace, typically your module name
  • Call Site Tracking: Sophisticated stack trace analysis to identify unique call sites and warn only once per location
  • Multiple Deprecation Methods: Support for function wrapping, property access deprecation, and direct calls
  • Environment Integration: Works with Node.js process events and environment variables for control
  • Browser Compatibility: Provides no-op implementation for browser environments

Capabilities

Core Deprecation Function

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');
  }
}

Function Wrapping

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)

Property Wrapping

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 functions

Error Handling Integration

Deprecation 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);
  }
}

Environment Controls

NO_DEPRECATION Environment Variable

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 deprecations

The --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');
}

TRACE_DEPRECATION Environment Variable

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.js

The --trace-deprecation Node.js flag shows stack traces for all deprecations.

Browser Compatibility

When bundled for browser environments (e.g., with Browserify or webpack), depd automatically provides a no-op implementation to avoid browser incompatibilities.

Browser API Differences

/**
 * 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:

  • Main function: deprecate(message) becomes a no-op (does nothing)
  • Function wrapping: deprecate.function(fn, message) validates parameters but returns original function unchanged
  • Property wrapping: deprecate.property(obj, prop, message) validates parameters but doesn't modify property behavior
  • No console output: No warnings are written to console or emitted as events
  • Validation preserved: Parameter validation (TypeError throwing) is maintained for consistency

Usage 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);
}

Types

/**
 * 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;
}

docs

index.md

tile.json