Repository: blitz-js/superjson
Pull request #92 (2021-01-20 19:47:50)

allowErrorProps(...) (#91)
This adds `SuperJSON.allowErrorProps(...)`, which can be used to register non-standard error props to be transformed.

See #91


Patch:
diff --git a/src/error-props.ts b/src/error-props.ts
new file mode 100644
index 0000000..e052a37
--- /dev/null
+++ b/src/error-props.ts
@@ -0,0 +1,5 @@
+export const allowedErrorProps: string[] = [];
+
+export const allowErrorProps = (...props: string[]) => {
+  allowedErrorProps.push(...props);
+};
diff --git a/src/index.ts b/src/index.ts
index 1af2f82..9a3926c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -14,6 +14,7 @@ import {
   CustomTransfomer,
   CustomTransformerRegistry,
 } from './custom-transformer-registry';
+import { allowErrorProps } from './error-props';
 
 export const serialize = (object: SuperJSONValue): SuperJSONResult => {
   const { getAnnotations, annotator } = makeAnnotator();
@@ -72,4 +73,5 @@ export default {
   registerClass,
   registerSymbol,
   registerCustom,
+  allowErrorProps,
 };
diff --git a/src/transformer.ts b/src/transformer.ts
index 6b31033..ea6e808 100644
--- a/src/transformer.ts
+++ b/src/transformer.ts
@@ -14,6 +14,7 @@ import { ClassRegistry } from './class-registry';
 import { SymbolRegistry } from './symbol-registry';
 import { fromPairs, includes, entries, find, isError } from 'lodash';
 import { CustomTransformerRegistry } from './custom-transformer-registry';
+import { allowedErrorProps } from './error-props';
 
 export type PrimitiveTypeAnnotation = 'number' | 'undefined' | 'bigint';
 
@@ -101,11 +102,28 @@ const simpleRules = [
   simpleTransformation(
     isError,
     'Error',
-    v => ({ name: v.name, message: v.message, stack: v.stack }),
-    ({ name, message, stack }) => {
-      const e = new Error(message);
-      e.name = name;
-      e.stack = stack;
+    v => {
+      const baseError: any = {
+        name: v.name,
+        message: v.message,
+        stack: v.stack,
+      };
+
+      allowedErrorProps.forEach(prop => {
+        baseError[prop] = (v as any)[prop];
+      });
+
+      return baseError;
+    },
+    v => {
+      const e = new Error(v.message);
+      e.name = v.name;
+      e.stack = v.stack;
+
+      allowedErrorProps.forEach(prop => {
+        (e as any)[prop] = v[prop];
+      });
+
       return e;
     }
   ),


Test patch:
diff --git a/src/index.test.ts b/src/index.test.ts
index d5d99bc..e83d68e 100644
--- a/src/index.test.ts
+++ b/src/index.test.ts
@@ -741,6 +741,44 @@ describe('stringify & parse', () => {
   });
 });
 
+describe('allowErrorProps(...) (#91)', () => {
+  it('works with simple prop values', () => {
+    const errorWithAdditionalProps: Error & any = new Error(
+      'I have additional props 😄'
+    );
+    errorWithAdditionalProps.code = 'P2002';
+    errorWithAdditionalProps.meta = '👾';
+
+    // same as allowErrorProps("code", "meta")
+    SuperJSON.allowErrorProps('code');
+    SuperJSON.allowErrorProps('meta');
+
+    const errorAfterTransition: any = SuperJSON.parse(
+      SuperJSON.stringify(errorWithAdditionalProps)
+    );
+
+    expect(errorAfterTransition).toBeInstanceOf(Error);
+    expect(errorAfterTransition.message).toEqual('I have additional props 😄');
+    expect(errorAfterTransition.code).toEqual('P2002');
+    expect(errorAfterTransition.meta).toEqual('👾');
+  });
+
+  it.skip('works with complex prop values', () => {
+    const errorWithAdditionalProps: any = new Error();
+    errorWithAdditionalProps.map = new Map();
+
+    SuperJSON.allowErrorProps('map');
+
+    const errorAfterTransition: any = SuperJSON.parse(
+      SuperJSON.stringify(errorWithAdditionalProps)
+    );
+
+    expect(errorAfterTransition.map).toEqual(undefined);
+
+    expect(errorAfterTransition.map).toBeInstanceOf(Map);
+  });
+});
+
 test('regression #83: negative zero', () => {
   const input = -0;