@based/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 +2 -0
- package/package.json +28 -0
- package/src/index.ts +482 -0
- package/test/index.ts +26 -0
- package/tsconfig.json +17 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@based/errors",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/src/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "rm -rf ./dist && tsc",
|
|
9
|
+
"watch": "npx tsc --watch",
|
|
10
|
+
"test": "npx ava",
|
|
11
|
+
"clean": "rimraf {.turbo,dist,node_modules}"
|
|
12
|
+
},
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"ava": {
|
|
15
|
+
"timeout": "2m",
|
|
16
|
+
"workerThreads": false,
|
|
17
|
+
"files": [
|
|
18
|
+
"./dist/test/**/*.js"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"ts-node": "10.9.1",
|
|
24
|
+
"ava": "5.3.1",
|
|
25
|
+
"typescript": "^4.3.5",
|
|
26
|
+
"rimraf": "^3.0.2"
|
|
27
|
+
}
|
|
28
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { BasedRoute, isAnyBasedRoute } from '@based/functions'
|
|
2
|
+
|
|
3
|
+
export enum BasedErrorCode {
|
|
4
|
+
// Parse Errors
|
|
5
|
+
incorrectFieldType = 1000,
|
|
6
|
+
incorrectNodeType = 1001,
|
|
7
|
+
exceedsMaximum = 1002,
|
|
8
|
+
subceedsMinimum = 1003,
|
|
9
|
+
fieldDoesNotExist = 1004,
|
|
10
|
+
incorrectFormat = 1005,
|
|
11
|
+
referenceIsIncorrectType = 1006,
|
|
12
|
+
valueAndDefault = 1007,
|
|
13
|
+
defaultNotSupported = 1008,
|
|
14
|
+
multipleOperationsNotAllowed = 1009,
|
|
15
|
+
requiredFieldNotDefined = 1010,
|
|
16
|
+
languageNotSupported = 1011,
|
|
17
|
+
invalidJSON = 1012,
|
|
18
|
+
noLanguageFound = 1013,
|
|
19
|
+
cannotDeleteNodeFromModify = 1014,
|
|
20
|
+
nestedModifyObjectNotAllowed = 1015,
|
|
21
|
+
infinityNotSupported = 1016,
|
|
22
|
+
invalidSchemaFormat = 1017,
|
|
23
|
+
invalidProperty = 1018,
|
|
24
|
+
|
|
25
|
+
// client/server errors
|
|
26
|
+
FunctionError = 50001,
|
|
27
|
+
AuthorizeFunctionError = 50002,
|
|
28
|
+
NoOservableCacheAvailable = 50003,
|
|
29
|
+
ObservableFunctionError = 50004,
|
|
30
|
+
ObserveCallbackError = 50005,
|
|
31
|
+
FunctionNotFound = 40401,
|
|
32
|
+
FunctionIsNotObservable = 40402,
|
|
33
|
+
FunctionIsObservable = 40403,
|
|
34
|
+
FunctionIsStream = 40404,
|
|
35
|
+
CannotStreamToObservableFunction = 40405,
|
|
36
|
+
FunctionIsWrongType = 40406, // was 40402 in server
|
|
37
|
+
AuthorizeRejectedError = 40301,
|
|
38
|
+
InvalidPayload = 40001,
|
|
39
|
+
PayloadTooLarge = 40002,
|
|
40
|
+
ChunkTooLarge = 40003,
|
|
41
|
+
UnsupportedContentEncoding = 40004,
|
|
42
|
+
NoBinaryProtocol = 40005,
|
|
43
|
+
LengthRequired = 41101,
|
|
44
|
+
MethodNotAllowed = 40501,
|
|
45
|
+
RateLimit = 40029,
|
|
46
|
+
MissingAuthStateProtocolHeader = 40030,
|
|
47
|
+
IncorrectAccessKey = 40031,
|
|
48
|
+
Block = 90001,
|
|
49
|
+
|
|
50
|
+
// Mutation error
|
|
51
|
+
// PrefixAlreadyInUse = 2000,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
type BasedParseErrorPayload = {
|
|
55
|
+
path: string[]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
type FunctionErrorProps = {
|
|
59
|
+
err: Error | string
|
|
60
|
+
requestId?: number
|
|
61
|
+
route: BasedRoute
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
type ObservableFunctionErrorProps = {
|
|
65
|
+
observableId: number
|
|
66
|
+
err: Error | string
|
|
67
|
+
route: BasedRoute
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
type ChannelFunctionErrorProps = {
|
|
71
|
+
channelId: number
|
|
72
|
+
err: Error | string
|
|
73
|
+
route: BasedRoute
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type BasedErrorPayload =
|
|
77
|
+
| {
|
|
78
|
+
observableId: number
|
|
79
|
+
route: BasedRoute
|
|
80
|
+
}
|
|
81
|
+
| {
|
|
82
|
+
requestId: number
|
|
83
|
+
route: BasedRoute
|
|
84
|
+
}
|
|
85
|
+
| {
|
|
86
|
+
channelId: number
|
|
87
|
+
route: BasedRoute
|
|
88
|
+
}
|
|
89
|
+
| { route: BasedRoute }
|
|
90
|
+
|
|
91
|
+
type BasedFunctionError =
|
|
92
|
+
| FunctionErrorProps
|
|
93
|
+
| ObservableFunctionErrorProps
|
|
94
|
+
| ChannelFunctionErrorProps
|
|
95
|
+
|
|
96
|
+
export type ErrorPayload = {
|
|
97
|
+
[BasedErrorCode.incorrectFieldType]: BasedParseErrorPayload
|
|
98
|
+
[BasedErrorCode.incorrectNodeType]: BasedParseErrorPayload
|
|
99
|
+
[BasedErrorCode.exceedsMaximum]: BasedParseErrorPayload
|
|
100
|
+
[BasedErrorCode.subceedsMinimum]: BasedParseErrorPayload
|
|
101
|
+
[BasedErrorCode.fieldDoesNotExist]: BasedParseErrorPayload
|
|
102
|
+
[BasedErrorCode.incorrectFormat]: BasedParseErrorPayload,
|
|
103
|
+
[BasedErrorCode.referenceIsIncorrectType]: BasedParseErrorPayload,
|
|
104
|
+
[BasedErrorCode.valueAndDefault]: BasedParseErrorPayload,
|
|
105
|
+
[BasedErrorCode.defaultNotSupported]: BasedParseErrorPayload,
|
|
106
|
+
[BasedErrorCode.multipleOperationsNotAllowed]: BasedParseErrorPayload,
|
|
107
|
+
[BasedErrorCode.requiredFieldNotDefined]: BasedParseErrorPayload,
|
|
108
|
+
[BasedErrorCode.languageNotSupported]: BasedParseErrorPayload,
|
|
109
|
+
[BasedErrorCode.invalidJSON]: BasedParseErrorPayload,
|
|
110
|
+
[BasedErrorCode.noLanguageFound]: BasedParseErrorPayload,
|
|
111
|
+
[BasedErrorCode.cannotDeleteNodeFromModify]: BasedParseErrorPayload,
|
|
112
|
+
[BasedErrorCode.nestedModifyObjectNotAllowed]: BasedParseErrorPayload,
|
|
113
|
+
[BasedErrorCode.infinityNotSupported]: BasedParseErrorPayload,
|
|
114
|
+
[BasedErrorCode.invalidSchemaFormat]: BasedParseErrorPayload,
|
|
115
|
+
[BasedErrorCode.invalidProperty]: BasedParseErrorPayload,
|
|
116
|
+
|
|
117
|
+
[BasedErrorCode.FunctionError]: BasedFunctionError
|
|
118
|
+
[BasedErrorCode.AuthorizeFunctionError]: BasedFunctionError
|
|
119
|
+
[BasedErrorCode.NoOservableCacheAvailable]: {
|
|
120
|
+
observableId: number
|
|
121
|
+
route: BasedRoute
|
|
122
|
+
}
|
|
123
|
+
[BasedErrorCode.ObservableFunctionError]: BasedFunctionError
|
|
124
|
+
[BasedErrorCode.ObserveCallbackError]: {
|
|
125
|
+
err: Error
|
|
126
|
+
observableId: number
|
|
127
|
+
route: BasedRoute
|
|
128
|
+
}
|
|
129
|
+
[BasedErrorCode.FunctionNotFound]: BasedErrorPayload
|
|
130
|
+
[BasedErrorCode.FunctionIsNotObservable]: BasedErrorPayload // FunctionIsWrongType?
|
|
131
|
+
[BasedErrorCode.FunctionIsObservable]: BasedErrorPayload // FunctionIsWrongType?
|
|
132
|
+
[BasedErrorCode.FunctionIsStream]: BasedErrorPayload // FunctionIsWrongType?
|
|
133
|
+
[BasedErrorCode.CannotStreamToObservableFunction]: BasedErrorPayload
|
|
134
|
+
[BasedErrorCode.FunctionIsWrongType]: BasedErrorPayload
|
|
135
|
+
[BasedErrorCode.AuthorizeRejectedError]: BasedErrorPayload
|
|
136
|
+
[BasedErrorCode.InvalidPayload]: BasedErrorPayload
|
|
137
|
+
[BasedErrorCode.PayloadTooLarge]: BasedErrorPayload
|
|
138
|
+
[BasedErrorCode.ChunkTooLarge]: BasedRoute
|
|
139
|
+
[BasedErrorCode.UnsupportedContentEncoding]: BasedRoute
|
|
140
|
+
[BasedErrorCode.NoBinaryProtocol]: { buffer: ArrayBuffer }
|
|
141
|
+
[BasedErrorCode.LengthRequired]: BasedRoute
|
|
142
|
+
[BasedErrorCode.MethodNotAllowed]: BasedRoute
|
|
143
|
+
[BasedErrorCode.RateLimit]: {}
|
|
144
|
+
[BasedErrorCode.MissingAuthStateProtocolHeader]: {}
|
|
145
|
+
[BasedErrorCode.IncorrectAccessKey]: {}
|
|
146
|
+
[BasedErrorCode.Block]: {}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export type ErrorHandler<T extends BasedErrorCode> = {
|
|
150
|
+
statusCode?: number
|
|
151
|
+
statusMessage?: string
|
|
152
|
+
message: (payload: ErrorPayload[T]) => string
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export type BasedErrorData<T extends BasedErrorCode = BasedErrorCode> = {
|
|
156
|
+
route?: BasedRoute
|
|
157
|
+
message: string
|
|
158
|
+
code: T
|
|
159
|
+
statusCode?: number
|
|
160
|
+
statusMessage?: string
|
|
161
|
+
requestId?: number
|
|
162
|
+
observableId?: number
|
|
163
|
+
channelId?: number
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const addName = (
|
|
167
|
+
payload: { name: string } & { [key: string]: unknown }
|
|
168
|
+
): string => {
|
|
169
|
+
return payload.name ? `[${payload.name}] ` : ''
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
type ErrorType = {
|
|
173
|
+
[K in BasedErrorCode]: ErrorHandler<K>
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const errorTypeHandlers: ErrorType = {
|
|
177
|
+
// Parse errors
|
|
178
|
+
[BasedErrorCode.incorrectFieldType]: {
|
|
179
|
+
message: (payload) => `[${payload.path.join('.')}] Incorrect field type.`
|
|
180
|
+
},
|
|
181
|
+
[BasedErrorCode.incorrectNodeType]: {
|
|
182
|
+
message: (payload) => `[${payload.path.join('.')}] Incorrect node type.`
|
|
183
|
+
},
|
|
184
|
+
[BasedErrorCode.exceedsMaximum]: {
|
|
185
|
+
message: (payload) => `[${payload.path.join('.')}] Exceeds maximum property.`
|
|
186
|
+
},
|
|
187
|
+
[BasedErrorCode.subceedsMinimum]: {
|
|
188
|
+
message: (payload) => `[${payload.path.join('.')}] Subceeds minimum property.`
|
|
189
|
+
},
|
|
190
|
+
[BasedErrorCode.fieldDoesNotExist]: {
|
|
191
|
+
message: (payload) => `[${payload.path.join('.')}] Field does not exist.`
|
|
192
|
+
},
|
|
193
|
+
[BasedErrorCode.incorrectFormat]: {
|
|
194
|
+
message: (payload) => `[${payload.path.join('.')}] Incorrect format.`
|
|
195
|
+
},
|
|
196
|
+
[BasedErrorCode.referenceIsIncorrectType]: {
|
|
197
|
+
message: (payload) => `[${payload.path.join('.')}] Reference is from incorrect type.`
|
|
198
|
+
},
|
|
199
|
+
[BasedErrorCode.valueAndDefault]: {
|
|
200
|
+
message: (payload) => `[${payload.path.join('.')}] Value and $default are being used at the same time.`
|
|
201
|
+
},
|
|
202
|
+
[BasedErrorCode.defaultNotSupported]: {
|
|
203
|
+
message: (payload) => `[${payload.path.join('.')}] $default is not suported.`
|
|
204
|
+
},
|
|
205
|
+
[BasedErrorCode.multipleOperationsNotAllowed]: {
|
|
206
|
+
message: (payload) => `[${payload.path.join('.')}] Multiple operations are not allowed here.`
|
|
207
|
+
},
|
|
208
|
+
[BasedErrorCode.requiredFieldNotDefined]: {
|
|
209
|
+
message: (payload) => `[${payload.path.join('.')}] Required field is not defined.`
|
|
210
|
+
},
|
|
211
|
+
[BasedErrorCode.languageNotSupported]: {
|
|
212
|
+
message: (payload) => `[${payload.path.join('.')}] Language not supported.`
|
|
213
|
+
},
|
|
214
|
+
[BasedErrorCode.invalidJSON]: {
|
|
215
|
+
message: (payload) => `[${payload.path.join('.')}] Invalid JSON.`
|
|
216
|
+
},
|
|
217
|
+
[BasedErrorCode.noLanguageFound]: {
|
|
218
|
+
message: (payload) => `[${payload.path.join('.')}] No language found.`
|
|
219
|
+
},
|
|
220
|
+
[BasedErrorCode.cannotDeleteNodeFromModify]: {
|
|
221
|
+
message: (payload) => `[${payload.path.join('.')}] Cannot delete node from modify.`
|
|
222
|
+
},
|
|
223
|
+
[BasedErrorCode.nestedModifyObjectNotAllowed]: {
|
|
224
|
+
message: (payload) => `[${payload.path.join('.')}] Nested modify object not allowed.`
|
|
225
|
+
},
|
|
226
|
+
[BasedErrorCode.infinityNotSupported]: {
|
|
227
|
+
message: (payload) => `[${payload.path.join('.')}] Infinity not supported.`
|
|
228
|
+
},
|
|
229
|
+
[BasedErrorCode.invalidSchemaFormat]: {
|
|
230
|
+
message: (payload) => `[${payload.path.join('.')}] Invalid schema format.`
|
|
231
|
+
},
|
|
232
|
+
[BasedErrorCode.invalidProperty]: {
|
|
233
|
+
message: (payload) => `[${payload.path.join('.')}] Invalid property.`
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
[BasedErrorCode.FunctionError]: {
|
|
237
|
+
statusCode: 500,
|
|
238
|
+
statusMessage: 'Internal Server Error',
|
|
239
|
+
message: (payload) => {
|
|
240
|
+
if (typeof payload.err === 'string' || !payload.err.message) {
|
|
241
|
+
return `[${payload.route.name}] ${JSON.stringify(payload.err)}`
|
|
242
|
+
}
|
|
243
|
+
return (
|
|
244
|
+
addName(payload.route) +
|
|
245
|
+
`${payload.err.name && payload.err.name !== 'Error'
|
|
246
|
+
? `[${payload.err.name}] `
|
|
247
|
+
: ''
|
|
248
|
+
}${payload.err.message || ''}.`
|
|
249
|
+
)
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
[BasedErrorCode.AuthorizeFunctionError]: {
|
|
253
|
+
statusCode: 403,
|
|
254
|
+
statusMessage: 'Forbidden',
|
|
255
|
+
message: (payload) => {
|
|
256
|
+
if (typeof payload.err === 'string' || !payload.err.message) {
|
|
257
|
+
return `[${payload.route.name}] ${JSON.stringify(payload.err)}`
|
|
258
|
+
}
|
|
259
|
+
return (
|
|
260
|
+
addName(payload.route) +
|
|
261
|
+
`${payload.err.name && payload.err.name !== 'Error'
|
|
262
|
+
? `[${payload.err.name}] `
|
|
263
|
+
: ''
|
|
264
|
+
}${payload.err.message || ''}.`
|
|
265
|
+
)
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
[BasedErrorCode.NoOservableCacheAvailable]: {
|
|
269
|
+
statusCode: 500,
|
|
270
|
+
statusMessage: 'Internal Server Error',
|
|
271
|
+
message: (
|
|
272
|
+
payload: ErrorPayload[BasedErrorCode.NoOservableCacheAvailable]
|
|
273
|
+
) =>
|
|
274
|
+
addName(payload.route) +
|
|
275
|
+
`No observable cache available${payload.route.name} - ${payload.observableId}.`,
|
|
276
|
+
},
|
|
277
|
+
[BasedErrorCode.ObservableFunctionError]: {
|
|
278
|
+
statusCode: 500,
|
|
279
|
+
statusMessage: 'Internal Server Error',
|
|
280
|
+
message: (payload) => {
|
|
281
|
+
if (typeof payload.err === 'string' || !payload.err.message) {
|
|
282
|
+
return `[${payload.route.name} (observable)] ${JSON.stringify(payload.err)}.`
|
|
283
|
+
}
|
|
284
|
+
return (
|
|
285
|
+
addName(payload.route) +
|
|
286
|
+
`${payload.err.name && payload.err.name !== 'Error'
|
|
287
|
+
? `[${payload.err.name}] `
|
|
288
|
+
: ''
|
|
289
|
+
}${payload.err.message || ''}.`
|
|
290
|
+
)
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
[BasedErrorCode.ObserveCallbackError]: {
|
|
294
|
+
statusCode: 500,
|
|
295
|
+
statusMessage: 'Internal Server Error',
|
|
296
|
+
message: () => {
|
|
297
|
+
return 'Error in server side observer.'
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
[BasedErrorCode.FunctionNotFound]: {
|
|
301
|
+
statusCode: 404,
|
|
302
|
+
statusMessage: 'Not Found',
|
|
303
|
+
message: (payload) => {
|
|
304
|
+
return (
|
|
305
|
+
addName(payload.route) +
|
|
306
|
+
`Function not found${payload.route.path ? ` path '${payload.route.path}'` : ''
|
|
307
|
+
}.`
|
|
308
|
+
)
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
[BasedErrorCode.FunctionIsNotObservable]: {
|
|
312
|
+
statusCode: 400,
|
|
313
|
+
statusMessage: 'Incorrect Protocol',
|
|
314
|
+
message: (payload) => {
|
|
315
|
+
return addName(payload.route) + 'Target function is not observable.'
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
[BasedErrorCode.FunctionIsObservable]: {
|
|
319
|
+
statusCode: 400,
|
|
320
|
+
statusMessage: 'Incorrect Protocol',
|
|
321
|
+
message: (payload) => {
|
|
322
|
+
return addName(payload.route) + 'Target function is observable.'
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
[BasedErrorCode.FunctionIsStream]: {
|
|
326
|
+
statusCode: 400,
|
|
327
|
+
statusMessage: 'Incorrect Protocol',
|
|
328
|
+
message: (payload) => {
|
|
329
|
+
return addName(payload.route) + 'Target function is stream.'
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
[BasedErrorCode.CannotStreamToObservableFunction]: {
|
|
333
|
+
statusCode: 400,
|
|
334
|
+
statusMessage: 'Incorrect Protocol',
|
|
335
|
+
message: (payload) => {
|
|
336
|
+
return addName(payload.route) + 'Cannot stream to observable function.'
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
[BasedErrorCode.FunctionIsWrongType]: {
|
|
340
|
+
statusCode: 400,
|
|
341
|
+
statusMessage: 'Incorrect Protocol',
|
|
342
|
+
message: (payload) => {
|
|
343
|
+
return addName(payload.route) + 'Target function is of wrong type.'
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
[BasedErrorCode.AuthorizeRejectedError]: {
|
|
347
|
+
statusCode: 403,
|
|
348
|
+
statusMessage: 'Forbidden',
|
|
349
|
+
message: (payload) => addName(payload.route) + `Authorize rejected access.`,
|
|
350
|
+
},
|
|
351
|
+
[BasedErrorCode.InvalidPayload]: {
|
|
352
|
+
statusCode: 400,
|
|
353
|
+
statusMessage: 'Bad Request',
|
|
354
|
+
message: (payload) => addName(payload.route) + 'Invalid payload.',
|
|
355
|
+
},
|
|
356
|
+
[BasedErrorCode.PayloadTooLarge]: {
|
|
357
|
+
statusCode: 413,
|
|
358
|
+
statusMessage: 'Payload Too Large',
|
|
359
|
+
message: (payload) => addName(payload.route) + ' PayloadTooLarge.',
|
|
360
|
+
},
|
|
361
|
+
[BasedErrorCode.ChunkTooLarge]: {
|
|
362
|
+
statusCode: 413,
|
|
363
|
+
statusMessage: 'Payload Too Large',
|
|
364
|
+
message: (payload) => addName(payload) + 'ChunkTooLarge ' + payload.name + '.',
|
|
365
|
+
},
|
|
366
|
+
[BasedErrorCode.UnsupportedContentEncoding]: {
|
|
367
|
+
statusCode: 400,
|
|
368
|
+
statusMessage: 'Incorrect content encoding',
|
|
369
|
+
message: (payload) => addName(payload) + 'Incorrect content encoding.',
|
|
370
|
+
},
|
|
371
|
+
[BasedErrorCode.NoBinaryProtocol]: {
|
|
372
|
+
statusCode: 400,
|
|
373
|
+
statusMessage: 'Protocol mismatch',
|
|
374
|
+
message: () => 'Please upgrade to the latest based client.',
|
|
375
|
+
},
|
|
376
|
+
[BasedErrorCode.LengthRequired]: {
|
|
377
|
+
statusCode: 411,
|
|
378
|
+
statusMessage: 'Length Required',
|
|
379
|
+
message: (payload) => addName(payload) + 'Length Required.',
|
|
380
|
+
},
|
|
381
|
+
[BasedErrorCode.MethodNotAllowed]: {
|
|
382
|
+
statusCode: 405,
|
|
383
|
+
statusMessage: 'Method Not Allowed',
|
|
384
|
+
message: (payload) => addName(payload) + 'Method Not Allowed.',
|
|
385
|
+
},
|
|
386
|
+
[BasedErrorCode.RateLimit]: {
|
|
387
|
+
statusCode: 429,
|
|
388
|
+
statusMessage: 'Rate limit',
|
|
389
|
+
message: () => 'Rate limit.',
|
|
390
|
+
},
|
|
391
|
+
[BasedErrorCode.MissingAuthStateProtocolHeader]: {
|
|
392
|
+
statusCode: 500,
|
|
393
|
+
statusMessage: 'Internal Server Error',
|
|
394
|
+
message: () => '',
|
|
395
|
+
},
|
|
396
|
+
[BasedErrorCode.IncorrectAccessKey]: {
|
|
397
|
+
statusCode: 429,
|
|
398
|
+
statusMessage: 'Rate limit',
|
|
399
|
+
message: () => 'Rate limit.',
|
|
400
|
+
},
|
|
401
|
+
[BasedErrorCode.Block]: {
|
|
402
|
+
statusCode: 429,
|
|
403
|
+
statusMessage: 'Blocked ip',
|
|
404
|
+
message: () => 'Blocked ip.',
|
|
405
|
+
},
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export const EMPTY_ROUTE: BasedRoute = {
|
|
409
|
+
name: 'no-route',
|
|
410
|
+
path: '',
|
|
411
|
+
type: 'function',
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function isServerError(
|
|
415
|
+
payload: {} | BasedErrorPayload | BasedParseErrorPayload
|
|
416
|
+
): payload is BasedErrorPayload {
|
|
417
|
+
return (payload as BasedErrorPayload).route !== undefined
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function createErrorData<T extends BasedErrorCode>(
|
|
421
|
+
code: T,
|
|
422
|
+
payload: ErrorPayload[T]
|
|
423
|
+
) {
|
|
424
|
+
const type = errorTypeHandlers[code]
|
|
425
|
+
const route = !payload
|
|
426
|
+
? EMPTY_ROUTE
|
|
427
|
+
: isAnyBasedRoute(payload)
|
|
428
|
+
? payload
|
|
429
|
+
: 'route' in payload
|
|
430
|
+
? payload.route
|
|
431
|
+
: EMPTY_ROUTE
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
code,
|
|
435
|
+
message: type.message(payload),
|
|
436
|
+
...(isServerError(payload) ? {
|
|
437
|
+
statusCode: type.statusCode,
|
|
438
|
+
statusMessage: type.statusMessage,
|
|
439
|
+
route: {
|
|
440
|
+
name: route.name,
|
|
441
|
+
path: route.path,
|
|
442
|
+
type: route.type,
|
|
443
|
+
},
|
|
444
|
+
} : null)
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export class BasedError extends Error {
|
|
449
|
+
public statusMessage?: string
|
|
450
|
+
public code?: BasedErrorCode
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export const convertDataToBasedError = (
|
|
454
|
+
payload: BasedErrorData,
|
|
455
|
+
stack?: string
|
|
456
|
+
): BasedError => {
|
|
457
|
+
if (!payload || typeof payload !== 'object') {
|
|
458
|
+
const err = new BasedError(`Payload: ${payload}`)
|
|
459
|
+
// err.code = BasedErrorCode.FunctionError
|
|
460
|
+
err.name = 'Invalid returned payload'
|
|
461
|
+
return err
|
|
462
|
+
}
|
|
463
|
+
const { message, code } = payload
|
|
464
|
+
const msg = message
|
|
465
|
+
? message[0] === '['
|
|
466
|
+
? message
|
|
467
|
+
: `[${BasedErrorCode[code]}] ` + message
|
|
468
|
+
: !code
|
|
469
|
+
? JSON.stringify(payload, null, 2)
|
|
470
|
+
: 'Cannot read error msg'
|
|
471
|
+
const error = new BasedError(msg)
|
|
472
|
+
error.stack = stack ? msg + ' ' + stack : msg
|
|
473
|
+
error.name = BasedErrorCode[code]
|
|
474
|
+
error.code = code
|
|
475
|
+
return error
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// export const errorDescriptions: {
|
|
479
|
+
// [BasedErrorCode.PrefixAlreadyInUse]: (payload) =>
|
|
480
|
+
// `Prefix${payload?.prefix ? ` ${payload.prefix}` : ''} is already in use.`,
|
|
481
|
+
// }
|
|
482
|
+
// export const makeException = (error: BasedError) => new BasedException(error)
|
package/test/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import test from 'ava'
|
|
2
|
+
import {
|
|
3
|
+
BasedErrorCode,
|
|
4
|
+
BasedErrorPayload,
|
|
5
|
+
createErrorData,
|
|
6
|
+
errorTypeHandlers
|
|
7
|
+
} from '../src/index.js'
|
|
8
|
+
|
|
9
|
+
test('createErrorData server error', (t) => {
|
|
10
|
+
const payload: BasedErrorPayload = {
|
|
11
|
+
observableId: 1234,
|
|
12
|
+
route: { type: 'function', name: 'test' }
|
|
13
|
+
}
|
|
14
|
+
const result = createErrorData(BasedErrorCode.InvalidPayload, payload)
|
|
15
|
+
t.is(result.code, BasedErrorCode.InvalidPayload)
|
|
16
|
+
t.is(result.statusCode, errorTypeHandlers[BasedErrorCode.InvalidPayload].statusCode)
|
|
17
|
+
t.is(result.statusMessage, errorTypeHandlers[BasedErrorCode.InvalidPayload].statusMessage)
|
|
18
|
+
t.is(result.message, errorTypeHandlers[BasedErrorCode.InvalidPayload].message(payload))
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test('createErrorData parse error', (t) => {
|
|
22
|
+
const payload = { path: ['a', 'field'] }
|
|
23
|
+
const result = createErrorData(BasedErrorCode.incorrectFieldType, payload)
|
|
24
|
+
t.is(result.code, BasedErrorCode.incorrectFieldType)
|
|
25
|
+
t.is(result.message, errorTypeHandlers[BasedErrorCode.incorrectFieldType].message(payload))
|
|
26
|
+
})
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "@saulx/tsconfig/default.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "dist",
|
|
5
|
+
"esModuleInterop": true,
|
|
6
|
+
"allowJs": true,
|
|
7
|
+
"noPropertyAccessFromIndexSignature": false
|
|
8
|
+
},
|
|
9
|
+
"include": [
|
|
10
|
+
"./src",
|
|
11
|
+
"./test"
|
|
12
|
+
],
|
|
13
|
+
"exclude": [
|
|
14
|
+
"./dist/src",
|
|
15
|
+
"./dist/test"
|
|
16
|
+
]
|
|
17
|
+
}
|