Skip to content

Commit 845d403

Browse files
authored
Merge pull request #76 from Travelport-Ukraine/dev
Version 0.1.0
2 parents a22bfd5 + 45cd2b4 commit 845d403

19 files changed

+463
-195
lines changed

.babelrc

Lines changed: 0 additions & 3 deletions
This file was deleted.

.eslintrc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
2-
"parser": "babel-eslint",
32
"extends": "airbnb",
4-
"env": {
5-
"mocha": true
3+
"rules": {
4+
"no-console": 0
65
}
76
}

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
6.2.0
1+
6.3.1

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ node_js:
44
script:
55
- npm run lint
66
- npm run test
7-
- npm run build
87
- npm run test:examples
98
branches:
109
only:

README.md

Lines changed: 116 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
# ⚠ Errors Helpers [![Build Status](https://travis-ci.org/Travelport-Ukraine/errors-helpers.svg?branch=master)](https://travis-ci.org/Travelport-Ukraine/errors-helpers)
22

3-
Current lib helps with error handling in Node.
4-
It provides few helpers that makes life easier. If you want error handling and creation be easy use this lib.
5-
3+
This library helps with error handling in Node.
4+
5+
It provides following API:
6+
- Generators API
7+
- Custom error creation (with inheritance and chaining)
8+
- Creates lists of errors from simple key-value objects
9+
- Helpers API
10+
- Getting iterable object from error instance
11+
- Getting full name for inherited error instance
12+
- Getting array of stacks for an error chain
13+
- Detecting if there is an error of particular error class in the chain
14+
615
## Installation
716

817
Run `npm install --save node-errors-helpers`
@@ -12,71 +21,132 @@ Run `npm install --save node-errors-helpers`
1221
Simple usage of this lib.
1322

1423
```javascript
15-
const e = require('node-errors-helpers');
16-
const StarWarsErrors = e.generate({
17-
'NO_LUKE': 'No Luke Skywalker!',
18-
'NO_DARTH': 'No Darth Vader!',
19-
'YOUR_FATHER': 'I am you father, Luke!',
20-
},
21-
Error);
22-
23-
throw new StartWarsErrors.YOUR_FATHER({ /* additional data */ });
24-
throw new StartWarsErrors.NO_LUKE({ far: 'away' }, CasedByError /* some error */);
24+
const { createErrorClass, createErrorsList } = require('errors-helpers');
25+
26+
const SWError = createErrorClass(
27+
'RuntimeError',
28+
'Runtime error',
29+
Error // parent error class, optional
30+
);
31+
32+
const StarWarsErrors = createErrorsList({
33+
'NO_LUKE': 'No Luke Skywalker!',
34+
'NO_DARTH': 'No Darth Vader!',
35+
'YOUR_FATHER': 'I am you father, Luke!',
36+
}, SWError);
37+
38+
throw new SWError();
39+
throw new StarWarsErrors.YOUR_FATHER({ location: 'Bespin' });
40+
throw new StarWarsErrors.NO_LUKE({ far: 'away' }, causedByError /* some generated or catched error */);
2541
```
2642

43+
[More examples.](/examples/generateFromList.js)
2744

