CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-stack-utils

Captures and cleans stack traces for JavaScript applications

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/

Stack Utils

Stack Utils is a JavaScript library for capturing, cleaning, and manipulating stack traces in Node.js applications. It provides powerful utilities to remove internal Node.js lines from stack traces, shorten file paths relative to a working directory, and parse individual stack trace lines into structured objects. Originally extracted from the node-tap testing framework, it's particularly useful for testing frameworks, error handling systems, and debugging tools that need to present clean, readable stack traces.

Package Information

  • Package Name: stack-utils
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install stack-utils

Core Imports

const StackUtils = require('stack-utils');

Basic Usage

const StackUtils = require('stack-utils');

// Create a new instance with default settings
const stack = new StackUtils({
  cwd: process.cwd(),
  internals: StackUtils.nodeInternals()
});

// Clean a stack trace from an error
console.log(stack.clean(new Error().stack));

// Capture current stack trace as string
const currentStack = stack.captureString();
console.log(currentStack);

// Get information about current location
const location = stack.at();
console.log(location); // { line: 15, column: 23, file: 'app.js' }

Capabilities

Constructor

Creates a new StackUtils instance with customizable filtering and formatting options.

/**
 * Creates a new StackUtils instance
 * @param options - Configuration options
 */
new StackUtils(options);

interface StackUtilsOptions {
  /** Array of npm package names to ignore in stack traces */
  ignoredPackages?: string[];
  /** Array of RegExp patterns for internal lines to filter */
  internals?: RegExp[];
  /** Current working directory for relative path resolution */
  cwd?: string;
  /** Optional function to wrap CallSite objects */
  wrapCallSite?: (callSite: CallSite) => CallSite;
}

Usage Example:

const stack = new StackUtils({
  cwd: process.cwd(),
  ignoredPackages: ['lodash', 'bluebird'],
  internals: StackUtils.nodeInternals().concat([
    /\/my-internal-module\//
  ]),
  wrapCallSite: (callSite) => {
    // Custom CallSite manipulation for source maps
    return callSite;
  }
});

Static Methods

Node Internals

Returns default regular expressions for filtering Node.js internal stack trace lines.

/**
 * Get default RegExp patterns for Node.js internals
 * @returns Array of RegExp objects for filtering Node.js internal lines
 */
static nodeInternals(): RegExp[];

Stack Trace Cleaning

Clean Stack Traces

Removes internal lines and formats stack traces for better readability.

/**
 * Clean and format a stack trace by removing internal lines
 * @param stack - Stack trace string or array of lines
 * @param indent - Number of spaces to indent each line
 * @returns Cleaned stack trace string
 */
clean(stack: string | string[], indent?: number): string;

Usage Examples:

// Clean an error stack trace
try {
  throw new Error('Something went wrong');
} catch (err) {
  const cleanStack = stack.clean(err.stack);
  console.log(cleanStack);
}

// Clean with custom indentation
const indentedStack = stack.clean(err.stack, 4);

// Clean an array of stack lines
const stackLines = err.stack.split('\n');
const cleaned = stack.clean(stackLines);

Stack Trace Capture

Capture as String

Captures the current stack trace and returns it as a cleaned string.

/**
 * Capture current stack trace as cleaned string
 * @param limit - Maximum number of stack frames or start function
 * @param fn - Function to start capture from
 * @returns Cleaned stack trace string
 */
captureString(limit?: number | function, fn?: function): string;

Usage Examples:

// Capture current stack with default settings
const stack1 = stackUtils.captureString();

// Limit to 5 frames
const stack2 = stackUtils.captureString(5);

// Start capture from specific function
function myFunction() {
  return stackUtils.captureString(myFunction);
}

// Using limit and start function
const stack3 = stackUtils.captureString(10, myFunction);

Capture as CallSites

Captures the current stack trace as an array of CallSite objects for programmatic analysis.

/**
 * Capture current stack trace as CallSite objects
 * @param limit - Maximum number of stack frames or start function
 * @param fn - Function to start capture from
 * @returns Array of CallSite objects
 */
capture(limit?: number | function, fn?: function): CallSite[];

Location Information

Get Current Location

Captures information about the current execution location as a serializable object.

/**
 * Get current execution location information
 * @param fn - Function to start capture from
 * @returns Object with location information
 */
at(fn?: function): LocationInfo;

