Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 105 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
![size](https://img.shields.io/npm/unpacked-size/@mnrendra/stack-trace)
![downloads](https://img.shields.io/npm/dm/@mnrendra/stack-trace)

A utility for tracing the caller's call sites starting from a specific callee.<br/>
*Useful for debugging, logging, or building tools that need to get the call origins or file locations at runtime.*
A utility for tracing the caller's call sites, starting after a specific callee.<br/>
*Useful for debugging, logging, or building tools that need to get the call origin details at runtime.*

## Install
```bash
Expand All @@ -16,75 +16,121 @@ npm i @mnrendra/stack-trace

## API

### **`stackTrace`**
Traces the caller's call sites starting from a specific callee.<br/>
*Captures the current stack trace as an array of `NodeJS.CallSite` objects. If a callee is provided, the trace will start from the caller of the callee.*<br/>
### `stackTrace`
Traces the caller's call sites, starting after a specific callee.<br/>
*Captures the current stack trace as an array of `NodeJS.CallSite`. If a callee is provided, the trace will start from the caller of the callee.*

#### **Type**:
#### Type
```typescript
(callee?: ((...args: any) => any) | null, options?: Options) => NodeJS.CallSite[]
```

#### Parameters

| Name | Type | Description |
|-----------|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `callee` | `((...args: any) => any) \| null` | Optional callee function or method to start tracing from. If `undefined` or `null`, tracing starts from the current caller. |
| `callee` | `((...args: any) => any) \| null` | Optional callee function or method to start tracing after. If `undefined` or `null`, tracing starts from the current caller. |
| `options` | `Options` | Configuration options for tracing behavior. By default, the `limit` option is set to `Infinity` to capture all frames. To capture only a specific number of frames, set the `limit` option to a positive number. |

#### **Return Type**:
#### Return
```typescript
NodeJS.CallSite[]
```
An array of call sites representing the captured stack trace.
An array of `NodeJS.CallSite` representing the captured stack trace.

## Usage
#### Options
| Name | Type | Default | Description |
|---------|----------|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `limit` | `number` | `Infinity` | Specifies the number of stack frames to be collected by a stack trace. The default value is `Infinity` but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed. If set to a non-number value, or set to a negative number, stack traces will not capture any frames. |

### • `getCallerSite`
Gets the caller's call site, starting after a specific callee.<br/>
*Returns the first call site from the current stack trace as a `NodeJS.CallSite`. If a callee is provided, the trace will start from the caller of the callee.*

#### Type
```typescript
(callee?: ((...args: any) => any) | null) => NodeJS.CallSite
```

### **CommonJS**
#### Parameters
| Name | Type | Description |
|-----------|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| `callee` | `((...args: any) => any) \| null` | Optional callee function or method to start tracing after. If `undefined` or `null`, tracing starts from the current caller. |

#### Return
```typescript
NodeJS.CallSite
```
A `NodeJS.CallSite` representing the first call site from the captured stack trace.

## Usage

### CommonJS
`/foo/callee.cjs`
```javascript
const { stackTrace } = require('@mnrendra/stack-trace')
const { stackTrace, getCallerSite } = require('@mnrendra/stack-trace')

const callee = () => {
// stackTrace:
const [callSite1] = stackTrace()
const [callSite2] = stackTrace(callee, { limit: 1 }) // set the `callee` function as the callee.

console.log(callSite1.getFileName()) // output: /foo/callee.cjs
console.log(callSite2.getFileName()) // output: /foo/caller.cjs
console.log(callSite1.getFileName()) // Output: /foo/callee.cjs
console.log(callSite2.getFileName()) // Output: /foo/caller.cjs

console.log(callSite1.getFunctionName()) // Output: callee
console.log(callSite2.getFunctionName()) // Output: caller

// getCallerSite:
const callerSite1 = getCallerSite()
const callerSite2 = getCallerSite(callee) // set the `callee` function as the callee.

console.log(callerSite1.getFileName()) // Output: /foo/callee.cjs
console.log(callerSite2.getFileName()) // Output: /foo/caller.cjs

console.log(callSite1.getFunctionName()) // output: callee
console.log(callSite2.getFunctionName()) // output: caller
console.log(callerSite1.getFunctionName()) // Output: callee
console.log(callerSite2.getFunctionName()) // Output: caller
}

module.exports = callee
```

`/foo/caller.cjs`
```javascript
const callee = require('./callee.cjs')
const caller = () => callee()
caller()
```

### **ES Modules**

### ES Modules
`/foo/callee.mjs`
```javascript
import { stackTrace } from '@mnrendra/stack-trace'
import { stackTrace, getCallerSite } from '@mnrendra/stack-trace'

const callee = () => {
// stackTrace:
const [callSite1] = stackTrace()
const [callSite2] = stackTrace(callee, { limit: 1 }) // set the `callee` function as the callee.

console.log(callSite1.getFileName()) // output: file:///foo/callee.mjs
console.log(callSite2.getFileName()) // output: file:///foo/caller.mjs
console.log(callSite1.getFileName()) // Output: file:///foo/callee.mjs
console.log(callSite2.getFileName()) // Output: file:///foo/caller.mjs

console.log(callSite1.getFunctionName()) // Output: callee
console.log(callSite2.getFunctionName()) // Output: caller

// getCallerSite:
const callerSite1 = getCallerSite()
const callerSite2 = getCallerSite(callee) // set the `callee` function as the callee.

console.log(callSite1.getFunctionName()) // output: callee
console.log(callSite2.getFunctionName()) // output: caller
console.log(callerSite1.getFileName()) // Output: file:///foo/callee.mjs
console.log(callerSite2.getFileName()) // Output: file:///foo/caller.mjs

console.log(callerSite1.getFunctionName()) // Output: callee
console.log(callerSite2.getFunctionName()) // Output: caller
}

export default callee
```

`/foo/caller.mjs`
```javascript
import callee from './callee.mjs'
Expand All @@ -93,51 +139,63 @@ caller()
```

**Note**:
- When calling `getFileName` in an **ES Modules**, the file name will be returned as a **file URL** (e.g., `'file:///foo'`) instead of a **file path** (e.g., `'/foo'`).<br/>
*You can use `url.fileURLToPath` to convert the **file URL** to a **file path**.*
- In ES Modules, `getFileName` returns a **file URL** (e.g., `file:///foo`), instead of a **file path** (`/foo`).<br/>
*Use `url.fileURLToPath` to convert it if needed.*
- By default `stackTrace` will capture all caller frames.<br/>
*To capture only a specific number of frames, set the `limit` option to a positive number.*

### Examples
1. Call from your development project:<br/>

1. **Call from your development project**

`/foo/project-name/src/index.mjs`:
```javascript
import { fileURLToPath } from 'node:url'
import { stackTrace } from '@mnrendra/stack-trace'
import { stackTrace, getCallerSite } from '@mnrendra/stack-trace'

// stackTrace:
const caller1 = () => stackTrace()
const [callSite] = caller1()

const fileName = callSite.getFileName()

console.log(fileName) // Output: file:///foo/project-name/src/index.mjs
console.log(fileURLToPath(fileName)) // Output: /foo/project-name/src/index.mjs

const caller = () => stackTrace()
const [stack] = caller()
// getCallerSite:
const caller2 = () => getCallerSite()
const callerSite = caller2()

const fileName = stack.getFileName()
const fileName = callerSite.getFileName()

console.log(fileName) // output: file:///foo/project-name/src/index.mjs
console.log(fileURLToPath(fileName)) // output: /foo/project-name/src/index.mjs
console.log(fileName) // Output: file:///foo/project-name/src/index.mjs
console.log(fileURLToPath(fileName)) // Output: /foo/project-name/src/index.mjs
```

2. Call from your production package:<br/>
2. **Call from your production package**

`/foo/consumer/node_modules/module-name/dist/index.js`:
```javascript
"use strict";

const { stackTrace } = require("@mnrendra/stack-trace");
const { stackTrace, getCallerSite } = require("@mnrendra/stack-trace");

const caller = () => stackTrace();
const [stack] = caller();
// stackTrace:
const caller1 = () => stackTrace();
const [callSite] = caller1();

const fileName = stack.getFileName();
const fileName = callSite.getFileName();

console.log(fileName); // output: /foo/consumer/node_modules/module-name/dist/index.js
```
console.log(fileName); // Output: /foo/consumer/node_modules/module-name/dist/index.js

## Options
// getCallerSite:
const caller2 = () => getCallerSite();
const callerSite = caller2();

### **`limit`**
#### **Type:** `number`
#### **Default:** `Infinity`
const fileName = callerSite.getFileName();

Specifies the number of stack frames to be collected by a stack trace.<br>
*The default value is `Infinity` but may be set to any valid JavaScript number. Changes will affect any stack trace captured after the value has been changed.*<br>
*If set to a non-number value, or set to a negative number, stack traces will not capture any frames.*
console.log(fileName); // Output: /foo/consumer/node_modules/module-name/dist/index.js
```

## Types
```typescript
Expand Down
24 changes: 15 additions & 9 deletions __tests__/__snapshots__/index.ts.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Test all APIs: Test \`stackTrace\` API: Should capture the current stack trace when the callee is \`null\`! 1`] = `
exports[`Test all APIs: Test \`getCallerSite\` Should return the first call site from the caller stack trace when the callee is a specific function! 1`] = `CallSite {}`;

