@emoyly/problem 5.0.7 → 6.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/.editorconfig +11 -0
- package/.vscode/extensions.json +7 -0
- package/.vscode/settings.json +2 -0
- package/.yarn/versions/524dd037.yml +0 -0
- package/.yarn/versions/b57d536b.yml +0 -0
- package/.yarn/versions/d984e272.yml +0 -0
- package/cjs/defaults/index.d.ts +7 -0
- package/cjs/defaults/index.js +17 -0
- package/cjs/index.d.ts +5 -0
- package/cjs/index.js +24 -0
- package/{middleware → cjs/middleware}/axios.d.ts +2 -2
- package/cjs/middleware/axios.js +24 -0
- package/{middleware → cjs/middleware}/base.d.ts +3 -3
- package/cjs/middleware/base.js +52 -0
- package/{middleware → cjs/middleware}/express.d.ts +2 -2
- package/cjs/middleware/express.js +65 -0
- package/cjs/package.json +3 -0
- package/cjs/parsers/axios.d.ts +3 -0
- package/cjs/parsers/axios.js +55 -0
- package/cjs/parsers/jsonwebtoken.d.ts +3 -0
- package/{parsers → cjs/parsers}/jsonwebtoken.js +4 -4
- package/cjs/parsers/mikroorm.d.ts +3 -0
- package/{parsers → cjs/parsers}/mikroorm.js +7 -3
- package/cjs/parsers/tsoa.d.ts +3 -0
- package/{parsers → cjs/parsers}/tsoa.js +10 -4
- package/{problem.d.ts → cjs/problem.d.ts} +1 -1
- package/{problem.js → cjs/problem.js} +24 -23
- package/cjs/tsconfig.tsbuildinfo +1 -0
- package/{typings → cjs/typings}/codes.d.ts +1 -1
- package/{typings → cjs/typings}/events.d.ts +1 -1
- package/cjs/typings/index.d.ts +5 -0
- package/{typings → cjs/typings}/index.js +5 -5
- package/{typings → cjs/typings}/middleware.d.ts +1 -1
- package/{typings → cjs/typings}/parser.d.ts +1 -1
- package/{util → cjs/util}/events.d.ts +2 -2
- package/cjs/util/events.js +27 -0
- package/{util → cjs/util}/getProblems.d.ts +2 -2
- package/{util → cjs/util}/getProblems.js +10 -11
- package/{util → cjs/util}/isProblemArray.d.ts +1 -1
- package/{util → cjs/util}/isProblemArray.js +3 -4
- package/{util → cjs/util}/misc.d.ts +1 -1
- package/cjs/util/misc.js +19 -0
- package/{util → cjs/util}/version.d.ts +1 -1
- package/{util → cjs/util}/version.js +3 -3
- package/eslint.config.mjs +5 -0
- package/esm/defaults/4xx.d.ts +147 -0
- package/esm/defaults/4xx.js +148 -0
- package/esm/defaults/5xx.d.ts +57 -0
- package/esm/defaults/5xx.js +58 -0
- package/esm/defaults/aws.d.ts +12 -0
- package/esm/defaults/aws.js +13 -0
- package/esm/defaults/cloudflare.d.ts +47 -0
- package/esm/defaults/cloudflare.js +49 -0
- package/esm/defaults/iis.d.ts +17 -0
- package/esm/defaults/iis.js +18 -0
- package/esm/defaults/index.d.ts +7 -0
- package/esm/defaults/index.js +7 -0
- package/esm/defaults/nginx.d.ts +32 -0
- package/esm/defaults/nginx.js +33 -0
- package/esm/defaults/others.d.ts +37 -0
- package/esm/defaults/others.js +37 -0
- package/esm/index.d.ts +5 -0
- package/esm/index.js +5 -0
- package/esm/middleware/axios.d.ts +13 -0
- package/esm/middleware/axios.js +20 -0
- package/esm/middleware/base.d.ts +24 -0
- package/esm/middleware/base.js +48 -0
- package/esm/middleware/express.d.ts +19 -0
- package/esm/middleware/express.js +61 -0
- package/esm/package.json +3 -0
- package/esm/parsers/axios.d.ts +3 -0
- package/esm/parsers/axios.js +53 -0
- package/esm/parsers/jsonwebtoken.d.ts +3 -0
- package/esm/parsers/jsonwebtoken.js +94 -0
- package/esm/parsers/mikroorm.d.ts +3 -0
- package/esm/parsers/mikroorm.js +17 -0
- package/esm/parsers/tsoa.d.ts +3 -0
- package/esm/parsers/tsoa.js +21 -0
- package/esm/problem.d.ts +14 -0
- package/esm/problem.js +56 -0
- package/esm/tsconfig.tsbuildinfo +1 -0
- package/esm/typings/codes.d.ts +5 -0
- package/esm/typings/codes.js +1 -0
- package/esm/typings/events.d.ts +2 -0
- package/esm/typings/events.js +1 -0
- package/esm/typings/index.d.ts +5 -0
- package/esm/typings/index.js +5 -0
- package/esm/typings/middleware.d.ts +9 -0
- package/esm/typings/middleware.js +1 -0
- package/esm/typings/parser.d.ts +2 -0
- package/esm/typings/parser.js +1 -0
- package/esm/typings/problem.d.ts +24 -0
- package/esm/typings/problem.js +11 -0
- package/esm/util/defaults.d.ts +4 -0
- package/esm/util/defaults.js +4 -0
- package/esm/util/events.d.ts +16 -0
- package/esm/util/events.js +25 -0
- package/esm/util/getProblems.d.ts +5 -0
- package/esm/util/getProblems.js +40 -0
- package/esm/util/isProblemArray.d.ts +2 -0
- package/esm/util/isProblemArray.js +6 -0
- package/esm/util/misc.d.ts +2 -0
- package/esm/util/misc.js +16 -0
- package/esm/util/version.d.ts +3 -0
- package/esm/util/version.js +16 -0
- package/package.json +51 -28
- package/scripts/ensureCorrectVersion.js +8 -4
- package/src/defaults/4xx.ts +149 -0
- package/src/defaults/5xx.ts +59 -0
- package/src/defaults/aws.ts +14 -0
- package/src/defaults/cloudflare.ts +50 -0
- package/src/defaults/iis.ts +19 -0
- package/src/defaults/index.ts +7 -0
- package/src/defaults/nginx.ts +34 -0
- package/src/defaults/others.ts +37 -0
- package/src/index.ts +5 -0
- package/src/middleware/axios.ts +29 -0
- package/src/middleware/base.ts +64 -0
- package/src/middleware/express.ts +72 -0
- package/src/parsers/axios.ts +61 -0
- package/src/parsers/jsonwebtoken.ts +104 -0
- package/src/parsers/mikroorm.ts +21 -0
- package/src/parsers/tsoa.ts +25 -0
- package/src/problem.ts +56 -0
- package/src/typings/codes.ts +6 -0
- package/src/typings/events.ts +3 -0
- package/src/typings/index.ts +5 -0
- package/src/typings/middleware.ts +11 -0
- package/src/typings/parser.ts +3 -0
- package/src/typings/problem.ts +27 -0
- package/src/util/defaults.ts +4 -0
- package/src/util/events.ts +34 -0
- package/src/util/getProblems.ts +43 -0
- package/src/util/isProblemArray.ts +6 -0
- package/src/util/misc.ts +20 -0
- package/src/util/version.ts +16 -0
- package/tsconfig.json +15 -0
- package/defaults/index.d.ts +0 -7
- package/defaults/index.js +0 -17
- package/index.d.ts +0 -5
- package/index.js +0 -39
- package/middleware/axios.js +0 -36
- package/middleware/base.js +0 -56
- package/middleware/express.js +0 -60
- package/parsers/axios.d.ts +0 -3
- package/parsers/axios.js +0 -41
- package/parsers/jsonwebtoken.d.ts +0 -3
- package/parsers/mikroorm.d.ts +0 -3
- package/parsers/tsoa.d.ts +0 -3
- package/tsconfig.tsbuildinfo +0 -1
- package/typings/index.d.ts +0 -5
- package/util/events.js +0 -29
- package/util/misc.js +0 -43
- /package/{defaults → cjs/defaults}/4xx.d.ts +0 -0
- /package/{defaults → cjs/defaults}/4xx.js +0 -0
- /package/{defaults → cjs/defaults}/5xx.d.ts +0 -0
- /package/{defaults → cjs/defaults}/5xx.js +0 -0
- /package/{defaults → cjs/defaults}/aws.d.ts +0 -0
- /package/{defaults → cjs/defaults}/aws.js +0 -0
- /package/{defaults → cjs/defaults}/cloudflare.d.ts +0 -0
- /package/{defaults → cjs/defaults}/cloudflare.js +0 -0
- /package/{defaults → cjs/defaults}/iis.d.ts +0 -0
- /package/{defaults → cjs/defaults}/iis.js +0 -0
- /package/{defaults → cjs/defaults}/nginx.d.ts +0 -0
- /package/{defaults → cjs/defaults}/nginx.js +0 -0
- /package/{defaults → cjs/defaults}/others.d.ts +0 -0
- /package/{defaults → cjs/defaults}/others.js +0 -0
- /package/{typings → cjs/typings}/codes.js +0 -0
- /package/{typings → cjs/typings}/events.js +0 -0
- /package/{typings → cjs/typings}/middleware.js +0 -0
- /package/{typings → cjs/typings}/parser.js +0 -0
- /package/{typings → cjs/typings}/problem.d.ts +0 -0
- /package/{typings → cjs/typings}/problem.js +0 -0
- /package/{util → cjs/util}/defaults.d.ts +0 -0
- /package/{util → cjs/util}/defaults.js +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { otherErrors } from '../defaults/index.js';
|
|
2
|
+
import { Problem } from '../problem.js';
|
|
3
|
+
import { getProblems } from '../util/getProblems.js';
|
|
4
|
+
/**
|
|
5
|
+
* Middleware collects errors from somewhere, transforms them into something recognizable by a parser, and then passes them to the parsers, and then returns an array of Problems to whatever is using the middleware
|
|
6
|
+
*/
|
|
7
|
+
export class MiddlewareBase {
|
|
8
|
+
options;
|
|
9
|
+
/**
|
|
10
|
+
* When nothing is returned from the parsers, just throw in a default "fallback" Problem object, so that a Problem is still actually returned/emitted
|
|
11
|
+
*/
|
|
12
|
+
enableFallback = true;
|
|
13
|
+
constructor(defaultOptions, options) {
|
|
14
|
+
this.options = { ...defaultOptions, ...options };
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse input using parsers
|
|
18
|
+
*/
|
|
19
|
+
parse = async (input) => {
|
|
20
|
+
const problems = [];
|
|
21
|
+
const prob = getProblems(input);
|
|
22
|
+
if (!prob) {
|
|
23
|
+
for (const parse of this.options.parsers) {
|
|
24
|
+
const resp = parse(input);
|
|
25
|
+
if (!resp.length)
|
|
26
|
+
continue;
|
|
27
|
+
problems.push(...resp);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
if (!problems.length && this.enableFallback) {
|
|
31
|
+
problems.push(new Problem({
|
|
32
|
+
...this.fallback,
|
|
33
|
+
'errorObject': input,
|
|
34
|
+
'stack': (typeof input === 'object' && input !== null && 'stack' in input && typeof input.stack === 'string') ? input.stack : undefined
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
problems.push(...prob);
|
|
40
|
+
}
|
|
41
|
+
for (const p of problems) {
|
|
42
|
+
if (!p.middleware)
|
|
43
|
+
p.middleware = this.name;
|
|
44
|
+
}
|
|
45
|
+
return problems;
|
|
46
|
+
};
|
|
47
|
+
fallback = otherErrors.unknown;
|
|
48
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
import type { PartialMiddlewareOptions } from '../typings/middleware.js';
|
|
3
|
+
import { MiddlewareBase } from './base.js';
|
|
4
|
+
export declare class ExpressMiddleware extends MiddlewareBase {
|
|
5
|
+
name: string;
|
|
6
|
+
middleware: (error: unknown, req: Request, res: Response, next: NextFunction) => void;
|
|
7
|
+
/**
|
|
8
|
+
* This function applies the middleware to your Express application. Put this at the very end of your middleware/routes.
|
|
9
|
+
* If you want to also handle 404 errors, check out the notFound middleware function.
|
|
10
|
+
* @example app.use(middleware.use())
|
|
11
|
+
*/
|
|
12
|
+
use: () => (error: unknown, req: Request, res: Response, next: NextFunction) => void;
|
|
13
|
+
constructor(options?: PartialMiddlewareOptions);
|
|
14
|
+
/**
|
|
15
|
+
* Put this right before the middleware.use() to catch all 404 errors and respond with a Problem instead of the default Express response
|
|
16
|
+
* @example app.use(middleware.notFound)
|
|
17
|
+
*/
|
|
18
|
+
notFound: (req: Request, res: Response, next: NextFunction) => void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { MiddlewareBase } from './base.js';
|
|
2
|
+
import { Problem } from '../problem.js';
|
|
3
|
+
import { codes4xx, otherErrors } from '../defaults/index.js';
|
|
4
|
+
import events from '../util/events.js';
|
|
5
|
+
import { defaultInstance } from '../util/defaults.js';
|
|
6
|
+
export class ExpressMiddleware extends MiddlewareBase {
|
|
7
|
+
name = 'express';
|
|
8
|
+
middleware = (error, req, res, next) => {
|
|
9
|
+
this.parse(error)
|
|
10
|
+
.then(problems => {
|
|
11
|
+
for (const problem of problems) {
|
|
12
|
+
if (problem.instance === defaultInstance) {
|
|
13
|
+
problem.instance = req.originalUrl;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
events.emit(problems);
|
|
17
|
+
res
|
|
18
|
+
.contentType('application/problem+json')
|
|
19
|
+
.status(problems[0]?.status ?? 500)
|
|
20
|
+
.json(problems.map(val => val.toObject()));
|
|
21
|
+
})
|
|
22
|
+
.catch(err => {
|
|
23
|
+
res
|
|
24
|
+
.contentType('application/problem+json')
|
|
25
|
+
.status(500)
|
|
26
|
+
.json([
|
|
27
|
+
new Problem({
|
|
28
|
+
...otherErrors.unknown,
|
|
29
|
+
'instance': req.originalUrl,
|
|
30
|
+
'status': 500,
|
|
31
|
+
'stack': err?.stack,
|
|
32
|
+
'errorObject': err,
|
|
33
|
+
}).toObject()
|
|
34
|
+
]);
|
|
35
|
+
throw err;
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* This function applies the middleware to your Express application. Put this at the very end of your middleware/routes.
|
|
40
|
+
* If you want to also handle 404 errors, check out the notFound middleware function.
|
|
41
|
+
* @example app.use(middleware.use())
|
|
42
|
+
*/
|
|
43
|
+
use = () => this.middleware;
|
|
44
|
+
constructor(options) {
|
|
45
|
+
super({
|
|
46
|
+
'parsers': []
|
|
47
|
+
}, options);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Put this right before the middleware.use() to catch all 404 errors and respond with a Problem instead of the default Express response
|
|
51
|
+
* @example app.use(middleware.notFound)
|
|
52
|
+
*/
|
|
53
|
+
notFound = (req, res, next) => {
|
|
54
|
+
const error = new Problem({
|
|
55
|
+
...codes4xx[404],
|
|
56
|
+
'instance': req.originalUrl,
|
|
57
|
+
'detail': `No API endpoints exist on ${req.url} for request method ${req.method}`
|
|
58
|
+
});
|
|
59
|
+
return next(error);
|
|
60
|
+
};
|
|
61
|
+
}
|
package/esm/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { otherErrors } from '../defaults/others.js';
|
|
2
|
+
import { Problem } from '../problem.js';
|
|
3
|
+
import { getProblems } from '../util/getProblems.js';
|
|
4
|
+
import { getHttpError } from '../util/misc.js';
|
|
5
|
+
function isAxiosError(payload) {
|
|
6
|
+
return typeof payload === 'object' && payload !== null && 'isAxiosError' in payload && payload.isAxiosError === true;
|
|
7
|
+
}
|
|
8
|
+
const parse = (input) => {
|
|
9
|
+
if (typeof input !== 'object' || input == null)
|
|
10
|
+
return [];
|
|
11
|
+
if (!isAxiosError(input))
|
|
12
|
+
return [];
|
|
13
|
+
const request = input.request;
|
|
14
|
+
if (input?.response?.data) {
|
|
15
|
+
const problems = getProblems(input?.response?.data);
|
|
16
|
+
if (problems?.length)
|
|
17
|
+
return problems;
|
|
18
|
+
}
|
|
19
|
+
if (input?.response) {
|
|
20
|
+
const opts = getHttpError(input.response.status);
|
|
21
|
+
if (opts)
|
|
22
|
+
return [new Problem({
|
|
23
|
+
...opts,
|
|
24
|
+
'instance': input?.config?.url,
|
|
25
|
+
'stack': input?.stack,
|
|
26
|
+
'errorObject': input
|
|
27
|
+
})];
|
|
28
|
+
}
|
|
29
|
+
// TODO: Fix this, this seems bad
|
|
30
|
+
if (request) {
|
|
31
|
+
const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
|
|
32
|
+
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
33
|
+
if (isBrowser && request instanceof XMLHttpRequest) {
|
|
34
|
+
return [new Problem({
|
|
35
|
+
...otherErrors.networkError,
|
|
36
|
+
'instance': input?.config?.url,
|
|
37
|
+
'stack': input?.stack,
|
|
38
|
+
'errorObject': input
|
|
39
|
+
})];
|
|
40
|
+
}
|
|
41
|
+
// Probably a ClientRequest
|
|
42
|
+
if (isNode && 'pipe' in request && 'destroy' in request) {
|
|
43
|
+
return [new Problem({
|
|
44
|
+
...otherErrors.networkError,
|
|
45
|
+
'instance': input?.config?.url,
|
|
46
|
+
'stack': input?.stack,
|
|
47
|
+
'errorObject': input
|
|
48
|
+
})];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return [];
|
|
52
|
+
};
|
|
53
|
+
export default parse;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Problem } from '../problem.js';
|
|
2
|
+
import { JsonWebTokenError, NotBeforeError, TokenExpiredError } from 'jsonwebtoken';
|
|
3
|
+
const errorMap = [
|
|
4
|
+
{
|
|
5
|
+
'search': 'invalid token',
|
|
6
|
+
'result': {
|
|
7
|
+
'type': '/errors/jsonwebtoken/invalidtoken',
|
|
8
|
+
'status': 400,
|
|
9
|
+
'title': 'Invalid JSON Web Token',
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
'search': 'jwt malformed',
|
|
14
|
+
'result': {
|
|
15
|
+
'type': '/errors/jsonwebtoken/malformed',
|
|
16
|
+
'status': 400,
|
|
17
|
+
'title': 'Malformed JSON Web Token',
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
'search': 'jwt signature is required',
|
|
22
|
+
'result': {
|
|
23
|
+
'type': '/errors/jsonwebtoken/signaturerequired',
|
|
24
|
+
'status': 400,
|
|
25
|
+
'title': 'JSON Web Token is missing, but required',
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
'search': 'invalid signature',
|
|
30
|
+
'result': {
|
|
31
|
+
'type': '/errors/jsonwebtoken/invalidsignature',
|
|
32
|
+
'status': 400,
|
|
33
|
+
'title': 'The JSON Web Token signature is invalid',
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
'search': /^(jwt audience invalid\. expected:)/,
|
|
38
|
+
'result': {
|
|
39
|
+
'type': '/errors/jsonwebtoken/invalidaud',
|
|
40
|
+
'status': 400,
|
|
41
|
+
'title': 'The JSON Web Token audience is invalid',
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
'search': /^(jwt issuer invalid\. expected:)/,
|
|
46
|
+
'result': {
|
|
47
|
+
'type': '/errors/jsonwebtoken/invalidiss',
|
|
48
|
+
'status': 400,
|
|
49
|
+
'title': 'The JSON Web Token issuer is invalid',
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
'search': /^(jwt id invalid\. expected:)/,
|
|
54
|
+
'result': {
|
|
55
|
+
'type': '/errors/jsonwebtoken/invalidid',
|
|
56
|
+
'status': 400,
|
|
57
|
+
'title': 'The JSON Web Token id is invalid',
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
'search': /^(jwt subject invalid\. expected:)/,
|
|
62
|
+
'result': {
|
|
63
|
+
'type': '/errors/jsonwebtoken/invalidsubject',
|
|
64
|
+
'status': 400,
|
|
65
|
+
'title': 'The JSON Web Token subject is invalid',
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
];
|
|
69
|
+
const parse = (input) => {
|
|
70
|
+
if (input instanceof JsonWebTokenError && input.name === 'JsonWebTokenError') {
|
|
71
|
+
const found = errorMap.find(val => typeof val.search === 'string' ? val.search === input.message : val.search.test(input.message));
|
|
72
|
+
if (found) {
|
|
73
|
+
return [new Problem(found.result)];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (input instanceof TokenExpiredError && input.name === 'TokenExpiredError') {
|
|
77
|
+
return [new Problem({
|
|
78
|
+
'title': 'The JSON Web Token has expired',
|
|
79
|
+
'type': '/errors/jsonwebtoken/tokenexpired',
|
|
80
|
+
'detail': `The JSON Web Token expired at ${input.expiredAt}`,
|
|
81
|
+
'status': 400,
|
|
82
|
+
})];
|
|
83
|
+
}
|
|
84
|
+
else if (input instanceof NotBeforeError && input.name === 'NotBeforeError') {
|
|
85
|
+
return [new Problem({
|
|
86
|
+
'title': 'The JSON Web Token is not valid yet',
|
|
87
|
+
'type': '/errors/jsonwebtoken/notbefore',
|
|
88
|
+
'detail': `The JSON Web Token is not valid before ${input.date}`,
|
|
89
|
+
'status': 400,
|
|
90
|
+
})];
|
|
91
|
+
}
|
|
92
|
+
return [];
|
|
93
|
+
};
|
|
94
|
+
export default parse;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Problem } from '../problem.js';
|
|
2
|
+
import { statusCodes } from '../defaults/4xx.js';
|
|
3
|
+
import { NotFoundError } from '@mikro-orm/core';
|
|
4
|
+
// TODO: Make this less bad
|
|
5
|
+
const parse = (input) => {
|
|
6
|
+
if (!(input instanceof NotFoundError)) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return [
|
|
10
|
+
new Problem({
|
|
11
|
+
...statusCodes['404'],
|
|
12
|
+
'stack': input.stack,
|
|
13
|
+
'errorObject': input,
|
|
14
|
+
})
|
|
15
|
+
];
|
|
16
|
+
};
|
|
17
|
+
export default parse;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ValidateError } from 'tsoa';
|
|
2
|
+
import { Problem } from '../problem.js';
|
|
3
|
+
import { otherErrors } from '../defaults/others.js';
|
|
4
|
+
const parse = (input) => {
|
|
5
|
+
if (!(input instanceof ValidateError)) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
// TODO: Give actual useful responses instead of this shit
|
|
9
|
+
return [
|
|
10
|
+
new Problem({
|
|
11
|
+
...otherErrors.inputValidationError,
|
|
12
|
+
'detail': input.message,
|
|
13
|
+
'status': input.status,
|
|
14
|
+
'data': {
|
|
15
|
+
'fields': input.fields,
|
|
16
|
+
},
|
|
17
|
+
'stack': input.stack,
|
|
18
|
+
})
|
|
19
|
+
];
|
|
20
|
+
};
|
|
21
|
+
export default parse;
|
package/esm/problem.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IProblem, ProblemOpts, JsonProblem } from './typings/problem.js';
|
|
2
|
+
export declare class Problem extends Error implements IProblem {
|
|
3
|
+
type: string;
|
|
4
|
+
title: string;
|
|
5
|
+
status: number;
|
|
6
|
+
detail: string;
|
|
7
|
+
instance: string;
|
|
8
|
+
errorObject?: unknown;
|
|
9
|
+
__problemVersion: string;
|
|
10
|
+
data: unknown;
|
|
11
|
+
middleware?: string;
|
|
12
|
+
constructor({ type, title, status, detail, instance, stack, errorObject, data, middleware }: ProblemOpts);
|
|
13
|
+
toObject: () => JsonProblem;
|
|
14
|
+
}
|
package/esm/problem.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { defaultDetail, defaultInstance, defaultTitle, defaultType } from './util/defaults.js';
|
|
2
|
+
import { version } from './util/version.js';
|
|
3
|
+
export class Problem extends Error {
|
|
4
|
+
type = defaultType;
|
|
5
|
+
title = defaultTitle;
|
|
6
|
+
status = 500;
|
|
7
|
+
detail = defaultDetail;
|
|
8
|
+
instance = defaultInstance;
|
|
9
|
+
errorObject;
|
|
10
|
+
__problemVersion = version;
|
|
11
|
+
data = undefined;
|
|
12
|
+
middleware;
|
|
13
|
+
constructor({ type, title, status, detail, instance, stack, errorObject, data, middleware }) {
|
|
14
|
+
super(detail ?? title ?? 'HTTP Problem Details');
|
|
15
|
+
// TODO: Figure out why i wrote this?
|
|
16
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
17
|
+
this.type = type;
|
|
18
|
+
this.title = title;
|
|
19
|
+
this.status = status;
|
|
20
|
+
if (detail)
|
|
21
|
+
this.detail = detail;
|
|
22
|
+
if (instance)
|
|
23
|
+
this.instance = instance;
|
|
24
|
+
if (errorObject)
|
|
25
|
+
this.errorObject = errorObject;
|
|
26
|
+
if (middleware)
|
|
27
|
+
this.middleware = middleware;
|
|
28
|
+
if (stack) {
|
|
29
|
+
this.stack = stack;
|
|
30
|
+
}
|
|
31
|
+
else if (errorObject && typeof errorObject === 'object' && 'stack' in errorObject && typeof errorObject.stack === 'string') {
|
|
32
|
+
this.stack = errorObject.stack;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
36
|
+
Error.captureStackTrace(this, this.constructor);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.stack = new Error(detail ?? title ?? 'HTTP Problem Details').stack;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (data)
|
|
43
|
+
this.data = data;
|
|
44
|
+
}
|
|
45
|
+
toObject = () => {
|
|
46
|
+
return {
|
|
47
|
+
'type': this.type,
|
|
48
|
+
'title': this.title,
|
|
49
|
+
'status': this.status,
|
|
50
|
+
'detail': this.detail,
|
|
51
|
+
'instance': this.instance,
|
|
52
|
+
'__problemVersion': this.__problemVersion,
|
|
53
|
+
'data': this.data
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
}
|