Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make basePath option support file:// URLs and ignore trailing slash #30

Merged
merged 2 commits into from
Sep 27, 2022
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
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const pathRegex = /^(?:(?:(?:node|node:[\w/]+|(?:(?:node:)?internal\/[\w/]*|.*no
const homeDir = typeof os.homedir === 'undefined' ? '' : os.homedir().replace(/\\/g, '/');

export default function cleanStack(stack, {pretty = false, basePath} = {}) {
const basePathRegex = basePath && new RegExp(`(at | \\()${escapeStringRegexp(basePath.replace(/\\/g, '/'))}`, 'g');
const basePathRegex = basePath && new RegExp(`(at | \\()(file://)?${escapeStringRegexp(basePath.replace(/\\/g, '/'))}/?`, 'g');

if (typeof stack !== 'string') {
return undefined;
Expand Down
4 changes: 2 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ Prettify the file paths in the stack:

Type: `string?`

Remove the given base path from stack trace file paths, effectively turning absolute paths into relative ones.
Remove the given base path from stack trace file paths, effectively turning absolute paths into relative ones. It will also transform absolute file URLs into relative paths.

Example with `'/Users/sindresorhus/dev/clean-stack/'` as `basePath`:
Example with `'/Users/sindresorhus/dev/clean-stack'` as `basePath`:

`/Users/sindresorhus/dev/clean-stack/unicorn.js:2:15` → `unicorn.js:2:15`

Expand Down
92 changes: 69 additions & 23 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ import test from 'ava';
import cleanStack from './index.js';

test('default', t => {
const pre = 'Error: foo\n at Test.fn (/Users/sindresorhus/dev/clean-stack/test.js:6:15)';
const pre = `Error: foo
at Test.fn (/Users/sindresorhus/dev/clean-stack/test.js:6:15)`;
const stack = `${pre}\n
at MySocket.emit (node:events:365:28)\n
at MySocket.emit (node:fs/promises:363:28)\n
at handleMessage (internal/child_process.js:695:10)\n
at Pipe.channel.onread (internal/child_process.js:440:11)\n
at MySocket.emit (node:events:365:28)
at MySocket.emit (node:fs/promises:363:28)
at handleMessage (internal/child_process.js:695:10)
at Pipe.channel.onread (internal/child_process.js:440:11)
at process.emit (events.js:172:7)`;
t.is(cleanStack(stack), pre);
});

test('default #2', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
Expand All @@ -26,7 +28,8 @@ test('default #2', t => {
});

test('directly executed node script', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
Expand All @@ -39,7 +42,8 @@ test('directly executed node script', t => {
});

test('internal child_process', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
Expand All @@ -48,15 +52,17 @@ test('internal child_process', t => {
});

test('internal next_tick', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)`;
t.is(cleanStack(stack), pre);
});

test('internal various modules', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at emitOne (events.js:101:20)
at process.emit (events.js:188:7)
Expand All @@ -65,26 +71,30 @@ test('internal various modules', t => {
});

test('babel-polyfill', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at run (/Users/sindresorhus/dev/clean-stack/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:87:22)
at /Users/sindresorhus/dev/clean-stack/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:100:28`;
t.is(cleanStack(stack), pre);
});

test('pirates', t => {
const pre = 'Error: foo\n at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)';
const pre = `Error: foo
at Object.<anonymous> (/Users/sindresorhus/dev/clean-stack/unicorn.js:4:7)`;
const stack = `${pre}\n
at Module._compile (/Users/zavr/dev/clean-stack/node_modules/pirates/lib/index.js:83:24)
at Object.newLoader [as .js] (/Users/zavr/dev/clean-stack/node_modules/pirates/lib/index.js:88:7)`;
t.is(cleanStack(stack), pre);
});

test('works on Windows', t => {
const expected = 'Error: foo\n at Test.fn (/Users/sindresorhus/dev/clean-stack/test.js:6:15)';
const stack = `Error: foo\n at Test.fn (\\Users\\sindresorhus\\dev\\clean-stack\\test.js:6:15)\n
at handleMessage (internal\\child_process.js:695:10)\n
at Pipe.channel.onread (internal\\child_process.js:440:11)\n
const expected = `Error: foo
at Test.fn (/Users/sindresorhus/dev/clean-stack/test.js:6:15)`;
const stack = `Error: foo
at Test.fn (\\Users\\sindresorhus\\dev\\clean-stack\\test.js:6:15)
at handleMessage (internal\\child_process.js:695:10)
at Pipe.channel.onread (internal\\child_process.js:440:11)
at process.emit (events.js:172:7)`;
t.is(cleanStack(stack), expected);
});
Expand Down Expand Up @@ -130,12 +140,13 @@ test('works with Electron stack traces - built app', t => {
});

test('`pretty` option', t => {
const stack = `Error: foo\n
at Test.fn (${os.homedir()}/dev/clean-stack/test.js:6:15)\n
at handleMessage (internal/child_process.js:695:10)\n
at Pipe.channel.onread (internal/child_process.js:440:11)\n
const stack = `Error: foo
at Test.fn (${os.homedir()}/dev/clean-stack/test.js:6:15)
at handleMessage (internal/child_process.js:695:10)
at Pipe.channel.onread (internal/child_process.js:440:11)
at process.emit (events.js:172:7)`;
const expected = 'Error: foo\n at Test.fn (~/dev/clean-stack/test.js:6:15)';
const expected = `Error: foo
at Test.fn (~/dev/clean-stack/test.js:6:15)`;
t.is(cleanStack(stack, {pretty: true}), expected);
});

Expand All @@ -151,7 +162,9 @@ test('`basePath` option', t => {
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47`;

const expected = 'Error: with basePath\n at Object.<anonymous> (node_modules/foo/bar.js:1:14)\n at node_modules/foo/baz.js:1:14';
const expected = `Error: with basePath
at Object.<anonymous> (node_modules/foo/bar.js:1:14)
at node_modules/foo/baz.js:1:14`;
t.is(cleanStack(stack, {basePath}), expected);
});

Expand All @@ -166,7 +179,40 @@ test('`basePath` option should have precedence over `pretty` option', t => {
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47`;

const expected = 'Error: with basePath\n at Object.<anonymous> (node_modules/foo/bar.js:1:14)';
const expected = `Error: with basePath
at Object.<anonymous> (node_modules/foo/bar.js:1:14)`;
t.is(cleanStack(stack, {basePath, pretty: true}), expected);
});

test('`basePath` option should ignore trailing slash', t => {
const basePath = `${os.homedir()}/dev`;
const stack = `Error: with basePath
at Object.<anonymous> (${os.homedir()}/dev/node_modules/foo/bar.js:1:14)
at Module._compile (internal/modules/cjs/loader.js:1200:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
at Module.load (internal/modules/cjs/loader.js:1049:32)
at Function.Module._load (internal/modules/cjs/loader.js:937:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47`;

const expected = `Error: with basePath
at Object.<anonymous> (node_modules/foo/bar.js:1:14)`;
t.is(cleanStack(stack, {basePath, pretty: true}), expected);
});

test('`basePath` option should support file URLs', t => {
const basePath = '/dev';
const stack = `Error
at file:///dev/node_modules/foo/bar.js:1:14
at ModuleJob.run (node:internal/modules/esm/module_job:193:25)
at async Promise.all (index 0)
at async ESMLoader.import (node:internal/modules/esm/loader:527:24)
at async loadESM (node:internal/process/esm_loader:91:5)
at async handleMainPromise (node:internal/modules/run_main:65:12)`;

const expected = `Error
at node_modules/foo/bar.js:1:14
at async Promise.all (index 0)`;
t.is(cleanStack(stack, {basePath, pretty: true}), expected);
});

Expand Down