exports[`Test all APIs: Test \`getCallerSite\` Should return the first call site from the current stack trace when the callee is \`null\`! 1`] = `CallSite {}`;

exports[`Test all APIs: Test \`getCallerSite\` Should return the first call site from the current stack trace when the callee is \`undefined\`! 1`] = `CallSite {}`;

exports[`Test all APIs: Test \`stackTrace\` API: Should only return the first stack trace frame when the \`limit\` option is set to \`1\`! 1`] = `
[
CallSite {},
]
`;

exports[`Test all APIs: Test \`stackTrace\` API: Should return the caller stack trace when the callee is a specific function! 1`] = `
[
CallSite {},
CallSite {},
Expand All @@ -21,7 +33,7 @@ exports[`Test all APIs: Test \`stackTrace\` API: Should capture the current stac
]
`;

exports[`Test all APIs: Test \`stackTrace\` API: Should capture the current stack trace when the callee is \`undefined\`! 1`] = `
exports[`Test all APIs: Test \`stackTrace\` API: Should return the current stack trace when the callee is \`null\`! 1`] = `
[
CallSite {},
CallSite {},
Expand All @@ -42,7 +54,7 @@ exports[`Test all APIs: Test \`stackTrace\` API: Should capture the current stac
]
`;

exports[`Test all APIs: Test \`stackTrace\` API: Should capture the stack trace of the caller when the callee is a specific function! 1`] = `
exports[`Test all APIs: Test \`stackTrace\` API: Should return the current stack trace when the callee is \`undefined\`! 1`] = `
[
CallSite {},
CallSite {},
Expand All @@ -62,9 +74,3 @@ exports[`Test all APIs: Test \`stackTrace\` API: Should capture the stack trace
CallSite {},
]
`;

exports[`Test all APIs: Test \`stackTrace\` API: Should only capture the first stack trace frame when the \`limit\` option is set to \`1\`! 1`] = `
[
CallSite {},
]
`;
Loading