-
Notifications
You must be signed in to change notification settings - Fork 41
/
errors.ts
338 lines (287 loc) · 10 KB
/
errors.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
import { Omit } from '../types';
import APIError, { Opts } from '../types/APIError';
export type ErrorOpts = Omit<Opts, "title" | "status" | "typeUri">;
/*
* "Generic" Errors
*
* These are errors that are no more specific/meaningful than their status
* code. They don't have/need a typeUri, in the same way problem+json uses
* "about:blank" for the analogous concept.
*
* Note: in all the functions below, we override data for status, title,
* and typeUri because these must (by definition) be the same for every
* ocurrence of the error.
*/
export const genericValidation = (data?: ErrorOpts) =>
new APIError({ ...data, status: 400, title: "Invalid data." });
export const genericNotFound = (data?: ErrorOpts) =>
new APIError({
...data,
status: 404,
title: "One or more of the targeted resources could not be found.",
});
export const generic405 = (data?: ErrorOpts) =>
new APIError({ ...data, status: 405, title: "Method not supported." })
export const generic406 = (data?: ErrorOpts) =>
new APIError({ ...data, status: 406, title: "Not Acceptable" });
export const generic415 = (data?: ErrorOpts) =>
new APIError({ ...data, status: 415, title: "Invalid Media Type" });
/*
* Query param/url related errors.
*/
export const invalidIncludePath = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-include-path",
title: "Invalid include path.",
});
export const unsupportedIncludePath = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/unsupported-include-path",
title: "Unsupported include path."
});
export const illegalQueryParam = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/illegal-query-param",
title: "One or more of the query parameters you provided is not allowed at this url.",
});
export const invalidQueryParamValue = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-query-param-value",
title: "One or more of the query parameters you provided has an invalid value."
});
/*
* Request body-derived errors.
*/
export const illegalTypeList = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/illegal-types-list",
title: "You cannot provide a list of (sub)-types on this request."
});
export const invalidTypeList = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-types-list",
title: "Invalid list of types."
});
export const invalidResourceType = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-resource-type",
title: "One or more of the provided/targeted resources is of a type " +
"that's invalid (at least at this endpoint)."
});
export const invalidRelationshipName = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-relationship-name",
title: "A provided relationhsip name is not valid (at least on this resource)."
});
export const invalidAttributeName = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-attribute-name",
title: "A provided attribute is not valid (at least on this resource)."
});
export const invalidLinkageStructure = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-linkage-json",
title: "Part of the provided JSON was expected to be a resource " +
"identifier object, but wasn't. Verify you have a { type, id } structure."
});
/**
* This is a catch-all error for cases when the resource object in question
* would be invalid in ANY json:api API.
* @type {[type]}
*/
export const invalidResourceStructure = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-object-invalid-json",
title: "Invalid resource object structure."
});
export const resourceMissingTypeKey = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-missing-type",
title: "Provided resource object was missing the required `type` key."
});
export const resourceMissingIdKey = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-missing-id",
title: "A provided resource object was missing a required `id` key."
});
export const resourceMetaNonObject = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-meta-non-object",
title: "Provided resource object had a `meta` value that wasn't an object."
});
export const resourceFieldsContainerNonObject = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-fields-container-non-object",
title: "Provided resource object had an `attributes` or `relationships` value that wasn't an object."
});
export const resourceIdentifierKeyAsField = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-identifier-key-used-as-field",
title: "Resource objects cannot use `type` or `id` as a field."
});
export const resourceDuplicateField = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/resource-duplicate-field",
title: "Resource objects can't have an attribute and a relationship with the same name."
});
export const relationshipMissingLinkage = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/relationship-missing-linkage",
title: "Client-sent relationship objects must include `data`."
});
export const invalidLinkageType = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-linkage-type",
title: "One or more of the provided resource identifier objects is of a " +
"type that's invalid in the targeted relationship."
});
/**
* Picks out field names that are illegal per the particular rules of this API
* and/or resource type. Could also apply to field names that are illegal per
* JSON:API, but, if you have to pick only one error to use, there are generally
* better ones for the latter case.
*/
export const illegalFieldName = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/illegal-field-name",
title: "One or more of the fields provided is not a legal field name this resource."
})
export const unsupportedClientId = (data?: ErrorOpts) =>
new APIError({
...data,
status: 403,
typeUri: "https://jsonapi.js.org/errors/unsupported-client-id",
title: "Client-generated ids are not supported."
})
export const missingField = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/missing-required-field",
title: "Missing required field."
})
export const invalidFieldValue = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-field-value",
title: "Invalid field value."
})
export const missingDataKey = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/missing-data-key",
title: "Request body is missing the top-level JSON:API `data` key."
});
export const expectedDataArray = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/expected-data-array",
title: "The JSON:API `data` key must hold an array for this request."
});
export const expectedDataObject = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/expected-data-object",
title: "The JSON:API `data` key must hold an object, not an array, for this request."
});
export const jsonParse = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/json-parse-error",
title: "Request is not valid JSON."
});
export const uniqueViolation = (data?: ErrorOpts) =>
new APIError({
...data,
status: 409,
typeUri: "https://jsonapi.js.org/errors/unique-error",
title: "This resource/update contained some data that was the same as " +
"data in another resource of the same type, but was supposed to be unique."
});
/*
* Errors that could be body or url related.
*/
export const invalidId = (data?: ErrorOpts) =>
new APIError({
...data,
status: 400,
typeUri: "https://jsonapi.js.org/errors/invalid-id",
title: "One or more of the provided resource ids is invalid."
});
export const unknownResourceType = (data?: ErrorOpts) =>
new APIError({
...data,
status: 404,
typeUri: "https://jsonapi.js.org/errors/unknown-resource-type",
title: 'Unknown resource type.'
});
export const unknownRelationshipName = (data?: ErrorOpts) =>
new APIError({
...data,
status: 404,
typeUri: "https://jsonapi.js.org/errors/unknown-relationship-name",
title: 'Unknown relationship name.'
});
/*
* Other error types.
*/
export const occFail = (data?: ErrorOpts) =>
new APIError({
...data,
status: 409,
typeUri: "https://jsonapi.js.org/errors/optimistic-concurrency-check-failed",
title: "One or more of the resources you are trying to use was either " +
"changed or was deleted while you were trying to read/update it. Try again."
});
export const invalidMediaTypeParam = (data?: ErrorOpts) =>
new APIError({
...data,
status: 415,
typeUri: "https://jsonapi.js.org/errors/invalid-media-type-parameter",
title: "Invalid Media Type Parameter"
})