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

feat: improve error serialization #111

Merged
merged 2 commits into from
Jul 2, 2020
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
110 changes: 104 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Serializer.register(type, options);
* **deserialize** (optional): Describes the function which should be used to deserialize a related property which is not included in the JSON:API document. It should be:
* A _function_ with one argument `function(data) { ... }`which defines the format to which a relation should be deserialized. By default, the ID of the related object is returned, which would be equal to `function(data) {return data.id}`. See [issue #65](https://github.com/danivek/json-api-serializer/issues/65).
* **convertCase** (optional): Case conversion for serializing data. Value can be : `kebab-case`, `snake_case`, `camelCase`
* **beforeSerialize** (optional): A _function_ with one argument `beforeSerialize(data) => newData` to transform data before serialization.
* **beforeSerialize** (optional): A _function_ with one argument `beforeSerialize(data) => newData` to transform data before serialization.

**Deserialization options:**

Expand Down Expand Up @@ -427,12 +427,18 @@ Serializer.deserializeAsync('article', data)
Serializes any error into a JSON API error document.

Input data can be:
- An instance of Error or an array of instance of Error.
- A [JSON API error object](http://jsonapi.org/format/#error-objects) or an array of [JSON API error object](http://jsonapi.org/format/#error-objects).
- An instance of `Error` or an array of `Error` instances.
- A [JSON API error object](http://jsonapi.org/format/#error-objects) or an array of [JSON API error objects](http://jsonapi.org/format/#error-objects).

Using an instance of `Error`:

```javascript
const error = new Error('An error occured');
error.status = 500;
const error = new Error('An error occurred');
error.id = 123
error.links = { about: 'https://example.com/errors/123' }
error.status = 500; // or `statusCode`
error.code = 'xyz'
error.meta = { time: Date.now() }

Serializer.serializeError(error);
```
Expand All @@ -443,8 +449,100 @@ The result will be:
{
"errors": [
{
"id": 123,
"links": {
"about": "https://example.com/errors/123"
},
"status": "500",
"code": "xyz",
"title": "Error",
"detail": "An error occurred",
"meta": {
"time": 1593561258853
}
}
]
}
```

Using an instance of a class that inherits from `Error`:

```js
class MyCustomError extends Error {
constructor(message = 'Something went wrong') {
super(message)
this.id = 123
this.links = {
about: 'https://example.com/errors/123'
}
this.status = 500 // or `statusCode`
this.code = 'xyz'
this.meta = {
time: Date.now()
}
}
}

Serializer.serializeError(new MyCustomError());
```

The result will be:

```JSON
{
"errors": [
{
"id": 123,
"links": {
"about": "https://example.com/errors/123"
},
"status": "500",
"detail": "An error occured"
"code": "xyz",
"title": "MyCustomError",
"detail": "Something went wrong",
"meta": {
"time": 1593561258853
}
}
]
}
```

Using a POJO:

```js
Serializer.serializeError({
id: 123,
links: {
about: 'https://example.com/errors/123'
},
status: 500, // or `statusCode`
code: 'xyz',
title: 'UserNotFound',
detail: 'Unable to find a user with the provided ID',
meta: {
time: Date.now()
}
});
```

The result will be:

```JSON
{
"errors": [
{
"id": 123,
"links": {
"about": "https://example.com/errors/123"
},
"status": "500",
"code": "xyz",
"title": "UserNotFound",
"detail": "Unable to find a user with the provided ID",
"meta": {
"time": 1593561258853
}
}
]
}
Expand Down
42 changes: 5 additions & 37 deletions lib/JSONAPISerializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,51 +383,19 @@ module.exports = class JSONAPISerializer {
/**
* Serialize any error into a JSON API error document.
* Input data can be:
* - An Error or an array of Error.
* - A JSON API error object or an array of JSON API error object.
* - An `Error` or an array of `Error` instances.
* - A JSON API error object or an array of JSON API error objects.
*
* @see {@link http://jsonapi.org/format/#errors}
* @function JSONAPISerializer#serializeError
* @param {Error|Error[]|object|object[]} error an Error, an array of Error, a JSON API error object, an array of JSON API error object.
* @returns {Promise} resolves with serialized error.
* @returns {object} resolves with serialized error.
*/
serializeError(error) {
/**
* An Error object enhanced with status or/and custom code properties.
*
* @typedef {Error} ErrorWithStatus
* @property {string} [status] status code error
* @property {string} [code] code error
*/

/**
* @private
* @param {Error|ErrorWithStatus|object} err an Error, a JSON API error object or an ErrorWithStatus.
* @returns {object} valid JSON API error.
*/
function convertToError(err) {
let serializedError;

if (err instanceof Error) {
const status = err.status || err.statusCode;

serializedError = {
status: status && status.toString(),
code: err.code,
title: err.title || err.constructor.name,
detail: err.message,
};
} else {
serializedError = validateError(err);
}

return serializedError;
}

return {
errors: Array.isArray(error)
? error.map((err) => convertToError(err))
: [convertToError(error)],
? error.map((err) => validateError(err))
: [validateError(error)]
};
}

Expand Down
Loading