@zeroxsolutions/response 0.12.1 → 0.12.2
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 +13 -0
- package/dist/api-response.d.ts +29 -3
- package/dist/api-response.d.ts.map +1 -1
- package/dist/api-response.js +26 -3
- package/dist/errors/error-registry.d.ts +4 -0
- package/dist/errors/error-registry.d.ts.map +1 -1
- package/dist/errors/error-registry.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 0.12.2 (2026-09-27)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **response:** declare a refusal's Retry-After off errorResponse ([53cc8d1](https://github.com/zeroxsolutions/zeroxsolutions/commit/53cc8d1))
|
|
6
|
+
- **response:** add the status a refused burst answers with ([910c52d](https://github.com/zeroxsolutions/zeroxsolutions/commit/910c52d))
|
|
7
|
+
|
|
8
|
+
### ❤️ Thank You
|
|
9
|
+
|
|
10
|
+
- Claude Opus 5 (1M context)
|
|
11
|
+
- Claude Opus 5.5 (1M context)
|
|
12
|
+
- Lương Văn Tú
|
|
13
|
+
|
|
1
14
|
## 0.12.1 (2026-09-18)
|
|
2
15
|
|
|
3
16
|
### 🚀 Features
|
package/dist/api-response.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { errorDocumentSchema } from './errors/index.js';
|
|
|
4
4
|
import { JSON_API_MEDIA_TYPE } from './media-type.js';
|
|
5
5
|
import type { JsonApiResource } from './resource.js';
|
|
6
6
|
/**
|
|
7
|
-
* An OpenAPI response object for this spelling - one media type, one schema
|
|
7
|
+
* An OpenAPI response object for this spelling - one media type, one schema, and the `Retry-After` a
|
|
8
|
+
* refusal that tells its caller how long to wait declares.
|
|
8
9
|
*
|
|
9
10
|
* Exported because a consumer emitting declarations has to NAME it: a route built from these helpers
|
|
10
11
|
* is an exported const whose type mentions it, and a private one fails that emit with TS4023.
|
|
@@ -14,9 +15,34 @@ export interface JsonApiResponse<S extends ZodType> {
|
|
|
14
15
|
content: Record<typeof JSON_API_MEDIA_TYPE, {
|
|
15
16
|
schema: S;
|
|
16
17
|
}>;
|
|
18
|
+
headers?: {
|
|
19
|
+
'Retry-After': RetryAfterHeader;
|
|
20
|
+
};
|
|
17
21
|
}
|
|
18
|
-
/**
|
|
19
|
-
|
|
22
|
+
/**
|
|
23
|
+
* The `Retry-After` header object a refusal declares: whole seconds, sent on every answer it gives.
|
|
24
|
+
*
|
|
25
|
+
* A type alias, not an interface: `@hono/zod-openapi` types a header as openapi3-ts's `HeaderObject`,
|
|
26
|
+
* which carries an `x-${string}` index signature, and an interface is not assignable to one.
|
|
27
|
+
*/
|
|
28
|
+
export type RetryAfterHeader = {
|
|
29
|
+
description: string;
|
|
30
|
+
required: true;
|
|
31
|
+
schema: {
|
|
32
|
+
type: 'integer';
|
|
33
|
+
minimum: 1;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* The response object for a failure status - the `errors[]` document.
|
|
38
|
+
*
|
|
39
|
+
* @param options.retryAfterSeconds - how long a refused caller is told to wait, in whole seconds.
|
|
40
|
+
* Pass it only where the refusal always sets `Retry-After`, since the header is declared required.
|
|
41
|
+
* @throws {RangeError} when `retryAfterSeconds` is not a positive integer.
|
|
42
|
+
*/
|
|
43
|
+
export declare function errorResponse(description: string, options?: {
|
|
44
|
+
retryAfterSeconds: number;
|
|
45
|
+
}): JsonApiResponse<typeof errorDocumentSchema>;
|
|
20
46
|
/** The response object for a single resource, off the resource's own declaration. */
|
|
21
47
|
export declare function okResponse<A extends ZodObject, C = unknown>(description: string, resource: JsonApiResource<A, C>): JsonApiResponse<ZodType<ResourceDocument<output<A>>>>;
|
|
22
48
|
/** The response object for a collection, off the resource's own declaration. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-response.d.ts","sourceRoot":"","sources":["../src/api-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD
|
|
1
|
+
{"version":3,"file":"api-response.d.ts","sourceRoot":"","sources":["../src/api-response.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,OAAO;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC,OAAO,mBAAmB,EAAE;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAC3D,OAAO,CAAC,EAAE;QAAE,aAAa,EAAE,gBAAgB,CAAA;KAAE,CAAC;CAC/C;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,IAAI,CAAC;IACf,MAAM,EAAE;QAAE,IAAI,EAAE,SAAS,CAAC;QAAC,OAAO,EAAE,CAAC,CAAA;KAAE,CAAC;CACzC,CAAC;AAOF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;IAAE,iBAAiB,EAAE,MAAM,CAAA;CAAE,GACtC,eAAe,CAAC,OAAO,mBAAmB,CAAC,CAqB7C;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,GAAG,OAAO,EACzD,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAC9B,eAAe,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAEvD;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC,GAAG,OAAO,EAC3D,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAC9B,eAAe,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAEzD"}
|
package/dist/api-response.js
CHANGED
|
@@ -4,9 +4,32 @@ const answers = (description, schema) => ({
|
|
|
4
4
|
description,
|
|
5
5
|
content: { [JSON_API_MEDIA_TYPE]: { schema } },
|
|
6
6
|
});
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/**
|
|
8
|
+
* The response object for a failure status - the `errors[]` document.
|
|
9
|
+
*
|
|
10
|
+
* @param options.retryAfterSeconds - how long a refused caller is told to wait, in whole seconds.
|
|
11
|
+
* Pass it only where the refusal always sets `Retry-After`, since the header is declared required.
|
|
12
|
+
* @throws {RangeError} when `retryAfterSeconds` is not a positive integer.
|
|
13
|
+
*/
|
|
14
|
+
export function errorResponse(description, options) {
|
|
15
|
+
const response = answers(description, errorDocumentSchema);
|
|
16
|
+
if (!options) {
|
|
17
|
+
return response;
|
|
18
|
+
}
|
|
19
|
+
const { retryAfterSeconds } = options;
|
|
20
|
+
if (!Number.isInteger(retryAfterSeconds) || retryAfterSeconds < 1) {
|
|
21
|
+
throw new RangeError(`retryAfterSeconds must be a positive integer, got ${retryAfterSeconds}`);
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
...response,
|
|
25
|
+
headers: {
|
|
26
|
+
'Retry-After': {
|
|
27
|
+
description: `Seconds to wait before calling again: ${retryAfterSeconds}`,
|
|
28
|
+
required: true,
|
|
29
|
+
schema: { type: 'integer', minimum: 1 },
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
10
33
|
}
|
|
11
34
|
/** The response object for a single resource, off the resource's own declaration. */
|
|
12
35
|
export function okResponse(description, resource) {
|
|
@@ -37,6 +37,10 @@ export declare const BASE_ERROR_CODES: {
|
|
|
37
37
|
readonly status: 422;
|
|
38
38
|
readonly title: "Unprocessable Entity";
|
|
39
39
|
};
|
|
40
|
+
readonly TOO_MANY_REQUESTS: {
|
|
41
|
+
readonly status: 429;
|
|
42
|
+
readonly title: "Too Many Requests";
|
|
43
|
+
};
|
|
40
44
|
readonly INTERNAL_SERVER_ERROR: {
|
|
41
45
|
readonly status: 500;
|
|
42
46
|
readonly title: "Internal Server Error";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-registry.d.ts","sourceRoot":"","sources":["../../src/errors/error-registry.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,sHAAsH;AACtH,eAAO,MAAM,gBAAgB
|
|
1
|
+
{"version":3,"file":"error-registry.d.ts","sourceRoot":"","sources":["../../src/errors/error-registry.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,sHAAsH;AACtH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYmB,CAAC"}
|
|
@@ -8,6 +8,7 @@ export const BASE_ERROR_CODES = {
|
|
|
8
8
|
CONFLICT: { status: 409, title: 'Conflict' },
|
|
9
9
|
UNSUPPORTED_MEDIA_TYPE: { status: 415, title: 'Unsupported Media Type' },
|
|
10
10
|
UNPROCESSABLE_ENTITY: { status: 422, title: 'Unprocessable Entity' },
|
|
11
|
+
TOO_MANY_REQUESTS: { status: 429, title: 'Too Many Requests' },
|
|
11
12
|
INTERNAL_SERVER_ERROR: { status: 500, title: 'Internal Server Error' },
|
|
12
13
|
BAD_GATEWAY: { status: 502, title: 'Bad Gateway' },
|
|
13
14
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The response half of the HTTP contract, in the one wire spelling this house answers: a JSON:API document.
|
|
3
3
|
*/
|
|
4
|
-
export { errorResponse, listResponse, okResponse, type JsonApiResponse } from './api-response.js';
|
|
4
|
+
export { errorResponse, listResponse, okResponse, type JsonApiResponse, type RetryAfterHeader, } from './api-response.js';
|
|
5
5
|
export type { CollectionDocument, Relationship, ResourceDocument, ResourceObject } from './document.js';
|
|
6
6
|
export { declaredDocumentShape, type DeclaredDocumentShape } from './document-shape.js';
|
|
7
7
|
export { createDomainErrorResolver, defineErrorMap, errorEntry, type DomainErrorAnswer, type DomainErrorEntry, } from './domain-error-resolver.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,
|
|
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,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACxG,OAAO,EAAE,qBAAqB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACxF,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,YAAY,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrH,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"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The response half of the HTTP contract, in the one wire spelling this house answers: a JSON:API document.
|
|
3
3
|
*/
|
|
4
|
-
export { errorResponse, listResponse, okResponse } from './api-response.js';
|
|
4
|
+
export { errorResponse, listResponse, okResponse, } from './api-response.js';
|
|
5
5
|
export { declaredDocumentShape } from './document-shape.js';
|
|
6
6
|
export { createDomainErrorResolver, defineErrorMap, errorEntry, } from './domain-error-resolver.js';
|
|
7
7
|
export { BASE_ERROR_CODES, errorDocumentSchema, JsonApiError, toErrorDocument, toErrorObject, } from './errors/index.js';
|