or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-depd

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

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/depd@2.0.x

To install, run

npx @tessl/cli install tessl/npm-depd@2.0.0

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