@zeroxsolutions/response 0.14.6 → 0.14.7
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 +10 -0
- package/README.md +29 -0
- package/dist/upstream-error.d.ts +9 -3
- package/dist/upstream-error.d.ts.map +1 -1
- package/dist/upstream-error.js +3 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 0.14.7 (2026-10-21)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **response:** let an upstream answer state its own source ([fdc8078](https://github.com/zeroxsolutions/zeroxsolutions/commit/fdc8078))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- Lương Văn Tú
|
|
10
|
+
|
|
1
11
|
## 0.14.6 (2026-10-21)
|
|
2
12
|
|
|
3
13
|
### 🚀 Features
|
package/README.md
CHANGED
|
@@ -246,6 +246,11 @@ exactly one error per failure. Of that error it keeps only what an answer's `met
|
|
|
246
246
|
pointers name the SERVICE's request shape, not the one this caller sent, so echoing them would point a
|
|
247
247
|
client at members it has no way to correct.
|
|
248
248
|
|
|
249
|
+
An answer can state a `source` of its own instead, in this transport's request terms. It is fixed per
|
|
250
|
+
upstream code, so it suits a refusal whose slot is the same on every occurrence; a slot that varies per
|
|
251
|
+
occurrence (one member of a list, say) has no way through, since the upstream error's `source` is the only
|
|
252
|
+
place that varies and it describes the wrong request. The fallback states none.
|
|
253
|
+
|
|
249
254
|
A `meta` callback returns its parse, never `upstream` as received - the schema is what keeps a member the
|
|
250
255
|
service adds later from crossing. Returning `undefined` answers the fallback: a mapped code missing the
|
|
251
256
|
data its contract promises is an answer the gateway does not recognise.
|
|
@@ -298,6 +303,30 @@ export const translateCatalogueError = translator(
|
|
|
298
303
|
throw error({ ...BASE_ERROR_CODES.FORBIDDEN, code: 'api.forbidden' });
|
|
299
304
|
```
|
|
300
305
|
|
|
306
|
+
A mapped answer states where in the client's request the refusal belongs with `source`, one of the
|
|
307
|
+
standard's `pointer`, `parameter` or `header`. JSON:API holds a `pointer` to "a value in the request
|
|
308
|
+
document that exists", so it names the member this transport's client sent, never the one the service
|
|
309
|
+
was sent:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
// entrypoints/http/error-map.ts - the client names the place by its slug; the service was sent its id
|
|
313
|
+
export const translateCatalogueWriteError = translator(
|
|
314
|
+
CATALOGUE_ERROR_CODES,
|
|
315
|
+
{
|
|
316
|
+
'catalogue.place.not_found': {
|
|
317
|
+
status: 422,
|
|
318
|
+
title: 'Unprocessable Entity',
|
|
319
|
+
code: 'api.place.not_found',
|
|
320
|
+
source: { pointer: '/data/attributes/placeSlug' },
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
{ status: 502, title: 'Bad Gateway', code: 'api.upstream_failed' },
|
|
324
|
+
);
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
The translated error renders `source: { pointer: '/data/attributes/placeSlug' }` whatever `source` the
|
|
328
|
+
service's error carried, and a member the standard does not define, `pointr`, does not compile.
|
|
329
|
+
|
|
301
330
|
The lists are values rather than type arguments: with nothing passed there is no list to fall back on,
|
|
302
331
|
where a type argument left out would widen to `string`. Neither is read at runtime. `error` also refuses
|
|
303
332
|
a key its answer does not declare, so a misspelled `detial` does not compile, and a thrown answer's `meta`
|
package/dist/upstream-error.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { UpstreamErrorMap } from './error-map.js';
|
|
2
|
-
import type { ErrorDocument, ErrorLinks } from './errors/error-document.js';
|
|
2
|
+
import type { ErrorDocument, ErrorLinks, ErrorSource } from './errors/error-document.js';
|
|
3
3
|
import type { ErrorStatus } from './errors/error-registry.js';
|
|
4
4
|
import { JsonApiError } from './errors/jsonapi-error.js';
|
|
5
5
|
import type { Meta } from './primitives.js';
|
|
@@ -11,6 +11,11 @@ export interface UpstreamErrorAnswer extends ErrorStatus {
|
|
|
11
11
|
code: string;
|
|
12
12
|
/** Human-readable and request-specific; the error's `message` falls back to the title without one. */
|
|
13
13
|
detail?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Where in this transport's own request the error originates, the same on every occurrence of the code - omit to render
|
|
16
|
+
* no `source`. The upstream error's own `source` is never read: it names a slot of the request the service received.
|
|
17
|
+
*/
|
|
18
|
+
source?: ErrorSource;
|
|
14
19
|
/** A page about this occurrence, and a page about its type of problem. */
|
|
15
20
|
links?: ErrorLinks;
|
|
16
21
|
/**
|
|
@@ -28,7 +33,8 @@ export interface UpstreamErrorAnswer extends ErrorStatus {
|
|
|
28
33
|
*
|
|
29
34
|
* The document's FIRST error decides, because `createErrorHandler` renders exactly one per failure. Nothing else of the
|
|
30
35
|
* service's error survives unless an answer's `meta` reads it: its `code` names a namespace this surface's contract
|
|
31
|
-
* never declared, and its `detail` and `source` describe a request this client never sent.
|
|
36
|
+
* never declared, and its `detail` and `source` describe a request this client never sent. An answer states its own
|
|
37
|
+
* `source` instead; the fallback states none, since the code it answers was not recognised.
|
|
32
38
|
*/
|
|
33
|
-
export declare function createUpstreamErrorTranslator(answers: UpstreamErrorMap, fallback: Omit<UpstreamErrorAnswer, 'meta'>): (document: ErrorDocument) => JsonApiError;
|
|
39
|
+
export declare function createUpstreamErrorTranslator(answers: UpstreamErrorMap, fallback: Omit<UpstreamErrorAnswer, 'meta' | 'source'>): (document: ErrorDocument) => JsonApiError;
|
|
34
40
|
//# sourceMappingURL=upstream-error.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upstream-error.d.ts","sourceRoot":"","sources":["../src/upstream-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"upstream-error.d.ts","sourceRoot":"","sources":["../src/upstream-error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,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;AAE5C;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,WAAW;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,sGAAsG;IACtG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,0EAA0E;IAC1E,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,GAAG,SAAS,KAAK,IAAI,GAAG,SAAS,CAAC;CACzD;AAcD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,IAAI,CAAC,mBAAmB,EAAE,MAAM,GAAG,QAAQ,CAAC,GACrD,CAAC,QAAQ,EAAE,aAAa,KAAK,YAAY,CAa3C"}
|
package/dist/upstream-error.js
CHANGED
|
@@ -5,6 +5,7 @@ function toJsonApiError(answer, meta) {
|
|
|
5
5
|
title: answer.title,
|
|
6
6
|
code: answer.code,
|
|
7
7
|
detail: answer.detail,
|
|
8
|
+
source: answer.source,
|
|
8
9
|
links: answer.links,
|
|
9
10
|
meta,
|
|
10
11
|
});
|
|
@@ -15,7 +16,8 @@ function toJsonApiError(answer, meta) {
|
|
|
15
16
|
*
|
|
16
17
|
* The document's FIRST error decides, because `createErrorHandler` renders exactly one per failure. Nothing else of the
|
|
17
18
|
* service's error survives unless an answer's `meta` reads it: its `code` names a namespace this surface's contract
|
|
18
|
-
* never declared, and its `detail` and `source` describe a request this client never sent.
|
|
19
|
+
* never declared, and its `detail` and `source` describe a request this client never sent. An answer states its own
|
|
20
|
+
* `source` instead; the fallback states none, since the code it answers was not recognised.
|
|
19
21
|
*/
|
|
20
22
|
export function createUpstreamErrorTranslator(answers, fallback) {
|
|
21
23
|
return (document) => {
|