@zeroxsolutions/response 0.14.5 → 0.14.6
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 +66 -56
- package/README.md +14 -11
- package/dist/api-response.d.ts +4 -3
- package/dist/api-response.d.ts.map +1 -1
- package/dist/document.d.ts +13 -13
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +2 -2
- package/dist/resource.d.ts +13 -7
- package/dist/resource.d.ts.map +1 -1
- package/dist/resource.js +5 -2
- package/dist/serialize.d.ts +2 -2
- package/dist/serialize.d.ts.map +1 -1
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 0.14.6 (2026-10-21)
|
|
2
|
+
|
|
3
|
+
### 🚀 Features
|
|
4
|
+
|
|
5
|
+
- **response:** type a resource's data.id through a declared id schema ([3dd4f2c](https://github.com/zeroxsolutions/zeroxsolutions/commit/3dd4f2c))
|
|
6
|
+
|
|
7
|
+
### ❤️ Thank You
|
|
8
|
+
|
|
9
|
+
- luongvantuit
|
|
10
|
+
|
|
1
11
|
## 0.14.5 (2026-10-19)
|
|
2
12
|
|
|
3
13
|
### 🚀 Features
|
|
@@ -69,31 +79,31 @@
|
|
|
69
79
|
### 🚀 Features
|
|
70
80
|
|
|
71
81
|
- **response:** answer a created resource with its location ([e9c0086](https://github.com/zeroxsolutions/zeroxsolutions/commit/e9c0086))
|
|
72
|
-
- ⚠️
|
|
82
|
+
- ⚠️ **response:** refuse a declaration the standard's field rules forbid ([30e6b77](https://github.com/zeroxsolutions/zeroxsolutions/commit/30e6b77))
|
|
73
83
|
|
|
74
84
|
### 🩹 Fixes
|
|
75
85
|
|
|
76
|
-
- ⚠️
|
|
86
|
+
- ⚠️ **response:** walk a pipe's input when checking member names ([0949d22](https://github.com/zeroxsolutions/zeroxsolutions/commit/0949d22))
|
|
77
87
|
- **response:** match link types to their schemas ([0f7c79b](https://github.com/zeroxsolutions/zeroxsolutions/commit/0f7c79b))
|
|
78
|
-
- ⚠️
|
|
88
|
+
- ⚠️ **response:** refuse a resource id that is not a string ([57f60ab](https://github.com/zeroxsolutions/zeroxsolutions/commit/57f60ab))
|
|
79
89
|
- **response:** keep a primary resource out of included ([c38859f](https://github.com/zeroxsolutions/zeroxsolutions/commit/c38859f))
|
|
80
|
-
- ⚠️
|
|
81
|
-
- ⚠️
|
|
90
|
+
- ⚠️ **response:** read only the document members the standard defines ([fc5c51a](https://github.com/zeroxsolutions/zeroxsolutions/commit/fc5c51a))
|
|
91
|
+
- ⚠️ **response:** refuse an error object that carries no member ([7d888ed](https://github.com/zeroxsolutions/zeroxsolutions/commit/7d888ed))
|
|
82
92
|
|
|
83
|
-
### ⚠️
|
|
93
|
+
### ⚠️ Breaking Changes
|
|
84
94
|
|
|
85
|
-
- **response:** walk a pipe's input when checking member names
|
|
95
|
+
- **response:** walk a pipe's input when checking member names ([0949d22](https://github.com/zeroxsolutions/zeroxsolutions/commit/0949d22))
|
|
86
96
|
a nested attribute member name that breaks the
|
|
87
97
|
standard's member-name rule, and sits behind a .transform() or
|
|
88
98
|
.pipe(), now throws at jsonApiResource's own declaration where it
|
|
89
99
|
previously passed unchecked.
|
|
90
|
-
- **response:** refuse a declaration the standard's field rules forbid
|
|
100
|
+
- **response:** refuse a declaration the standard's field rules forbid ([30e6b77](https://github.com/zeroxsolutions/zeroxsolutions/commit/30e6b77))
|
|
91
101
|
jsonApiResource throws, and fails to compile, on a field named type or id, a name shared by an attribute and a relationship, an illegal member name, or a foreign-key attribute beside its relationship.
|
|
92
|
-
- **response:** refuse a resource id that is not a string
|
|
102
|
+
- **response:** refuse a resource id that is not a string ([57f60ab](https://github.com/zeroxsolutions/zeroxsolutions/commit/57f60ab))
|
|
93
103
|
Row['id'] is typed string, and serializing a row, embedded row or foreign key whose id is not a string throws TypeError.
|
|
94
|
-
- **response:** read only the document members the standard defines
|
|
104
|
+
- **response:** read only the document members the standard defines ([fc5c51a](https://github.com/zeroxsolutions/zeroxsolutions/commit/fc5c51a))
|
|
95
105
|
a data document carrying errors, an error document carrying data, and an empty relationship object are refused.
|
|
96
|
-
- **response:** refuse an error object that carries no member
|
|
106
|
+
- **response:** refuse an error object that carries no member ([7d888ed](https://github.com/zeroxsolutions/zeroxsolutions/commit/7d888ed))
|
|
97
107
|
toErrorDocument throws on an empty error object.
|
|
98
108
|
|
|
99
109
|
### ❤️ Thank You
|
|
@@ -105,28 +115,28 @@
|
|
|
105
115
|
|
|
106
116
|
### 🚀 Features
|
|
107
117
|
|
|
108
|
-
- ⚠️
|
|
109
|
-
- ⚠️
|
|
118
|
+
- ⚠️ **response:** type the fieldsets and include paths a document answers ([98bbb58](https://github.com/zeroxsolutions/zeroxsolutions/commit/98bbb58))
|
|
119
|
+
- ⚠️ **response:** keep a resource's type, attributes and relationships as literals ([738889e](https://github.com/zeroxsolutions/zeroxsolutions/commit/738889e))
|
|
110
120
|
|
|
111
121
|
### 🩹 Fixes
|
|
112
122
|
|
|
113
|
-
- ⚠️
|
|
123
|
+
- ⚠️ **response:** pin an include path stopping at a wide edge ([515a3e9](https://github.com/zeroxsolutions/zeroxsolutions/commit/515a3e9))
|
|
114
124
|
|
|
115
|
-
### ⚠️
|
|
125
|
+
### ⚠️ Breaking Changes
|
|
116
126
|
|
|
117
|
-
- **response:** pin an include path stopping at a wide edge
|
|
127
|
+
- **response:** pin an include path stopping at a wide edge ([515a3e9](https://github.com/zeroxsolutions/zeroxsolutions/commit/515a3e9))
|
|
118
128
|
jsonApiResource's type parameters moved from <A, C> to
|
|
119
129
|
<T, A, R, C>, so an explicit `jsonApiResource<typeof attrs, Ctx>` no
|
|
120
130
|
longer compiles; remove the type arguments and let inference type it.
|
|
121
131
|
The exported ResourceOptions<C> is now ResourceOptions<R>.
|
|
122
132
|
BREAKING CHANGE: an explicit toOne<Ctx> or toMany<Ctx> no longer
|
|
123
133
|
compiles; remove the type argument.
|
|
124
|
-
- **response:** type the fieldsets and include paths a document answers
|
|
134
|
+
- **response:** type the fieldsets and include paths a document answers ([98bbb58](https://github.com/zeroxsolutions/zeroxsolutions/commit/98bbb58))
|
|
125
135
|
declaredDocumentShape answers typed fieldsets and include
|
|
126
136
|
paths, walks at most three relationships by default, and answers a fieldset
|
|
127
137
|
only for a type a kept path reaches. DeclaredDocumentShape is removed;
|
|
128
138
|
TypedDocumentShape replaces it.
|
|
129
|
-
- **response:** keep a resource's type, attributes and relationships as literals
|
|
139
|
+
- **response:** keep a resource's type, attributes and relationships as literals ([738889e](https://github.com/zeroxsolutions/zeroxsolutions/commit/738889e))
|
|
130
140
|
toOne and toMany take the related resource as their first type
|
|
131
141
|
parameter and infer the loader context; a call passing the context explicitly,
|
|
132
142
|
toOne<Ctx>(...), no longer compiles and drops the explicit argument.
|
|
@@ -164,13 +174,13 @@
|
|
|
164
174
|
|
|
165
175
|
### 💅 Refactors
|
|
166
176
|
|
|
167
|
-
- ⚠️
|
|
168
|
-
- ⚠️
|
|
169
|
-
- ⚠️
|
|
177
|
+
- ⚠️ **response:** list the names the package root publishes ([7b8a95d](https://github.com/zeroxsolutions/zeroxsolutions/commit/7b8a95d))
|
|
178
|
+
- ⚠️ **response:** answer mapped errors with links and meta ([b78bc08](https://github.com/zeroxsolutions/zeroxsolutions/commit/b78bc08))
|
|
179
|
+
- ⚠️ **response:** render every member of a JSON:API error object ([ca0c551](https://github.com/zeroxsolutions/zeroxsolutions/commit/ca0c551))
|
|
170
180
|
|
|
171
|
-
### ⚠️
|
|
181
|
+
### ⚠️ Breaking Changes
|
|
172
182
|
|
|
173
|
-
- **response:** list the names the package root publishes
|
|
183
|
+
- **response:** list the names the package root publishes ([7b8a95d](https://github.com/zeroxsolutions/zeroxsolutions/commit/7b8a95d))
|
|
174
184
|
the root no longer exports `createSerializer`,
|
|
175
185
|
`serializeResource`, `serializeCollection`, `reachableResources`,
|
|
176
186
|
`resourceObjectSchema`, `resourceDocumentSchema`,
|
|
@@ -180,7 +190,7 @@
|
|
|
180
190
|
`errorObjectSchema`. Their inferred types stay listed. A resource's own
|
|
181
191
|
`document`, `collectionDocument`, `serialize` and `serializeMany` declare
|
|
182
192
|
and render its documents; the schema consts have no public replacement.
|
|
183
|
-
- **response:** answer mapped errors with links and meta
|
|
193
|
+
- **response:** answer mapped errors with links and meta ([b78bc08](https://github.com/zeroxsolutions/zeroxsolutions/commit/b78bc08))
|
|
184
194
|
`ErrorMeta` is `DomainErrorAnswer`, whose `code` is
|
|
185
195
|
required. `defineErrorMap` takes `DomainErrorEntry` objects, which
|
|
186
196
|
`errorEntry(type, answer)` builds, in place of `[type, meta]` tuples.
|
|
@@ -188,7 +198,7 @@
|
|
|
188
198
|
type argument. `UpstreamErrorMeta` is `UpstreamErrorAnswer`, and
|
|
189
199
|
`toUpstreamError(map, document, fallback)` is
|
|
190
200
|
`createUpstreamErrorTranslator(map, fallback)(document)`.
|
|
191
|
-
- **response:** render every member of a JSON:API error object
|
|
201
|
+
- **response:** render every member of a JSON:API error object ([ca0c551](https://github.com/zeroxsolutions/zeroxsolutions/commit/ca0c551))
|
|
192
202
|
`buildErrorDocument` is `toErrorDocument`, and the
|
|
193
203
|
document it renders carries `jsonapi: { version: '1.1' }`.
|
|
194
204
|
`ErrorCodeMeta` is `ErrorStatus`; `ErrorRegistry` and `ErrorLike` are
|
|
@@ -236,19 +246,19 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
236
246
|
|
|
237
247
|
### 🚀 Features
|
|
238
248
|
|
|
239
|
-
- ⚠️
|
|
249
|
+
- ⚠️ **server,jsonapi:** one surface, one error-code vocabulary ([32b4aed](https://github.com/zeroxsolutions/zeroxsolutions/commit/32b4aed))
|
|
240
250
|
|
|
241
251
|
### 💅 Refactors
|
|
242
252
|
|
|
243
|
-
- ⚠️
|
|
253
|
+
- ⚠️ **query,response:** drop the seams the second spelling paid for ([40f1bca](https://github.com/zeroxsolutions/zeroxsolutions/commit/40f1bca))
|
|
244
254
|
|
|
245
|
-
### ⚠️
|
|
255
|
+
### ⚠️ Breaking Changes
|
|
246
256
|
|
|
247
|
-
- **server,jsonapi:** one surface, one error-code vocabulary
|
|
257
|
+
- **server,jsonapi:** one surface, one error-code vocabulary ([32b4aed](https://github.com/zeroxsolutions/zeroxsolutions/commit/32b4aed))
|
|
248
258
|
createErrorHandler, createValidationHook and
|
|
249
259
|
jsonApiContentNegotiation take a required `namespace`; negotiateJsonApi takes it
|
|
250
260
|
as a third argument. Codes these mint are now `<namespace>.<name>`.
|
|
251
|
-
- **query,response:** drop the seams the second spelling paid for
|
|
261
|
+
- **query,response:** drop the seams the second spelling paid for ([40f1bca](https://github.com/zeroxsolutions/zeroxsolutions/commit/40f1bca))
|
|
252
262
|
@zeroxsolutions/query no longer exports CollectionQueryParser,
|
|
253
263
|
CollectionQueryRenderer, collectionLinksWith, collectionQueryParser, parseSort,
|
|
254
264
|
parseFields, parseInclude or parsePagination. collectionLinks and
|
|
@@ -264,11 +274,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
264
274
|
|
|
265
275
|
### 💅 Refactors
|
|
266
276
|
|
|
267
|
-
- ⚠️
|
|
277
|
+
- ⚠️ **query,response,server:** one wire spelling, flat exports ([5c57b3a](https://github.com/zeroxsolutions/zeroxsolutions/commit/5c57b3a))
|
|
268
278
|
|
|
269
|
-
### ⚠️
|
|
279
|
+
### ⚠️ Breaking Changes
|
|
270
280
|
|
|
271
|
-
- **query,response,server:** one wire spelling, flat exports
|
|
281
|
+
- **query,response,server:** one wire spelling, flat exports ([5c57b3a](https://github.com/zeroxsolutions/zeroxsolutions/commit/5c57b3a))
|
|
272
282
|
`@zeroxsolutions/response/http`, `@zeroxsolutions/query/http`
|
|
273
283
|
and `@zeroxsolutions/server/hono/http` are gone, and the surviving `/jsonapi`
|
|
274
284
|
and `/hono` subpaths move to the package root. Every import drops its subpath.
|
|
@@ -281,11 +291,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
281
291
|
|
|
282
292
|
### 💅 Refactors
|
|
283
293
|
|
|
284
|
-
- ⚠️
|
|
294
|
+
- ⚠️ **response:** key the upstream map by string, drop its builder ([d5c5e6b](https://github.com/zeroxsolutions/zeroxsolutions/commit/d5c5e6b))
|
|
285
295
|
|
|
286
|
-
### ⚠️
|
|
296
|
+
### ⚠️ Breaking Changes
|
|
287
297
|
|
|
288
|
-
- **response:** key the upstream map by string, drop its builder
|
|
298
|
+
- **response:** key the upstream map by string, drop its builder ([d5c5e6b](https://github.com/zeroxsolutions/zeroxsolutions/commit/d5c5e6b))
|
|
289
299
|
defineUpstreamErrorMap is gone from both spellings. Declare the
|
|
290
300
|
map as an object literal with `satisfies UpstreamErrorMap<UpstreamErrorMeta>`;
|
|
291
301
|
toUpstreamError takes it unchanged.
|
|
@@ -299,11 +309,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
299
309
|
|
|
300
310
|
### 💅 Refactors
|
|
301
311
|
|
|
302
|
-
- ⚠️
|
|
312
|
+
- ⚠️ **response:** move the Hono handlers out, translate upstream errors ([ce60636](https://github.com/zeroxsolutions/zeroxsolutions/commit/ce60636))
|
|
303
313
|
|
|
304
|
-
### ⚠️
|
|
314
|
+
### ⚠️ Breaking Changes
|
|
305
315
|
|
|
306
|
-
- **response:** move the Hono handlers out, translate upstream errors
|
|
316
|
+
- **response:** move the Hono handlers out, translate upstream errors ([ce60636](https://github.com/zeroxsolutions/zeroxsolutions/commit/ce60636))
|
|
307
317
|
the ./http/server and ./jsonapi/server subpaths are gone -
|
|
308
318
|
createErrorHandler and createValidationHook are @zeroxsolutions/server/http
|
|
309
319
|
and @zeroxsolutions/server. Both remaining subpaths resolve to
|
|
@@ -351,11 +361,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
351
361
|
|
|
352
362
|
### 🚀 Features
|
|
353
363
|
|
|
354
|
-
- ⚠️
|
|
364
|
+
- ⚠️ **response:** type /jsonapi's documents off the resource's attributes ([1dcf923](https://github.com/zeroxsolutions/zeroxsolutions/commit/1dcf923))
|
|
355
365
|
|
|
356
|
-
### ⚠️
|
|
366
|
+
### ⚠️ Breaking Changes
|
|
357
367
|
|
|
358
|
-
- **response:** type /jsonapi's documents off the resource's attributes
|
|
368
|
+
- **response:** type /jsonapi's documents off the resource's attributes ([1dcf923](https://github.com/zeroxsolutions/zeroxsolutions/commit/1dcf923))
|
|
359
369
|
`serialize` returns `ResourceDocument<A>` and `serializeMany`
|
|
360
370
|
`CollectionDocument<A>` instead of `Row`, and `okResponse`/`listResponse` are
|
|
361
371
|
generic in the resource's attribute schema.
|
|
@@ -379,11 +389,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
379
389
|
|
|
380
390
|
### 🚀 Features
|
|
381
391
|
|
|
382
|
-
- ⚠️
|
|
392
|
+
- ⚠️ **response:** bring /jsonapi's server half up to /http's ([a40fed4](https://github.com/zeroxsolutions/zeroxsolutions/commit/a40fed4))
|
|
383
393
|
|
|
384
|
-
### ⚠️
|
|
394
|
+
### ⚠️ Breaking Changes
|
|
385
395
|
|
|
386
|
-
- **response:** bring /jsonapi's server half up to /http's
|
|
396
|
+
- **response:** bring /jsonapi's server half up to /http's ([a40fed4](https://github.com/zeroxsolutions/zeroxsolutions/commit/a40fed4))
|
|
387
397
|
/jsonapi/server's createErrorHandler now requires `category`.
|
|
388
398
|
|
|
389
399
|
### ❤️ Thank You
|
|
@@ -395,19 +405,19 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
395
405
|
|
|
396
406
|
### 🚀 Features
|
|
397
407
|
|
|
398
|
-
- ⚠️
|
|
399
|
-
- ⚠️
|
|
408
|
+
- ⚠️ **response:** declare each JSON:API resource once ([748e006](https://github.com/zeroxsolutions/zeroxsolutions/commit/748e006))
|
|
409
|
+
- ⚠️ **db:** let each table declare its own id column ([eca4aca](https://github.com/zeroxsolutions/zeroxsolutions/commit/eca4aca))
|
|
400
410
|
|
|
401
|
-
### ⚠️
|
|
411
|
+
### ⚠️ Breaking Changes
|
|
402
412
|
|
|
403
|
-
- **response:** declare each JSON:API resource once
|
|
413
|
+
- **response:** declare each JSON:API resource once ([748e006](https://github.com/zeroxsolutions/zeroxsolutions/commit/748e006))
|
|
404
414
|
`/jsonapi`'s `okResponse` / `listResponse` take a resource
|
|
405
415
|
declaration instead of `(type, attributesSchema)`. `resourceDocument`,
|
|
406
416
|
`resourceCollectionDocument`, `applyFields`, `mergeIncluded`,
|
|
407
417
|
`documentResources` and `ResourceObject` are removed - the descriptor covers
|
|
408
418
|
them. `/jsonapi/server` now exports only `createErrorHandler`; the serializer
|
|
409
419
|
entry points moved behind the descriptor.
|
|
410
|
-
- **db:** let each table declare its own id column
|
|
420
|
+
- **db:** let each table declare its own id column ([eca4aca](https://github.com/zeroxsolutions/zeroxsolutions/commit/eca4aca))
|
|
411
421
|
`baseTable` is removed - take `idColumn` and spread
|
|
412
422
|
`timestamps`. `defaultIndexedBaseColumns` is now `timestampIndexes` and
|
|
413
423
|
`BaseTableShape` is `TimestampColumns`; both were named for the removed concept.
|
|
@@ -421,11 +431,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
421
431
|
|
|
422
432
|
### 🚀 Features
|
|
423
433
|
|
|
424
|
-
- ⚠️
|
|
434
|
+
- ⚠️ **response:** take the isolate's own logging category, not the library's ([3409798](https://github.com/zeroxsolutions/zeroxsolutions/commit/3409798))
|
|
425
435
|
|
|
426
|
-
### ⚠️
|
|
436
|
+
### ⚠️ Breaking Changes
|
|
427
437
|
|
|
428
|
-
- **response:** take the isolate's own logging category, not the library's
|
|
438
|
+
- **response:** take the isolate's own logging category, not the library's ([3409798](https://github.com/zeroxsolutions/zeroxsolutions/commit/3409798))
|
|
429
439
|
`createErrorHandler` takes one options object and `category` is
|
|
430
440
|
required - `createErrorHandler(errors)` becomes
|
|
431
441
|
`createErrorHandler({ category, errors })`. Required rather than defaulted
|
|
@@ -440,11 +450,11 @@ Repackaged only, no source change: the previous tarball still carried the pre-fl
|
|
|
440
450
|
|
|
441
451
|
### 🚀 Features
|
|
442
452
|
|
|
443
|
-
- ⚠️
|
|
453
|
+
- ⚠️ **response:** write the unhandled 500 through logtape, under the caller's id ([fdcb75b](https://github.com/zeroxsolutions/zeroxsolutions/commit/fdcb75b))
|
|
444
454
|
|
|
445
|
-
### ⚠️
|
|
455
|
+
### ⚠️ Breaking Changes
|
|
446
456
|
|
|
447
|
-
- **response:** write the unhandled 500 through logtape, under the caller's id
|
|
457
|
+
- **response:** write the unhandled 500 through logtape, under the caller's id ([fdcb75b](https://github.com/zeroxsolutions/zeroxsolutions/commit/fdcb75b))
|
|
448
458
|
`@logtape/logtape` is a new peer of `./http/server`, and the
|
|
449
459
|
unhandled-500 line is silent in an isolate that never calls `configureSync`.
|
|
450
460
|
It previously always reached stdout.
|
package/README.md
CHANGED
|
@@ -67,8 +67,8 @@ them, and the serializer calls that loader when a request includes it. Nothing c
|
|
|
67
67
|
export const trips = jsonApiResource('trips', tripAttributesSchema, {
|
|
68
68
|
relationships: {
|
|
69
69
|
place: toOne(
|
|
70
|
-
() => places,
|
|
71
|
-
(row) => row.placeId,
|
|
70
|
+
() => places, // the resource the loaded rows are published as
|
|
71
|
+
(row) => row.placeId, // beside a loader this reads the ID off the row, not the row
|
|
72
72
|
{ load: (ids, context: TripDocumentContext) => context.catalogue.places.byIds(ids) },
|
|
73
73
|
),
|
|
74
74
|
},
|
|
@@ -83,11 +83,11 @@ deduplicated and in no order, so a page of fifty trips costs one call upstream r
|
|
|
83
83
|
called only where the request's `include` names the relationship: a document that includes nothing makes
|
|
84
84
|
no call at all, and still publishes the identifier, which is the key its own row carried.
|
|
85
85
|
|
|
86
|
-
| The loader
|
|
87
|
-
|
|
|
88
|
-
| answers a row for an id
|
|
89
|
-
| answers no row for an id it was given | that identifier, and nothing under `included`
|
|
90
|
-
| throws
|
|
86
|
+
| The loader | What the document carries |
|
|
87
|
+
| ------------------------------------- | --------------------------------------------------------------------- |
|
|
88
|
+
| answers a row for an id | that identifier, and the row under `included` |
|
|
89
|
+
| answers no row for an id it was given | that identifier, and nothing under `included` |
|
|
90
|
+
| throws | nothing; the failure comes out of `serialize` for the route to answer |
|
|
91
91
|
|
|
92
92
|
An id with no row back is how a row this caller may not see stays out of the document. Dropping the
|
|
93
93
|
identifier with it would tell the client the trip has no place, which the row it was read off does not
|
|
@@ -117,7 +117,7 @@ export const academicsErrors = defineErrorMap([
|
|
|
117
117
|
status: 409,
|
|
118
118
|
title: 'Conflict',
|
|
119
119
|
code: 'academics.class.full',
|
|
120
|
-
meta: (error) => ({ capacity: error.capacity }),
|
|
120
|
+
meta: (error) => ({ capacity: error.capacity }), // `capacity` is typed off ClassFull
|
|
121
121
|
}),
|
|
122
122
|
]);
|
|
123
123
|
```
|
|
@@ -148,7 +148,7 @@ import { createErrorHandler } from '@zeroxsolutions/server';
|
|
|
148
148
|
|
|
149
149
|
app.onError(
|
|
150
150
|
createErrorHandler({
|
|
151
|
-
namespace: 'academics',
|
|
151
|
+
namespace: 'academics', // every code THESE handlers mint carries it, so one surface has one vocabulary
|
|
152
152
|
category: ['academics', 'http'],
|
|
153
153
|
resolve: createDomainErrorResolver(academicsErrors),
|
|
154
154
|
authenticationChallenge: 'Bearer',
|
|
@@ -213,13 +213,16 @@ export const PLACE_UPSTREAM_ERRORS = {
|
|
|
213
213
|
// the return type is spelled: a callback in an object checked by `satisfies` alone is not a typed function
|
|
214
214
|
// expression to @typescript-eslint/explicit-function-return-type
|
|
215
215
|
meta: (upstream): Meta | undefined => {
|
|
216
|
-
const parsed = placeFullMetaSchema.safeParse(upstream);
|
|
216
|
+
const parsed = placeFullMetaSchema.safeParse(upstream); // what the service promises, and nothing else
|
|
217
217
|
return parsed.success ? parsed.data : undefined;
|
|
218
218
|
},
|
|
219
219
|
},
|
|
220
220
|
} satisfies UpstreamErrorMap;
|
|
221
221
|
|
|
222
|
-
export const translatePlaceUpstreamError = createUpstreamErrorTranslator(
|
|
222
|
+
export const translatePlaceUpstreamError = createUpstreamErrorTranslator(
|
|
223
|
+
PLACE_UPSTREAM_ERRORS,
|
|
224
|
+
PLACE_UPSTREAM_FALLBACK,
|
|
225
|
+
);
|
|
223
226
|
```
|
|
224
227
|
|
|
225
228
|
A route throws what the translator returns, so the one `onError` renders it like every other failure:
|
package/dist/api-response.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type CollectionDocument, type ResourceDocument } from './document.js';
|
|
|
3
3
|
import { errorDocumentSchema } from './errors/index.js';
|
|
4
4
|
import { JSON_API_MEDIA_TYPE } from './media-type.js';
|
|
5
5
|
import type { Meta, PaginationLinks } from './primitives.js';
|
|
6
|
+
import type { RelationshipDef } from './relationship.js';
|
|
6
7
|
import type { JsonApiResource } from './resource.js';
|
|
7
8
|
/**
|
|
8
9
|
* An OpenAPI response object for this spelling - one media type, one schema, and the `Retry-After` a
|
|
@@ -45,7 +46,7 @@ export declare function errorResponse(description: string, options?: {
|
|
|
45
46
|
retryAfterSeconds: number;
|
|
46
47
|
}): JsonApiResponse<typeof errorDocumentSchema>;
|
|
47
48
|
/** The response object for a single resource, off the resource's own declaration. */
|
|
48
|
-
export declare function okResponse<A extends ZodObject, C = unknown>(description: string, resource: JsonApiResource<A, C>): JsonApiResponse<ZodType<ResourceDocument<output<A
|
|
49
|
+
export declare function okResponse<A extends ZodObject, C = unknown, I extends string = string>(description: string, resource: JsonApiResource<A, C, string, Readonly<Record<string, RelationshipDef<C>>>, I>): JsonApiResponse<ZodType<ResourceDocument<output<A>, I>>>;
|
|
49
50
|
/**
|
|
50
51
|
* The response object for a collection, off the resource's own declaration.
|
|
51
52
|
*
|
|
@@ -53,8 +54,8 @@ export declare function okResponse<A extends ZodObject, C = unknown>(description
|
|
|
53
54
|
* as required and typed, so a client reads it without narrowing; one left out stays the standard's
|
|
54
55
|
* optional, free-form member.
|
|
55
56
|
*/
|
|
56
|
-
export declare function listResponse<A extends ZodObject, C = unknown, M extends ZodType<Meta> = never, L extends ZodType<PaginationLinks> = never>(description: string, resource: JsonApiResource<A, C>, members?: {
|
|
57
|
+
export declare function listResponse<A extends ZodObject, C = unknown, M extends ZodType<Meta> = never, L extends ZodType<PaginationLinks> = never, I extends string = string>(description: string, resource: JsonApiResource<A, C, string, Readonly<Record<string, RelationshipDef<C>>>, I>, members?: {
|
|
57
58
|
meta?: M;
|
|
58
59
|
links?: L;
|
|
59
|
-
}): JsonApiResponse<ZodType<CollectionDocument<output<A>, output<M>, output<L
|
|
60
|
+
}): JsonApiResponse<ZodType<CollectionDocument<output<A>, output<M>, output<L>, I>>>;
|
|
60
61
|
//# sourceMappingURL=api-response.d.ts.map
|
|
@@ -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,EAA4B,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7D,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,
|
|
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,EAA4B,KAAK,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,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,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,EACpF,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GACvF,eAAe,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,CAAC,SAAS,SAAS,EACnB,CAAC,GAAG,OAAO,EACX,CAAC,SAAS,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,EAC/B,CAAC,SAAS,OAAO,CAAC,eAAe,CAAC,GAAG,KAAK,EAC1C,CAAC,SAAS,MAAM,GAAG,MAAM,EAEzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EACxF,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,CAAC,CAAA;CAAO,GACpC,eAAe,CAAC,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAQlF"}
|
package/dist/document.d.ts
CHANGED
|
@@ -7,18 +7,18 @@ export interface Relationship {
|
|
|
7
7
|
links?: RelationshipLinks;
|
|
8
8
|
meta?: Meta;
|
|
9
9
|
}
|
|
10
|
-
/** A resource object, with `attributes` carrying the declared attribute type. */
|
|
11
|
-
export interface ResourceObject<A> {
|
|
10
|
+
/** A resource object, with `attributes` carrying the declared attribute type and `id` the declared id type. */
|
|
11
|
+
export interface ResourceObject<A, I extends string = string> {
|
|
12
12
|
type: string;
|
|
13
|
-
id:
|
|
13
|
+
id: I;
|
|
14
14
|
attributes: A;
|
|
15
15
|
relationships?: Record<string, Relationship>;
|
|
16
16
|
links?: ResourceLinks;
|
|
17
17
|
meta?: Meta;
|
|
18
18
|
}
|
|
19
19
|
/** A single-resource document. `included` holds other resource types, so its attributes stay unknown. */
|
|
20
|
-
export interface ResourceDocument<A> {
|
|
21
|
-
data: ResourceObject<A>;
|
|
20
|
+
export interface ResourceDocument<A, I extends string = string> {
|
|
21
|
+
data: ResourceObject<A, I>;
|
|
22
22
|
included?: ResourceObject<unknown>[];
|
|
23
23
|
links?: TopLevelLinks;
|
|
24
24
|
meta?: Meta;
|
|
@@ -38,8 +38,8 @@ type CollectionMember<K extends 'links' | 'meta', Declared, Loose> = [Declared]
|
|
|
38
38
|
*
|
|
39
39
|
* `M` and `L` are the `meta` and `links` a route declared, `never` where it declared none.
|
|
40
40
|
*/
|
|
41
|
-
export type CollectionDocument<A, M = never, L = never> = {
|
|
42
|
-
data: ResourceObject<A>[];
|
|
41
|
+
export type CollectionDocument<A, M = never, L = never, I extends string = string> = {
|
|
42
|
+
data: ResourceObject<A, I>[];
|
|
43
43
|
included?: ResourceObject<unknown>[];
|
|
44
44
|
jsonapi?: JsonApiObject;
|
|
45
45
|
} & CollectionMember<'links', L, PaginationLinks> & CollectionMember<'meta', M, Meta>;
|
|
@@ -50,7 +50,7 @@ export type CollectionDocument<A, M = never, L = never> = {
|
|
|
50
50
|
* Tuple-wrapped so it does not distribute: extras that carry `meta` on one branch of a union and not the
|
|
51
51
|
* other may send none, and must not type it as present.
|
|
52
52
|
*/
|
|
53
|
-
export type CollectionDocumentFor<A, X> = CollectionDocument<A, [
|
|
53
|
+
export type CollectionDocumentFor<A, X, I extends string = string> = CollectionDocument<A, [
|
|
54
54
|
X
|
|
55
55
|
] extends [{
|
|
56
56
|
meta: infer M;
|
|
@@ -58,14 +58,14 @@ export type CollectionDocumentFor<A, X> = CollectionDocument<A, [
|
|
|
58
58
|
X
|
|
59
59
|
] extends [{
|
|
60
60
|
links: infer L;
|
|
61
|
-
}] ? L : never>;
|
|
61
|
+
}] ? L : never, I>;
|
|
62
62
|
/**
|
|
63
63
|
* Wraps `attributes` into a resource object - `{ type, id, attributes?, relationships?, links?, meta? }`.
|
|
64
64
|
*
|
|
65
65
|
* `attributes` parses as absent here, unlike {@link ResourceObject}'s own required member: this schema
|
|
66
66
|
* also validates a document read off another server, which may publish a resource with none.
|
|
67
67
|
*/
|
|
68
|
-
export declare function resourceObjectSchema<C>(type: string, attributes: ZodObject, relationships?: Readonly<Record<string, RelationshipDef<C
|
|
68
|
+
export declare function resourceObjectSchema<C>(type: string, attributes: ZodObject, relationships?: Readonly<Record<string, RelationshipDef<C>>>, id?: ZodType<string, string>): ZodType;
|
|
69
69
|
/**
|
|
70
70
|
* The document for a SINGLE resource - `{ data, included?, links?, meta?, jsonapi? }`.
|
|
71
71
|
*
|
|
@@ -76,16 +76,16 @@ export declare function resourceObjectSchema<C>(type: string, attributes: ZodObj
|
|
|
76
76
|
* Strict at the top level: the standard forbids any top-level member beyond these (extension members
|
|
77
77
|
* aside), which is what refuses a `data` document that also carries `errors`.
|
|
78
78
|
*/
|
|
79
|
-
export declare function resourceDocumentSchema<A = unknown, C = unknown>(root: RelatedResource<C>): ZodType<ResourceDocument<A>>;
|
|
79
|
+
export declare function resourceDocumentSchema<A = unknown, C = unknown, I extends string = string>(root: RelatedResource<C>): ZodType<ResourceDocument<A, I>>;
|
|
80
80
|
/**
|
|
81
81
|
* The document for a COLLECTION - the same members, with `data` an array and paginated `links`.
|
|
82
82
|
*
|
|
83
83
|
* A member in `members` replaces the standard's optional one, so the route that declared it publishes it
|
|
84
84
|
* as required. Strict at the top level for the same reason as {@link resourceDocumentSchema}.
|
|
85
85
|
*/
|
|
86
|
-
export declare function collectionDocumentSchema<A = unknown, C = unknown, M = never, L = never>(root: RelatedResource<C>, members?: {
|
|
86
|
+
export declare function collectionDocumentSchema<A = unknown, C = unknown, M = never, L = never, I extends string = string>(root: RelatedResource<C>, members?: {
|
|
87
87
|
meta?: ZodType;
|
|
88
88
|
links?: ZodType;
|
|
89
|
-
}): ZodType<CollectionDocument<A, M, L>>;
|
|
89
|
+
}): ZodType<CollectionDocument<A, M, L, I>>;
|
|
90
90
|
export {};
|
|
91
91
|
//# sourceMappingURL=document.d.ts.map
|
package/dist/document.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9C,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,IAAI,EACT,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAA2C,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAExH,4FAA4F;AAC5F,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,kBAAkB,GAAG,kBAAkB,EAAE,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,IAAI,CAAC,EAAE,IAAI,CAAC;CACb;AAED
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"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"}
|
package/dist/document.js
CHANGED
|
@@ -7,11 +7,11 @@ import { relationshipsSchema, reachableResources } from './relationship.js';
|
|
|
7
7
|
* `attributes` parses as absent here, unlike {@link ResourceObject}'s own required member: this schema
|
|
8
8
|
* also validates a document read off another server, which may publish a resource with none.
|
|
9
9
|
*/
|
|
10
|
-
export function resourceObjectSchema(type, attributes, relationships = {}) {
|
|
10
|
+
export function resourceObjectSchema(type, attributes, relationships = {}, id = z.string()) {
|
|
11
11
|
const linkage = relationshipsSchema(relationships);
|
|
12
12
|
return z.object({
|
|
13
13
|
type: z.literal(type),
|
|
14
|
-
id
|
|
14
|
+
id,
|
|
15
15
|
attributes: attributes.optional(),
|
|
16
16
|
...(linkage ? { relationships: linkage.optional() } : {}),
|
|
17
17
|
links: resourceLinksSchema.optional(),
|
package/dist/resource.d.ts
CHANGED
|
@@ -5,9 +5,15 @@ import { type CollectionExtras, type RequestedDocumentShape, type Row } from './
|
|
|
5
5
|
/** The context every loader in a relationship map runs under. */
|
|
6
6
|
type ContextOfRelationships<R> = R[keyof R] extends RelationshipDef<infer C, any> ? C : unknown;
|
|
7
7
|
/** Per-entity overrides for a resource declaration. */
|
|
8
|
-
export interface ResourceOptions<R> {
|
|
8
|
+
export interface ResourceOptions<R, I extends string = string> {
|
|
9
9
|
/** Relationships this resource declares, keyed by the member name they take in `relationships`. */
|
|
10
10
|
relationships?: R;
|
|
11
|
+
/**
|
|
12
|
+
* The id as the wire carries it, which types `data.id` in every document and the `id` of every row serialized. Pass
|
|
13
|
+
* the wire half of a codec (a TypeID codec's `.in`), never the codec: a client reading the document back keeps the id
|
|
14
|
+
* it was sent. Omitted, the id is any text.
|
|
15
|
+
*/
|
|
16
|
+
id?: ZodType<I, I>;
|
|
11
17
|
}
|
|
12
18
|
/**
|
|
13
19
|
* One resource type declared once: the schemas a route answers with, and the serializer that produces
|
|
@@ -20,14 +26,14 @@ export interface ResourceOptions<R> {
|
|
|
20
26
|
* `C` is the context its loaders are called with, inferred from the relationships it declares and from
|
|
21
27
|
* the resources they point at, so every resource in one document's graph loads under one context.
|
|
22
28
|
*/
|
|
23
|
-
export interface JsonApiResource<A extends ZodObject, C = unknown, T extends string = string, R extends Readonly<Record<string, RelationshipDef<any, any>>> = Readonly<Record<string, RelationshipDef<C
|
|
29
|
+
export interface JsonApiResource<A extends ZodObject, C = unknown, T extends string = string, R extends Readonly<Record<string, RelationshipDef<any, any>>> = Readonly<Record<string, RelationshipDef<C>>>, I extends string = string> extends RelatedResource<C> {
|
|
24
30
|
readonly type: T;
|
|
25
31
|
readonly attributes: A;
|
|
26
32
|
readonly relationships: R;
|
|
27
33
|
/** The single-resource document schema - `{ data, included?, links?, meta?, jsonapi? }`. */
|
|
28
|
-
readonly document: ZodType<ResourceDocument<output<A
|
|
34
|
+
readonly document: ZodType<ResourceDocument<output<A>, I>>;
|
|
29
35
|
/** The collection document schema - the same members with `data` an array. */
|
|
30
|
-
readonly collectionDocument: ZodType<CollectionDocument<output<A
|
|
36
|
+
readonly collectionDocument: ZodType<CollectionDocument<output<A>, never, never, I>>;
|
|
31
37
|
/**
|
|
32
38
|
* Serializes one row into a single-resource document.
|
|
33
39
|
*
|
|
@@ -35,7 +41,7 @@ export interface JsonApiResource<A extends ZodObject, C = unknown, T extends str
|
|
|
35
41
|
* and an included relationship that declares a loader is loaded before the document is built
|
|
36
42
|
* @param context - what the loaders are given; the call takes it only where a loader is reachable
|
|
37
43
|
*/
|
|
38
|
-
serialize(row: Row
|
|
44
|
+
serialize(row: Row<I>, requested?: RequestedDocumentShape, ...context: LoadContextArguments<C>): Promise<ResourceDocument<output<A>, I>>;
|
|
39
45
|
/**
|
|
40
46
|
* Serializes rows into a collection document, merging in pagination `links` and `meta`.
|
|
41
47
|
*
|
|
@@ -43,7 +49,7 @@ export interface JsonApiResource<A extends ZodObject, C = unknown, T extends str
|
|
|
43
49
|
* declared with `listResponse`. A key that is neither `links` nor `meta` is refused, since the
|
|
44
50
|
* serializer drops it unsent.
|
|
45
51
|
*/
|
|
46
|
-
serializeMany<X extends CollectionExtras = Record<never, never>>(rows: Row[], extras?: X & Record<Exclude<keyof X, keyof CollectionExtras>, never>, requested?: RequestedDocumentShape, ...context: LoadContextArguments<C>): Promise<CollectionDocumentFor<output<A>, X>>;
|
|
52
|
+
serializeMany<X extends CollectionExtras = Record<never, never>>(rows: Row<I>[], extras?: X & Record<Exclude<keyof X, keyof CollectionExtras>, never>, requested?: RequestedDocumentShape, ...context: LoadContextArguments<C>): Promise<CollectionDocumentFor<output<A>, X, I>>;
|
|
47
53
|
}
|
|
48
54
|
/** A relationship map's own names, and none where the map is the empty default. */
|
|
49
55
|
type RelationshipName<R> = string extends keyof R ? never : keyof R & string;
|
|
@@ -55,6 +61,6 @@ type FieldNamespace<A extends ZodObject, R> = [
|
|
|
55
61
|
(keyof A['shape'] & string & ('type' | 'id' | RelationshipName<R>)) | (RelationshipName<R> & ('type' | 'id'))
|
|
56
62
|
] extends [never] ? unknown : never;
|
|
57
63
|
/** Declares a JSON:API resource type - its `type`, the schema of its `attributes`, and its relationships. */
|
|
58
|
-
export declare function jsonApiResource<const T extends string, A extends ZodObject, const R extends Readonly<Record<string, RelationshipDef<any, any>>> = Readonly<Record<string, never>>, C = ContextOfRelationships<R
|
|
64
|
+
export declare function jsonApiResource<const T extends string, A extends ZodObject, const R extends Readonly<Record<string, RelationshipDef<any, any>>> = Readonly<Record<string, never>>, C = ContextOfRelationships<R>, const I extends string = string>(type: T, attributes: A & FieldNamespace<A, R>, options?: ResourceOptions<R, I>): JsonApiResource<A, C, T, R, I>;
|
|
59
65
|
export {};
|
|
60
66
|
//# sourceMappingURL=resource.d.ts.map
|
package/dist/resource.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACtD,OAAO,EAIL,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACtB,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAe,KAAK,oBAAoB,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACvH,OAAO,EAKL,KAAK,gBAAgB,EAErB,KAAK,sBAAsB,EAE3B,KAAK,GAAG,EACT,MAAM,gBAAgB,CAAC;AAExB,iEAAiE;AAEjE,KAAK,sBAAsB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,eAAe,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC;AAEhG,uDAAuD;AACvD,MAAM,WAAW,eAAe,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
|
package/dist/resource.js
CHANGED
|
@@ -41,7 +41,10 @@ function membersOf(schema) {
|
|
|
41
41
|
/** Every member name an attribute schema declares, at every depth. */
|
|
42
42
|
function memberNames(schema) {
|
|
43
43
|
return membersOf(schema).flatMap((member) => member instanceof z.ZodObject
|
|
44
|
-
? Object.entries(member.shape).flatMap(([name, inner]) => [
|
|
44
|
+
? Object.entries(member.shape).flatMap(([name, inner]) => [
|
|
45
|
+
name,
|
|
46
|
+
...memberNames(inner),
|
|
47
|
+
])
|
|
45
48
|
: []);
|
|
46
49
|
}
|
|
47
50
|
/**
|
|
@@ -89,7 +92,7 @@ export function jsonApiResource(type, attributes, options = {}) {
|
|
|
89
92
|
attributes,
|
|
90
93
|
relationships,
|
|
91
94
|
get resourceObject() {
|
|
92
|
-
return (object ??= resourceObjectSchema(type, attributes, relationships));
|
|
95
|
+
return (object ??= resourceObjectSchema(type, attributes, relationships, options.id));
|
|
93
96
|
},
|
|
94
97
|
get document() {
|
|
95
98
|
return (one ??= resourceDocumentSchema(resource));
|
package/dist/serialize.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Serializer, type SerializerOptions } from 'ts-japi';
|
|
2
2
|
import type { PaginationLinks } from './primitives.js';
|
|
3
3
|
/** One row as a serializer hands it over. Its `id` is the resource id, which the standard makes a string. */
|
|
4
|
-
export interface Row {
|
|
5
|
-
id:
|
|
4
|
+
export interface Row<I extends string = string> {
|
|
5
|
+
id: I;
|
|
6
6
|
[member: string]: unknown;
|
|
7
7
|
}
|
|
8
8
|
/**
|
package/dist/serialize.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,UAAU,EAAqB,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,6GAA6G;AAC7G,MAAM,WAAW,GAAG;
|
|
1
|
+
{"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../src/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,UAAU,EAAqB,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEzF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvD,6GAA6G;AAC7G,MAAM,WAAW,GAAG,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAC5C,EAAE,EAAE,CAAC,CAAC;IACN,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,IAAI,CAK5D;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;AAEvE,sCAAsC;AACtC,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;AAEjD,KAAK,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;AAExD;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACrC,mFAAmF;IACnF,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;IACrD,mEAAmE;IACnE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAgCD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,gBAAgB,EAC1B,SAAS,CAAC,EAAE,sBAAsB,GACjC,kBAAkB,CAgBpB;AAED,2EAA2E;AAC3E,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AA8CD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,kBAAkB,EAC9B,IAAI,EAAE,GAAG,EACT,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAElC;AAED,0GAA0G;AAC1G,wBAAsB,mBAAmB,CACvC,UAAU,EAAE,kBAAkB,EAC9B,KAAK,EAAE,GAAG,EAAE,EACZ,MAAM,GAAE,gBAAqB,EAC7B,MAAM,CAAC,EAAE,UAAU,GAClB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAMlC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zeroxsolutions/response",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -30,7 +30,10 @@
|
|
|
30
30
|
"zod": "^4.3.6"
|
|
31
31
|
},
|
|
32
32
|
"nx": {
|
|
33
|
-
"name": "@zeroxsolutions/response"
|
|
33
|
+
"name": "@zeroxsolutions/response",
|
|
34
|
+
"targets": {
|
|
35
|
+
"lint-deps": {}
|
|
36
|
+
}
|
|
34
37
|
},
|
|
35
38
|
"main": "./dist/index.js",
|
|
36
39
|
"module": "./dist/index.js",
|