Skip to content

Commit f3b402a

Browse files
authored
Merge pull request #11 from DouglasNeuroInformatics/dev
add functions
2 parents 2f45941 + d30564d commit f3b402a

File tree

4 files changed

+84
-4
lines changed

4 files changed

+84
-4
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"dependencies": {
4545
"clean-stack": "^5.2.0",
4646
"extract-stack": "^3.0.0",
47+
"serialize-error": "^12.0.0",
4748
"stringify-object": "^5.0.0",
4849
"type-fest": "^4.34.1"
4950
},

pnpm-lock.yaml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__tests__/exception.test.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import type { Simplify } from 'type-fest';
22
import { describe, expect, expectTypeOf, it, test } from 'vitest';
33

4-
import { BaseException, ExceptionBuilder, OutOfRangeException, ValueException } from '../exception.js';
4+
import {
5+
BaseException,
6+
errorToJSON,
7+
ExceptionBuilder,
8+
OutOfRangeException,
9+
parseStack,
10+
RuntimeException,
11+
ValueException
12+
} from '../exception.js';
513
import { Err } from '../vendor/neverthrow.js';
614

715
import type { ExceptionConstructor } from '../exception.js';
@@ -189,3 +197,36 @@ describe('OutOfRangeException', () => {
189197
});
190198
});
191199
});
200+
201+
describe('parseStack', () => {
202+
it('should return the same value, in terms of value, whether called with an error or a string', () => {
203+
const error = new Error();
204+
const r1 = parseStack(error);
205+
const r2 = parseStack(error.stack);
206+
expect(r1).toStrictEqual(r2);
207+
});
208+
});
209+
210+
describe('errorToJSON', () => {
211+
it('should return the expected output', () => {
212+
const cause = new RuntimeException('Something else went wrong', {
213+
details: {
214+
foo: true
215+
}
216+
});
217+
const error = new Error('Something went wrong', { cause });
218+
expect(JSON.parse(errorToJSON(error))).toStrictEqual({
219+
cause: {
220+
details: {
221+
foo: true
222+
},
223+
message: 'Something else went wrong',
224+
name: 'RuntimeException',
225+
stack: expect.toSatisfy((arg) => Array.isArray(arg) && arg.every((item) => typeof item === 'string'))
226+
},
227+
message: 'Something went wrong',
228+
name: 'Error',
229+
stack: expect.toSatisfy((arg) => Array.isArray(arg) && arg.every((item) => typeof item === 'string'))
230+
});
231+
});
232+
});

src/exception.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import cleanStack from 'clean-stack';
66
import extractStack from 'extract-stack';
7+
import { isErrorLike, serializeError } from 'serialize-error';
78
import stringifyObject from 'stringify-object';
89
import type { IsNever, RequiredKeysOf } from 'type-fest';
910
import type { z } from 'zod';
@@ -63,8 +64,23 @@ interface ExceptionLike extends Error, ExceptionOptions {
6364
toString(): string;
6465
}
6566

66-
function parseStack(error: Error): string[] {
67-
return extractStack.lines(cleanStack(error.stack, { pretty: true }));
67+
function parseStack(stack: string | undefined): string[];
68+
function parseStack(error: Error): string[];
69+
function parseStack(errorOrStack: Error | string | undefined): string[] {
70+
const stack = typeof errorOrStack === 'string' ? errorOrStack : errorOrStack?.stack;
71+
return extractStack.lines(cleanStack(stack, { pretty: true }));
72+
}
73+
74+
function errorToJSON(error: Error): string {
75+
const serialize = (error: Error): { [key: string]: unknown } => {
76+
const { cause, stack, ...serialized } = serializeError(error);
77+
return {
78+
...serialized,
79+
cause: isErrorLike(cause) ? serialize(cause) : cause,
80+
stack: parseStack(stack)
81+
};
82+
};
83+
return JSON.stringify(serialize(error), null, 2);
6884
}
6985

7086
abstract class BaseException<TParams extends ExceptionParams, TOptions extends ExceptionOptions>
@@ -228,4 +244,14 @@ export type {
228244
ExceptionStatic,
229245
ExceptionType
230246
};
231-
export { BaseException, ExceptionBuilder, OutOfRangeException, parseStack, RuntimeException, ValueException };
247+
248+
export {
249+
BaseException,
250+
errorToJSON,
251+
ExceptionBuilder,
252+
OutOfRangeException,
253+
parseStack,
254+
RuntimeException,
255+
serializeError,
256+
ValueException
257+
};

0 commit comments

Comments
 (0)