Repository: sindresorhus/serialize-error
Pull request #24 (2019-09-23 01:01:11)

Add `deserializeError` method
- add function `deserializeError`
- serializeError is no longer export default, used like used like `import {serializeError, deserializeError} from '.'`, this is a breaking change.


Patch:
diff --git a/index.d.ts b/index.d.ts
index 526d103..a7f053d 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -7,35 +7,46 @@ declare namespace serializeError {
 		message?: string;
 		code?: string;
 	} & JsonObject;
-}
 
-declare const serializeError: {
-	/**
-	Serialize an error into a plain object.
-
-	@example
-	```
-	import serializeError = require('serialize-error');
-
-	const error = new Error('🦄');
-
-	console.log(error);
-	//=> [Error: 🦄]
-
-	console.log(serializeError(error));
-	//=> {name: 'Error', message: '🦄', stack: 'Error: 🦄\n    at Object.<anonymous> …'}
-	```
-	*/
-	<ErrorType>(error: ErrorType): ErrorType extends Primitive
-		? ErrorType
-		: serializeError.ErrorObject;
-
-	// TODO: Remove this for the next major release, refactor the whole definition to:
-	// declare function serializeError<ErrorType>(
-	// 	error: ErrorType
-	// ): ErrorType extends Primitive ? ErrorType : ErrorObject;
-	// export = serializeError;
-	default: typeof serializeError;
-};
+	const serializeError: {
+		/**
+		Serialize an error into a plain object.
+
+		@example
+		```
+		import {serializeError} = require('serialize-error');
+
+		const error = new Error('🦄');
+
+		console.log(error);
+		//=> [Error: 🦄]
+
+		console.log(serializeError(error));
+		//=> {name: 'Error', message: '🦄', stack: 'Error: 🦄\n    at Object.<anonymous> …'}
+		```
+		*/
+		<ErrorType>(error: ErrorType): ErrorType extends Primitive
+			? ErrorType
+			: ErrorObject;
+	};
+
+	const deserializeError: {
+		/**
+		Deserialize into a plain object into an error.
+
+		@example
+		```
+		import {deserializeError} = require('serialize-error');
+
+		const error = deserializeError(errorObject);
+
+		console.log(error);
+		//=> Error: aaa
+			at <anonymous>:1:13
+		```
+		*/
+		(errorObject: ErrorObject): Error
+	}
+}
 
 export = serializeError;
diff --git a/index.js b/index.js
index bc77cb4..307d12c 100644
--- a/index.js
+++ b/index.js
@@ -1,5 +1,12 @@
 'use strict';
 
+const commonProperties = [
+	'name',
+	'message',
+	'stack',
+	'code'
+];
+
 const destroyCircular = (from, seen) => {
 	const to = Array.isArray(from) ? [] : {};
 
@@ -23,13 +30,6 @@ const destroyCircular = (from, seen) => {
 		to[key] = '[Circular]';
 	}
 
-	const commonProperties = [
-		'name',
-		'message',
-		'stack',
-		'code'
-	];
-
 	for (const property of commonProperties) {
 		if (typeof from[property] === 'string') {
 			to[property] = from[property];
@@ -53,6 +53,29 @@ const serializeError = value => {
 	return value;
 };
 
-module.exports = serializeError;
+const deserializeError = error => {
+	if (error instanceof Error) {
+		return error;
+	}
+
+	if (error && typeof error === 'object' && !Array.isArray(error)) {
+		const err = new Error();
+		for (const property of commonProperties) {
+			err[property] = error[property];
+		}
+
+		return err;
+	}
+
+	return new Error('unknown');
+};
+
+module.exports = {
+	serializeError,
+	deserializeError
+};
 // TODO: Remove this for the next major release
-module.exports.default = serializeError;
+module.exports.default = {
+	serializeError,
+	deserializeError
+};
diff --git a/readme.md b/readme.md
index 0eb6ed1..07383db 100644
--- a/readme.md
+++ b/readme.md
@@ -15,17 +15,21 @@ $ npm install serialize-error
 ## Usage
 
 ```js
-const serializeError = require('serialize-error');
+const { serializeError, deserializeError } = require('serialize-error');
 
 const error = new Error('🦄');
 
 console.log(error);
 //=> [Error: 🦄]
 
-console.log(serializeError(error));
+const serialized = serializeError(error)
+
+console.log(serialized);
 //=> {name: 'Error', message: '🦄', stack: 'Error: 🦄\n    at Object.<anonymous> …'}
-```
 
+const deserialized = deserializeError(serialized);
+//=> [Error: 🦄]
+```
 
 ## License
 


Test patch:
diff --git a/index.test-d.ts b/index.test-d.ts
index ef16501..231c4fc 100644
--- a/index.test-d.ts
+++ b/index.test-d.ts
@@ -1,8 +1,14 @@
 import {expectType} from 'tsd';
-import serializeError = require('.');
-import {ErrorObject} from '.';
+import {ErrorObject, serializeError, deserializeError} from '.';
 
 const error = new Error('unicorn');
 
 expectType<number>(serializeError(1));
 expectType<ErrorObject>(serializeError(error));
+
+expectType<Error>(deserializeError({
+	message: 'error message',
+	stack: 'at <anonymous>:1:13',
+	name: 'name',
+	code: 'code'
+}));
diff --git a/test.js b/test.js
index 9e15a75..e808882 100644
--- a/test.js
+++ b/test.js
@@ -1,5 +1,5 @@
 import test from 'ava';
-import serializeError from '.';
+import {serializeError, deserializeError} from '.';
 
 test('main', t => {
 	const serialized = serializeError(new Error('foo'));
@@ -108,3 +108,43 @@ test('should serialize nested errors', t => {
 	t.is(serialized.message, 'outer error');
 	t.is(serialized.innerError.message, 'inner error');
 });
+
+test('should deserialize null', t => {
+	const deserialized = deserializeError(null);
+	t.is(deserialized instanceof Error, true);
+	t.is(deserialized.message, 'unknown');
+});
+
+test('should deserialize number', t => {
+	const deserialized = deserializeError(1);
+	t.is(deserialized instanceof Error, true);
+	t.is(deserialized.message, 'unknown');
+});
+
+test('should deserialize error', t => {
+	const deserialized = deserializeError(new Error('test'));
+	t.is(deserialized instanceof Error, true);
+	t.is(deserialized.message, 'test');
+});
+
+test('should deserialize array', t => {
+	const deserialized = deserializeError([1]);
+	t.is(deserialized instanceof Error, true);
+	t.is(deserialized.message, 'unknown');
+});
+
+test('should deserialize plain object', t => {
+	const object = {
+		message: 'error message',
+		stack: 'at <anonymous>:1:13',
+		name: 'name',
+		code: 'code'
+	};
+
+	const deserialized = deserializeError(object);
+	t.is(deserialized instanceof Error, true);
+	t.is(deserialized.message, 'error message');
+	t.is(deserialized.stack, 'at <anonymous>:1:13');
+	t.is(deserialized.name, 'name');
+	t.is(deserialized.code, 'code');
+});