@johntalton/http-core 1.0.7 → 1.1.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@johntalton/http-core",
3
3
  "type": "module",
4
- "version": "1.0.7",
4
+ "version": "1.1.0",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": "./src/index.js"
@@ -16,7 +16,7 @@
16
16
  "lint": "biome check"
17
17
  },
18
18
  "dependencies": {
19
- "@johntalton/http-util": "^6.1.0",
19
+ "@johntalton/http-util": "^7.0.1",
20
20
  "@johntalton/sse-util": "^1.0.0"
21
21
  },
22
22
  "devDependencies": {
package/src/epilogue.js CHANGED
@@ -52,12 +52,14 @@ export function epilogue(state) {
52
52
  switch(type) {
53
53
  //
54
54
  case 'trace': { Response.trace(stream, state.method, state.url, state.headers, meta) } break
55
+ // case 'im-a-teapot': { Response.imATeapot(stream, meta) } break
55
56
  //
56
- case 'preflight': { Response.preflight(stream, state.methods, state.supportedQueryTypes, undefined, meta) } break
57
- case 'no-content': { Response.noContent(stream, state.etag, state.lastModified, meta)} break
58
57
  // case 'accepted': { Response.accepted(stream, meta) } break
59
- case 'created': { Response.created(stream, new URL(state.location, meta.origin), state.etag, state.lastModified, meta) } break
60
- case 'not-modified': { Response.notModified(stream, state.etag, state.lastModified, state.age, state.cacheControl ?? {}, meta) } break
58
+ case 'created': { Response.created(stream, new URL(state.location, meta.origin), { etag: state.etag, lastModified: state.lastModified }, meta) } break
59
+ case 'preflight': { Response.preflight(stream, { supportedMethods: state.methods, supportedQueryTypes: state.supportedQueryTypes, acceptRanges: undefined }, meta) } break
60
+ case 'no-content': { Response.noContent(stream, { etag: state.etag, lastModified: state.lastModified }, meta)} break
61
+ case 'not-modified': { Response.notModified(stream, { etag: state.etag, lastModified: state.lastModified, age: state.age, cacheControl: state.cacheControl ?? {} }, meta) } break
62
+ case 'found': { Response.found(stream, state.location, meta) } break
61
63
 
62
64
  //
63
65
  // case 'multiple-choices': { Response.multipleChoices(stream, meta) } break
@@ -69,21 +71,23 @@ export function epilogue(state) {
69
71
 
70
72
  //
71
73
  case '404': { Response.notFound(stream, state.message, meta) } break
74
+ // case 'bad-request': { Response.badRequest(stream, meta) } break
72
75
  case 'conflict': { Response.conflict(stream, meta) } break
73
- case 'not-allowed': { Response.notAllowed(stream, state.methods, meta) } break
74
- case 'not-acceptable': { Response.notAcceptable(stream, state.acceptableMediaTypes ?? [], meta)} break
75
- case 'unsupported-media': { Response.unsupportedMediaType(stream, state.acceptableMediaTypes, state.supportedQueryTypes, meta) } break
76
- case 'unprocessable': { Response.unprocessable(stream, meta) } break
77
- case 'precondition-failed': { Response.preconditionFailed(stream, state.etag, state.lastModified, meta) } break
78
- case 'not-satisfiable': { Response.rangeNotSatisfiable(stream, { size: state.contentLength }, meta) } break
79
76
  case 'content-too-large': { Response.contentTooLarge(stream, meta) } break
80
- case 'insufficient-storage': { Response.insufficientStorage(stream, meta) } break
81
- case 'too-many-requests': { Response.tooManyRequests(stream, state.limit, state.policies, meta) } break
82
- case 'unauthorized': { Response.unauthorized(stream, state.challenge, meta) } break
83
77
  case 'forbidden': { Response.forbidden(stream, meta) } break
84
- case 'unavailable': { Response.unavailable(stream, state.message, state.retryAfter, meta)} break
85
- case 'not-implemented': { Response.notImplemented(stream, state.message, meta)} break
78
+ case 'not-acceptable': { Response.notAcceptable(stream, { supportedTypes: state.acceptableMediaTypes ?? [] }, meta) } break
79
+ case 'not-allowed': { Response.notAllowed(stream, { supportedMethods: state.methods }, meta) } break
80
+ // case 'payment-required': {} break
81
+ case 'precondition-failed': { Response.preconditionFailed(stream, { etag: state.etag, lastModified: state.lastModified }, meta) } break
82
+ case 'not-satisfiable': { Response.rangeNotSatisfiable(stream, { rangeDirective: { size: state.contentLength } }, meta) } break
86
83
  case 'timeout': { Response.timeout(stream, meta) } break
84
+ case 'too-many-requests': { Response.tooManyRequests(stream, { limitInfo: state.limit, policies: state.policies }, meta) } break
85
+ case 'unauthorized': { Response.unauthorized(stream, state.challenge, meta) } break
86
+ case 'unprocessable': { Response.unprocessable(stream, meta) } break
87
+ case 'unsupported-media': { Response.unsupportedMediaType(stream, { acceptableMediaType: state.acceptableMediaTypes, supportedQueryTypes: state.supportedQueryTypes }, meta) } break
88
+ case 'insufficient-storage': { Response.insufficientStorage(stream, meta) } break
89
+ case 'not-implemented': { Response.notImplemented(stream, state.message, meta) } break
90
+ case 'unavailable': { Response.unavailable(stream, state.message, { retryAfter: state.retryAfter }, meta) } break
87
91
 
88
92
  //
89
93
  case 'sse': {
@@ -91,22 +95,45 @@ export function epilogue(state) {
91
95
 
92
96
  Response.sse(stream, { ...meta, active, bom })
93
97
  if(active) { addSSEPortHandler(stream, port, state.streamId, state.shutdownSignal) }
94
- }
95
- break
98
+ } break
96
99
  case 'json': {
97
- const { obj, accept, etag, lastModified } = state
100
+ const { obj, accept, etag, lastModified, age, supportedQueryTypes } = state
98
101
 
99
102
  if(accept.type === MIME_TYPE_JSON) {
100
- Response.json(stream, obj, accept.encoding, etag, lastModified, state.age, state.cacheControl ?? {}, state.supportedQueryTypes, meta)
103
+ Response.json(stream, obj, { encoding: accept.encoding, etag, lastModified, age, cacheControl: state.cacheControl ?? {} }, { supportedQueryTypes }, meta)
101
104
  }
102
105
  else {
103
106
  // todo: but we did process the request - is that ok?
104
- Response.notAcceptable(stream, [ MIME_TYPE_JSON ], meta)
107
+ Response.notAcceptable(stream, { supportedTypes: [ MIME_TYPE_JSON ] }, meta)
105
108
  }
106
- }
107
- break
108
- case 'partial-bytes': { Response.partialContent(stream, state.contentType, state.objs, state.contentLength, undefined, state.etag, state.lastModified, state.age, state.cacheControl ?? {}, meta) } break
109
- case 'bytes': { Response.bytes(stream, state.contentType, state.obj, state.contentLength, 'identity', state.etag, state.lastModified, state.age, state.cacheControl ?? {}, state.acceptRanges, meta) } break
109
+ } break
110
+ case 'partial-bytes': {
111
+ const { contentType, contentLength, etag, lastModified, age } = state
112
+
113
+ Response.partialContent(stream, state.objs, {
114
+ contentType,
115
+ contentLength,
116
+ encoding: undefined,
117
+ etag,
118
+ lastModified,
119
+ age,
120
+ cacheControl: state.cacheControl ?? {} }, meta)
121
+ } break
122
+ case 'bytes': {
123
+ const { contentType, contentLength, etag, lastModified, age, acceptRanges } = state
124
+
125
+ Response.bytes(stream, state.obj, {
126
+ contentType,
127
+ contentLength,
128
+ encoding: 'identity',
129
+ etag,
130
+ lastModified,
131
+ age,
132
+ cacheControl: state.cacheControl ?? {}
133
+ }, {
134
+ acceptRanges
135
+ }, meta)
136
+ } break
110
137
 
111
138
  //
112
139
  case 'error': {
package/src/index.js CHANGED
@@ -60,37 +60,45 @@ export const KNOWN_METHODS = [
60
60
 
61
61
  /** @typedef {'request'} RouteTypeRequest */
62
62
  /** @typedef {
63
- 'partial-bytes' |
64
- 'bytes' |
65
- 'json' |
66
- '404' |
67
- 'sse' |
68
- 'error' |
69
- 'preflight' |
70
- 'not-allowed' |
71
63
  'trace' |
64
+ 'im-a-teapot' |
65
+ 'accepted' |
72
66
  'created' |
73
- 'unsupported-media' |
67
+ 'preflight' |
68
+ 'no-content' |
74
69
  'not-modified' |
75
- 'precondition-failed' |
76
- 'unprocessable' |
77
- 'not-acceptable' |
78
- 'conflict' |
79
- 'not-implemented' |
80
- 'unavailable' |
81
- 'not-satisfiable' |
70
+ 'found' |
71
+
72
+ 'gone' |
73
+ 'moved-permanently' |
82
74
  'see-other' |
83
75
  'temporary-redirect' |
84
76
  'permanent-redirect' |
85
- 'moved-permanently' |
86
- 'gone' |
87
- 'no-content' |
77
+
78
+ '404' |
79
+ 'bad-request' |
80
+ 'conflict' |
88
81
  'content-too-large' |
89
- 'insufficient-storage' |
82
+ 'forbidden' |
83
+ 'not-acceptable' |
84
+ 'not-allowed' |
85
+ 'payment-required' |
86
+ 'precondition-failed' |
87
+ 'not-satisfiable' |
88
+ 'timeout' |
90
89
  'too-many-requests' |
91
90
  'unauthorized' |
92
- 'forbidden' |
93
- 'timeout'
91
+ 'unprocessable' |
92
+ 'unsupported-media' |
93
+ 'insufficient-storage' |
94
+ 'not-implemented' |
95
+ 'unavailable' |
96
+
97
+ 'sse' |
98
+ 'bytes' |
99
+ 'partial-bytes' |
100
+ 'json' |
101
+ 'error'
94
102
  } RouteType */
95
103
  /** @typedef {'GET'|'HEAD'|'POST'|'PUT'|'PATCH'|'OPTIONS'|'DELETE'|'TRACE'|'QUERY'} RouteMethod */
96
104
 
@@ -125,6 +133,22 @@ export const KNOWN_METHODS = [
125
133
  * @property {number|undefined} port
126
134
  */
127
135
 
136
+ /**
137
+ * @typedef {Object} RouteConditions
138
+ * @property {Array<EtagItem>} match
139
+ * @property {Array<EtagItem>} noneMatch
140
+ * @property {IMFFixDate|undefined} modifiedSince
141
+ * @property {IMFFixDate|undefined} unmodifiedSince
142
+ * @property {IMFFixDate|EtagItem|undefined} [range]
143
+ */
144
+
145
+ /**
146
+ * @typedef {Object} SecFetchMetadata
147
+ * @property {SecFetchSite|undefined} site
148
+ * @property {SecFetchMode|undefined} mode
149
+ * @property {SecFetchDest|undefined} dest
150
+ */
151
+
128
152
  /**
129
153
  * @typedef {Object} RouteRequestBase
130
154
  * @property {'request'} type
@@ -141,21 +165,20 @@ export const KNOWN_METHODS = [
141
165
  /** @typedef {RouteBase & RouteRequestBase} RouteRequest */
142
166
 
143
167
  /**
144
- * @typedef {Object} RouteErrorBase
145
- * @property {'error'} type
146
- * @property {string} cause
147
- * @property {Error|undefined} [error]
168
+ * @template T
169
+ * @typedef {[ T, ...T[] ]} NonEmptyArray
148
170
  */
149
- /** @typedef {RouteBase & RouteErrorBase } RouteError */
150
171
 
151
172
  /**
152
- * @typedef {Object} RouteNotAllowedBase
153
- * @property {'not-allowed'} type
154
- * @property {RouteMethod} method
155
- * @property {URL} url
156
- * @property {Array<RouteMethod>} methods
173
+ * @typedef {Object} PartialBytes
174
+ * @property {SendBody} obj
175
+ * @property {ContentRangeDirective} range
157
176
  */
158
- /** @typedef {RouteBase & RouteNotAllowedBase} RouteNotAllowed */
177
+
178
+
179
+
180
+
181
+
159
182
 
160
183
  /**
161
184
  * @typedef {Object} RouteTraceBase
@@ -164,25 +187,17 @@ export const KNOWN_METHODS = [
164
187
  * @property {URL} url
165
188
  * @property {IncomingHttpHeaders} headers
166
189
  * @property {number} maxForwards
167
- */
190
+ */
168
191
  /** @typedef {RouteBase & RouteTraceBase} RouteTrace */
169
192
 
170
193
  /**
171
- * @typedef {Object} RouteConditions
172
- * @property {Array<EtagItem>} match
173
- * @property {Array<EtagItem>} noneMatch
174
- * @property {IMFFixDate|undefined} modifiedSince
175
- * @property {IMFFixDate|undefined} unmodifiedSince
176
- * @property {IMFFixDate|EtagItem|undefined} [range]
177
- */
178
-
179
- /**
180
- * @typedef {Object} SecFetchMetadata
181
- * @property {SecFetchSite|undefined} site
182
- * @property {SecFetchMode|undefined} mode
183
- * @property {SecFetchDest|undefined} dest
194
+ * @typedef {Object} RouteCreatedBase
195
+ * @property {'created'} type
196
+ * @property {URL|string} location
197
+ * @property {EtagItem|undefined} [etag]
198
+ * @property {IMFFixDateInput|string|undefined} [lastModified]
184
199
  */
185
-
200
+ /** @typedef {RouteBase & RouteCreatedBase} RouteCreated */
186
201
 
187
202
  /**
188
203
  * @typedef {Object} RoutePreflightBase
@@ -195,78 +210,77 @@ export const KNOWN_METHODS = [
195
210
  /** @typedef {RouteBase & RoutePreflightBase} RoutePreflight */
196
211
 
197
212
  /**
198
- * @typedef {Object} RouteJSONBase
199
- * @property {'json'} type
200
- * @property {RouteRequestAccept} accept
201
- * @property {Record<any, any>} obj
213
+ * @typedef {Object} RouteNoContentBase
214
+ * @property {'no-content'} type
215
+ * @property {EtagItem|undefined} [etag]
202
216
  * @property {IMFFixDateInput|string|undefined} [lastModified]
217
+ */
218
+ /** @typedef {RouteBase & RouteNoContentBase} RouteNoContent */
219
+
220
+ /**
221
+ * @typedef {Object} RouteNotModifiedBase
222
+ * @property {'not-modified'} type
223
+ * @property {number} age
203
224
  * @property {EtagItem|undefined} [etag]
225
+ * @property {IMFFixDateInput|string|undefined} [lastModified]
204
226
  * @property {number|undefined} [age]
205
227
  * @property {CacheControlOptions|undefined} [cacheControl]
206
- * @property {Array<string>|undefined} [supportedQueryTypes]
207
228
  */
208
- /** @typedef {RouteBase & RouteJSONBase} RouteJSON */
229
+ /** @typedef {RouteBase & RouteNotModifiedBase} RouteNotModified */
209
230
 
210
231
  /**
211
- * @typedef {Object} Route404Base
212
- * @property {'404'} type
213
- * @property {string} method
214
- * @property {URL} url
215
- * @property {string} message
232
+ * @typedef {Object} RouteFoundBase
233
+ * @property {'found'} type
234
+ * @property {URL|string} location
216
235
  */
217
- /** @typedef {RouteBase & Route404Base} Route404 */
236
+ /** @typedef {RouteBase & RouteFoundBase} RouteFound */
237
+
238
+
218
239
 
219
240
  /**
220
- * @typedef {Object} RouteCreatedBase
221
- * @property {'created'} type
222
- * @property {URL|string} location
223
- * @property {EtagItem|undefined} [etag]
224
- * @property {IMFFixDateInput|string|undefined} [lastModified]
241
+ * @typedef {Object} RouteGoneBase
242
+ * @property {'gone'} type
225
243
  */
226
- /** @typedef {RouteBase & RouteCreatedBase} RouteCreated */
244
+ /** @typedef {RouteBase & RouteGoneBase} RouteGone */
227
245
 
228
246
  /**
229
- * @typedef {Object} RouteUnsupportedMediaTypeBase
230
- * @property {'unsupported-media'} type
231
- * @property {Array<string>|string} acceptableMediaTypes
232
- * @property {Array<string>|undefined} [supportedQueryTypes]
247
+ * @typedef {Object} RouteMovedPermanentlyBase
248
+ * @property {'moved-permanently'} type
249
+ * @property {URL|string} location
233
250
  */
234
- /** @typedef {RouteBase & RouteUnsupportedMediaTypeBase} RouteUnsupportedMediaType */
251
+ /** @typedef {RouteBase & RouteMovedPermanentlyBase} RouteMovedPermanently */
235
252
 
236
253
  /**
237
- * @typedef {Object} RouteNotModifiedBase
238
- * @property {'not-modified'} type
239
- * @property {number} age
240
- * @property {EtagItem|undefined} [etag]
241
- * @property {IMFFixDateInput|string|undefined} [lastModified]
242
- * @property {number|undefined} [age]
243
- * @property {CacheControlOptions|undefined} [cacheControl]
254
+ * @typedef {Object} RouteSeeOtherBase
255
+ * @property {'see-other'} type
256
+ * @property {URL|string} location
244
257
  */
245
- /** @typedef {RouteBase & RouteNotModifiedBase} RouteNotModified */
258
+ /** @typedef {RouteBase & RouteSeeOtherBase} RouteSeeOther */
246
259
 
247
260
  /**
248
- * @typedef {Object} RoutePreconditionFailedBase
249
- * @property {'precondition-failed'} type
250
- * @property {EtagItem|undefined} [etag]
251
- * @property {IMFFixDateInput|string|undefined} [lastModified]
261
+ * @typedef {Object} RouteTemporaryRedirectBase
262
+ * @property {'temporary-redirect'} type
263
+ * @property {URL|string} location
252
264
  */
253
- /** @typedef {RouteBase & RoutePreconditionFailedBase} RoutePreconditionFailed */
265
+ /** @typedef {RouteBase & RouteTemporaryRedirectBase} RouteTemporaryRedirect */
254
266
 
255
267
  /**
256
- * @typedef {Object} RouteNotAcceptableBase
257
- * @property {'not-acceptable'} type
258
- * @property {Array<string>|undefined} [acceptableMediaTypes]
259
- * @property {Array<string>|undefined} [acceptableEncodings]
260
- * @property {Array<string>|undefined} [acceptableLanguages]
268
+ * @typedef {Object} RoutePermanentRedirectBase
269
+ * @property {'permanent-redirect'} type
270
+ * @property {URL|string} location
261
271
  */
262
- /** @typedef {RouteBase & RouteNotAcceptableBase} RouteNotAcceptable */
272
+ /** @typedef {RouteBase & RoutePermanentRedirectBase} RoutePermanentRedirect */
273
+
274
+
275
+
263
276
 
264
277
  /**
265
- * @typedef {Object} RouteUnprocessableBase
266
- * @property {'unprocessable'} type
278
+ * @typedef {Object} Route404Base
279
+ * @property {'404'} type
280
+ * @property {string} method
267
281
  * @property {string} message
268
282
  */
269
- /** @typedef {RouteBase & RouteUnprocessableBase} RouteUnprocessable */
283
+ /** @typedef {RouteBase & Route404Base} Route404 */
270
284
 
271
285
  /**
272
286
  * @typedef {Object} RouteConflictBase
@@ -276,57 +290,41 @@ export const KNOWN_METHODS = [
276
290
  /** @typedef {RouteBase & RouteConflictBase} RouteConflict */
277
291
 
278
292
  /**
279
- * @typedef {Object} RouteNotImplementedBase
280
- * @property {'not-implemented'} type
281
- * @property {string|undefined} [message]
282
- */
283
- /** @typedef {RouteBase & RouteNotImplementedBase} RouteNotImplemented */
284
-
285
- /**
286
- * @typedef {Object} RouteUnavailableBase
287
- * @property {'unavailable'} type
288
- * @property {string|undefined} [message]
289
- * @property {number|undefined} [retryAfter]
293
+ * @typedef {Object} RouteContentTooLargeBase
294
+ * @property {'content-too-large'} type
290
295
  */
291
- /** @typedef {RouteBase & RouteUnavailableBase} RouteUnavailable */
296
+ /** @typedef {RouteBase & RouteContentTooLargeBase} RouteContentTooLarge */
292
297
 
293
298
  /**
294
- * @typedef {Object} RouteBytesBase
295
- * @property {'bytes'} type
296
- * @property {string} contentType
297
- * @property {number|undefined} [contentLength]
298
- * @property {SendBody|undefined} obj
299
- * @property {IMFFixDateInput|string|undefined} [lastModified]
300
- * @property {EtagItem|undefined} [etag]
301
- * @property {number|undefined} [age]
302
- * @property {CacheControlOptions|undefined} [cacheControl]
303
- * @property {'bytes'|'none'|undefined} [acceptRanges]
299
+ * @typedef {Object} RouteForbiddenBase
300
+ * @property {'forbidden'} type
304
301
  */
305
- /** @typedef {RouteBase & RouteBytesBase} RouteBytes */
302
+ /** @typedef {RouteBase & RouteForbiddenBase} RouteForbidden */
306
303
 
307
304
  /**
308
- * @typedef {Object} PartialBytes
309
- * @property {SendBody} obj
310
- * @property {ContentRangeDirective} range
305
+ * @typedef {Object} RouteNotAcceptableBase
306
+ * @property {'not-acceptable'} type
307
+ * @property {Array<string>|undefined} [acceptableMediaTypes]
308
+ * @property {Array<string>|undefined} [acceptableEncodings]
309
+ * @property {Array<string>|undefined} [acceptableLanguages]
311
310
  */
311
+ /** @typedef {RouteBase & RouteNotAcceptableBase} RouteNotAcceptable */
312
312
 
313
313
  /**
314
- * @template T
315
- * @typedef {[ T, ...T[] ]} NonEmptyArray
314
+ * @typedef {Object} RouteNotAllowedBase
315
+ * @property {'not-allowed'} type
316
+ * @property {RouteMethod} method
317
+ * @property {Array<RouteMethod>} methods
316
318
  */
319
+ /** @typedef {RouteBase & RouteNotAllowedBase} RouteNotAllowed */
317
320
 
318
321
  /**
319
- * @typedef {Object} RoutePartialBytesBase
320
- * @property {'partial-bytes'} type
321
- * @property {NonEmptyArray<PartialBytes>} objs
322
- * @property {string} contentType
323
- * @property {number|undefined} [contentLength]
322
+ * @typedef {Object} RoutePreconditionFailedBase
323
+ * @property {'precondition-failed'} type
324
324
  * @property {EtagItem|undefined} [etag]
325
325
  * @property {IMFFixDateInput|string|undefined} [lastModified]
326
- * @property {number|undefined} [age]
327
- * @property {CacheControlOptions|undefined} [cacheControl]
328
326
  */
329
- /** @typedef {RouteBase & RoutePartialBytesBase} RoutePartialBytes */
327
+ /** @typedef {RouteBase & RoutePreconditionFailedBase} RoutePreconditionFailed */
330
328
 
331
329
  /**
332
330
  * @typedef {Object} RouteNotSatisfiableBase
@@ -336,52 +334,40 @@ export const KNOWN_METHODS = [
336
334
  /** @typedef {RouteBase & RouteNotSatisfiableBase} RouteNotSatisfiable */
337
335
 
338
336
  /**
339
- * @typedef {Object} RouteSeeOtherBase
340
- * @property {'see-other'} type
341
- * @property {URL} location
342
- */
343
- /** @typedef {RouteBase & RouteSeeOtherBase} RouteSeeOther */
344
-
345
- /**
346
- * @typedef {Object} RouteTemporaryRedirectBase
347
- * @property {'temporary-redirect'} type
348
- * @property {URL} location
349
- */
350
- /** @typedef {RouteBase & RouteTemporaryRedirectBase} RouteTemporaryRedirect */
351
-
352
- /**
353
- * @typedef {Object} RoutePermanentRedirectBase
354
- * @property {'permanent-redirect'} type
355
- * @property {URL} location
337
+ * @typedef {Object} RouteTimeoutBase
338
+ * @property {'timeout'} type
356
339
  */
357
- /** @typedef {RouteBase & RoutePermanentRedirectBase} RoutePermanentRedirect */
340
+ /** @typedef {RouteBase & RouteTimeoutBase} RouteTimeout */
358
341
 
359
342
  /**
360
- * @typedef {Object} RouteMovedPermanentlyBase
361
- * @property {'moved-permanently'} type
362
- * @property {URL} location
343
+ * @typedef {Object} RouteTooManyRequestsBase
344
+ * @property {'too-many-requests'} type
345
+ * @property {RateLimitInfo} limit
346
+ * @property {Array<RateLimitPolicyInfo>} policies
363
347
  */
364
- /** @typedef {RouteBase & RouteMovedPermanentlyBase} RouteMovedPermanently */
348
+ /** @typedef {RouteBase & RouteTooManyRequestsBase} RouteTooManyRequests */
365
349
 
366
350
  /**
367
- * @typedef {Object} RouteNoContentBase
368
- * @property {'no-content'} type
369
- * @property {EtagItem|undefined} [etag]
370
- * @property {IMFFixDateInput|string|undefined} [lastModified]
351
+ * @typedef {Object} RouteUnauthorizedBase
352
+ * @property {'unauthorized'} type
353
+ * @property {Array<ChallengeItem>} challenge
371
354
  */
372
- /** @typedef {RouteBase & RouteNoContentBase} RouteNoContent */
355
+ /** @typedef {RouteBase & RouteUnauthorizedBase} RouteUnauthorized */
373
356
 
374
357
  /**
375
- * @typedef {Object} RouteGoneBase
376
- * @property {'gone'} type
358
+ * @typedef {Object} RouteUnprocessableBase
359
+ * @property {'unprocessable'} type
360
+ * @property {string} message
377
361
  */
378
- /** @typedef {RouteBase & RouteGoneBase} RouteGone */
362
+ /** @typedef {RouteBase & RouteUnprocessableBase} RouteUnprocessable */
379
363
 
380
364
  /**
381
- * @typedef {Object} RouteContentTooLargeBase
382
- * @property {'content-too-large'} type
365
+ * @typedef {Object} RouteUnsupportedMediaTypeBase
366
+ * @property {'unsupported-media'} type
367
+ * @property {Array<string>|string} acceptableMediaTypes
368
+ * @property {Array<string>|undefined} [supportedQueryTypes]
383
369
  */
384
- /** @typedef {RouteBase & RouteContentTooLargeBase} RouteContentTooLarge */
370
+ /** @typedef {RouteBase & RouteUnsupportedMediaTypeBase} RouteUnsupportedMediaType */
385
371
 
386
372
  /**
387
373
  * @typedef {Object} RouteInsufficientStorageBase
@@ -390,31 +376,21 @@ export const KNOWN_METHODS = [
390
376
  /** @typedef {RouteBase & RouteInsufficientStorageBase} RouteInsufficientStorage */
391
377
 
392
378
  /**
393
- * @typedef {Object} RouteTooManyRequestsBase
394
- * @property {'too-many-requests'} type
395
- * @property {RateLimitInfo} limit
396
- * @property {Array<RateLimitPolicyInfo>} policies
379
+ * @typedef {Object} RouteNotImplementedBase
380
+ * @property {'not-implemented'} type
381
+ * @property {string|undefined} [message]
397
382
  */
398
- /** @typedef {RouteBase & RouteTooManyRequestsBase} RouteTooManyRequests */
383
+ /** @typedef {RouteBase & RouteNotImplementedBase} RouteNotImplemented */
399
384
 
400
385
  /**
401
- * @typedef {Object} RouteUnauthorizedBase
402
- * @property {'unauthorized'} type
403
- * @property {Array<ChallengeItem>} challenge
386
+ * @typedef {Object} RouteUnavailableBase
387
+ * @property {'unavailable'} type
388
+ * @property {string|undefined} [message]
389
+ * @property {number|undefined} [retryAfter]
404
390
  */
405
- /** @typedef {RouteBase & RouteUnauthorizedBase} RouteUnauthorized */
391
+ /** @typedef {RouteBase & RouteUnavailableBase} RouteUnavailable */
406
392
 
407
- /**
408
- * @typedef {Object} RouteForbiddenBase
409
- * @property {'forbidden'} type
410
- */
411
- /** @typedef {RouteBase & RouteForbiddenBase} RouteForbidden */
412
393
 
413
- /**
414
- * @typedef {Object} RouteTimeoutBase
415
- * @property {'timeout'} type
416
- */
417
- /** @typedef {RouteBase & RouteTimeoutBase} RouteTimeout */
418
394
 
419
395
  /**
420
396
  * @typedef {Object} RouteSSEBase
@@ -425,38 +401,93 @@ export const KNOWN_METHODS = [
425
401
  */
426
402
  /** @typedef {RouteBase & RouteSSEBase} RouteSSE */
427
403
 
404
+ /**
405
+ * @typedef {Object} RouteBytesBase
406
+ * @property {'bytes'} type
407
+ * @property {string} contentType
408
+ * @property {number|undefined} [contentLength]
409
+ * @property {SendBody|undefined} obj
410
+ * @property {IMFFixDateInput|string|undefined} [lastModified]
411
+ * @property {EtagItem|undefined} [etag]
412
+ * @property {number|undefined} [age]
413
+ * @property {CacheControlOptions|undefined} [cacheControl]
414
+ * @property {'bytes'|'none'|undefined} [acceptRanges]
415
+ */
416
+ /** @typedef {RouteBase & RouteBytesBase} RouteBytes */
417
+
418
+
419
+
420
+ /**
421
+ * @typedef {Object} RoutePartialBytesBase
422
+ * @property {'partial-bytes'} type
423
+ * @property {NonEmptyArray<PartialBytes>} objs
424
+ * @property {string} contentType
425
+ * @property {number|undefined} [contentLength]
426
+ * @property {EtagItem|undefined} [etag]
427
+ * @property {IMFFixDateInput|string|undefined} [lastModified]
428
+ * @property {number|undefined} [age]
429
+ * @property {CacheControlOptions|undefined} [cacheControl]
430
+ */
431
+ /** @typedef {RouteBase & RoutePartialBytesBase} RoutePartialBytes */
432
+
433
+ /**
434
+ * @typedef {Object} RouteJSONBase
435
+ * @property {'json'} type
436
+ * @property {RouteRequestAccept} accept
437
+ * @property {Record<any, any>} obj
438
+ * @property {IMFFixDateInput|string|undefined} [lastModified]
439
+ * @property {EtagItem|undefined} [etag]
440
+ * @property {number|undefined} [age]
441
+ * @property {CacheControlOptions|undefined} [cacheControl]
442
+ * @property {Array<string>|undefined} [supportedQueryTypes]
443
+ */
444
+ /** @typedef {RouteBase & RouteJSONBase} RouteJSON */
445
+
446
+ /**
447
+ * @typedef {Object} RouteErrorBase
448
+ * @property {'error'} type
449
+ * @property {string} cause
450
+ * @property {Error|undefined} [error]
451
+ */
452
+ /** @typedef {RouteBase & RouteErrorBase } RouteError */
453
+
454
+
428
455
  /** @typedef {
429
- RouteError |
430
- RouteNotAllowed |
431
- RoutePreflight |
432
- RouteBytes |
433
- RouteJSON |
434
- Route404 |
435
- RouteSSE |
436
456
  RouteTrace |
437
457
  RouteCreated |
438
- RouteUnsupportedMediaType |
458
+ RoutePreflight |
459
+ RouteNoContent |
439
460
  RouteNotModified |
440
- RoutePreconditionFailed |
441
- RouteUnprocessable |
442
- RouteNotAcceptable |
443
- RouteConflict |
444
- RouteNotImplemented |
445
- RouteUnavailable |
446
- RoutePartialBytes |
447
- RouteNotSatisfiable |
461
+ RouteFound |
462
+
463
+ RouteGone |
464
+ RouteMovedPermanently |
448
465
  RouteSeeOther |
449
466
  RouteTemporaryRedirect |
450
467
  RoutePermanentRedirect |
451
- RouteMovedPermanently |
452
- RouteNoContent |
453
- RouteGone |
468
+
469
+ Route404 |
470
+ RouteConflict |
454
471
  RouteContentTooLarge |
455
- RouteInsufficientStorage |
472
+ RouteForbidden |
473
+ RouteNotAcceptable |
474
+ RouteNotAllowed |
475
+ RoutePreconditionFailed |
476
+ RouteNotSatisfiable |
477
+ RouteTimeout |
456
478
  RouteTooManyRequests |
457
479
  RouteUnauthorized |
458
- RouteForbidden |
459
- RouteTimeout
480
+ RouteUnprocessable |
481
+ RouteUnsupportedMediaType |
482
+ RouteInsufficientStorage |
483
+ RouteNotImplemented |
484
+ RouteUnavailable |
485
+
486
+ RouteSSE |
487
+ RouteBytes |
488
+ RoutePartialBytes |
489
+ RouteJSON |
490
+ RouteError
460
491
  } RouteAction */
461
492
 
462
493
  /** @typedef {Record<string, string|undefined>} RouteMatches */
package/src/preamble.js CHANGED
@@ -162,7 +162,6 @@ export function preamble(preState, headers, servername) {
162
162
  //
163
163
  const allowedOrigin = (ALLOWED_ORIGINS.includes('*') || ((origin !== undefined) && URL.canParse(origin) && ALLOWED_ORIGINS.includes(origin))) ? origin : undefined
164
164
 
165
-
166
165
  /** @type {RouteRequest|RouteAction} */
167
166
  const state = {
168
167
  type: 'error',