Skip to content

Commit 6258d15

Browse files
authored
Merge pull request #485 from instantcommerce/fix/error-stack-parsing
fix: error stack parsing
2 parents 1a1217c + 1a0c2f9 commit 6258d15

File tree

3 files changed

+55
-33
lines changed

3 files changed

+55
-33
lines changed

lib/internals/getCallerInfo.spec.ts

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ describe('getCallerInfo', () => {
1717
? `Error
1818
at Object.getCallerInfo (/unix-example-path/node_modules/next-api-decorators/dist/internals/getCallerInfo.js:9:30)
1919
at createHandler (/unix-example-path/node_modules/next-api-decorators/dist/createHandler.js:30:51)
20-
at eval (webpack-internal:///(api)/./${path}.ts:91:144)
21-
at Object.(api)/./${path}.ts (/unix-example-path/.next/server/${path}.js:32:1)
20+
at eval (webpack-internal:///(api)/./${path}.js:91:144)
21+
at Object.(api)/./${path}.js (/unix-example-path/.next/server/${path}.js:32:1)
2222
at __webpack_require__ (/unix-example-path/.next/server/webpack-api-runtime.js:33:42)
2323
at __webpack_exec__ (/unix-example-path/.next/server/${path}.js:42:39)
2424
at /unix-example-path/.next/server/${path}.js:43:28
@@ -28,8 +28,8 @@ describe('getCallerInfo', () => {
2828
: `Error
2929
at Object.getCallerInfo (/unix-example-path/node_modules/next-api-decorators/dist/internals/getCallerInfo.js:9:30)
3030
at createHandler (/unix-example-path/node_modules/next-api-decorators/dist/createHandler.js:30:51)
31-
at eval (webpack-internal:///./${path}.ts:91:144)
32-
at Object../${path}.ts (/unix-example-path/.next/server/${path}.js:32:1)
31+
at eval (webpack-internal:///./${path}.js:91:144)
32+
at Object../${path}.js (/unix-example-path/.next/server/${path}.js:32:1)
3333
at __webpack_require__ (/unix-example-path/.next/server/webpack-api-runtime.js:33:42)
3434
at __webpack_exec__ (/unix-example-path/.next/server/${path}.js:42:39)
3535
at /unix-example-path/.next/server/${path}.js:43:28
@@ -56,7 +56,7 @@ describe('getCallerInfo', () => {
5656
Object.defineProperty(process, 'platform', { value: 'darwin' });
5757

5858
const dir = getCallerInfo();
59-
expect(dir).toStrictEqual(['/unix-example-path/.next/server/pages/api/tags/[id]', '[[...params]].js']);
59+
expect(dir).toStrictEqual(['/pages/api/tags/[id]', '[[...params]].js']);
6060

6161
spyError.mockRestore();
6262
});
@@ -66,7 +66,7 @@ describe('getCallerInfo', () => {
6666
Object.defineProperty(process, 'platform', { value: 'darwin' });
6767

6868
const dir = getCallerInfo();
69-
expect(dir).toStrictEqual(['/unix-example-path/.next/server/pages/api/tags/[id]', '[[...params]].js']);
69+
expect(dir).toStrictEqual(['/pages/api/tags/[id]', '[[...params]].js']);
7070

7171
spyError.mockRestore();
7272
});
@@ -76,7 +76,7 @@ describe('getCallerInfo', () => {
7676
Object.defineProperty(process, 'platform', { value: 'win32' });
7777

7878
const dir = getCallerInfo();
79-
expect(dir).toStrictEqual(['C:/win-example-path/.next/server/pages/api/tags/[id]', '[[...params]].js']);
79+
expect(dir).toStrictEqual(['/pages/api/tags/[id]', '[[...params]].js']);
8080

8181
spyError.mockRestore();
8282
});
@@ -86,7 +86,7 @@ describe('getCallerInfo', () => {
8686
Object.defineProperty(process, 'platform', { value: 'win32' });
8787

8888
const dir = getCallerInfo();
89-
expect(dir).toStrictEqual(['C:/win-example-path/.next/server/pages/api/tags/[id]', '[[...params]].js']);
89+
expect(dir).toStrictEqual(['/pages/api/tags/[id]', '[[...params]].js']);
9090

9191
spyError.mockRestore();
9292
});
@@ -96,7 +96,7 @@ describe('getCallerInfo', () => {
9696
Object.defineProperty(process, 'platform', { value: 'darwin' });
9797

9898
const dir = getCallerInfo();
99-
expect(dir).toStrictEqual(['/unix-example-path/.next/server/pages/api', '[[...user]].js']);
99+
expect(dir).toStrictEqual(['/pages/api', '[[...user]].js']);
100100

101101
spyError.mockRestore();
102102
});
@@ -106,7 +106,7 @@ describe('getCallerInfo', () => {
106106
Object.defineProperty(process, 'platform', { value: 'darwin' });
107107

108108
const dir = getCallerInfo();
109-
expect(dir).toStrictEqual(['/unix-example-path/.next/server/pages/api', '[[...user]].js']);
109+
expect(dir).toStrictEqual(['/pages/api', '[[...user]].js']);
110110

111111
spyError.mockRestore();
112112
});
@@ -130,10 +130,41 @@ describe('getCallerInfo', () => {
130130
Object.defineProperty(process, 'platform', { value: 'win32' });
131131

132132
const dir = getCallerInfo();
133-
expect(dir).toStrictEqual([
134-
'C:/Users/exampleuser/project/route-matching/.next/server/pages/api/users/deep',
135-
'[[...params]].js'
136-
]);
133+
expect(dir).toStrictEqual(['/pages/api/users/deep', '[[...params]].js']);
134+
135+
spyError.mockRestore();
136+
});
137+
138+
test('Issue #482 - Development error', () => {
139+
const spyError = mockError(
140+
'pages/api/deep/nested/route/[[...params]]',
141+
undefined,
142+
'Error\n' +
143+
' at Object.getCallerInfo (/unix-example-path/node_modules/next-api-decorators/dist/internals/getCallerInfo.js:9:22)\n' +
144+
' at createHandler (/unix-example-path/node_modules/next-api-decorators/dist/createHandler.js:30:51)\n' +
145+
' at eval (webpack-internal:///(api)/./pages/api/deep/nested/route/[[...params]].js:35:132)'
146+
);
147+
Object.defineProperty(process, 'platform', { value: 'darwin' });
148+
149+
const dir = getCallerInfo();
150+
expect(dir).toStrictEqual(['/pages/api/deep/nested/route', '[[...params]].js']);
151+
152+
spyError.mockRestore();
153+
});
154+
155+
test('Issue #482 - Production error', () => {
156+
const spyError = mockError(
157+
'pages/api/deep/nested/route/[[...params]]',
158+
undefined,
159+
'Error\n' +
160+
' at Object.getCallerInfo (/unix-example-path/node_modules/next-api-decorators/dist/internals/getCallerInfo.js:9:22)\n' +
161+
' at createHandler (/unix-example-path/node_modules/next-api-decorators/dist/createHandler.js:30:51)\n' +
162+
' at /unix-example-path/.next/server/pages/api/deep/nested/route/[[...params]].js:58:132'
163+
);
164+
Object.defineProperty(process, 'platform', { value: 'darwin' });
165+
166+
const dir = getCallerInfo();
167+
expect(dir).toStrictEqual(['/pages/api/deep/nested/route', '[[...params]].js']);
137168

138169
spyError.mockRestore();
139170
});

lib/internals/getCallerInfo.ts

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,20 @@
1-
import { basename, dirname } from 'path';
1+
import { basename, dirname, join } from 'path';
22

33
export function getCallerInfo(): [directoryPath: string | undefined, fileName: string | undefined] {
4-
let directoryPath: string | undefined;
5-
let fileName: string | undefined;
6-
74
let errorStack = new Error().stack;
5+
/* istanbul ignore else */
86
if (errorStack && process.platform === 'win32') {
97
errorStack = errorStack.replace(/\\/g, '/');
108
}
119

12-
const parenthesisRegExp = /\(([^)]+)\)$/;
13-
const pathInError = errorStack
14-
?.split('\n')
15-
.find(line => parenthesisRegExp.test(line) && line.includes('/.next/server/pages/api'));
16-
10+
const errorLine = errorStack?.split('\n').find(line => line.includes('/pages/api/'));
11+
const fileInfo = errorLine?.split(/:\d+:\d+/);
1712
/* istanbul ignore else */
18-
if (pathInError) {
19-
const [, pathWithRowCol] = parenthesisRegExp.exec(pathInError) ?? [];
20-
/* istanbul ignore else */
21-
if (pathWithRowCol) {
22-
const fullPath = pathWithRowCol.replace(/:(\d+):(\d+)$/, '');
23-
directoryPath = dirname(fullPath);
24-
fileName = basename(fullPath);
25-
}
13+
if (!fileInfo?.length) {
14+
return [undefined, undefined];
2615
}
2716

28-
return [directoryPath, fileName];
17+
const fileName = fileInfo[0].trim().split('/pages/api/');
18+
19+
return [join('/pages/api', dirname(fileName[fileName.length - 1])), basename(fileName[fileName.length - 1])];
2920
}

lib/internals/parseRequestUrl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function parseRequestUrl(req: NextApiRequest, directoryPath?: string, fil
1919
if (directoryPath && !fileName?.startsWith('[...')) {
2020
const pathRegExp = new RegExp(
2121
// "pages/api/articles/index.ts" is compiled into "pages/api/articles.js" which has to be appended to the directory path for parsing
22-
directoryPath.split('/.next/server/pages')[1].replace(/(\[[0-9a-zA-Z-]+\])/, '([0-9a-zA-Z-]+)') +
22+
directoryPath.split('/pages')[1].replace(/(\[[0-9a-zA-Z-]+\])/, '([0-9a-zA-Z-]+)') +
2323
(fileName && !fileName.startsWith('[...') && !fileName.startsWith('[[...')
2424
? `/${basename(fileName, extname(fileName))}`
2525
: '')

0 commit comments

Comments
 (0)