@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 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
@@ -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":"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"}
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';
@@ -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
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroxsolutions/response",
3
- "version": "0.14.4",
3
+ "version": "0.14.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,