2845
## API
46+
* [createErrorClass(name, message, baseType)](#createclass)[`CustomError`](#customerror)
47+
* [createErrorsList(list, extend)](#createlist)`Object`
48+
* helpers
49+
* .[getFullName(error)](#fullname)`String`
50+
* .[getObject(error)](#getobject)`Object`
51+
* .[getFullStack(error)](#fullstack)`Array\<String>`
52+
* .[hasErrorClass(error, ErrorClass)](#haserrorclass)`Boolean`
53+
54+
<a name="createclass"></a>
55+
### createErrorClass(name, message, baseType))
56+
57+
Creates error class with the `name` provided, that will throw error with `message`. When `baseType` class provided, new error class will be extending base one, if not `Error` class is extended. Each error generated with this helper will have specific structure and [constructor](#customerror).
2958

30-
* [get(error)](#getError) ⇒ <code>Object</code>
31-
* [generate(list, extend, [customFields, [getErr]])](#generateFromList) ⇒ <code>Object</code>
32-
* [inner(error, ErrorClass)](#inner) ⇒ <code>Boolean</code>
33-
* [lib](#FBPlatform+sendImage) ⇒ <code>Object</code>
59+
**Returns**: `CustomError`
3460

35-
<a name="getError"></a>
36-
### get(error)
61+
| Param | Type | Description | Optional |
62+
| --- | --- | --- | --- |
63+
| name | `String` | Name the for class to generate. | no |
64+
| message | `String` | The message calss instance will be thrown with. | no |
65+
| baseType | `String` | Class to extend. If not provided `Error` class is extended. | yes |
3766

38-
Generate object representation of the Error.
67+
<a name="customerror"></a>
68+
#### CustomError
69+
70+
Any custom error has such constructor:
71+
```javascript
72+
const err = new CustomError(data = null, causedBy = null);
73+
// err.data
74+
// err.name
75+
// err.causedBy
76+
```
3977

40-
**Returns**: <code>{ code, message, stack, data }</code>
78+
Created error class will throw error instance with [`message`](#createclass) provided in class constructor.
79+
Field `data` has `any` type. So you can pass there everything.
4180

42-
| Param | Type | Description |
43-
| --- | --- | --- |
44-
| error | <code>Error</code> | Any error created with [generateFromList](#generateFromList) |
81+
You can pass an error as second param and it will be saved as cause of current error. See [examples](/examples/generateFromList.js) for more information.
4582

83+
<a name="createlist"></a>
84+
### createErrorsList(list, extend)
85+
Generates object of errors from object of definitions.
86+
If no `extend` class provided error classes are extended from `Error`.
4687

47-
<a name="generateFromList"></a>
48-
### generate(list, extend, [customFields, [getErr]])]
49-
Generate array of errors from object of definitions.
50-
Object sample:
88+
Object sample:
5189
```javascript
5290
{
5391
'SOME_ERROR_CODE': 'Message that will be shown.',
5492
'ANOTHER_ERROR': 'Another message %)'
5593
}
5694
```
57-
**Returns**: <code>Object (key - code, value - Error)</code>
95+
**Returns**: `Object (key - code, value - Error)`
96+
97+
| Param | Type | Description | Optional |
98+
| --- | --- | --- | --- |
99+
| list | `Object` | Object that define errors. | no |
100+
| extend | `AnyErrorType` | Class that all generated errors will extend. | yes |
101+
102+
<a name="fullname"></a>
103+
### helpers.getFullName(error)
104+
105+
Returns full name of error. Concats all parent classes names with `.`.
106+
107+
**Returns**: `String`
108+
109+
| Param | Type | Description | Optional |
110+
| --- | --- | --- | --- |
111+
| error | `CustomError` | CustomError | no |
112+
113+
114+
<a name="getobject"></a>
115+
### helpers.getObject(error)
116+
117+
Retruns iterable error data object.
118+
119+
For better errors representation in JSON format.
120+
121+
**Returns**: `Object { name, stack, message, data, causedBy }`
122+
123+
| Param | Type | Description | Optional |
124+
| --- | --- | --- | --- |
125+
| error | `CustomError` | CustomError | no |
126+
127+
128+
<a name="fullstack"></a>
129+
### helpers.getFullStack(error)
130+
131+
Recursively gets stacks from `causedBy` errors and return `Array` of them.
58132

59-
| Param | Type | Description |
60-
| --- | --- | --- |
61-
| list | <code>Object</code> | Object that define errors. |
62-
| extend | <code>AnyErrorType</code> | Class that will all generated errors extend. |
63-
| customFields | <code>Array\<String\></code> | Additional fields that each error will have. Objects will contain fields as props of an object. Default `['data']` |
64-
| getErr | <code>Function(AnyErrorType)</code> | Function that generate object from error. Default: [getError](#getError) |
133+
**Returns**: `Array\<String>`
65134

135+
| Param | Type | Description | Optional |
136+
| --- | --- | --- | --- |
137+
| error | `CustomError` | CustomError | no |
66138

67-
<a name="inner"></a>
68-
### inner(error, ErrorClass)
139+
<a name="haserrorclass"></a>
140+
### helpers.hasErrorClass(error, ErrorClass)
69141

70-
Check if error has any inner errors with ErrorClass.
142+
Looks for `ErrorClass` in `error`. Recursivly looks in `causedBy` fields.
143+
Returns `true` if an instance of `ErrorClass` is found, `false` otherwise.
71144

72-
**Returns**: <code>Boolean</code>
73145

74-
| Param | Type | Description |
75-
| --- | --- | --- |
76-
| error | <code>Error</code> | Any error created with [generateFromList](#generateFromList) |
77-
| ErrorClass | <code>Error</code> | Any Error from Node or current lib. |
146+
**Returns**: `Boolean`
78147

79-
<a name="lib"></a>
80-
### lib
148+
| Param | Type | Description | Optional |
149+
| --- | --- | --- | --- |
150+
| error | `CustomError` | Where to look for class. | no |
151+
| ErrorClass | `AnotherCustomError` | What class to look for. | no |
81152

82-
This lib points to [node-common-errors](https://github.com/shutterstock/node-common-errors)

examples/generateFromList.js

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,32 @@
1-
var m = require('../lib');
1+
const { createErrorClass, createErrorsList, helpers } = require('../');
22

3-
var list = {
4-
NO_MONEY: 'There is no money at this account',
5-
TIMEOUT: 'Timeout reached.'
6-
};
3+
const RuntimeError = createErrorClass('RuntimeError', 'Error during validation.', Error);
4+
const ValidationError = createErrorClass('ValidationError', 'Error during validation.', Error);
75

8-
var list2 = {
9-
NO_COCA_COLA: 'No coke in bar.',
10-
NO_FANTA: 'No fanta in bar.',
11-
NO_SPRITE: 'No sprite in bar.',
12-
};
6+
const UserValidationError = createErrorClass(
7+
'UserValidationError',
8+
'Error during user validation.',
9+
ValidationError
10+
);
1311

14-
var PayGateError = m.lib.helpers.generateClass('PayGateError', {
15-
extends: Error,
16-
});
12+
const UserValidationErrors = createErrorsList({
13+
NO_NAME: 'Please specify name.',
14+
NO_LOGIN: 'Please specify login.',
15+
}, UserValidationError);
1716

18-
var BarError = m.lib.helpers.generateClass('BarError', {
19-
extends: PayGateError,
20-
});
2117

22-
var PayGateErrors = m.generate(list, PayGateError);
23-
var BarErrors = m.generate(list2, BarError);
24-
25-
try {
26-
throw new PayGateErrors.NO_MONEY({ balance: 0 });
27-
} catch(e) {
28-
// error has data attribute with prop balance
29-
e instanceof PayGateError;
18+
try{
3019
try {
31-
throw new BarErrors.NO_FANTA(null, e);
32-
} catch(e2) {
33-
e2 instanceof BarError // true
34-
e2 instanceof PayGateError // true
35-
e2.inner_error // NoMoneyError
20+
throw new UserValidationErrors.NO_NAME({ user: { name: null } });
21+
} catch (e) {
22+
// e instanceof UserValidationError; // true
23+
// e instanceof ValidationError; // true
24+
// e instanceof Error; // true
25+
// e instanceof RuntimeError; // false
26+
throw new RuntimeError(null, e);
3627
}
28+
} catch (e) {
29+
// e instanceof RuntimeError; // true
30+
helpers.hasErrorClass(e, ValidationError); // true
3731
}
32+

examples/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
var g = require('./generateFromList');
1+
const g = require('./generateFromList');

index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const createErrorClass = require('./src/error-factory');
2+
const createErrorsList = require('./src/errors-list');
3+
const getFullName = require('./src/helpers/get-full-name');
4+
const getObject = require('./src/helpers/get-object');
5+
const getFullStack = require('./src/helpers/get-full-stack');
6+
const hasErrorClass = require('./src/helpers/has-error-class');
7+
8+
module.exports = {
9+
createErrorClass,
10+
createErrorsList,
11+
helpers: {
12+
getFullName,
13+
getObject,
14+
getFullStack,
15+
hasErrorClass,
16+
},
17+
};

package.json

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
{
22
"name": "node-errors-helpers",
3-
"version": "0.0.4",
3+
"version": "0.1.0",
44
"description": "Some helpers for better error handling in Node.js",
5-
"main": "./lib/index.js",
5+
"main": "index.js",
66
"files": [
7-
"lib",
8-
"src"
7+
"src",
8+
"index.js"
99
],
1010
"scripts": {
11-
"clean": "rimraf lib",
1211
"lint": "eslint src test",
13-
"test": "cross-env BABEL_ENV=commonjs mocha --compilers js:babel-register --recursive",
12+
"cover": "istanbul cover _mocha --recursive",
13+
"test": "mocha --recursive",
1414
"test:examples": "node examples/",
15-
"build": "cross-env BABEL_ENV=commonjs babel src --out-dir lib",
16-
"prepublish": "npm run clean && npm run lint && npm run test && npm run build"
15+
"prepublish": "npm run lint && npm run test"
1716
},
1817
"repository": {
1918
"type": "git",
@@ -23,26 +22,19 @@
2322
"error",
2423
"helpers"
2524
],
26-
"author": "Mark mail.ormark@gmail.com",
25+
"author": "Mark Orel <mail.ormark@gmail.com>",
26+
"contributors": [
27+
"Dmitry Chertousov <d.chertousov@gmail.com>"
28+
],
2729
"license": "MIT",
28-
"dependencies": {
29-
"common-errors": "^1.0.0"
30-
},
3130
"devDependencies": {
32-
"babel": "^6.5.2",
33-
"babel-cli": "^6.14.0",
34-
"babel-eslint": "^7.0.0",
35-
"babel-preset-es2015": "^6.14.0",
36-
"babel-preset-stage-2": "^6.13.0",
37-
"babel-register": "^6.14.0",
3831
"chai": "^3.5.0",
39-
"cross-env": "^3.0.0",
4032
"eslint": "^3.6.0",
4133
"eslint-config-airbnb": "^12.0.0",
4234
"eslint-plugin-import": "^2.0.1",
4335
"eslint-plugin-jsx-a11y": "^2.2.2",
4436
"eslint-plugin-react": "^6.3.0",
4537
"mocha": "^3.0.2",
46-
"rimraf": "^2.5.4"
38+
"istanbul": "^0.4.5"
4739
}
4840
}

src/error-factory.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const util = require('util');
2+
3+
const errorFactory = (name, message, baseType) => {
4+
const baseTypeName = baseType ? baseType.name : 'Error';
5+
6+
/* eslint-disable prefer-template */
7+
const fnBody = `return function ${name} (d, p) {` +
8+
`if (!(this instanceof ${name})) {` +
9+
`return new ${name}(d, p);` +
10+
'}' +
11+
`this.name = '${baseTypeName}.${name}';` +
12+
'this.data = d || null;' +
13+
'if (p) {' +
14+
'this.causedBy = p;' +
15+
'}' +
16+
'Error.captureStackTrace(this, this.constructor);' +
17+
'}';
18+
/* eslint-enable prefer-template */
19+
20+
/* eslint-disable no-new-func */
21+
const CustomError = (new Function('baseType', fnBody))(baseType);
22+
/* eslint-enable no-new-func */
23+
24+
util.inherits(CustomError, baseType || Error);
25+
CustomError.prototype.name = name;
26+
CustomError.prototype.message = message;
27+
28+
return CustomError;
29+
};
30+
31+
module.exports = errorFactory;

0 commit comments

Comments
 (0)