Skip to content

Commit ba63067

Browse files
authored
merge: v3.0.0 (#77)
BREAKING CHANGE: Minimize the package size by dropping unnecessary APIs and focusing on the main (`stackTrace`) API. issues: * merge: v3.0.0 (#76) commits: * feat: stacktrace api (#75) (9888a0f)
2 parents 6a8092c + 9888a0f commit ba63067

20 files changed

Lines changed: 465 additions & 560 deletions

README.md

Lines changed: 97 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,148 @@
11
# @mnrendra/stack-trace
22

3-
![npm version](https://img.shields.io/npm/v/@mnrendra/stack-trace)
3+
![version](https://img.shields.io/npm/v/@mnrendra/stack-trace)
44
![types](https://img.shields.io/npm/types/@mnrendra/stack-trace)
55
![license](https://img.shields.io/npm/l/@mnrendra/stack-trace)
6+
![size](https://img.shields.io/npm/unpacked-size/@mnrendra/stack-trace)
7+
![downloads](https://img.shields.io/npm/dm/@mnrendra/stack-trace)
68

7-
A utility for stack tracing based on the [NodeJS.CallSite](https://nodejs.org/api/errors.html#callsite-object) object, enabling dynamic inspection of function calls.<br/>
8-
*Useful for debugging, logging, or building tools that need to understand call origins and file references at runtime.*
9+
A utility for tracing the caller's call sites starting from a specific callee.<br/>
10+
*Useful for debugging, logging, or building tools that need to get the call origins or file locations at runtime.*
911

1012
## Install
1113
```bash
1214
npm i @mnrendra/stack-trace
1315
```
1416

17+
## API
18+
19+
### **`stackTrace`**
20+
Traces the caller's call sites starting from a specific callee.<br/>
21+
*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/>
22+
23+
#### **Type**:
24+
```typescript
25+
(callee?: ((...args: any) => any) | null, options?: Options) => NodeJS.CallSite[]
26+
```
27+
28+
#### Parameters
29+
30+
| Name | Type | Description |
31+
|-----------|-----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
32+
| `callee` | `((...args: any) => any) \| null` | Optional callee function or method to start tracing from. If `undefined` or `null`, tracing starts from the current caller. |
33+
| `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. |
34+
35+
#### **Return Type**:
36+
```typescript
37+
NodeJS.CallSite[]
38+
```
39+
An array of call sites representing the captured stack trace.
40+
1541
## Usage
16-
- `traceStacks(targetFn?, options?)`:<br/>
17-
Returns an array of `NodeJS.CallSite` objects representing the captured stack trace.
18-
- `traceFiles(targetFn?, options?)`:<br/>
19-
Returns an array of file names (as `string` in **CommonJS** or `URL` in **ES Modules**) extracted from the stack trace of the specified function.
20-
- `traceFnNames(targetFn?, options?)`:<br/>
21-
Returns an array of function names extracted from the stack trace of the given function.
2242

23-
**Note**: If `targetFn` is not provided, it captures the current call stack.
43+
### **CommonJS**
2444

25-
### Usage in `CommonJS`:
45+
`/foo/callee.cjs`
2646
```javascript
27-
const { traceStacks, traceFiles, traceFnNames } = require('@mnrendra/stack-trace')
47+
const { stackTrace } = require('@mnrendra/stack-trace')
2848

29-
const caller1 = () => traceStacks()
30-
const [stack] = caller1()
31-
console.log(stack.getFileName() === __filename) // Output: true
49+
const callee = () => {
50+
const [callSite1] = stackTrace()
51+
const [callSite2] = stackTrace(callee, { limit: 1 }) // set the `callee` function as the callee.
3252

33-
const caller2 = () => traceFiles()
34-
const [file] = caller2()
35-
console.log(file === __filename) // Output: true
53+
console.log(callSite1.getFileName()) // output: /foo/callee.cjs
54+
console.log(callSite2.getFileName()) // output: /foo/caller.cjs
3655

37-
const caller3 = () => traceFnNames()
38-
const [fnName] = caller3()
39-
console.log(fnName) // Output: caller3
56+
console.log(callSite1.getFunctionName()) // output: callee
57+
console.log(callSite2.getFunctionName()) // output: caller
58+
}
59+
60+
module.exports = callee
61+
```
62+
`/foo/caller.cjs`
63+
```javascript
64+
const callee = require('./callee.cjs')
65+
const caller = () => callee()
66+
caller()
4067
```
4168

42-
### Usage in `ES Modules`:
69+
### **ES Modules**
70+
71+
`/foo/callee.mjs`
4372
```javascript
44-
import { traceStacks, traceFiles, traceFnNames } from '@mnrendra/stack-trace'
73+
import { stackTrace } from '@mnrendra/stack-trace'
4574

46-
const caller1 = () => traceStacks()
47-
const [stack] = caller1()
48-
console.log(stack.getFileName() === import.meta.url) // Output: true
75+
const callee = () => {
76+
const [callSite1] = stackTrace()
77+
const [callSite2] = stackTrace(callee, { limit: 1 }) // set the `callee` function as the callee.
4978

50-
const caller2 = () => traceFiles()
51-
const [file] = caller2()
52-
console.log(file === import.meta.url) // Output: true
79+
console.log(callSite1.getFileName()) // output: file:///foo/callee.mjs
80+
console.log(callSite2.getFileName()) // output: file:///foo/caller.mjs
81+
82+
console.log(callSite1.getFunctionName()) // output: callee
83+
console.log(callSite2.getFunctionName()) // output: caller
84+
}
5385

54-
const caller3 = () => traceFnNames()
55-
const [fnName] = caller3()
56-
console.log(fnName) // Output: caller3
86+
export default callee
5787
```
88+
`/foo/caller.mjs`
89+
```javascript
90+
import callee from './callee.mjs'
91+
const caller = () => callee()
92+
caller()
93+
```
94+
95+
**Note**:
96+
- 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/>
97+
*You can use `url.fileURLToPath` to convert the **file URL** to a **file path**.*
98+
- By default `stackTrace` will capture all caller frames.<br/>
99+
*To capture only a specific number of frames, set the `limit` option to a positive number.*
58100

59101
### Examples
60-
1. Call from your development project `/foo/project-name/src/index.mjs`:
102+
1. Call from your development project:<br/>
103+
`/foo/project-name/src/index.mjs`:
61104
```javascript
62-
import { traceStacks, traceFiles, traceFnNames } from '@mnrendra/stack-trace'
105+
import { fileURLToPath } from 'node:url'
106+
import { stackTrace } from '@mnrendra/stack-trace'
63107

64-
const caller1 = () => traceStacks()
65-
const [stack] = caller1()
66-
console.log(stack.getFileName()) // Output: file:///foo/project-name/src/index.mjs
108+
const caller = () => stackTrace()
109+
const [stack] = caller()
67110

68-
const caller2 = () => traceFiles()
69-
const [file] = caller2()
70-
console.log(file) // Output: file:///foo/project-name/src/index.mjs
111+
const fileName = stack.getFileName()
71112

72-
const caller3 = () => traceFnNames()
73-
const [fnName] = caller3()
74-
console.log(fnName) // Output: caller3
113+
console.log(fileName) // output: file:///foo/project-name/src/index.mjs
114+
console.log(fileURLToPath(fileName)) // output: /foo/project-name/src/index.mjs
75115
```
76116

77-
2. Call from your production module `/foo/project-name/node_modules/module-name/dist/index.js`:
117+
2. Call from your production package:<br/>
118+
`/foo/consumer/node_modules/module-name/dist/index.js`:
78119
```javascript
79120
"use strict";
80121

81-
const { traceStacks, traceFiles, traceFnNames } = require('@mnrendra/stack-trace');
122+
const { stackTrace } = require("@mnrendra/stack-trace");
82123

83-
const caller1 = () => traceStacks();
84-
const [stack] = caller1();
85-
console.log(stack.getFileName()); // Output: /foo/project-name/node_modules/module-name/dist/index.js
124+
const caller = () => stackTrace();
125+
const [stack] = caller();
86126

87-
const caller2 = () => traceFiles();
88-
const [file] = caller2();
89-
console.log(file); // Output: /foo/project-name/node_modules/module-name/dist/index.js
127+
const fileName = stack.getFileName();
90128

91-
const caller3 = () => traceFnNames();
92-
const [fnName] = caller3();
93-
console.log(fnName); // Output: caller3
129+
console.log(fileName); // output: /foo/consumer/node_modules/module-name/dist/index.js
94130
```
95131

96-
**Note**: When calling `getFileName` in an **ES Modules** module, the file name will be returned as a **URL** instead of a file path.
97-
98132
## Options
99-
```javascript
100-
import { traceStacks, traceFiles, traceFnNames } from '@mnrendra/stack-trace'
101-
102-
const options = {
103-
limit: 10 // The maximum number of stack frames to capture (default: 10).
104-
}
105-
106-
const caller1 = () => traceStacks(
107-
caller1, // The option target function to be traced.
108-
options
109-
)
110133

111-
const caller2 = () => traceFiles(
112-
caller2, // The option target function to be traced.
113-
options
114-
)
134+
### **`limit`**
135+
#### **Type:** `number`
136+
#### **Default:** `Infinity`
115137

116-
const caller3 = () => traceFnNames(
117-
caller3, // The option target function to be traced.
118-
options
119-
)
120-
```
138+
Specifies the number of stack frames to be collected by a stack trace.<br>
139+
*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>
140+
*If set to a non-number value, or set to a negative number, stack traces will not capture any frames.*
121141

122142
## Types
123143
```typescript
124144
import type {
125-
CallSite, // The alias of `NodeJS.CallSite`.
126-
Options, // The options object for `traceStacks`, `traceFiles`, or `traceFnNames`.
145+
Options
127146
} from '@mnrendra/stack-trace'
128147
```
129148

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Test all APIs: Test \`stackTrace\` API: Should capture the current stack trace when the callee is \`null\`! 1`] = `
4+
[
5+
CallSite {},
6+
CallSite {},
7+
CallSite {},
8+
CallSite {},
9+
CallSite {},
10+
CallSite {},
11+
CallSite {},
12+
CallSite {},
13+
CallSite {},
14+
CallSite {},
15+
CallSite {},
16+
CallSite {},
17+
CallSite {},
18+
CallSite {},
19+
CallSite {},
20+
CallSite {},
21+
]
22+
`;
23+
24+
exports[`Test all APIs: Test \`stackTrace\` API: Should capture the current stack trace when the callee is \`undefined\`! 1`] = `
25+
[
26+
CallSite {},
27+
CallSite {},
28+
CallSite {},
29+
CallSite {},
30+
CallSite {},
31+
CallSite {},
32+
CallSite {},
33+
CallSite {},
34+
CallSite {},
35+
CallSite {},
36+
CallSite {},
37+
CallSite {},
38+
CallSite {},
39+
CallSite {},
40+
CallSite {},
41+
CallSite {},
42+
]
43+
`;
44+
45+
exports[`Test all APIs: Test \`stackTrace\` API: Should capture the stack trace of the caller when the callee is a specific function! 1`] = `
46+
[
47+
CallSite {},
48+
CallSite {},
49+
CallSite {},
50+
CallSite {},
51+
CallSite {},
52+
CallSite {},
53+
CallSite {},
54+
CallSite {},
55+
CallSite {},
56+
CallSite {},
57+
CallSite {},
58+
CallSite {},
59+
CallSite {},
60+
CallSite {},
61+
CallSite {},
62+
CallSite {},
63+
]
64+
`;
65+
66+
exports[`Test all APIs: Test \`stackTrace\` API: Should only capture the first stack trace frame when the \`limit\` option is set to \`1\`! 1`] = `
67+
[
68+
CallSite {},
69+
]
70+
`;

0 commit comments

Comments
 (0)