@emoyly/problem 5.0.8 → 7.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/README.md +1 -1
- package/cjs/defaults/index.d.ts +7 -0
- package/cjs/defaults/index.js +17 -0
- package/cjs/index.d.ts +4 -0
- package/cjs/index.js +22 -0
- package/{middleware → cjs/middleware}/axios.d.ts +2 -2
- package/cjs/middleware/axios.js +23 -0
- package/{middleware → cjs/middleware}/base.d.ts +13 -3
- package/cjs/middleware/base.js +73 -0
- package/{middleware → cjs/middleware}/express.d.ts +2 -2
- package/cjs/middleware/express.js +64 -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/cjs/typings/index.d.ts +4 -0
- package/{typings → cjs/typings}/index.js +4 -5
- package/{typings → cjs/typings}/middleware.d.ts +3 -1
- package/{typings → cjs/typings}/parser.d.ts +1 -1
- 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 +4 -0
- package/esm/index.js +4 -0
- package/esm/middleware/axios.d.ts +13 -0
- package/esm/middleware/axios.js +19 -0
- package/esm/middleware/base.d.ts +34 -0
- package/esm/middleware/base.js +69 -0
- package/esm/middleware/express.d.ts +19 -0
- package/esm/middleware/express.js +60 -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/index.d.ts +4 -0
- package/esm/typings/index.js +4 -0
- package/esm/typings/middleware.d.ts +11 -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/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 +4 -0
- package/src/middleware/axios.ts +28 -0
- package/src/middleware/base.ts +90 -0
- package/src/middleware/express.ts +71 -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/index.ts +4 -0
- package/src/typings/middleware.ts +14 -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/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/events.d.ts +0 -2
- package/typings/events.js +0 -2
- package/typings/index.d.ts +0 -5
- package/util/events.d.ts +0 -16
- 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}/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,104 @@
|
|
|
1
|
+
import { Problem } from '../problem.js'
|
|
2
|
+
import type { Parser } from '../typings/parser.js'
|
|
3
|
+
import { JsonWebTokenError, NotBeforeError, TokenExpiredError } from 'jsonwebtoken'
|
|
4
|
+
import type { ProblemOpts } from '../typings/problem.js'
|
|
5
|
+
|
|
6
|
+
interface ErrorMap {
|
|
7
|
+
'search': string | RegExp,
|
|
8
|
+
'result': ProblemOpts,
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const errorMap: ErrorMap[] = [
|
|
12
|
+
{
|
|
13
|
+
'search': 'invalid token',
|
|
14
|
+
'result': {
|
|
15
|
+
'type': '/errors/jsonwebtoken/invalidtoken',
|
|
16
|
+
'status': 400,
|
|
17
|
+
'title': 'Invalid JSON Web Token',
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
'search': 'jwt malformed',
|
|
22
|
+
'result': {
|
|
23
|
+
'type': '/errors/jsonwebtoken/malformed',
|
|
24
|
+
'status': 400,
|
|
25
|
+
'title': 'Malformed JSON Web Token',
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
'search': 'jwt signature is required',
|
|
30
|
+
'result': {
|
|
31
|
+
'type': '/errors/jsonwebtoken/signaturerequired',
|
|
32
|
+
'status': 400,
|
|
33
|
+
'title': 'JSON Web Token is missing, but required',
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
'search': 'invalid signature',
|
|
38
|
+
'result': {
|
|
39
|
+
'type': '/errors/jsonwebtoken/invalidsignature',
|
|
40
|
+
'status': 400,
|
|
41
|
+
'title': 'The JSON Web Token signature is invalid',
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
'search': /^(jwt audience invalid\. expected:)/,
|
|
46
|
+
'result': {
|
|
47
|
+
'type': '/errors/jsonwebtoken/invalidaud',
|
|
48
|
+
'status': 400,
|
|
49
|
+
'title': 'The JSON Web Token audience is invalid',
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
'search': /^(jwt issuer invalid\. expected:)/,
|
|
54
|
+
'result': {
|
|
55
|
+
'type': '/errors/jsonwebtoken/invalidiss',
|
|
56
|
+
'status': 400,
|
|
57
|
+
'title': 'The JSON Web Token issuer is invalid',
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
'search': /^(jwt id invalid\. expected:)/,
|
|
62
|
+
'result': {
|
|
63
|
+
'type': '/errors/jsonwebtoken/invalidid',
|
|
64
|
+
'status': 400,
|
|
65
|
+
'title': 'The JSON Web Token id is invalid',
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
'search': /^(jwt subject invalid\. expected:)/,
|
|
70
|
+
'result': {
|
|
71
|
+
'type': '/errors/jsonwebtoken/invalidsubject',
|
|
72
|
+
'status': 400,
|
|
73
|
+
'title': 'The JSON Web Token subject is invalid',
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
const parse: Parser = (input) => {
|
|
79
|
+
if (input instanceof JsonWebTokenError && input.name === 'JsonWebTokenError') {
|
|
80
|
+
const found = errorMap.find(val => typeof val.search === 'string' ? val.search === input.message : val.search.test(input.message))
|
|
81
|
+
|
|
82
|
+
if (found) {
|
|
83
|
+
return [new Problem(found.result)]
|
|
84
|
+
}
|
|
85
|
+
} else if (input instanceof TokenExpiredError && input.name === 'TokenExpiredError') {
|
|
86
|
+
return [new Problem({
|
|
87
|
+
'title': 'The JSON Web Token has expired',
|
|
88
|
+
'type': '/errors/jsonwebtoken/tokenexpired',
|
|
89
|
+
'detail': `The JSON Web Token expired at ${input.expiredAt}`,
|
|
90
|
+
'status': 400,
|
|
91
|
+
})]
|
|
92
|
+
} else if (input instanceof NotBeforeError && input.name === 'NotBeforeError') {
|
|
93
|
+
return [new Problem({
|
|
94
|
+
'title': 'The JSON Web Token is not valid yet',
|
|
95
|
+
'type': '/errors/jsonwebtoken/notbefore',
|
|
96
|
+
'detail': `The JSON Web Token is not valid before ${input.date}`,
|
|
97
|
+
'status': 400,
|
|
98
|
+
})]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return []
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export default parse
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Problem } from '../problem.js'
|
|
2
|
+
import { statusCodes } from '../defaults/4xx.js'
|
|
3
|
+
import type { Parser } from '../typings/parser.js'
|
|
4
|
+
import { NotFoundError } from '@mikro-orm/core'
|
|
5
|
+
|
|
6
|
+
// TODO: Make this less bad
|
|
7
|
+
const parse: Parser = (input) => {
|
|
8
|
+
if (!(input instanceof NotFoundError)) {
|
|
9
|
+
return []
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return [
|
|
13
|
+
new Problem({
|
|
14
|
+
...statusCodes['404'],
|
|
15
|
+
'stack': input.stack,
|
|
16
|
+
'errorObject': input,
|
|
17
|
+
})
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default parse
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ValidateError } from 'tsoa'
|
|
2
|
+
import { Problem } from '../problem.js'
|
|
3
|
+
import { otherErrors } from '../defaults/others.js'
|
|
4
|
+
import type { Parser } from '../typings/parser.js'
|
|
5
|
+
|
|
6
|
+
const parse: Parser = (input) => {
|
|
7
|
+
if (!(input instanceof ValidateError)) {
|
|
8
|
+
return []
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// TODO: Give actual useful responses instead of this shit
|
|
12
|
+
return [
|
|
13
|
+
new Problem({
|
|
14
|
+
...otherErrors.inputValidationError,
|
|
15
|
+
'detail': input.message,
|
|
16
|
+
'status': input.status,
|
|
17
|
+
'data': {
|
|
18
|
+
'fields': input.fields,
|
|
19
|
+
},
|
|
20
|
+
'stack': input.stack,
|
|
21
|
+
})
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default parse
|
package/src/problem.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { IProblem, ProblemOpts, JsonProblem } from './typings/problem.js'
|
|
2
|
+
import { defaultDetail, defaultInstance, defaultTitle, defaultType } from './util/defaults.js'
|
|
3
|
+
import { version } from './util/version.js'
|
|
4
|
+
|
|
5
|
+
export class Problem extends Error implements IProblem {
|
|
6
|
+
public type = defaultType
|
|
7
|
+
public title = defaultTitle
|
|
8
|
+
public status = 500
|
|
9
|
+
public detail = defaultDetail
|
|
10
|
+
public instance = defaultInstance
|
|
11
|
+
public errorObject?: unknown
|
|
12
|
+
public __problemVersion = version
|
|
13
|
+
public data: unknown = undefined
|
|
14
|
+
public middleware?: string
|
|
15
|
+
|
|
16
|
+
constructor({ type, title, status, detail, instance, stack, errorObject, data, middleware }: ProblemOpts) {
|
|
17
|
+
super(detail ?? title ?? 'HTTP Problem Details')
|
|
18
|
+
// TODO: Figure out why i wrote this?
|
|
19
|
+
Object.setPrototypeOf(this, new.target.prototype)
|
|
20
|
+
|
|
21
|
+
this.type = type
|
|
22
|
+
this.title = title
|
|
23
|
+
this.status = status
|
|
24
|
+
|
|
25
|
+
if (detail) this.detail = detail
|
|
26
|
+
if (instance) this.instance = instance
|
|
27
|
+
if (errorObject) this.errorObject = errorObject
|
|
28
|
+
if (middleware) this.middleware = middleware
|
|
29
|
+
|
|
30
|
+
if (stack) {
|
|
31
|
+
this.stack = stack
|
|
32
|
+
} else if (errorObject && typeof errorObject === 'object' && 'stack' in errorObject && typeof errorObject.stack === 'string') {
|
|
33
|
+
this.stack = errorObject.stack
|
|
34
|
+
} else {
|
|
35
|
+
if (typeof Error.captureStackTrace === 'function') {
|
|
36
|
+
Error.captureStackTrace(this, this.constructor)
|
|
37
|
+
} else {
|
|
38
|
+
this.stack = new Error(detail ?? title ?? 'HTTP Problem Details').stack
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (data) this.data = data
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public toObject = (): JsonProblem => {
|
|
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
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Problem } from '../problem.js'
|
|
2
|
+
import type { Parser } from './parser.js'
|
|
3
|
+
|
|
4
|
+
export interface MiddlewareOptions {
|
|
5
|
+
/**
|
|
6
|
+
* A list of parsers to be used by the middleware.
|
|
7
|
+
* Parsers are run in the order they sit in the array
|
|
8
|
+
*/
|
|
9
|
+
parsers: Parser[]
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type PartialMiddlewareOptions = Partial<MiddlewareOptions>
|
|
13
|
+
|
|
14
|
+
export type ProblemListener = (problems: Problem[]) => void
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} type - A URI refrence that identifies the problem type.
|
|
3
|
+
* @param {string} title - A short, human-readable summary of the problem
|
|
4
|
+
* type. It SHOULD NOT change from occurrence to occurrence of the problem
|
|
5
|
+
* @param {number} status - The HTTP status code
|
|
6
|
+
* @param {string} detail - A human-readable explanation specific to this
|
|
7
|
+
occurrence of the problem.
|
|
8
|
+
* @property {string} instance - A URI reference that identifies the specific
|
|
9
|
+
occurrence of the problem
|
|
10
|
+
**/
|
|
11
|
+
|
|
12
|
+
export interface IProblem {
|
|
13
|
+
type: string
|
|
14
|
+
title: string
|
|
15
|
+
status: number
|
|
16
|
+
detail?: string
|
|
17
|
+
instance?: string
|
|
18
|
+
stack?: string
|
|
19
|
+
errorObject?: unknown
|
|
20
|
+
__problemVersion: string
|
|
21
|
+
data?: unknown
|
|
22
|
+
middleware?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type JsonProblem = Omit<IProblem, 'stack' | 'errorObject' | 'middleware'>
|
|
26
|
+
|
|
27
|
+
export type ProblemOpts = Omit<IProblem, '__problemVersion'>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Problem } from '../problem.js'
|
|
2
|
+
import type { JsonProblem } from '../typings/problem.js'
|
|
3
|
+
import { isProblemArray } from './isProblemArray.js'
|
|
4
|
+
import { isCompatibleVersion } from './version.js'
|
|
5
|
+
|
|
6
|
+
const strings = ['title', 'type', 'instance', 'detail', '__problemVersion']
|
|
7
|
+
export function isJsonProblem(input: unknown): input is JsonProblem {
|
|
8
|
+
if (input === null) return false
|
|
9
|
+
if (typeof input !== 'object') return false
|
|
10
|
+
|
|
11
|
+
if (!strings.every(val => val in input && typeof input[val as keyof typeof input] === 'string')) return false
|
|
12
|
+
if (!isCompatibleVersion(('__problemVersion' in input && typeof input['__problemVersion'] === 'string') ? input['__problemVersion'] : '')) return false
|
|
13
|
+
|
|
14
|
+
if (!('status' in input) || typeof input.status !== 'number') return false
|
|
15
|
+
|
|
16
|
+
return true
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createFromJson({ title, type, instance, detail, status, data }: JsonProblem): Problem {
|
|
20
|
+
return new Problem({ title, type, instance, detail, status, data })
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getProblems(input: unknown): Problem[] | void {
|
|
24
|
+
if (typeof input === 'string') {
|
|
25
|
+
try {
|
|
26
|
+
const p = JSON.parse(input)
|
|
27
|
+
input = p
|
|
28
|
+
} catch (err) { /**/ }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (input instanceof Problem) return [input]
|
|
32
|
+
if (isProblemArray(input)) return input
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(input) && input.every(val => isJsonProblem(val))) {
|
|
35
|
+
const _input = input as JsonProblem[]
|
|
36
|
+
|
|
37
|
+
return _input.map(val => createFromJson(val))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (isJsonProblem(input)) {
|
|
41
|
+
return [createFromJson(input)]
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/util/misc.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as allCodes from '../defaults/index.js'
|
|
2
|
+
import { ProblemOpts, Codes } from '../typings/index.js'
|
|
3
|
+
|
|
4
|
+
export function getHttpError(statusCode: number | string): ProblemOpts | undefined {
|
|
5
|
+
for (const key in allCodes) {
|
|
6
|
+
// This ensures all codes are written correctly as well, so that's a bonus
|
|
7
|
+
const codeObject: Codes = allCodes[key as keyof typeof allCodes]
|
|
8
|
+
|
|
9
|
+
if (typeof statusCode === 'string') {
|
|
10
|
+
const conv = Number(statusCode)
|
|
11
|
+
if (!isNaN(conv)) statusCode = conv
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const code = codeObject[statusCode]
|
|
15
|
+
|
|
16
|
+
if (!code) return
|
|
17
|
+
|
|
18
|
+
return code
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const version = '7.0.0'
|
|
2
|
+
export const major = Number(version.split('.')[0])
|
|
3
|
+
|
|
4
|
+
export function isCompatibleVersion(inputVersion: string) {
|
|
5
|
+
// TODO: Remove this
|
|
6
|
+
if (inputVersion === 'lua-dev') return true
|
|
7
|
+
|
|
8
|
+
const parts = inputVersion.split('.')
|
|
9
|
+
const inputMajor = Number(parts[0])
|
|
10
|
+
|
|
11
|
+
if (parts.length !== 3) return false
|
|
12
|
+
if (isNaN(inputMajor)) return false
|
|
13
|
+
if (inputMajor !== major) return false
|
|
14
|
+
|
|
15
|
+
return true
|
|
16
|
+
}
|
package/tsconfig.json
ADDED
package/defaults/index.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { statusCodes as codes4xx } from '../defaults/4xx';
|
|
2
|
-
export { statusCodes as codes5xx } from '../defaults/5xx';
|
|
3
|
-
export { statusCodes as codesAws } from '../defaults/aws';
|
|
4
|
-
export { statusCodes as codesCloudflare } from '../defaults/cloudflare';
|
|
5
|
-
export { statusCodes as codesIis } from '../defaults/iis';
|
|
6
|
-
export { statusCodes as codesNginx } from '../defaults/nginx';
|
|
7
|
-
export { otherErrors } from '../defaults/others';
|
package/defaults/index.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.otherErrors = exports.codesNginx = exports.codesIis = exports.codesCloudflare = exports.codesAws = exports.codes5xx = exports.codes4xx = void 0;
|
|
4
|
-
var _4xx_1 = require("../defaults/4xx");
|
|
5
|
-
Object.defineProperty(exports, "codes4xx", { enumerable: true, get: function () { return _4xx_1.statusCodes; } });
|
|
6
|
-
var _5xx_1 = require("../defaults/5xx");
|
|
7
|
-
Object.defineProperty(exports, "codes5xx", { enumerable: true, get: function () { return _5xx_1.statusCodes; } });
|
|
8
|
-
var aws_1 = require("../defaults/aws");
|
|
9
|
-
Object.defineProperty(exports, "codesAws", { enumerable: true, get: function () { return aws_1.statusCodes; } });
|
|
10
|
-
var cloudflare_1 = require("../defaults/cloudflare");
|
|
11
|
-
Object.defineProperty(exports, "codesCloudflare", { enumerable: true, get: function () { return cloudflare_1.statusCodes; } });
|
|
12
|
-
var iis_1 = require("../defaults/iis");
|
|
13
|
-
Object.defineProperty(exports, "codesIis", { enumerable: true, get: function () { return iis_1.statusCodes; } });
|
|
14
|
-
var nginx_1 = require("../defaults/nginx");
|
|
15
|
-
Object.defineProperty(exports, "codesNginx", { enumerable: true, get: function () { return nginx_1.statusCodes; } });
|
|
16
|
-
var others_1 = require("../defaults/others");
|
|
17
|
-
Object.defineProperty(exports, "otherErrors", { enumerable: true, get: function () { return others_1.otherErrors; } });
|
package/index.d.ts
DELETED
package/index.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
26
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
|
-
};
|
|
28
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
29
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
30
|
-
};
|
|
31
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.events = exports.defaults = exports.Problem = void 0;
|
|
33
|
-
var problem_1 = require("./problem");
|
|
34
|
-
Object.defineProperty(exports, "Problem", { enumerable: true, get: function () { return problem_1.Problem; } });
|
|
35
|
-
exports.defaults = __importStar(require("./defaults"));
|
|
36
|
-
var events_1 = require("./util/events");
|
|
37
|
-
Object.defineProperty(exports, "events", { enumerable: true, get: function () { return __importDefault(events_1).default; } });
|
|
38
|
-
__exportStar(require("./typings"), exports);
|
|
39
|
-
__exportStar(require("./util/isProblemArray"), exports);
|
package/middleware/axios.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.AxiosMiddleware = void 0;
|
|
16
|
-
const base_1 = require("./base");
|
|
17
|
-
const axios_1 = __importDefault(require("../parsers/axios"));
|
|
18
|
-
const events_1 = __importDefault(require("../util/events"));
|
|
19
|
-
class AxiosMiddleware extends base_1.MiddlewareBase {
|
|
20
|
-
constructor(options) {
|
|
21
|
-
super({
|
|
22
|
-
'parsers': [axios_1.default]
|
|
23
|
-
}, options);
|
|
24
|
-
this.name = 'axios';
|
|
25
|
-
this.interceptor = (error) => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const problems = yield this.parse(error);
|
|
27
|
-
events_1.default.emit(problems);
|
|
28
|
-
return Promise.reject(problems);
|
|
29
|
-
});
|
|
30
|
-
/**
|
|
31
|
-
* @example instance.interceptors.response.use(...middleware.use())
|
|
32
|
-
*/
|
|
33
|
-
this.use = () => [undefined, this.interceptor];
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
exports.AxiosMiddleware = AxiosMiddleware;
|
package/middleware/base.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.MiddlewareBase = void 0;
|
|
13
|
-
const defaults_1 = require("../defaults");
|
|
14
|
-
const problem_1 = require("../problem");
|
|
15
|
-
const getProblems_1 = require("../util/getProblems");
|
|
16
|
-
/**
|
|
17
|
-
* 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
|
|
18
|
-
*/
|
|
19
|
-
class MiddlewareBase {
|
|
20
|
-
constructor(defaultOptions, options) {
|
|
21
|
-
/**
|
|
22
|
-
* When nothing is returned from the parsers, just throw in a default "fallback" Problem object, so that a Problem is still actually returned/emitted
|
|
23
|
-
*/
|
|
24
|
-
this.enableFallback = true;
|
|
25
|
-
/**
|
|
26
|
-
* Parse input using parsers
|
|
27
|
-
*/
|
|
28
|
-
this.parse = (input) => __awaiter(this, void 0, void 0, function* () {
|
|
29
|
-
const problems = [];
|
|
30
|
-
const prob = (0, getProblems_1.getProblems)(input);
|
|
31
|
-
if (!prob) {
|
|
32
|
-
for (const parse of this.options.parsers) {
|
|
33
|
-
const resp = parse(input);
|
|
34
|
-
if (!resp.length)
|
|
35
|
-
continue;
|
|
36
|
-
problems.push(...resp);
|
|
37
|
-
break;
|
|
38
|
-
}
|
|
39
|
-
if (!problems.length && this.enableFallback) {
|
|
40
|
-
problems.push(new problem_1.Problem(Object.assign(Object.assign({}, this.fallback), { 'errorObject': input, 'stack': (typeof input === 'object' && input !== null && 'stack' in input && typeof input.stack === 'string') ? input.stack : undefined })));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
problems.push(...prob);
|
|
45
|
-
}
|
|
46
|
-
for (const p of problems) {
|
|
47
|
-
if (!p.middleware)
|
|
48
|
-
p.middleware = this.name;
|
|
49
|
-
}
|
|
50
|
-
return problems;
|
|
51
|
-
});
|
|
52
|
-
this.fallback = defaults_1.otherErrors.unknown;
|
|
53
|
-
this.options = Object.assign(Object.assign({}, defaultOptions), options);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
exports.MiddlewareBase = MiddlewareBase;
|
package/middleware/express.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
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.ExpressMiddleware = void 0;
|
|
7
|
-
const base_1 = require("./base");
|
|
8
|
-
const problem_1 = require("../problem");
|
|
9
|
-
const defaults_1 = require("../defaults");
|
|
10
|
-
const events_1 = __importDefault(require("../util/events"));
|
|
11
|
-
const defaults_2 = require("../util/defaults");
|
|
12
|
-
class ExpressMiddleware extends base_1.MiddlewareBase {
|
|
13
|
-
constructor(options) {
|
|
14
|
-
super({
|
|
15
|
-
'parsers': []
|
|
16
|
-
}, options);
|
|
17
|
-
this.name = 'express';
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
19
|
-
this.middleware = (error, req, res, next) => {
|
|
20
|
-
this.parse(error)
|
|
21
|
-
.then(problems => {
|
|
22
|
-
var _a, _b;
|
|
23
|
-
for (const problem of problems) {
|
|
24
|
-
if (problem.instance === defaults_2.defaultInstance) {
|
|
25
|
-
problem.instance = req.originalUrl;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
events_1.default.emit(problems);
|
|
29
|
-
res
|
|
30
|
-
.contentType('application/problem+json')
|
|
31
|
-
.status((_b = (_a = problems[0]) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : 500)
|
|
32
|
-
.json(problems.map(val => val.toObject()));
|
|
33
|
-
})
|
|
34
|
-
.catch(err => {
|
|
35
|
-
res
|
|
36
|
-
.contentType('application/problem+json')
|
|
37
|
-
.status(500)
|
|
38
|
-
.json([
|
|
39
|
-
new problem_1.Problem(Object.assign(Object.assign({}, defaults_1.otherErrors.unknown), { 'instance': req.originalUrl, 'status': 500, 'stack': err === null || err === void 0 ? void 0 : err.stack, 'errorObject': err })).toObject()
|
|
40
|
-
]);
|
|
41
|
-
throw err;
|
|
42
|
-
});
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* This function applies the middleware to your Express application. Put this at the very end of your middleware/routes.
|
|
46
|
-
* If you want to also handle 404 errors, check out the notFound middleware function.
|
|
47
|
-
* @example app.use(middleware.use())
|
|
48
|
-
*/
|
|
49
|
-
this.use = () => this.middleware;
|
|
50
|
-
/**
|
|
51
|
-
* Put this right before the middleware.use() to catch all 404 errors and respond with a Problem instead of the default Express response
|
|
52
|
-
* @example app.use(middleware.notFound)
|
|
53
|
-
*/
|
|
54
|
-
this.notFound = (req, res, next) => {
|
|
55
|
-
const error = new problem_1.Problem(Object.assign(Object.assign({}, defaults_1.codes4xx[404]), { 'instance': req.originalUrl, 'detail': `No API endpoints exist on ${req.url} for request method ${req.method}` }));
|
|
56
|
-
return next(error);
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
exports.ExpressMiddleware = ExpressMiddleware;
|
package/parsers/axios.d.ts
DELETED
package/parsers/axios.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const others_1 = require("../defaults/others");
|
|
4
|
-
const problem_1 = require("../problem");
|
|
5
|
-
const getProblems_1 = require("../util/getProblems");
|
|
6
|
-
const misc_1 = require("../util/misc");
|
|
7
|
-
function isAxiosError(payload) {
|
|
8
|
-
return typeof payload === 'object' && payload !== null && 'isAxiosError' in payload && payload.isAxiosError === true;
|
|
9
|
-
}
|
|
10
|
-
const parse = (input) => {
|
|
11
|
-
var _a, _b, _c, _d, _e;
|
|
12
|
-
if (typeof input !== 'object' || input == null)
|
|
13
|
-
return [];
|
|
14
|
-
if (!isAxiosError(input))
|
|
15
|
-
return [];
|
|
16
|
-
const request = input.request;
|
|
17
|
-
if ((_a = input === null || input === void 0 ? void 0 : input.response) === null || _a === void 0 ? void 0 : _a.data) {
|
|
18
|
-
const problems = (0, getProblems_1.getProblems)((_b = input === null || input === void 0 ? void 0 : input.response) === null || _b === void 0 ? void 0 : _b.data);
|
|
19
|
-
if (problems === null || problems === void 0 ? void 0 : problems.length)
|
|
20
|
-
return problems;
|
|
21
|
-
}
|
|
22
|
-
if (input === null || input === void 0 ? void 0 : input.response) {
|
|
23
|
-
const opts = (0, misc_1.getHttpError)(input.response.status);
|
|
24
|
-
if (opts)
|
|
25
|
-
return [new problem_1.Problem(Object.assign(Object.assign({}, opts), { 'instance': (_c = input === null || input === void 0 ? void 0 : input.config) === null || _c === void 0 ? void 0 : _c.url, 'stack': input === null || input === void 0 ? void 0 : input.stack, 'errorObject': input }))];
|
|
26
|
-
}
|
|
27
|
-
// TODO: Fix this, this seems bad
|
|
28
|
-
if (request) {
|
|
29
|
-
const isNode = typeof process !== 'undefined' && process.versions && process.versions.node;
|
|
30
|
-
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
31
|
-
if (isBrowser && request instanceof XMLHttpRequest) {
|
|
32
|
-
return [new problem_1.Problem(Object.assign(Object.assign({}, others_1.otherErrors.networkError), { 'instance': (_d = input === null || input === void 0 ? void 0 : input.config) === null || _d === void 0 ? void 0 : _d.url, 'stack': input === null || input === void 0 ? void 0 : input.stack, 'errorObject': input }))];
|
|
33
|
-
}
|
|
34
|
-
// Probably a ClientRequest
|
|
35
|
-
if (isNode && 'pipe' in request && 'destroy' in request) {
|
|
36
|
-
return [new problem_1.Problem(Object.assign(Object.assign({}, others_1.otherErrors.networkError), { 'instance': (_e = input === null || input === void 0 ? void 0 : input.config) === null || _e === void 0 ? void 0 : _e.url, 'stack': input === null || input === void 0 ? void 0 : input.stack, 'errorObject': input }))];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return [];
|
|
40
|
-
};
|
|
41
|
-
exports.default = parse;
|