@storyous/errors 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/__tests__/appError.test.js +70 -0
- package/__tests__/appError.test.ts +77 -0
- package/__tests__/errorHandler.test.js +40 -0
- package/__tests__/errorHandler.test.ts +44 -0
- package/lib/appError.js +85 -0
- package/lib/appError.ts +117 -0
- package/lib/errorHandler.js +71 -0
- package/lib/errorHandler.ts +81 -0
- package/lib/index.js +11 -0
- package/lib/index.ts +4 -0
- package/package.json +40 -0
- package/tsconfig.json +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# `errors`
|
|
2
|
+
|
|
3
|
+
## Usage
|
|
4
|
+
|
|
5
|
+
``` typescript
|
|
6
|
+
import { AppError } from '@storyous/errors';
|
|
7
|
+
|
|
8
|
+
throw AppError.internal('Something went wrong.');
|
|
9
|
+
|
|
10
|
+
...
|
|
11
|
+
|
|
12
|
+
import { initErrHandler } from '@storyous/errors';
|
|
13
|
+
|
|
14
|
+
const app = new Koa();
|
|
15
|
+
app.use(initErrHandler(logger));
|
|
16
|
+
|
|
17
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const assert_1 = __importDefault(require("assert"));
|
|
7
|
+
const mocha_1 = require("mocha");
|
|
8
|
+
const lib_1 = require("../lib");
|
|
9
|
+
(0, mocha_1.describe)('packages/errors/AppError', () => {
|
|
10
|
+
(0, mocha_1.it)('should receive Error with additional Meta', () => {
|
|
11
|
+
const err = new lib_1.AppError('');
|
|
12
|
+
err.setMeta({ foo: 'bar' });
|
|
13
|
+
assert_1.default.deepStrictEqual(err.meta, { foo: 'bar' });
|
|
14
|
+
});
|
|
15
|
+
(0, mocha_1.it)('should receive NotFound Error', () => {
|
|
16
|
+
const err = lib_1.AppError.notFound('Ups ...', { foo: 'bar' });
|
|
17
|
+
assert_1.default.deepStrictEqual(err.message, 'Not found: Ups ...');
|
|
18
|
+
assert_1.default.deepStrictEqual(err.meta, { foo: 'bar', code: 404, httpStatus: 404 });
|
|
19
|
+
});
|
|
20
|
+
(0, mocha_1.it)('should receive NotFound Error without custom message', () => {
|
|
21
|
+
const err = lib_1.AppError.notFound();
|
|
22
|
+
assert_1.default.deepStrictEqual(err.message, 'Not found');
|
|
23
|
+
assert_1.default.deepStrictEqual(err.meta, { code: 404, httpStatus: 404 });
|
|
24
|
+
});
|
|
25
|
+
(0, mocha_1.it)('should receive BadRequest Error', () => {
|
|
26
|
+
const err = lib_1.AppError.badRequest('Ups ...', { foo: 'bar' });
|
|
27
|
+
assert_1.default.deepStrictEqual(err.message, 'Bad request: Ups ...');
|
|
28
|
+
assert_1.default.deepStrictEqual(err.meta, { foo: 'bar', code: 400, httpStatus: 400 });
|
|
29
|
+
});
|
|
30
|
+
(0, mocha_1.it)('should receive BadRequest Error without custom message', () => {
|
|
31
|
+
const err = lib_1.AppError.badRequest();
|
|
32
|
+
assert_1.default.deepStrictEqual(err.message, 'Bad request');
|
|
33
|
+
assert_1.default.deepStrictEqual(err.meta, { code: 400, httpStatus: 400 });
|
|
34
|
+
});
|
|
35
|
+
(0, mocha_1.it)('should receive ConcurrentRequest Error', () => {
|
|
36
|
+
const err = lib_1.AppError.concurrentRequest('Ups ...', { foo: 'bar' });
|
|
37
|
+
assert_1.default.deepStrictEqual(err.message, 'Concurrent request: Ups ...');
|
|
38
|
+
assert_1.default.deepStrictEqual(err.meta, { foo: 'bar', code: 409, httpStatus: 409 });
|
|
39
|
+
});
|
|
40
|
+
(0, mocha_1.it)('should receive ConcurrentRequest Error without custom message', () => {
|
|
41
|
+
const err = lib_1.AppError.concurrentRequest();
|
|
42
|
+
assert_1.default.deepStrictEqual(err.message, 'Concurrent request');
|
|
43
|
+
assert_1.default.deepStrictEqual(err.meta, { code: 409, httpStatus: 409 });
|
|
44
|
+
});
|
|
45
|
+
(0, mocha_1.it)('should receive is ConcurrentRequest Error', () => {
|
|
46
|
+
const err = lib_1.AppError.concurrentRequest();
|
|
47
|
+
assert_1.default.deepStrictEqual(lib_1.AppError.isConcurrentRequestError(err), true);
|
|
48
|
+
});
|
|
49
|
+
(0, mocha_1.it)('should receive Internal Error', () => {
|
|
50
|
+
const err = lib_1.AppError.internal('Ups ...', { foo: 'bar' });
|
|
51
|
+
assert_1.default.deepStrictEqual(err.message, 'Internal: Ups ...');
|
|
52
|
+
assert_1.default.deepStrictEqual(err.meta, { foo: 'bar', code: 500, httpStatus: 500 });
|
|
53
|
+
});
|
|
54
|
+
(0, mocha_1.it)('should receive Internal Error without custom message', () => {
|
|
55
|
+
const err = lib_1.AppError.internal();
|
|
56
|
+
assert_1.default.deepStrictEqual(err.message, 'Internal');
|
|
57
|
+
assert_1.default.deepStrictEqual(err.meta, { code: 500, httpStatus: 500 });
|
|
58
|
+
});
|
|
59
|
+
(0, mocha_1.it)('should receive Unauthorized Error', () => {
|
|
60
|
+
const err = lib_1.AppError.unauthorized('Ups ...', { foo: 'bar' });
|
|
61
|
+
assert_1.default.deepStrictEqual(err.message, 'Unauthorized: Ups ...');
|
|
62
|
+
assert_1.default.deepStrictEqual(err.meta, { foo: 'bar', code: 401, httpStatus: 401 });
|
|
63
|
+
});
|
|
64
|
+
(0, mocha_1.it)('should receive Unauthorized Error without custom message', () => {
|
|
65
|
+
const err = lib_1.AppError.unauthorized();
|
|
66
|
+
assert_1.default.deepStrictEqual(err.message, 'Unauthorized');
|
|
67
|
+
assert_1.default.deepStrictEqual(err.meta, { code: 401, httpStatus: 401 });
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwRXJyb3IudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFwcEVycm9yLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsaUNBQXFDO0FBQ3JDLGdDQUFrQztBQUVsQyxJQUFBLGdCQUFRLEVBQUMsMEJBQTBCLEVBQUUsR0FBRyxFQUFFO0lBRXRDLElBQUEsVUFBRSxFQUFDLDJDQUEyQyxFQUFFLEdBQUcsRUFBRTtRQUNqRCxNQUFNLEdBQUcsR0FBRyxJQUFJLGNBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM3QixHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDNUIsZ0JBQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxVQUFFLEVBQUMsK0JBQStCLEVBQUUsR0FBRyxFQUFFO1FBQ3JDLE1BQU0sR0FBRyxHQUFHLGNBQVEsQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekQsZ0JBQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1FBQzFELGdCQUFNLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDakYsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQyxzREFBc0QsRUFBRSxHQUFHLEVBQUU7UUFDNUQsTUFBTSxHQUFHLEdBQUcsY0FBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2hDLGdCQUFNLENBQUMsZUFBZSxD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
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import { describe, it } from 'mocha';
|
|
3
|
+
import { AppError } from '../lib';
|
|
4
|
+
|
|
5
|
+
describe('packages/errors/AppError', () => {
|
|
6
|
+
|
|
7
|
+
it('should receive Error with additional Meta', () => {
|
|
8
|
+
const err = new AppError('');
|
|
9
|
+
err.setMeta({ foo: 'bar' });
|
|
10
|
+
assert.deepStrictEqual(err.meta, { foo: 'bar' });
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should receive NotFound Error', () => {
|
|
14
|
+
const err = AppError.notFound('Ups ...', { foo: 'bar' });
|
|
15
|
+
assert.deepStrictEqual(err.message, 'Not found: Ups ...');
|
|
16
|
+
assert.deepStrictEqual(err.meta, { foo: 'bar', code: 404, httpStatus: 404 });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should receive NotFound Error without custom message', () => {
|
|
20
|
+
const err = AppError.notFound();
|
|
21
|
+
assert.deepStrictEqual(err.message, 'Not found');
|
|
22
|
+
assert.deepStrictEqual(err.meta, { code: 404, httpStatus: 404 });
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should receive BadRequest Error', () => {
|
|
26
|
+
const err = AppError.badRequest('Ups ...', { foo: 'bar' });
|
|
27
|
+
assert.deepStrictEqual(err.message, 'Bad request: Ups ...');
|
|
28
|
+
assert.deepStrictEqual(err.meta, { foo: 'bar', code: 400, httpStatus: 400 });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should receive BadRequest Error without custom message', () => {
|
|
32
|
+
const err = AppError.badRequest();
|
|
33
|
+
assert.deepStrictEqual(err.message, 'Bad request');
|
|
34
|
+
assert.deepStrictEqual(err.meta, { code: 400, httpStatus: 400 });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should receive ConcurrentRequest Error', () => {
|
|
38
|
+
const err = AppError.concurrentRequest('Ups ...', { foo: 'bar' });
|
|
39
|
+
assert.deepStrictEqual(err.message, 'Concurrent request: Ups ...');
|
|
40
|
+
assert.deepStrictEqual(err.meta, { foo: 'bar', code: 409, httpStatus: 409 });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should receive ConcurrentRequest Error without custom message', () => {
|
|
44
|
+
const err = AppError.concurrentRequest();
|
|
45
|
+
assert.deepStrictEqual(err.message, 'Concurrent request');
|
|
46
|
+
assert.deepStrictEqual(err.meta, { code: 409, httpStatus: 409 });
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should receive is ConcurrentRequest Error', () => {
|
|
50
|
+
const err = AppError.concurrentRequest();
|
|
51
|
+
assert.deepStrictEqual(AppError.isConcurrentRequestError(err), true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should receive Internal Error', () => {
|
|
55
|
+
const err = AppError.internal('Ups ...', { foo: 'bar' });
|
|
56
|
+
assert.deepStrictEqual(err.message, 'Internal: Ups ...');
|
|
57
|
+
assert.deepStrictEqual(err.meta, { foo: 'bar', code: 500, httpStatus: 500 });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should receive Internal Error without custom message', () => {
|
|
61
|
+
const err = AppError.internal();
|
|
62
|
+
assert.deepStrictEqual(err.message, 'Internal');
|
|
63
|
+
assert.deepStrictEqual(err.meta, { code: 500, httpStatus: 500 });
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should receive Unauthorized Error', () => {
|
|
67
|
+
const err = AppError.unauthorized('Ups ...', { foo: 'bar' });
|
|
68
|
+
assert.deepStrictEqual(err.message, 'Unauthorized: Ups ...');
|
|
69
|
+
assert.deepStrictEqual(err.meta, { foo: 'bar', code: 401, httpStatus: 401 });
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should receive Unauthorized Error without custom message', () => {
|
|
73
|
+
const err = AppError.unauthorized();
|
|
74
|
+
assert.deepStrictEqual(err.message, 'Unauthorized');
|
|
75
|
+
assert.deepStrictEqual(err.meta, { code: 401, httpStatus: 401 });
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const test_utils_1 = __importDefault(require("@storyous/test-utils"));
|
|
7
|
+
const koa_1 = __importDefault(require("koa"));
|
|
8
|
+
const koa_router_1 = __importDefault(require("koa-router"));
|
|
9
|
+
const mocha_1 = require("mocha");
|
|
10
|
+
const winston_1 = require("winston");
|
|
11
|
+
const lib_1 = require("../lib");
|
|
12
|
+
const app = new koa_1.default();
|
|
13
|
+
app.use((0, lib_1.initErrHandler)((0, winston_1.createLogger)()));
|
|
14
|
+
const router = new koa_router_1.default();
|
|
15
|
+
router.get('/internal', () => {
|
|
16
|
+
throw lib_1.AppError.internal();
|
|
17
|
+
});
|
|
18
|
+
router.get('/notFound', () => {
|
|
19
|
+
throw lib_1.AppError.notFound();
|
|
20
|
+
});
|
|
21
|
+
router.get('/err', () => {
|
|
22
|
+
throw new Error();
|
|
23
|
+
});
|
|
24
|
+
app.use(router.routes());
|
|
25
|
+
(0, mocha_1.describe)('packages/errors/ErrorHandler', () => {
|
|
26
|
+
test_utils_1.default.init(() => app);
|
|
27
|
+
(0, mocha_1.it)('should badRequest', async () => {
|
|
28
|
+
await test_utils_1.default.request().get('/').expect(404);
|
|
29
|
+
});
|
|
30
|
+
(0, mocha_1.it)('should internal error thrown', async () => {
|
|
31
|
+
await test_utils_1.default.request().get('/internal').expect(500);
|
|
32
|
+
});
|
|
33
|
+
(0, mocha_1.it)('should notFound error thrown', async () => {
|
|
34
|
+
await test_utils_1.default.request().get('/notFound').expect(404);
|
|
35
|
+
});
|
|
36
|
+
(0, mocha_1.it)('should error thrown', async () => {
|
|
37
|
+
await test_utils_1.default.request().get('/err').expect(500);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JIYW5kbGVyLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJlcnJvckhhbmRsZXIudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHNFQUE2QztBQUM3Qyw4Q0FBc0I7QUFDdEIsNERBQW1DO0FBQ25DLGlDQUFxQztBQUNyQyxxQ0FBdUM7QUFDdkMsZ0NBQWtEO0FBRWxELE1BQU0sR0FBRyxHQUFHLElBQUksYUFBRyxFQUFFLENBQUM7QUFDdEIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFBLG9CQUFjLEVBQUMsSUFBQSxzQkFBWSxHQUFFLENBQUMsQ0FBQyxDQUFDO0FBQ3hDLE1BQU0sTUFBTSxHQUFHLElBQUksb0JBQVMsRUFBRSxDQUFDO0FBRS9CLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRTtJQUN6QixNQUFNLGNBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUM5QixDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLEdBQUcsRUFBRTtJQUN6QixNQUFNLGNBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUM5QixDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRTtJQUNwQixNQUFNLElBQUksS0FBSyxFQUFFLENBQUM7QUFDdEIsQ0FBQyxDQUFDLENBQUM7QUFFSCxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBRXpCLElBQUEsZ0JBQVEsRUFBQyw4QkFBOEIsRUFBRSxHQUFHLEVBQUU7SUFDMUMsb0JBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7SUFFMUIsSUFBQSxVQUFFLEVBQUMsbUJBQW1CLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDL0IsTUFBTSxvQkFBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkQsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQyw4QkFBOEIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUMxQyxNQUFNLG9CQUFTLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzRCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsVUFBRSxFQUFDLDhCQUE4QixFQUFFLEtBQUssSUFBSSxFQUFFO1FBQzFDLE1BQU0sb0JBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzNELENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBQSxVQUFFLEVBQUMscUJBQXFCLEVBQUUsS0FBSyxJQUFJLEVBQUU7UUFDakMsTUFBTSxvQkFBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEQsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDLENBQUMsQ0FBQyJ9
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import testUtils from '@storyous/test-utils';
|
|
2
|
+
import Koa from 'koa';
|
|
3
|
+
import KoaRouter from 'koa-router';
|
|
4
|
+
import { describe, it } from 'mocha';
|
|
5
|
+
import { createLogger } from 'winston';
|
|
6
|
+
import { AppError, initErrHandler } from '../lib';
|
|
7
|
+
|
|
8
|
+
const app = new Koa();
|
|
9
|
+
app.use(initErrHandler(createLogger()));
|
|
10
|
+
const router = new KoaRouter();
|
|
11
|
+
|
|
12
|
+
router.get('/internal', () => {
|
|
13
|
+
throw AppError.internal();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
router.get('/notFound', () => {
|
|
17
|
+
throw AppError.notFound();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
router.get('/err', () => {
|
|
21
|
+
throw new Error();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
app.use(router.routes());
|
|
25
|
+
|
|
26
|
+
describe('packages/errors/ErrorHandler', () => {
|
|
27
|
+
testUtils.init(() => app);
|
|
28
|
+
|
|
29
|
+
it('should badRequest', async () => {
|
|
30
|
+
await testUtils.request().get('/').expect(404);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should internal error thrown', async () => {
|
|
34
|
+
await testUtils.request().get('/internal').expect(500);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should notFound error thrown', async () => {
|
|
38
|
+
await testUtils.request().get('/notFound').expect(404);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should error thrown', async () => {
|
|
42
|
+
await testUtils.request().get('/err').expect(500);
|
|
43
|
+
});
|
|
44
|
+
});
|
package/lib/appError.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class AppError extends Error {
|
|
4
|
+
constructor(message, meta) {
|
|
5
|
+
super();
|
|
6
|
+
this.message = message;
|
|
7
|
+
this.code = (meta && meta.code) || null;
|
|
8
|
+
this.httpStatus = (meta && meta.httpStatus) || 500;
|
|
9
|
+
this.meta = meta || undefined;
|
|
10
|
+
this.redirect = undefined;
|
|
11
|
+
}
|
|
12
|
+
setMeta(meta) {
|
|
13
|
+
this.meta = meta;
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
static purifyStack(error) {
|
|
17
|
+
error.stack = error?.stack?.split('\n').filter((line, index) => index !== 1).join('\n');
|
|
18
|
+
return error;
|
|
19
|
+
}
|
|
20
|
+
static notFound(message, meta) {
|
|
21
|
+
let allMessage = 'Not found';
|
|
22
|
+
if (message) {
|
|
23
|
+
allMessage += `: ${message}`;
|
|
24
|
+
}
|
|
25
|
+
const error = new AppError(allMessage, ({
|
|
26
|
+
code: 404,
|
|
27
|
+
httpStatus: 404,
|
|
28
|
+
...meta,
|
|
29
|
+
}));
|
|
30
|
+
return AppError.purifyStack(error);
|
|
31
|
+
}
|
|
32
|
+
static badRequest(message, meta) {
|
|
33
|
+
let allMessage = 'Bad request';
|
|
34
|
+
if (message) {
|
|
35
|
+
allMessage += `: ${message}`;
|
|
36
|
+
}
|
|
37
|
+
const error = new AppError(allMessage, ({
|
|
38
|
+
code: 400,
|
|
39
|
+
httpStatus: 400,
|
|
40
|
+
...meta,
|
|
41
|
+
}));
|
|
42
|
+
return AppError.purifyStack(error);
|
|
43
|
+
}
|
|
44
|
+
static concurrentRequest(message, meta) {
|
|
45
|
+
let allMessage = 'Concurrent request';
|
|
46
|
+
if (message) {
|
|
47
|
+
allMessage += `: ${message}`;
|
|
48
|
+
}
|
|
49
|
+
const error = new AppError(allMessage, ({
|
|
50
|
+
code: 409,
|
|
51
|
+
httpStatus: 409,
|
|
52
|
+
...meta,
|
|
53
|
+
}));
|
|
54
|
+
return AppError.purifyStack(error);
|
|
55
|
+
}
|
|
56
|
+
static internal(message, meta) {
|
|
57
|
+
let allMessage = 'Internal';
|
|
58
|
+
if (message) {
|
|
59
|
+
allMessage += `: ${message}`;
|
|
60
|
+
}
|
|
61
|
+
const error = new AppError(allMessage, ({
|
|
62
|
+
code: 500,
|
|
63
|
+
httpStatus: 500,
|
|
64
|
+
...meta,
|
|
65
|
+
}));
|
|
66
|
+
return AppError.purifyStack(error);
|
|
67
|
+
}
|
|
68
|
+
static unauthorized(message, meta) {
|
|
69
|
+
let allMessage = 'Unauthorized';
|
|
70
|
+
if (message) {
|
|
71
|
+
allMessage += `: ${message}`;
|
|
72
|
+
}
|
|
73
|
+
const error = new AppError(allMessage, ({
|
|
74
|
+
code: 401,
|
|
75
|
+
httpStatus: 401,
|
|
76
|
+
...meta,
|
|
77
|
+
}));
|
|
78
|
+
return AppError.purifyStack(error);
|
|
79
|
+
}
|
|
80
|
+
static isConcurrentRequestError(err) {
|
|
81
|
+
return err instanceof AppError && err.code === 409 && /^Concurrent request/.test(err.message);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = AppError;
|
|
85
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwRXJyb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJhcHBFcnJvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE1BQXFCLFFBQVMsU0FBUSxLQUFLO0lBVXZDLFlBQWEsT0FBZSxFQUFFLElBQVU7UUFDcEMsS0FBSyxFQUFFLENBQUM7UUFFUixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUV2QixJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUM7UUFFeEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksR0FBRyxDQUFDO1FBRW5ELElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxJQUFJLFNBQVMsQ0FBQztRQUU5QixJQUFJLENBQUMsUUFBUSxHQUFHLFNBQVMsQ0FBQztJQUM5QixDQUFDO0lBRUQsT0FBTyxDQUFFLElBQXlCO1FBQzlCLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWpCLE9BQU8sSUFBSSxDQUFDO0lBQ2hCLENBQUM7SUFFRCxNQUFNLENBQUMsV0FBVyxDQUFFLEtBQWU7UUFDL0IsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXhGLE9BQU8sS0FBSyxDQUFDO0lBQ2pCLENBQUM7SUFFRCxNQUFNLENBQUMsUUFBUSxDQUFFLE9BQWdCLEVBQUUsSUFBMEI7UUFFekQsSUFBSSxVQUFVLEdBQUcsV0FBVyxDQUFDO1FBQzdCLElBQUksT0FBTyxFQUFFO1lBQ1QsVUFBVSxJQUFJLEtBQUssT0FBTyxFQUFFLENBQUM7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
|
package/lib/appError.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export default class AppError extends Error {
|
|
2
|
+
|
|
3
|
+
public code?: number;
|
|
4
|
+
|
|
5
|
+
public httpStatus: number|string;
|
|
6
|
+
|
|
7
|
+
public meta?: Record<string, any>;
|
|
8
|
+
|
|
9
|
+
public redirect?: string;
|
|
10
|
+
|
|
11
|
+
constructor (message: string, meta?: any) {
|
|
12
|
+
super();
|
|
13
|
+
|
|
14
|
+
this.message = message;
|
|
15
|
+
|
|
16
|
+
this.code = (meta && meta.code) || null;
|
|
17
|
+
|
|
18
|
+
this.httpStatus = (meta && meta.httpStatus) || 500;
|
|
19
|
+
|
|
20
|
+
this.meta = meta || undefined;
|
|
21
|
+
|
|
22
|
+
this.redirect = undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setMeta (meta: Record<string, any>): AppError {
|
|
26
|
+
this.meta = meta;
|
|
27
|
+
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static purifyStack (error: AppError): AppError {
|
|
32
|
+
error.stack = error?.stack?.split('\n').filter((line, index) => index !== 1).join('\n');
|
|
33
|
+
|
|
34
|
+
return error;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static notFound (message?: string, meta?: Record<string, any>): AppError {
|
|
38
|
+
|
|
39
|
+
let allMessage = 'Not found';
|
|
40
|
+
if (message) {
|
|
41
|
+
allMessage += `: ${message}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const error = new AppError(allMessage, ({
|
|
45
|
+
code: 404,
|
|
46
|
+
httpStatus: 404,
|
|
47
|
+
...meta,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
return AppError.purifyStack(error);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static badRequest (message?: string, meta?: Record<string, any>): AppError {
|
|
54
|
+
let allMessage = 'Bad request';
|
|
55
|
+
if (message) {
|
|
56
|
+
allMessage += `: ${message}`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const error = new AppError(allMessage, ({
|
|
60
|
+
code: 400,
|
|
61
|
+
httpStatus: 400,
|
|
62
|
+
...meta,
|
|
63
|
+
}));
|
|
64
|
+
|
|
65
|
+
return AppError.purifyStack(error);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static concurrentRequest (message?: string, meta?: Record<string, any>): AppError {
|
|
69
|
+
let allMessage = 'Concurrent request';
|
|
70
|
+
if (message) {
|
|
71
|
+
allMessage += `: ${message}`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const error = new AppError(allMessage, ({
|
|
75
|
+
code: 409,
|
|
76
|
+
httpStatus: 409,
|
|
77
|
+
...meta,
|
|
78
|
+
}));
|
|
79
|
+
|
|
80
|
+
return AppError.purifyStack(error);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static internal (message?: string, meta?: Record<string, any>): AppError {
|
|
84
|
+
let allMessage = 'Internal';
|
|
85
|
+
if (message) {
|
|
86
|
+
allMessage += `: ${message}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const error = new AppError(allMessage, ({
|
|
90
|
+
code: 500,
|
|
91
|
+
httpStatus: 500,
|
|
92
|
+
...meta,
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
return AppError.purifyStack(error);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static unauthorized (message?: string, meta?: Record<string, any>): AppError {
|
|
99
|
+
let allMessage = 'Unauthorized';
|
|
100
|
+
if (message) {
|
|
101
|
+
allMessage += `: ${message}`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const error = new AppError(allMessage, ({
|
|
105
|
+
code: 401,
|
|
106
|
+
httpStatus: 401,
|
|
107
|
+
...meta,
|
|
108
|
+
}));
|
|
109
|
+
|
|
110
|
+
return AppError.purifyStack(error);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
static isConcurrentRequestError (err: Error): boolean {
|
|
114
|
+
return err instanceof AppError && err.code === 409 && /^Concurrent request/.test(err.message);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const lodash_1 = require("lodash");
|
|
7
|
+
const appError_1 = __importDefault(require("./appError"));
|
|
8
|
+
const initErrHandler = (log) => async function (ctx, next) {
|
|
9
|
+
try {
|
|
10
|
+
await next();
|
|
11
|
+
}
|
|
12
|
+
catch (originalError) {
|
|
13
|
+
let err = originalError;
|
|
14
|
+
if (!(err instanceof appError_1.default)) {
|
|
15
|
+
if (err instanceof Error) {
|
|
16
|
+
// @ts-ignore
|
|
17
|
+
const redirect = err.redirect || null;
|
|
18
|
+
err = new appError_1.default(`${err.name}: ${err.message}`);
|
|
19
|
+
err.redirect = redirect;
|
|
20
|
+
}
|
|
21
|
+
else if (typeof err === 'string') {
|
|
22
|
+
err = new appError_1.default(err);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
err = new appError_1.default('Unknown error');
|
|
26
|
+
}
|
|
27
|
+
err.stack = originalError.stack;
|
|
28
|
+
}
|
|
29
|
+
const metaData = {
|
|
30
|
+
httpStatus: err.httpStatus || 500,
|
|
31
|
+
url: ctx.request.originalUrl,
|
|
32
|
+
query: ctx.request.query,
|
|
33
|
+
method: ctx.req.method,
|
|
34
|
+
remoteAddress: ctx.get('x-forwarded-for') || ctx.req.connection.remoteAddress,
|
|
35
|
+
};
|
|
36
|
+
if (err.code) {
|
|
37
|
+
metaData.code = err.code;
|
|
38
|
+
}
|
|
39
|
+
if (!ctx.request.is('multipart/*')) {
|
|
40
|
+
metaData.body = ctx.request.body;
|
|
41
|
+
}
|
|
42
|
+
if (ctx.req.headers && ctx.req.headers.referer) {
|
|
43
|
+
metaData.referer = ctx.req.headers.referer;
|
|
44
|
+
}
|
|
45
|
+
if (err.redirect) {
|
|
46
|
+
metaData.redirect = err.redirect;
|
|
47
|
+
}
|
|
48
|
+
const originalMeta = err.meta;
|
|
49
|
+
if (!(0, lodash_1.isEmpty)(err.meta)) {
|
|
50
|
+
metaData.meta = err.meta;
|
|
51
|
+
}
|
|
52
|
+
err.setMeta(metaData);
|
|
53
|
+
if (err.httpStatus === 404 || err.httpStatus === 401 || err.httpStatus === 429) {
|
|
54
|
+
log.warn(err);
|
|
55
|
+
}
|
|
56
|
+
else if (err.httpStatus === 500 || err.httpStatus === 408) {
|
|
57
|
+
log.error(err);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
log.info(err);
|
|
61
|
+
}
|
|
62
|
+
ctx.body = {
|
|
63
|
+
code: err.code,
|
|
64
|
+
message: err.message,
|
|
65
|
+
...(0, lodash_1.pick)(originalMeta, err.publicFields || []),
|
|
66
|
+
};
|
|
67
|
+
ctx.status = err.httpStatus;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
exports.default = initErrHandler;
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZXJyb3JIYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQXVDO0FBRXZDLDBEQUFrQztBQUVsQyxNQUFNLGNBQWMsR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsS0FBSyxXQUFXLEdBQVEsRUFBRSxJQUFjO0lBQzVFLElBQUk7UUFDQSxNQUFNLElBQUksRUFBRSxDQUFDO0tBQ2hCO0lBQUMsT0FBTyxhQUFpQixFQUFFO1FBRXhCLElBQUksR0FBRyxHQUFRLGFBQWEsQ0FBQztRQUU3QixJQUFJLENBQUMsQ0FBQyxHQUFHLFlBQVksa0JBQVEsQ0FBQyxFQUFFO1lBRTVCLElBQUksR0FBRyxZQUFZLEtBQUssRUFBRTtnQkFDdEIsYUFBYTtnQkFDYixNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQztnQkFDdEMsR0FBRyxHQUFHLElBQUksa0JBQVEsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQ2xELEdBQUcsQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO2FBRTNCO2lCQUFNLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFO2dCQUNoQyxHQUFHLEdBQUcsSUFBSSxrQkFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBRTNCO2lCQUFNO2dCQUNILEdBQUcsR0FBRyxJQUFJLGtCQUFRLENBQUMsZUFBZSxDQUFDLENBQUM7YUFDdkM7WUFFRCxHQUFHLENBQUMsS0FBSyxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUM7U0FDbkM7UUFFRCxNQUFNLFFBQVEsR0FBUTtZQUNsQixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVUsSUFBSSxHQUFHO1lBQ2pDLEdBQUcsRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLFdBQVc7WUFDNUIsS0FBSyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsS0FBSztZQUN4QixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNO1lBQ3RCLGFBQWEsRUFBRSxHQUFHLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsYUFBYTtTQUNoRixDQUFDO1FBRUYsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFO1lBQ1YsUUFBUSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1NBQzVCO1FBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQ2hDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUM7U0FDcEM7UUFFRCxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRTtZQUM1QyxRQUFRLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztTQUM5QztRQUVELElBQUksR0FBRyxDQUFDLFFBQVEsRUFBRTtZQUNkLFFBQVEsQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQztTQUNwQztRQUVELE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUM7UUFFOUIsSUFBSSxDQUFDLElBQUEsZ0JBQU8sRUFBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDcEIsUUFBUSxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO1NBQzVCO1FBRUQsR0FBRyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUV0QixJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssR0FBRyxFQUFFO1lBQzVFLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7U0FFakI7YUFBTSxJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssR0FBRyxJQUFJLEdBQUcsQ0FBQyxVQUFVLEtBQUssR0FBRyxFQUFFO1lBQ3pELEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7U0FFbEI7YUFBTTtZQUNILEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7U0FDakI7UUFFRCxHQUFHLENBQUMsSUFBSSxHQUFHO1lBQ1AsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO1lBQ2QsT0FBTyxFQUFFLEdBQUcsQ0FBQyxPQUFPO1lBQ3BCLEdBQUcsSUFBQSxhQUFJLEVBQUMsWUFBWSxFQUFFLEdBQUcsQ0FBQyxZQUFZLElBQUksRUFBRSxDQUFDO1NBQ2hELENBQUM7UUFDRixHQUFHLENBQUMsTUFBTSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUM7S0FDL0I7QUFDTCxDQUFDLENBQUM7QUFFRixrQkFBZSxjQUFjLENBQUMifQ==
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { isEmpty, pick } from 'lodash';
|
|
2
|
+
import { Logger } from 'winston';
|
|
3
|
+
import AppError from './appError';
|
|
4
|
+
|
|
5
|
+
const initErrHandler = (log: Logger) => async function (ctx: any, next: Function) {
|
|
6
|
+
try {
|
|
7
|
+
await next();
|
|
8
|
+
} catch (originalError:any) {
|
|
9
|
+
|
|
10
|
+
let err: any = originalError;
|
|
11
|
+
|
|
12
|
+
if (!(err instanceof AppError)) {
|
|
13
|
+
|
|
14
|
+
if (err instanceof Error) {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
const redirect = err.redirect || null;
|
|
17
|
+
err = new AppError(`${err.name}: ${err.message}`);
|
|
18
|
+
err.redirect = redirect;
|
|
19
|
+
|
|
20
|
+
} else if (typeof err === 'string') {
|
|
21
|
+
err = new AppError(err);
|
|
22
|
+
|
|
23
|
+
} else {
|
|
24
|
+
err = new AppError('Unknown error');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
err.stack = originalError.stack;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const metaData: any = {
|
|
31
|
+
httpStatus: err.httpStatus || 500,
|
|
32
|
+
url: ctx.request.originalUrl,
|
|
33
|
+
query: ctx.request.query,
|
|
34
|
+
method: ctx.req.method,
|
|
35
|
+
remoteAddress: ctx.get('x-forwarded-for') || ctx.req.connection.remoteAddress,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (err.code) {
|
|
39
|
+
metaData.code = err.code;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (!ctx.request.is('multipart/*')) {
|
|
43
|
+
metaData.body = ctx.request.body;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (ctx.req.headers && ctx.req.headers.referer) {
|
|
47
|
+
metaData.referer = ctx.req.headers.referer;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (err.redirect) {
|
|
51
|
+
metaData.redirect = err.redirect;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const originalMeta = err.meta;
|
|
55
|
+
|
|
56
|
+
if (!isEmpty(err.meta)) {
|
|
57
|
+
metaData.meta = err.meta;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
err.setMeta(metaData);
|
|
61
|
+
|
|
62
|
+
if (err.httpStatus === 404 || err.httpStatus === 401 || err.httpStatus === 429) {
|
|
63
|
+
log.warn(err);
|
|
64
|
+
|
|
65
|
+
} else if (err.httpStatus === 500 || err.httpStatus === 408) {
|
|
66
|
+
log.error(err);
|
|
67
|
+
|
|
68
|
+
} else {
|
|
69
|
+
log.info(err);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ctx.body = {
|
|
73
|
+
code: err.code,
|
|
74
|
+
message: err.message,
|
|
75
|
+
...pick(originalMeta, err.publicFields || []),
|
|
76
|
+
};
|
|
77
|
+
ctx.status = err.httpStatus;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default initErrHandler;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.initErrHandler = exports.AppError = void 0;
|
|
7
|
+
const appError_1 = __importDefault(require("./appError"));
|
|
8
|
+
exports.AppError = appError_1.default;
|
|
9
|
+
const errorHandler_1 = __importDefault(require("./errorHandler"));
|
|
10
|
+
exports.initErrHandler = errorHandler_1.default;
|
|
11
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSwwREFBa0M7QUFHekIsbUJBSEYsa0JBQVEsQ0FHRTtBQUZqQixrRUFBNEM7QUFFekIseUJBRlosc0JBQWMsQ0FFWSJ9
|
package/lib/index.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@storyous/errors",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"homepage": "https://github.com/Storyous/mono-utils#readme",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"main": "lib/index.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start": "tsc",
|
|
10
|
+
"build": "tsc && npm publish"
|
|
11
|
+
},
|
|
12
|
+
"mocha": {
|
|
13
|
+
"recursive": true,
|
|
14
|
+
"timeout": 15000,
|
|
15
|
+
"extension": [
|
|
16
|
+
"ts"
|
|
17
|
+
],
|
|
18
|
+
"exit": true,
|
|
19
|
+
"require": "ts-node/register"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/Storyous/mono-utils.git"
|
|
24
|
+
},
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/Storyous/mono-utils/issues"
|
|
27
|
+
},
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public",
|
|
30
|
+
"registry": "https://registry.npmjs.org/"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"lodash": "^4.17.21",
|
|
34
|
+
"winston": "^3.7.2"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@storyous/test-utils": "^1.0.0"
|
|
38
|
+
},
|
|
39
|
+
"gitHead": "2ba0209d33ac7cd2fd1136a9123134f656750102"
|
|
40
|
+
}
|