@zeroxsolutions/response 0.14.4 → 0.14.5
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/CHANGELOG.md +11 -0
- package/README.md +33 -0
- package/dist/document-graph.d.ts +0 -3
- package/dist/document-graph.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/json-api-errors.d.ts +60 -0
- package/dist/json-api-errors.d.ts.map +1 -0
- package/dist/json-api-errors.js +16 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## 0.14.5 (2026-10-19)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **response:** hold every error answer to the codes a transport publishes ([0824f8e](https://github.com/zeroxsolutions/zeroxsolutions/commit/0824f8e))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Claude Opus 5.5
|
|
10
|
+
- Lương Văn Tú
|
|
11
|
+
|
|
1
12
|
## 0.14.4 (2026-10-06)
|
|
2
13
|
|
|
3
14
|
### 🩹 Fixes
|
package/README.md
CHANGED
|
@@ -271,6 +271,37 @@ It locates each issue by the slot it was read from: a body member as `source.poi
|
|
|
271
271
|
`source.parameter`, a header as `source.header`. A path segment gets `meta` instead - the spec defines
|
|
272
272
|
those three members and none of them means a path segment, so borrowing one would say something false.
|
|
273
273
|
|
|
274
|
+
## Holding every answer to the codes a transport publishes
|
|
275
|
+
|
|
276
|
+
A transport that publishes its error codes as a list binds that list once, and every answer it throws,
|
|
277
|
+
translates or maps then spells one of them or fails to compile. Each fronted service's list keys its
|
|
278
|
+
translator the same way, so an upstream key the service never renders is a compile error rather than a
|
|
279
|
+
document that silently answers the fallback.
|
|
280
|
+
|
|
281
|
+
```ts
|
|
282
|
+
// entrypoints/http/error-map.ts
|
|
283
|
+
import { BASE_ERROR_CODES, createJsonApiErrors } from '@zeroxsolutions/response';
|
|
284
|
+
import { CATALOGUE_ERROR_CODES } from '@<scope>/catalogue/schema';
|
|
285
|
+
import { API_ERROR_CODES } from '../../lib/schema/errors.js';
|
|
286
|
+
|
|
287
|
+
const { error, translator, entry } = createJsonApiErrors(API_ERROR_CODES);
|
|
288
|
+
|
|
289
|
+
export const translateCatalogueError = translator(
|
|
290
|
+
CATALOGUE_ERROR_CODES,
|
|
291
|
+
{ 'catalogue.place.not_found': { status: 404, title: 'Not Found', code: 'api.place.not_found' } },
|
|
292
|
+
{ status: 502, title: 'Bad Gateway', code: 'api.upstream_failed' },
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
throw error({ ...BASE_ERROR_CODES.FORBIDDEN, code: 'api.forbidden' });
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
The lists are values rather than type arguments: with nothing passed there is no list to fall back on,
|
|
299
|
+
where a type argument left out would widen to `string`. Neither is read at runtime. `error` also refuses
|
|
300
|
+
a key its answer does not declare, so a misspelled `detial` does not compile, and a thrown answer's `meta`
|
|
301
|
+
is data, never the reader an upstream answer carries. `entry` is `errorEntry` with its code held to the
|
|
302
|
+
same list. A constant passed to `error` keeps its literal code with `as const` or
|
|
303
|
+
`satisfies ErrorAnswer<...>`; without either, `code` widens to `string` and the call does not compile.
|
|
304
|
+
|
|
274
305
|
## A request document
|
|
275
306
|
|
|
276
307
|
A write's body is declared off the same resource the route answers with, so the document a client reads
|
|
@@ -322,6 +353,8 @@ One root, no subpath, and `src/index.ts` lists every name it publishes:
|
|
|
322
353
|
- the error document's types, `JsonApiError`, `BASE_ERROR_CODES`, `toErrorObject` / `toErrorDocument`;
|
|
323
354
|
- `defineErrorMap` / `errorEntry` / `createDomainErrorResolver` and `createUpstreamErrorTranslator`, with
|
|
324
355
|
the answer, entry and map types they take;
|
|
356
|
+
- `createJsonApiErrors`, the `JsonApiErrors` it returns, and `ErrorAnswer`, `CodedUpstreamErrorAnswer`
|
|
357
|
+
and `CodedDomainErrorAnswer`, the answers it takes;
|
|
325
358
|
- `JSON_API_MEDIA_TYPE`.
|
|
326
359
|
|
|
327
360
|
The document and resource-object schemas, the other link and identifier primitives and the serializer
|
package/dist/document-graph.d.ts
CHANGED
|
@@ -24,9 +24,6 @@ type IsWide<X> = string extends TypeOf<X> ? true : false;
|
|
|
24
24
|
/**
|
|
25
25
|
* Every dotted relationship path from `R`, at most `Depth` relationships long. A path never revisits a type,
|
|
26
26
|
* which is the rule `declaredDocumentShape` walks by, and a wide edge contributes its own name and nothing below.
|
|
27
|
-
*
|
|
28
|
-
* It names a resource's relationship paths, not the drizzle relation paths `@zeroxsolutions/db` exports under the same
|
|
29
|
-
* name `IncludePath`; a module importing both must alias one.
|
|
30
27
|
*/
|
|
31
28
|
export type IncludePath<R, Depth extends number = 3, Seen extends string = TypeOf<R>> = Depth extends 0 ? never : {
|
|
32
29
|
[K in keyof RelationshipsOf<R> & string]: RelatedOf<RelationshipsOf<R>[K]> extends infer X ? IsWide<X> extends true ? K : TypeOf<X> extends Seen ? never : K | `${K}.${IncludePath<X, Down[Depth], Seen | TypeOf<X>>}` : never;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-graph.d.ts","sourceRoot":"","sources":["../src/document-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,iEAAiE;AACjE,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAE/C,KAAK,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAEtC;;;GAGG;AACH,KAAK,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;CAAE,GACnE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC1B,SAAS,GACT,CAAC,GACH,SAAS,CAAC;AACd,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AAC9E,KAAK,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;CAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AACjF,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,SAAS;IAAE,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,SAAS,CAAC;AAE7F,oGAAoG;AACpG,KAAK,MAAM,CAAC,CAAC,IAAI,MAAM,SAAS,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC;AAEzD
|
|
1
|
+
{"version":3,"file":"document-graph.d.ts","sourceRoot":"","sources":["../src/document-graph.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export { declaredDocumentShape } from './document-shape.js';
|
|
|
9
9
|
export { createDomainErrorResolver, defineErrorMap, errorEntry, type DomainErrorAnswer, type DomainErrorEntry, } from './domain-error-resolver.js';
|
|
10
10
|
export type { DomainErrorMap, ErrorClass, UpstreamErrorMap } from './error-map.js';
|
|
11
11
|
export { BASE_ERROR_CODES, errorDocumentSchema, JsonApiError, toErrorDocument, toErrorObject, type ErrorDocument, type ErrorLinks, type ErrorObject, type ErrorSource, type ErrorStatus, type JsonApiErrorInit, type ResolvedError, } from './errors/index.js';
|
|
12
|
+
export { createJsonApiErrors, type CodedDomainErrorAnswer, type CodedUpstreamErrorAnswer, type ErrorAnswer, type JsonApiErrors, } from './json-api-errors.js';
|
|
12
13
|
export { JSON_API_MEDIA_TYPE } from './media-type.js';
|
|
13
14
|
export { countedCollectionMetaSchema, offsetPaginationLinksSchema } from './primitives.js';
|
|
14
15
|
export type { JsonApiObject, Link, Meta, PaginationLinks, RelationshipLinks, ResourceIdentifier, ResourceLinks, TopLevelLinks, } from './primitives.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC3F,YAAY,EACV,aAAa,EACb,IAAI,EACJ,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,MAAM,EACN,KAAK,EACL,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5F,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACpH,OAAO,EAAE,6BAA6B,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,UAAU,EACV,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EACV,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACnF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,aAAa,GACnB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC3F,YAAY,EACV,aAAa,EACb,IAAI,EACJ,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,MAAM,EACN,KAAK,EACL,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5F,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACpH,OAAO,EAAE,6BAA6B,EAAE,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC9F,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EAChB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './document-graph.js';
|
|
|
7
7
|
export { declaredDocumentShape } from './document-shape.js';
|
|
8
8
|
export { createDomainErrorResolver, defineErrorMap, errorEntry, } from './domain-error-resolver.js';
|
|
9
9
|
export { BASE_ERROR_CODES, errorDocumentSchema, JsonApiError, toErrorDocument, toErrorObject, } from './errors/index.js';
|
|
10
|
+
export { createJsonApiErrors, } from './json-api-errors.js';
|
|
10
11
|
export { JSON_API_MEDIA_TYPE } from './media-type.js';
|
|
11
12
|
export { countedCollectionMetaSchema, offsetPaginationLinksSchema } from './primitives.js';
|
|
12
13
|
export { toMany, toOne, } from './relationship.js';
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type DomainErrorAnswer, type DomainErrorEntry } from './domain-error-resolver.js';
|
|
2
|
+
import type { ErrorClass } from './error-map.js';
|
|
3
|
+
import type { ErrorDocument, ErrorLinks, ErrorSource } from './errors/error-document.js';
|
|
4
|
+
import type { ErrorStatus } from './errors/error-registry.js';
|
|
5
|
+
import { JsonApiError } from './errors/jsonapi-error.js';
|
|
6
|
+
import type { Meta } from './primitives.js';
|
|
7
|
+
import { type UpstreamErrorAnswer } from './upstream-error.js';
|
|
8
|
+
/** An answer thrown as it stands, its `code` one of the consumer's own. */
|
|
9
|
+
export interface ErrorAnswer<C extends string> extends ErrorStatus {
|
|
10
|
+
code: C;
|
|
11
|
+
/** Human-readable and request-specific; the error's `message` falls back to the title without one. */
|
|
12
|
+
detail?: string;
|
|
13
|
+
/** Where in the request the error originates. */
|
|
14
|
+
source?: ErrorSource;
|
|
15
|
+
/** A page about this occurrence, and a page about its type of problem. */
|
|
16
|
+
links?: ErrorLinks;
|
|
17
|
+
/** The data a client acts on that no other member carries. */
|
|
18
|
+
meta?: Meta;
|
|
19
|
+
}
|
|
20
|
+
/** {@link UpstreamErrorAnswer}, its `code` one of the consumer's own. */
|
|
21
|
+
export type CodedUpstreamErrorAnswer<C extends string> = UpstreamErrorAnswer & {
|
|
22
|
+
code: C;
|
|
23
|
+
};
|
|
24
|
+
/** {@link DomainErrorAnswer}, its `code` one of the consumer's own. */
|
|
25
|
+
export type CodedDomainErrorAnswer<C extends string, E extends Error> = DomainErrorAnswer<E> & {
|
|
26
|
+
code: C;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Every key of `A` that `Shape` does not declare, typed `never`. An argument inferred into a type parameter gets no
|
|
30
|
+
* excess-property check, so without this a misspelled optional key, `detial` for `detail`, would compile and the
|
|
31
|
+
* answer would reach a client without it.
|
|
32
|
+
*/
|
|
33
|
+
type Exact<A, Shape> = A & {
|
|
34
|
+
[K in Exclude<keyof A, keyof Shape>]: never;
|
|
35
|
+
};
|
|
36
|
+
/** What {@link createJsonApiErrors} hands back, every answer held to the codes it was given. */
|
|
37
|
+
export interface JsonApiErrors<C extends string> {
|
|
38
|
+
/** The error to throw for one answer, which `onError` renders. */
|
|
39
|
+
error<A extends ErrorAnswer<C>>(answer: Exact<A, ErrorAnswer<C>>): JsonApiError;
|
|
40
|
+
/**
|
|
41
|
+
* {@link createUpstreamErrorTranslator}, its answers keyed by the codes the fronted service publishes: a key it never
|
|
42
|
+
* renders would never match, and its document would answer the fallback without anything saying so.
|
|
43
|
+
*/
|
|
44
|
+
translator<const U extends string>(upstreamCodes: readonly U[], answers: {
|
|
45
|
+
readonly [K in U]?: CodedUpstreamErrorAnswer<C>;
|
|
46
|
+
}, fallback: Omit<ErrorAnswer<C>, 'meta' | 'source'>): (document: ErrorDocument) => JsonApiError;
|
|
47
|
+
/** {@link errorEntry}, its answer's code held to the consumer's list. */
|
|
48
|
+
entry<E extends Error>(type: ErrorClass<E>, answer: CodedDomainErrorAnswer<C, E>): DomainErrorEntry;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Binds the error codes a transport publishes, so every answer it throws, translates or maps spells one of them or
|
|
52
|
+
* fails to compile.
|
|
53
|
+
*
|
|
54
|
+
* The list is a value rather than a type argument, and so is each fronted service's in `translator`: with nothing
|
|
55
|
+
* passed there is no list to fall back on, where a type parameter left out would widen to `string`. Neither list is
|
|
56
|
+
* read at runtime; the compiler has already held every answer to it.
|
|
57
|
+
*/
|
|
58
|
+
export declare const createJsonApiErrors: <const C extends string>(codes: readonly C[]) => JsonApiErrors<C>;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=json-api-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-api-errors.d.ts","sourceRoot":"","sources":["../src/json-api-errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACvG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAiC,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE9F,2EAA2E;AAC3E,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,MAAM,CAAE,SAAQ,WAAW;IAChE,IAAI,EAAE,CAAC,CAAC;IACR,sGAAsG;IACtG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED,yEAAyE;AACzE,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,MAAM,IAAI,mBAAmB,GAAG;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC;AAE3F,uEAAuE;AACvE,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,KAAK,IAAI,iBAAiB,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC;AAE3G;;;;GAIG;AACH,KAAK,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,GAAG;KAAG,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,CAAC,GAAG,KAAK;CAAE,CAAC;AAE3E,gGAAgG;AAChG,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM;IAC7C,kEAAkE;IAClE,KAAK,CAAC,CAAC,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;IAChF;;;OAGG;IACH,UAAU,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAC/B,aAAa,EAAE,SAAS,CAAC,EAAE,EAC3B,OAAO,EAAE;QAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,wBAAwB,CAAC,CAAC,CAAC;KAAE,EAC5D,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC,GAChD,CAAC,QAAQ,EAAE,aAAa,KAAK,YAAY,CAAC;IAC7C,yEAAyE;IACzE,KAAK,CAAC,CAAC,SAAS,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,gBAAgB,CAAC;CACrG;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,KAAK,aAAa,CAAC,CAAC,CAKhG,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { errorEntry } from './domain-error-resolver.js';
|
|
2
|
+
import { JsonApiError } from './errors/jsonapi-error.js';
|
|
3
|
+
import { createUpstreamErrorTranslator } from './upstream-error.js';
|
|
4
|
+
/**
|
|
5
|
+
* Binds the error codes a transport publishes, so every answer it throws, translates or maps spells one of them or
|
|
6
|
+
* fails to compile.
|
|
7
|
+
*
|
|
8
|
+
* The list is a value rather than a type argument, and so is each fronted service's in `translator`: with nothing
|
|
9
|
+
* passed there is no list to fall back on, where a type parameter left out would widen to `string`. Neither list is
|
|
10
|
+
* read at runtime; the compiler has already held every answer to it.
|
|
11
|
+
*/
|
|
12
|
+
export const createJsonApiErrors = () => ({
|
|
13
|
+
error: (answer) => new JsonApiError(answer),
|
|
14
|
+
translator: (_upstreamCodes, answers, fallback) => createUpstreamErrorTranslator(answers, fallback),
|
|
15
|
+
entry: (type, answer) => errorEntry(type, answer),
|
|
16
|
+
});
|