@lovrozagar/honey 0.5.1 → 0.5.3
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/README.md +11 -9
- package/dist/codegen-route-tree-intern.d.ts +29 -0
- package/dist/codegen-route-tree-intern.d.ts.map +1 -0
- package/dist/codegen.d.ts +5 -22
- package/dist/codegen.d.ts.map +1 -1
- package/dist/openapi/collect.d.ts +17 -0
- package/dist/openapi/collect.d.ts.map +1 -0
- package/dist/openapi/document.d.ts +29 -0
- package/dist/openapi/document.d.ts.map +1 -0
- package/dist/openapi/json-schema-slot.d.ts +5 -0
- package/dist/openapi/json-schema-slot.d.ts.map +1 -0
- package/dist/openapi/spec-factory.d.ts +1 -0
- package/dist/openapi/spec-factory.d.ts.map +1 -1
- package/dist/openapi/spec.d.ts +1 -1
- package/dist/openapi/spec.d.ts.map +1 -1
- package/dist/tree.d.ts +5 -39
- package/dist/tree.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/codegen-route-tree-intern.ts +171 -0
- package/src/codegen.ts +210 -728
- package/src/index.ts +7 -7
- package/src/openapi/collect.ts +75 -0
- package/src/openapi/document.ts +614 -0
- package/src/openapi/json-schema-slot.ts +13 -0
- package/src/openapi/spec-factory.ts +4 -0
- package/src/openapi/spec.ts +21 -11
- package/src/tree.ts +5 -398
package/src/tree.ts
CHANGED
|
@@ -12,8 +12,8 @@ export type RouteHandler = {
|
|
|
12
12
|
_skip?: boolean
|
|
13
13
|
/** boundary error key — wraps undeclared/unexpected errors (null = use default or internal_server_error) */
|
|
14
14
|
bek: string | null
|
|
15
|
-
/** pre-computed error factory subset (null = use global factory) */
|
|
16
|
-
ef
|
|
15
|
+
/** pre-computed error factory subset (omit/`null` = use global factory) */
|
|
16
|
+
ef?: Record<string, (...args: never[]) => unknown> | null
|
|
17
17
|
/** declared error keys for this route — used for runtime enforcement */
|
|
18
18
|
ek: Set<string>
|
|
19
19
|
/** handler function */
|
|
@@ -32,9 +32,9 @@ export type RouteHandler = {
|
|
|
32
32
|
/** output schemas by content-type (null = no output validation) */
|
|
33
33
|
os: OutputSchemaDef | null
|
|
34
34
|
/** output validator function — validates response body against schema */
|
|
35
|
-
ov
|
|
36
|
-
/** registered path pattern (e.g. "/users/:id") */
|
|
37
|
-
rp
|
|
35
|
+
ov?: OutputValidator | null
|
|
36
|
+
/** registered path pattern (e.g. "/users/:id"); intern trees omit this */
|
|
37
|
+
rp?: string
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export type { OutputSchemaDef }
|
|
@@ -108,399 +108,6 @@ export function createNode(): TreeNode {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
const UNSET_FN = null as unknown as RouteHandler["fn"]
|
|
112
|
-
|
|
113
|
-
/** Dense array, or unique-value table + per-row indices when that JSON is smaller. */
|
|
114
|
-
export type PackedColumn<T> = readonly T[] | { readonly t: readonly T[]; readonly x: readonly number[] }
|
|
115
|
-
|
|
116
|
-
/** Columnar packed route table consumed by `assembleRouteTree`. */
|
|
117
|
-
export type PackedRouteTable = {
|
|
118
|
-
/** Boundary error key. A string applies to every route. */
|
|
119
|
-
b?: Array<string | null> | string
|
|
120
|
-
/** Per-route error-key lists. When `k` is set, each row is the extras beyond `k`. */
|
|
121
|
-
e?: PackedColumn<readonly string[] | null>
|
|
122
|
-
/** Per-route input schemas. */
|
|
123
|
-
i?: PackedColumn<unknown>
|
|
124
|
-
/** Error keys shared by every route; prepended onto each `e` row at inflate. */
|
|
125
|
-
k?: readonly string[]
|
|
126
|
-
/** Per-route meta objects. Keys are `u` indices when `u` is set. */
|
|
127
|
-
m?: PackedColumn<Record<string, unknown> | null>
|
|
128
|
-
/** Per-route output schemas. */
|
|
129
|
-
o?: PackedColumn<unknown>
|
|
130
|
-
/** Route selectors (`METHOD /path`), same order as the other columns. */
|
|
131
|
-
s: readonly string[]
|
|
132
|
-
/** Meta key dictionary; packed meta objects use decimal index keys. */
|
|
133
|
-
u?: readonly string[]
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const SCHEMA_KEY_PACK = new Map<string, string>([
|
|
137
|
-
["$ref", "$"],
|
|
138
|
-
["additionalItems", "ai"],
|
|
139
|
-
["additionalProperties", "ap"],
|
|
140
|
-
["allOf", "ao"],
|
|
141
|
-
["anyOf", "yo"],
|
|
142
|
-
["const", "c"],
|
|
143
|
-
["contains", "cs"],
|
|
144
|
-
["contentEncoding", "ce"],
|
|
145
|
-
["contentMediaType", "cm"],
|
|
146
|
-
["contentSchema", "cc"],
|
|
147
|
-
["default", "d"],
|
|
148
|
-
["definitions", "df"],
|
|
149
|
-
["dependentRequired", "dr"],
|
|
150
|
-
["dependentSchemas", "dh"],
|
|
151
|
-
["description", "ds"],
|
|
152
|
-
["else", "el"],
|
|
153
|
-
["enum", "en"],
|
|
154
|
-
["examples", "ex"],
|
|
155
|
-
["exclusiveMaximum", "xm"],
|
|
156
|
-
["exclusiveMinimum", "xn"],
|
|
157
|
-
["format", "f"],
|
|
158
|
-
["if", "if"],
|
|
159
|
-
["items", "it"],
|
|
160
|
-
["maxItems", "xi"],
|
|
161
|
-
["maxLength", "xl"],
|
|
162
|
-
["maxProperties", "xp"],
|
|
163
|
-
["maximum", "xa"],
|
|
164
|
-
["minItems", "ni"],
|
|
165
|
-
["minLength", "nl"],
|
|
166
|
-
["minProperties", "np"],
|
|
167
|
-
["minimum", "na"],
|
|
168
|
-
["multipleOf", "mo"],
|
|
169
|
-
["not", "nt"],
|
|
170
|
-
["nullable", "nu"],
|
|
171
|
-
["oneOf", "oo"],
|
|
172
|
-
["pattern", "pt"],
|
|
173
|
-
["patternProperties", "pp"],
|
|
174
|
-
["prefixItems", "pi"],
|
|
175
|
-
["properties", "p"],
|
|
176
|
-
["propertyNames", "pn"],
|
|
177
|
-
["required", "r"],
|
|
178
|
-
["then", "th"],
|
|
179
|
-
["title", "ti"],
|
|
180
|
-
["type", "t"],
|
|
181
|
-
["unevaluatedItems", "ue"],
|
|
182
|
-
["unevaluatedProperties", "up"],
|
|
183
|
-
["uniqueItems", "ui"],
|
|
184
|
-
])
|
|
185
|
-
|
|
186
|
-
function invertStringMap(src: Map<string, string>): Map<string, string> {
|
|
187
|
-
const out = new Map<string, string>()
|
|
188
|
-
for (const [long, short] of src) out.set(short, long)
|
|
189
|
-
return out
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const SCHEMA_KEY_UNPACK = invertStringMap(SCHEMA_KEY_PACK)
|
|
193
|
-
|
|
194
|
-
const SCHEMA_TYPE_PACK = new Map<string, string>([
|
|
195
|
-
["array", "a"],
|
|
196
|
-
["boolean", "b"],
|
|
197
|
-
["integer", "i"],
|
|
198
|
-
["null", "l"],
|
|
199
|
-
["number", "n"],
|
|
200
|
-
["object", "o"],
|
|
201
|
-
["string", "s"],
|
|
202
|
-
])
|
|
203
|
-
const SCHEMA_TYPE_UNPACK = invertStringMap(SCHEMA_TYPE_PACK)
|
|
204
|
-
|
|
205
|
-
const SCHEMA_FORMAT_PACK = new Map<string, string>([
|
|
206
|
-
["binary", "bin"],
|
|
207
|
-
["date", "d"],
|
|
208
|
-
["date-time", "dt"],
|
|
209
|
-
["email", "e"],
|
|
210
|
-
["hostname", "hn"],
|
|
211
|
-
["int32", "i3"],
|
|
212
|
-
["int64", "i6"],
|
|
213
|
-
["ipv4", "v4"],
|
|
214
|
-
["ipv6", "v6"],
|
|
215
|
-
["time", "tm"],
|
|
216
|
-
["uri", "u"],
|
|
217
|
-
["uri-reference", "ur"],
|
|
218
|
-
["uuid", "id"],
|
|
219
|
-
])
|
|
220
|
-
const SCHEMA_FORMAT_UNPACK = invertStringMap(SCHEMA_FORMAT_PACK)
|
|
221
|
-
|
|
222
|
-
const INPUT_KEY_PACK = new Map<string, string>([
|
|
223
|
-
["cookies", "c"],
|
|
224
|
-
["form", "f"],
|
|
225
|
-
["headers", "h"],
|
|
226
|
-
["json", "j"],
|
|
227
|
-
["params", "p"],
|
|
228
|
-
["search", "q"],
|
|
229
|
-
])
|
|
230
|
-
const INPUT_KEY_UNPACK = invertStringMap(INPUT_KEY_PACK)
|
|
231
|
-
|
|
232
|
-
const OUTPUT_CT_PACK = new Map<string, string>([
|
|
233
|
-
["application/cbor", "cb"],
|
|
234
|
-
["application/json", "j"],
|
|
235
|
-
["application/msgpack", "mp"],
|
|
236
|
-
["application/octet-stream", "os"],
|
|
237
|
-
["application/pdf", "pf"],
|
|
238
|
-
["application/xml", "xm"],
|
|
239
|
-
["redirect", "rd"],
|
|
240
|
-
["text/csv", "csv"],
|
|
241
|
-
["text/event-stream", "sse"],
|
|
242
|
-
["text/html", "ht"],
|
|
243
|
-
["text/plain", "tp"],
|
|
244
|
-
])
|
|
245
|
-
const OUTPUT_CT_UNPACK = invertStringMap(OUTPUT_CT_PACK)
|
|
246
|
-
|
|
247
|
-
const SCHEMA_NAME_CHILDREN = new Set(["$defs", "definitions", "dependentSchemas", "patternProperties", "properties"])
|
|
248
|
-
const SCHEMA_NODE_CHILDREN = new Set([
|
|
249
|
-
"$defs",
|
|
250
|
-
"additionalItems",
|
|
251
|
-
"additionalProperties",
|
|
252
|
-
"allOf",
|
|
253
|
-
"anyOf",
|
|
254
|
-
"contains",
|
|
255
|
-
"contentSchema",
|
|
256
|
-
"definitions",
|
|
257
|
-
"dependentSchemas",
|
|
258
|
-
"else",
|
|
259
|
-
"if",
|
|
260
|
-
"items",
|
|
261
|
-
"not",
|
|
262
|
-
"oneOf",
|
|
263
|
-
"patternProperties",
|
|
264
|
-
"prefixItems",
|
|
265
|
-
"properties",
|
|
266
|
-
"propertyNames",
|
|
267
|
-
"then",
|
|
268
|
-
"unevaluatedItems",
|
|
269
|
-
"unevaluatedProperties",
|
|
270
|
-
])
|
|
271
|
-
|
|
272
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
273
|
-
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function remapLeaf(value: unknown, map: Map<string, string>): unknown {
|
|
277
|
-
if (typeof value === "string") return map.get(value) ?? value
|
|
278
|
-
if (Array.isArray(value)) {
|
|
279
|
-
return value.map((item) => (typeof item === "string" ? (map.get(item) ?? item) : item))
|
|
280
|
-
}
|
|
281
|
-
return value
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function isNullTypeSchema(value: unknown): boolean {
|
|
285
|
-
return isPlainObject(value) && Object.keys(value).length === 1 && value.type === "null"
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function packJsonSchema(node: unknown): unknown {
|
|
289
|
-
if (Array.isArray(node)) return node.map(packJsonSchema)
|
|
290
|
-
if (!isPlainObject(node)) return node
|
|
291
|
-
|
|
292
|
-
const oneOf = node.oneOf
|
|
293
|
-
if (Array.isArray(oneOf) && oneOf.length === 2 && Object.keys(node).length === 1) {
|
|
294
|
-
if (isPlainObject(oneOf[0]) && isNullTypeSchema(oneOf[1])) {
|
|
295
|
-
const packed = packJsonSchema(oneOf[0])
|
|
296
|
-
if (isPlainObject(packed)) {
|
|
297
|
-
packed.n1 = 1
|
|
298
|
-
return packed
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if (isNullTypeSchema(oneOf[0]) && isPlainObject(oneOf[1])) {
|
|
302
|
-
const packed = packJsonSchema(oneOf[1])
|
|
303
|
-
if (isPlainObject(packed)) {
|
|
304
|
-
packed.n1 = 0
|
|
305
|
-
return packed
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
311
|
-
for (const [key, value] of Object.entries(node)) {
|
|
312
|
-
const nextKey = SCHEMA_KEY_PACK.get(key) ?? key
|
|
313
|
-
if (key === "type") {
|
|
314
|
-
out[nextKey] = remapLeaf(value, SCHEMA_TYPE_PACK)
|
|
315
|
-
continue
|
|
316
|
-
}
|
|
317
|
-
if (key === "format") {
|
|
318
|
-
out[nextKey] = remapLeaf(value, SCHEMA_FORMAT_PACK)
|
|
319
|
-
continue
|
|
320
|
-
}
|
|
321
|
-
if (SCHEMA_NAME_CHILDREN.has(key) && isPlainObject(value)) {
|
|
322
|
-
const inner: Record<string, unknown> = Object.create(null)
|
|
323
|
-
for (const [name, child] of Object.entries(value)) inner[name] = packJsonSchema(child)
|
|
324
|
-
out[nextKey] = inner
|
|
325
|
-
continue
|
|
326
|
-
}
|
|
327
|
-
if (SCHEMA_NODE_CHILDREN.has(key)) {
|
|
328
|
-
out[nextKey] = packJsonSchema(value)
|
|
329
|
-
continue
|
|
330
|
-
}
|
|
331
|
-
out[nextKey] = value
|
|
332
|
-
}
|
|
333
|
-
return out
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
function unpackJsonSchema(node: unknown): unknown {
|
|
337
|
-
if (Array.isArray(node)) return node.map(unpackJsonSchema)
|
|
338
|
-
if (!isPlainObject(node)) return node
|
|
339
|
-
|
|
340
|
-
if (Object.hasOwn(node, "n1")) {
|
|
341
|
-
const copy: Record<string, unknown> = Object.create(null)
|
|
342
|
-
for (const [key, value] of Object.entries(node)) {
|
|
343
|
-
if (key !== "n1") copy[key] = value
|
|
344
|
-
}
|
|
345
|
-
const rest = unpackJsonSchema(copy)
|
|
346
|
-
const nullBranch = { type: "null" }
|
|
347
|
-
return node.n1 === 0 ? { oneOf: [nullBranch, rest] } : { oneOf: [rest, nullBranch] }
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
351
|
-
for (const [key, value] of Object.entries(node)) {
|
|
352
|
-
const nextKey = SCHEMA_KEY_UNPACK.get(key) ?? key
|
|
353
|
-
if (nextKey === "type") {
|
|
354
|
-
out[nextKey] = remapLeaf(value, SCHEMA_TYPE_UNPACK)
|
|
355
|
-
continue
|
|
356
|
-
}
|
|
357
|
-
if (nextKey === "format") {
|
|
358
|
-
out[nextKey] = remapLeaf(value, SCHEMA_FORMAT_UNPACK)
|
|
359
|
-
continue
|
|
360
|
-
}
|
|
361
|
-
if (SCHEMA_NAME_CHILDREN.has(nextKey) && isPlainObject(value)) {
|
|
362
|
-
const inner: Record<string, unknown> = Object.create(null)
|
|
363
|
-
for (const [name, child] of Object.entries(value)) inner[name] = unpackJsonSchema(child)
|
|
364
|
-
out[nextKey] = inner
|
|
365
|
-
continue
|
|
366
|
-
}
|
|
367
|
-
if (SCHEMA_NODE_CHILDREN.has(nextKey)) {
|
|
368
|
-
out[nextKey] = unpackJsonSchema(value)
|
|
369
|
-
continue
|
|
370
|
-
}
|
|
371
|
-
out[nextKey] = value
|
|
372
|
-
}
|
|
373
|
-
return out
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
export function packInputSchemas(iv: unknown): unknown {
|
|
377
|
-
if (iv === null || typeof iv !== "object") return iv
|
|
378
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
379
|
-
for (const [source, schema] of Object.entries(iv as Record<string, unknown>)) {
|
|
380
|
-
out[INPUT_KEY_PACK.get(source) ?? source] = packJsonSchema(schema)
|
|
381
|
-
}
|
|
382
|
-
return out
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
export function unpackInputSchemas(iv: unknown): unknown {
|
|
386
|
-
if (iv === null || typeof iv !== "object") return iv
|
|
387
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
388
|
-
for (const [source, schema] of Object.entries(iv as Record<string, unknown>)) {
|
|
389
|
-
out[INPUT_KEY_UNPACK.get(source) ?? source] = unpackJsonSchema(schema)
|
|
390
|
-
}
|
|
391
|
-
return out
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
export function packOutputSchemas(os: unknown): unknown {
|
|
395
|
-
if (os === null || typeof os !== "object") return os
|
|
396
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
397
|
-
for (const [contentType, statuses] of Object.entries(os as Record<string, unknown>)) {
|
|
398
|
-
const packedCt = OUTPUT_CT_PACK.get(contentType) ?? contentType
|
|
399
|
-
if (contentType === "redirect" || statuses === null || typeof statuses !== "object") {
|
|
400
|
-
out[packedCt] = statuses
|
|
401
|
-
continue
|
|
402
|
-
}
|
|
403
|
-
const inner: Record<string, unknown> = Object.create(null)
|
|
404
|
-
for (const [statusKey, schema] of Object.entries(statuses as Record<string, unknown>)) {
|
|
405
|
-
inner[statusKey] = schema === true ? true : packJsonSchema(schema)
|
|
406
|
-
}
|
|
407
|
-
out[packedCt] = inner
|
|
408
|
-
}
|
|
409
|
-
return out
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
export function unpackOutputSchemas(os: unknown): unknown {
|
|
413
|
-
if (os === null || typeof os !== "object") return os
|
|
414
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
415
|
-
for (const [contentType, statuses] of Object.entries(os as Record<string, unknown>)) {
|
|
416
|
-
const longCt = OUTPUT_CT_UNPACK.get(contentType) ?? contentType
|
|
417
|
-
if (longCt === "redirect" || statuses === null || typeof statuses !== "object") {
|
|
418
|
-
out[longCt] = statuses
|
|
419
|
-
continue
|
|
420
|
-
}
|
|
421
|
-
const inner: Record<string, unknown> = Object.create(null)
|
|
422
|
-
for (const [statusKey, schema] of Object.entries(statuses as Record<string, unknown>)) {
|
|
423
|
-
inner[statusKey] = schema === true ? true : unpackJsonSchema(schema)
|
|
424
|
-
}
|
|
425
|
-
out[longCt] = inner
|
|
426
|
-
}
|
|
427
|
-
return out
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
function columnAt<T>(col: PackedColumn<T> | undefined, index: number, fallback: T): T {
|
|
431
|
-
if (col === undefined) return fallback
|
|
432
|
-
if (!Array.isArray(col) && "x" in col) {
|
|
433
|
-
const value = col.t[col.x[index]]
|
|
434
|
-
return (value === undefined ? fallback : value) as T
|
|
435
|
-
}
|
|
436
|
-
const value = col[index]
|
|
437
|
-
return (value === undefined ? fallback : value) as T
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
function mapColumn<T, U>(col: PackedColumn<T> | undefined, fn: (value: T) => U): PackedColumn<U> | undefined {
|
|
441
|
-
if (col === undefined) return undefined
|
|
442
|
-
if (!Array.isArray(col) && "x" in col) {
|
|
443
|
-
return { t: col.t.map(fn), x: col.x }
|
|
444
|
-
}
|
|
445
|
-
return (col as readonly T[]).map(fn)
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
function unpackMeta(
|
|
449
|
-
mt: Record<string, unknown> | null,
|
|
450
|
-
names: readonly string[] | undefined,
|
|
451
|
-
): Record<string, unknown> | null {
|
|
452
|
-
if (mt === null || names === undefined) return mt
|
|
453
|
-
const out: Record<string, unknown> = Object.create(null)
|
|
454
|
-
for (const [key, value] of Object.entries(mt)) {
|
|
455
|
-
const idx = Number(key)
|
|
456
|
-
const name = Number.isInteger(idx) ? names[idx] : undefined
|
|
457
|
-
out[name ?? key] = value
|
|
458
|
-
}
|
|
459
|
-
return out
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Inflate a packed route table into a live route tree.
|
|
464
|
-
* Each handler and each `ek` Set is a unique object so `.routeTree()` patches
|
|
465
|
-
* cannot cross-wire routes.
|
|
466
|
-
*/
|
|
467
|
-
export function assembleRouteTree(table: PackedRouteTable): RouteTree {
|
|
468
|
-
const root = createNode()
|
|
469
|
-
const handlers: Record<string, RouteHandler> = Object.create(null)
|
|
470
|
-
const meta: Record<string, Record<string, unknown>> = Object.create(null)
|
|
471
|
-
const selectors = table.s
|
|
472
|
-
const sharedEk = table.k ?? []
|
|
473
|
-
const inputCol = mapColumn(table.i, unpackInputSchemas)
|
|
474
|
-
const outputCol = mapColumn(table.o, unpackOutputSchemas)
|
|
475
|
-
const metaCol = mapColumn(table.m, (mt) => unpackMeta(mt, table.u))
|
|
476
|
-
for (let i = 0; i < selectors.length; i++) {
|
|
477
|
-
const sel = selectors[i]
|
|
478
|
-
const bek = typeof table.b === "string" ? table.b : (table.b?.[i] ?? null)
|
|
479
|
-
const extra = columnAt(table.e, i, [] as readonly string[])
|
|
480
|
-
const mt = columnAt(metaCol, i, null)
|
|
481
|
-
const handler: RouteHandler = {
|
|
482
|
-
bek,
|
|
483
|
-
ef: null,
|
|
484
|
-
ek: new Set(sharedEk.length === 0 ? (extra ?? []) : [...sharedEk, ...(extra ?? [])]),
|
|
485
|
-
fn: UNSET_FN,
|
|
486
|
-
iv: columnAt(inputCol, i, null) as RouteHandler["iv"],
|
|
487
|
-
mt,
|
|
488
|
-
mw: [],
|
|
489
|
-
os: columnAt(outputCol, i, null) as RouteHandler["os"],
|
|
490
|
-
ov: null,
|
|
491
|
-
rp: "",
|
|
492
|
-
}
|
|
493
|
-
handlers[sel] = handler
|
|
494
|
-
if (mt !== null) meta[sel] = mt
|
|
495
|
-
const sp = sel.indexOf(" ")
|
|
496
|
-
if (sp === -1) {
|
|
497
|
-
throw new Error(`Invalid route selector: ${sel}`)
|
|
498
|
-
}
|
|
499
|
-
insertRoute(root, sel.slice(0, sp) as HttpMethod, sel.slice(sp + 1), handler)
|
|
500
|
-
}
|
|
501
|
-
return { handlers, meta, root }
|
|
502
|
-
}
|
|
503
|
-
|
|
504
111
|
function splitSegments(path: string): string[] {
|
|
505
112
|
return path.split("/").filter((s) => s.length > 0)
|
|
506
113
|
}
|