interface LocationInfo {
  /** Line number */
  line?: number;
  /** Column number */
  column?: number;
  /** File path (relative to cwd) */
  file?: string;
  /** Whether this is a constructor call */
  constructor?: boolean;
  /** Eval origin information if applicable */
  evalOrigin?: string;
  /** Whether this is native code */
  native?: boolean;
  /** Type name */
  type?: string;
  /** Function name */
  function?: string;
  /** Method name */
  method?: string;
}

Usage Examples:

function exampleFunction() {
  const location = stack.at();
  console.log(`Called from ${location.file}:${location.line}:${location.column}`);
  console.log(`Function: ${location.function}`);
}

// Get location starting from specific function
function wrapper() {
  const location = stack.at(wrapper);
  return location;
}

Stack Line Parsing

Parse Individual Lines

Parses a single stack trace line into a structured object with detailed information.

/**
 * Parse a single stack trace line into structured object
 * @param line - Single line from a stack trace
 * @returns Parsed line information or null if no match
 */
parseLine(line: string): ParsedLine | null;

interface ParsedLine {
  /** Line number */
  line?: number;
  /** Column number */
  column?: number;
  /** File path */
  file?: string;
  /** Whether this is a constructor call */
  constructor?: boolean;
  /** Eval origin information */
  evalOrigin?: string;
  /** Eval line number */
  evalLine?: number;
  /** Eval column number */
  evalColumn?: number;
  /** Eval file path */
  evalFile?: string;
  /** Whether this is native code */
  native?: boolean;
  /** Function name */
  function?: string;
  /** Method name */
  method?: string;
}

Usage Examples:

// Parse individual stack trace lines
const stackTrace = new Error().stack;
const lines = stackTrace.split('\n');

lines.forEach(line => {
  const parsed = stack.parseLine(line);
  if (parsed) {
    console.log(`${parsed.function} in ${parsed.file}:${parsed.line}`);
  }
});

// Handle different line formats
const testLines = [
  '    at myFunction (app.js:10:5)',
  '    at new Constructor (lib.js:25:12)',
  '    at eval (eval at <anonymous> (app.js:5:1), <anonymous>:1:1)',
  '    at native'
];

testLines.forEach(line => {
  const result = stack.parseLine(line);
  console.log(result);
});

Types

CallSite Interface

The native V8 CallSite interface provides detailed information about stack frames.

interface CallSite {
  getThis(): any;
  getTypeName(): string | null;
  getFunction(): Function;
  getFunctionName(): string | null;
  getMethodName(): string | null;
  getFileName(): string | null;
  getLineNumber(): number | null;
  getColumnNumber(): number | null;
  getEvalOrigin(): string | null;
  isToplevel(): boolean;
  isEval(): boolean;
  isNative(): boolean;
  isConstructor(): boolean;
}

Error Handling

Stack Utils gracefully handles various edge cases:

  • Invalid stack traces: Returns empty results for malformed input
  • Missing files: Handles stack traces with missing or invalid file paths
  • Native code: Properly identifies and handles native code frames
  • Eval contexts: Parses and preserves eval origin information
  • Process availability: Works even when process object is not available

Common Use Cases

Testing Frameworks

const StackUtils = require('stack-utils');

class TestFramework {
  constructor() {
    this.stack = new StackUtils({
      ignoredPackages: ['tap', 'mocha', 'jest'],
      cwd: process.cwd()
    });
  }

  reportError(error) {
    console.error('Test failed:');
    console.error(this.stack.clean(error.stack, 2));
  }

  getCurrentTestLocation() {
    return this.stack.at(this.reportError);
  }
}

Error Logging

const StackUtils = require('stack-utils');

const logger = {
  stack: new StackUtils({
    ignoredPackages: ['winston', 'pino'],
    cwd: process.cwd()
  }),

  error(message, error) {
    console.log({
      message,
      stack: this.stack.clean(error.stack),
      location: this.stack.at(this.error)
    });
  }
};

Debug Information

const StackUtils = require('stack-utils');

function createDebugger(namespace) {
  const stack = new StackUtils();
  
  return function debug(message) {
    const location = stack.at(debug);
    console.log(`[${namespace}] ${location.file}:${location.line} - ${message}`);
  };
}

const debug = createDebugger('myapp');
debug('Something happened'); // [myapp] app.js:15 - Something happened

docs

index.md

tile.json