or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-stack-utils

Captures and cleans stack traces for JavaScript applications

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

To install, run

npx @tessl/cli install tessl/npm-stack-utils@2.0.0

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