@lovrozagar/honey 0.5.0 → 0.5.1
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 +1 -1
- package/dist/codegen.d.ts +1 -1
- package/dist/codegen.d.ts.map +1 -1
- package/dist/tree.d.ts +34 -0
- package/dist/tree.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/codegen.ts +106 -184
- package/src/tree.ts +393 -0
- package/dist/codegen-route-tree-intern.d.ts +0 -29
- package/dist/codegen-route-tree-intern.d.ts.map +0 -1
- package/src/codegen-route-tree-intern.ts +0 -171
package/README.md
CHANGED
|
@@ -1539,7 +1539,7 @@ Import features from their path.
|
|
|
1539
1539
|
| `honey/codegen-go-cli` | `generateGoCLI` |
|
|
1540
1540
|
| `honey/codegen/extract` | ts-morph chain extractor |
|
|
1541
1541
|
| `honey/build` | `createBuildPlugin` |
|
|
1542
|
-
| `honey/tree` | Tree types + `mergeTree`
|
|
1542
|
+
| `honey/tree` | Tree types + `mergeTree` + `assembleRouteTree` |
|
|
1543
1543
|
| `honey/cli` | `honey` binary |
|
|
1544
1544
|
| `honey/errors` | `defineErrors` (also on the root export) |
|
|
1545
1545
|
|
package/dist/codegen.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type InvalidateCheckConfig } from "./invalidate-check.ts";
|
|
2
2
|
import type { Honey } from "./index.ts";
|
|
3
|
-
import type
|
|
3
|
+
import { type TreeNode } from "./tree.ts";
|
|
4
4
|
export { prepareCodegen } from "./codegen-loaders.ts";
|
|
5
5
|
export type { InvalidateCheckConfig, InvalidateCheckLevel } from "./invalidate-check.ts";
|
|
6
6
|
export { toYaml, yamlSiblingPath } from "./yaml.ts";
|
package/dist/codegen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
|
package/dist/tree.d.ts
CHANGED
|
@@ -76,6 +76,40 @@ export type RouteTree = {
|
|
|
76
76
|
root: TreeNode;
|
|
77
77
|
};
|
|
78
78
|
export declare function createNode(): TreeNode;
|
|
79
|
+
/** Dense array, or unique-value table + per-row indices when that JSON is smaller. */
|
|
80
|
+
export type PackedColumn<T> = readonly T[] | {
|
|
81
|
+
readonly t: readonly T[];
|
|
82
|
+
readonly x: readonly number[];
|
|
83
|
+
};
|
|
84
|
+
/** Columnar packed route table consumed by `assembleRouteTree`. */
|
|
85
|
+
export type PackedRouteTable = {
|
|
86
|
+
/** Boundary error key. A string applies to every route. */
|
|
87
|
+
b?: Array<string | null> | string;
|
|
88
|
+
/** Per-route error-key lists. When `k` is set, each row is the extras beyond `k`. */
|
|
89
|
+
e?: PackedColumn<readonly string[] | null>;
|
|
90
|
+
/** Per-route input schemas. */
|
|
91
|
+
i?: PackedColumn<unknown>;
|
|
92
|
+
/** Error keys shared by every route; prepended onto each `e` row at inflate. */
|
|
93
|
+
k?: readonly string[];
|
|
94
|
+
/** Per-route meta objects. Keys are `u` indices when `u` is set. */
|
|
95
|
+
m?: PackedColumn<Record<string, unknown> | null>;
|
|
96
|
+
/** Per-route output schemas. */
|
|
97
|
+
o?: PackedColumn<unknown>;
|
|
98
|
+
/** Route selectors (`METHOD /path`), same order as the other columns. */
|
|
99
|
+
s: readonly string[];
|
|
100
|
+
/** Meta key dictionary; packed meta objects use decimal index keys. */
|
|
101
|
+
u?: readonly string[];
|
|
102
|
+
};
|
|
103
|
+
export declare function packInputSchemas(iv: unknown): unknown;
|
|
104
|
+
export declare function unpackInputSchemas(iv: unknown): unknown;
|
|
105
|
+
export declare function packOutputSchemas(os: unknown): unknown;
|
|
106
|
+
export declare function unpackOutputSchemas(os: unknown): unknown;
|
|
107
|
+
/**
|
|
108
|
+
* Inflate a packed route table into a live route tree.
|
|
109
|
+
* Each handler and each `ek` Set is a unique object so `.routeTree()` patches
|
|
110
|
+
* cannot cross-wire routes.
|
|
111
|
+
*/
|
|
112
|
+
export declare function assembleRouteTree(table: PackedRouteTable): RouteTree;
|
|
79
113
|
export declare function insertRoute(root: TreeNode, method: HttpMethod | "ALL", path: string, handler: RouteHandler): void;
|
|
80
114
|
export declare function matchRoute(root: TreeNode, method: HttpMethod, path: string): MatchResult;
|
|
81
115
|
export declare function insertWsRoute(root: TreeNode, path: string, handler: WSRouteHandler): void;
|
package/dist/tree.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAEnD,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B,MAAM,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEjF,MAAM,MAAM,YAAY,GAAG;IAC1B,qEAAqE;IACrE,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IACzD,oDAAoD;IACpD,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,4GAA4G;IAC5G,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,oEAAoE;IACpE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,CAAC,GAAG,IAAI,CAAA;IACxD,wEAAwE;IACxE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACf,uBAAuB;IACvB,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAClD,4DAA4D;IAC5D,EAAE,EAAE,eAAe,GAAG,IAAI,CAAA;IAC1B,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAClC,kFAAkF;IAClF,EAAE,EAAE,KAAK,CACR,CACC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,KAC5D,OAAO,CAAC,QAAQ,CAAC,CACtB,CAAA;IACD,mEAAmE;IACnE,EAAE,EAAE,eAAe,GAAG,IAAI,CAAA;IAC1B,yEAAyE;IACzE,EAAE,EAAE,eAAe,GAAG,IAAI,CAAA;IAC1B,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAA;CACV,CAAA;AAED,YAAY,EAAE,eAAe,EAAE,CAAA;AAE/B,MAAM,MAAM,cAAc,GAAG;IAC5B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACf,EAAE,EAAE,SAAS,CAAC,OAAO,CAAC,CAAA;IACtB,EAAE,EAAE,eAAe,GAAG,IAAI,CAAA;IAC1B,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;IAClC,EAAE,EAAE,KAAK,CACR,CACC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,KAC5D,OAAO,CAAC,QAAQ,CAAC,CACtB,CAAA;IACD,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAA;CACV,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACtB,gEAAgE;IAChE,CAAC,EAAE;QAAE,CAAC,EAAE,QAAQ,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACpC,qFAAqF;IACrF,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,mEAAmE;IACnE,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,KAAK,EAAE,YAAY,CAAC,GAAG,IAAI,CAAA;IAClD,mEAAmE;IACnE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAC3B,qEAAqE;IACrE,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,KAAK,EAAE,YAAY,CAAC,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACpE,sCAAsC;IACtC,EAAE,EAAE,cAAc,GAAG,IAAI,CAAA;CACzB,CAAA;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAIrD;AAED,MAAM,MAAM,WAAW,GACpB;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,KAAK,CAAA;CAAE,GACzC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACxE,IAAI,CAAA;AAEP,MAAM,WAAW,SAAS;CAAG;AAE7B,MAAM,MAAM,SAAS,GAAG;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACvC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;IAC/B,IAAI,EAAE,QAAQ,CAAA;CACd,CAAA;AAWD,wBAAgB,UAAU,IAAI,QAAQ,CAQrC;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAmEjH;AAqBD,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAsDxF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAoCzF;AAED,wBAAgB,YAAY,CAC3B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,MAAM,GACV;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,IAAI,CAqCpE;AAyED,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAG,IAAI,CAGlE;AAED,KAAK,SAAS,GAAG,SAAS,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;AAmBjE,wBAAgB,SAAS,CAAC,GAAG,KAAK,EAAE,SAAS,EAAE,GAAG,SAAS,CAc1D"}
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/codegen.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { InternPool } from "./codegen-route-tree-intern.ts"
|
|
2
1
|
import { deriveErrorEnvelopeName, deriveSchemaName, isErrorEnvelope, shortHash } from "./codegen-schema-naming.ts"
|
|
3
2
|
import type { SchemaNameContext } from "./codegen-schema-naming.ts"
|
|
4
3
|
import { effectJsonSchemaFn, loadEffectJsonSchema, loadToJSONSchema, toJSONSchemaFn } from "./codegen-loaders.ts"
|
|
@@ -23,7 +22,14 @@ import {
|
|
|
23
22
|
import { ERROR_META } from "./errors.ts"
|
|
24
23
|
import type { ErrorMetaEntry } from "./errors.ts"
|
|
25
24
|
import type { Honey } from "./index.ts"
|
|
26
|
-
import
|
|
25
|
+
import {
|
|
26
|
+
type PackedColumn,
|
|
27
|
+
type PackedRouteTable,
|
|
28
|
+
packInputSchemas,
|
|
29
|
+
packOutputSchemas,
|
|
30
|
+
type RouteHandler,
|
|
31
|
+
type TreeNode,
|
|
32
|
+
} from "./tree.ts"
|
|
27
33
|
import { irToTs } from "./ts-type-emitter.ts"
|
|
28
34
|
import { createTypeEmitState, emitSchemaType } from "./type-emitter.ts"
|
|
29
35
|
import type { TypeEmitState } from "./type-emitter.ts"
|
|
@@ -1992,129 +1998,98 @@ function collectRoutesForTree(node: TreeNode, currentPath: string, routes: Route
|
|
|
1992
1998
|
}
|
|
1993
1999
|
}
|
|
1994
2000
|
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
dynamic: { child: TreeBuild; name: string } | null
|
|
1998
|
-
handlers: Array<{ handler: string; method: string }>
|
|
1999
|
-
wildcard: {
|
|
2000
|
-
handlers: Array<{ handler: string; method: string }>
|
|
2001
|
-
name: string
|
|
2002
|
-
} | null
|
|
2003
|
-
}
|
|
2004
|
-
|
|
2005
|
-
function createTreeBuild(): TreeBuild {
|
|
2006
|
-
return { children: {}, dynamic: null, handlers: [], wildcard: null }
|
|
2001
|
+
function selectorOf(route: RouteConfig): string {
|
|
2002
|
+
return `${route.method} ${route.path}`
|
|
2007
2003
|
}
|
|
2008
2004
|
|
|
2009
|
-
function
|
|
2010
|
-
const
|
|
2011
|
-
const
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
const wExpr = node.wildcard
|
|
2021
|
-
? `{ n: ${JSON.stringify(node.wildcard.name)}, m: { ${node.wildcard.handlers.map((h) => `${h.method}: ${h.handler}`).join(", ")} } }`
|
|
2022
|
-
: "null"
|
|
2023
|
-
|
|
2024
|
-
const mExpr =
|
|
2025
|
-
node.handlers.length > 0 ? `{ ${node.handlers.map((h) => `${h.method}: ${h.handler}`).join(", ")} }` : "null"
|
|
2026
|
-
|
|
2027
|
-
const args = [sExpr]
|
|
2028
|
-
if (mExpr !== "null" || dExpr !== "null" || wExpr !== "null") {
|
|
2029
|
-
args.push(mExpr)
|
|
2030
|
-
if (dExpr !== "null" || wExpr !== "null") {
|
|
2031
|
-
args.push(dExpr)
|
|
2032
|
-
if (wExpr !== "null") args.push(wExpr)
|
|
2005
|
+
function encodePackedColumn<T>(values: T[]): PackedColumn<T> {
|
|
2006
|
+
const table: T[] = []
|
|
2007
|
+
const index: number[] = []
|
|
2008
|
+
const seen = new Map<string, number>()
|
|
2009
|
+
for (const value of values) {
|
|
2010
|
+
const key = JSON.stringify(value) ?? "null"
|
|
2011
|
+
let id = seen.get(key)
|
|
2012
|
+
if (id === undefined) {
|
|
2013
|
+
id = table.length
|
|
2014
|
+
seen.set(key, id)
|
|
2015
|
+
table.push(value)
|
|
2033
2016
|
}
|
|
2017
|
+
index.push(id)
|
|
2034
2018
|
}
|
|
2035
|
-
|
|
2019
|
+
const dict: PackedColumn<T> = { t: table, x: index }
|
|
2020
|
+
return JSON.stringify(dict).length < JSON.stringify(values).length ? dict : values
|
|
2036
2021
|
}
|
|
2037
2022
|
|
|
2038
|
-
function
|
|
2039
|
-
|
|
2040
|
-
if (node.dynamic !== null) return nodeHasStatic(node.dynamic.child)
|
|
2041
|
-
return false
|
|
2023
|
+
function pickSmallerJson<T extends object>(candidate: T, fallback: T): T {
|
|
2024
|
+
return JSON.stringify(candidate).length < JSON.stringify(fallback).length ? candidate : fallback
|
|
2042
2025
|
}
|
|
2043
2026
|
|
|
2044
|
-
function
|
|
2045
|
-
|
|
2027
|
+
function sharedErrorKeys(rows: string[][]): string[] {
|
|
2028
|
+
if (rows.length === 0) return []
|
|
2029
|
+
const sets = rows.map((row) => new Set(row))
|
|
2030
|
+
return rows[0].filter((key) => sets.every((set) => set.has(key)))
|
|
2046
2031
|
}
|
|
2047
2032
|
|
|
2048
|
-
function
|
|
2049
|
-
|
|
2050
|
-
|
|
2033
|
+
function encodeErrorKeys(rows: string[][]): Pick<PackedRouteTable, "e" | "k"> {
|
|
2034
|
+
if (!rows.some((row) => row.length > 0)) return {}
|
|
2035
|
+
const full: Pick<PackedRouteTable, "e" | "k"> = { e: encodePackedColumn(rows) }
|
|
2036
|
+
const shared = sharedErrorKeys(rows)
|
|
2037
|
+
if (shared.length === 0) return full
|
|
2038
|
+
const sharedSet = new Set(shared)
|
|
2039
|
+
const extras = rows.map((row) => row.filter((key) => !sharedSet.has(key)))
|
|
2040
|
+
const withBase: Pick<PackedRouteTable, "e" | "k"> = { k: shared }
|
|
2041
|
+
if (extras.some((row) => row.length > 0)) withBase.e = encodePackedColumn(extras)
|
|
2042
|
+
return pickSmallerJson(withBase, full)
|
|
2051
2043
|
}
|
|
2052
2044
|
|
|
2053
|
-
function
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
intern.force(route.outputSchemas, "O")
|
|
2066
|
-
intern.force(route.meta, "M")
|
|
2067
|
-
intern.force(selectorOf(route), "P")
|
|
2045
|
+
function encodeMetaColumn(rows: Array<Record<string, unknown> | null>): Pick<PackedRouteTable, "m" | "u"> {
|
|
2046
|
+
if (!rows.some((row) => row !== null)) return {}
|
|
2047
|
+
const names: string[] = []
|
|
2048
|
+
const seen = new Set<string>()
|
|
2049
|
+
for (const row of rows) {
|
|
2050
|
+
if (row === null) continue
|
|
2051
|
+
for (const key of Object.keys(row)) {
|
|
2052
|
+
if (seen.has(key)) continue
|
|
2053
|
+
if (/^\d+$/.test(key)) return { m: encodePackedColumn(rows) }
|
|
2054
|
+
seen.add(key)
|
|
2055
|
+
names.push(key)
|
|
2056
|
+
}
|
|
2068
2057
|
}
|
|
2069
|
-
|
|
2070
|
-
|
|
2058
|
+
if (names.length === 0) return { m: encodePackedColumn(rows) }
|
|
2059
|
+
const packed = rows.map((row) => {
|
|
2060
|
+
if (row === null) return null
|
|
2061
|
+
const out: Record<string, unknown> = Object.create(null)
|
|
2062
|
+
for (const [key, value] of Object.entries(row)) out[String(names.indexOf(key))] = value
|
|
2063
|
+
return out
|
|
2064
|
+
})
|
|
2065
|
+
return pickSmallerJson({ m: encodePackedColumn(packed), u: names }, { m: encodePackedColumn(rows) })
|
|
2071
2066
|
}
|
|
2072
2067
|
|
|
2073
|
-
function
|
|
2074
|
-
const
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
node.wildcard.handlers.push({ handler: hName, method: route.method })
|
|
2085
|
-
return
|
|
2086
|
-
}
|
|
2087
|
-
if (seg.startsWith(":")) {
|
|
2088
|
-
const name = seg.endsWith("?") ? seg.slice(1, -1) : seg.slice(1)
|
|
2089
|
-
if (node.dynamic === null) {
|
|
2090
|
-
node.dynamic = { child: createTreeBuild(), name }
|
|
2091
|
-
}
|
|
2092
|
-
if (i === segments.length - 1) {
|
|
2093
|
-
node.dynamic.child.handlers.push({
|
|
2094
|
-
handler: hName,
|
|
2095
|
-
method: route.method,
|
|
2096
|
-
})
|
|
2097
|
-
} else {
|
|
2098
|
-
node = node.dynamic.child
|
|
2099
|
-
}
|
|
2100
|
-
continue
|
|
2101
|
-
}
|
|
2102
|
-
if (node.children[seg] === undefined) {
|
|
2103
|
-
node.children[seg] = createTreeBuild()
|
|
2104
|
-
}
|
|
2105
|
-
if (i === segments.length - 1) {
|
|
2106
|
-
node.children[seg].handlers.push({
|
|
2107
|
-
handler: hName,
|
|
2108
|
-
method: route.method,
|
|
2109
|
-
})
|
|
2110
|
-
} else {
|
|
2111
|
-
node = node.children[seg]
|
|
2112
|
-
}
|
|
2068
|
+
function packRouteTable(routes: RouteConfig[]): PackedRouteTable {
|
|
2069
|
+
const table: PackedRouteTable = { s: routes.map(selectorOf) }
|
|
2070
|
+
const b = routes.map((r) => r.boundaryErrorKey)
|
|
2071
|
+
const e = routes.map((r) => r.errorKeys)
|
|
2072
|
+
const i = routes.map((r) => packInputSchemas(r.inputSchemas))
|
|
2073
|
+
const o = routes.map((r) => packOutputSchemas(r.outputSchemas))
|
|
2074
|
+
const m = routes.map((r) => r.meta)
|
|
2075
|
+
if (b.some((x) => x !== null)) {
|
|
2076
|
+
const first = b[0]
|
|
2077
|
+
if (first !== null && b.every((x) => x === first)) table.b = first
|
|
2078
|
+
else table.b = b
|
|
2113
2079
|
}
|
|
2080
|
+
Object.assign(table, encodeErrorKeys(e))
|
|
2081
|
+
if (i.some((x) => x !== null)) table.i = encodePackedColumn(i)
|
|
2082
|
+
if (o.some((x) => x !== null)) table.o = encodePackedColumn(o)
|
|
2083
|
+
Object.assign(table, encodeMetaColumn(m))
|
|
2084
|
+
return table
|
|
2085
|
+
}
|
|
2114
2086
|
|
|
2115
|
-
|
|
2116
|
-
|
|
2087
|
+
function emitPackedLiteral(value: unknown): string {
|
|
2088
|
+
const json = JSON.stringify(value)
|
|
2089
|
+
if (json.includes('"__proto__"')) {
|
|
2090
|
+
return `JSON.parse(${JSON.stringify(json)})`
|
|
2117
2091
|
}
|
|
2092
|
+
return json
|
|
2118
2093
|
}
|
|
2119
2094
|
|
|
2120
2095
|
function collectMetaShape(collected: CollectedRoute[]): {
|
|
@@ -2150,103 +2125,50 @@ function emitMetaShapeType(shape: ReturnType<typeof collectMetaShape>): string {
|
|
|
2150
2125
|
}
|
|
2151
2126
|
|
|
2152
2127
|
function emitRouteTree(routes: RouteConfig[], collected: CollectedRoute[] | null): string {
|
|
2153
|
-
const intern = buildInternPool(routes)
|
|
2154
2128
|
const metaShape = collected !== null ? collectMetaShape(collected) : null
|
|
2155
2129
|
const hasMetaShape = metaShape !== null && metaShape.allKeys.size > 0
|
|
2130
|
+
const selectors = routes.map(selectorOf)
|
|
2131
|
+
const table = packRouteTable(routes)
|
|
2156
2132
|
const lines: string[] = []
|
|
2157
|
-
lines.push('import type { TreeNode, RouteHandler, RouteTree } from "@lovrozagar/honey/tree"')
|
|
2158
|
-
lines.push("")
|
|
2159
|
-
lines.push("const E = Object.create(null) as Record<string, TreeNode>")
|
|
2160
2133
|
lines.push(
|
|
2161
|
-
'
|
|
2134
|
+
'import { assembleRouteTree, type PackedRouteTable, type RouteHandler, type RouteTree, type TreeNode } from "@lovrozagar/honey/tree"',
|
|
2162
2135
|
)
|
|
2163
|
-
lines.push('\treturn { s, d, w: w as TreeNode["w"], m: m as TreeNode["m"], ws: null }')
|
|
2164
|
-
lines.push("}")
|
|
2165
|
-
|
|
2166
|
-
const rootBuild = createTreeBuild()
|
|
2167
|
-
for (let i = 0; i < routes.length; i++) {
|
|
2168
|
-
insertHandler(rootBuild, routes[i], `H${i}`)
|
|
2169
|
-
}
|
|
2170
|
-
|
|
2171
|
-
if (nodeHasStatic(rootBuild)) {
|
|
2172
|
-
lines.push("function S(o: Record<string, TreeNode>): Record<string, TreeNode> {")
|
|
2173
|
-
lines.push("\treturn Object.assign(Object.create(null), o) as Record<string, TreeNode>")
|
|
2174
|
-
lines.push("}")
|
|
2175
|
-
}
|
|
2176
|
-
|
|
2177
|
-
if (routes.length > 0) {
|
|
2178
|
-
lines.push('const FN = null as unknown as RouteHandler["fn"]')
|
|
2179
|
-
}
|
|
2180
|
-
|
|
2181
|
-
const consts = intern.emitConstLines()
|
|
2182
|
-
if (consts.length > 0) {
|
|
2183
|
-
lines.push("")
|
|
2184
|
-
for (const line of consts) {
|
|
2185
|
-
if (hasMetaShape && /^const M\d+ = /.test(line)) lines.push(`${line} as unknown as MetaShape`)
|
|
2186
|
-
else lines.push(line)
|
|
2187
|
-
}
|
|
2188
|
-
}
|
|
2189
|
-
|
|
2190
|
-
if (routes.length > 0) {
|
|
2191
|
-
lines.push("")
|
|
2192
|
-
/* unique handler per route — sharing H objects would cross-wire .routeTree() patches */
|
|
2193
|
-
for (let i = 0; i < routes.length; i++) {
|
|
2194
|
-
const route = routes[i]
|
|
2195
|
-
const bekExpr = route.boundaryErrorKey !== null ? intern.expr(route.boundaryErrorKey) : "null"
|
|
2196
|
-
const ekSet = route.errorKeys.length > 0 ? `new Set(${intern.expr(route.errorKeys)})` : "new Set()"
|
|
2197
|
-
const ivExpr = route.inputSchemas !== null ? intern.expr(route.inputSchemas) : "null"
|
|
2198
|
-
const osExpr = route.outputSchemas !== null ? intern.expr(route.outputSchemas) : "null"
|
|
2199
|
-
const mtExpr = route.meta !== null ? intern.expr(route.meta) : "null"
|
|
2200
|
-
lines.push(
|
|
2201
|
-
`const H${i}: RouteHandler = { bek: ${bekExpr}, ef: null, fn: FN, mw: [], ek: ${ekSet}, iv: ${ivExpr}, os: ${osExpr}, mt: ${mtExpr}, ov: null, rp: "" }`,
|
|
2202
|
-
)
|
|
2203
|
-
}
|
|
2204
|
-
}
|
|
2205
|
-
|
|
2206
2136
|
lines.push("")
|
|
2207
|
-
lines.push(`
|
|
2208
|
-
lines.push(
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
lines.push(
|
|
2212
|
-
lines.
|
|
2213
|
-
|
|
2214
|
-
let code = lines.join("\n")
|
|
2137
|
+
lines.push(`declare const P: readonly ${JSON.stringify(selectors)}`)
|
|
2138
|
+
lines.push(`const D: PackedRouteTable = ${emitPackedLiteral(table)}`)
|
|
2139
|
+
lines.push("export const routeTree: RouteTree = assembleRouteTree(D)")
|
|
2140
|
+
lines.push("export const tree: TreeNode = routeTree.root")
|
|
2141
|
+
lines.push("export const handlers: Record<string, RouteHandler> = routeTree.handlers ?? {}")
|
|
2142
|
+
let code = `${lines.join("\n")}\n`
|
|
2215
2143
|
if (collected === null) return code
|
|
2216
2144
|
|
|
2217
|
-
const metaEntries: string[] = []
|
|
2218
|
-
for (const { handler, method, path } of collected) {
|
|
2219
|
-
if (handler.mt === null || Object.keys(handler.mt).length === 0) continue
|
|
2220
|
-
const selector = `${method} ${path}`
|
|
2221
|
-
metaEntries.push(`\t${mapKeyExpr(intern, selector)}: ${intern.expr(handler.mt)}`)
|
|
2222
|
-
}
|
|
2223
|
-
|
|
2224
2145
|
if (hasMetaShape && metaShape !== null) {
|
|
2225
2146
|
code += `\n${emitMetaShapeType(metaShape)}\n`
|
|
2226
2147
|
}
|
|
2227
2148
|
|
|
2228
|
-
const
|
|
2149
|
+
const publicSelectors: string[] = []
|
|
2229
2150
|
for (const { handler, method, path } of collected) {
|
|
2230
2151
|
if (handler._skip || isMetaInternal(handler)) continue
|
|
2231
|
-
|
|
2152
|
+
publicSelectors.push(`${method} ${path}`)
|
|
2232
2153
|
}
|
|
2233
|
-
if (
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2154
|
+
if (publicSelectors.length > 0) {
|
|
2155
|
+
if (publicSelectors.length === selectors.length) {
|
|
2156
|
+
code += "export type RouteSelector = typeof P[number]\n"
|
|
2157
|
+
} else {
|
|
2158
|
+
const parts = publicSelectors.map((s) => {
|
|
2159
|
+
const idx = selectors.indexOf(s)
|
|
2160
|
+
return idx >= 0 ? `typeof P[${idx}]` : JSON.stringify(s)
|
|
2161
|
+
})
|
|
2162
|
+
code += `export type RouteSelector = ${parts.join(" | ")}\n`
|
|
2163
|
+
}
|
|
2240
2164
|
}
|
|
2241
2165
|
|
|
2242
|
-
|
|
2166
|
+
const hasMeta = routes.some((r) => r.meta !== null && Object.keys(r.meta).length > 0)
|
|
2167
|
+
if (hasMeta) {
|
|
2243
2168
|
const metaType = hasMetaShape ? "Record<string, MetaShape>" : "Record<string, Record<string, unknown>>"
|
|
2244
|
-
code += `export const meta: ${metaType} =
|
|
2169
|
+
code += `export const meta: ${metaType} = routeTree.meta as ${metaType}\n`
|
|
2245
2170
|
}
|
|
2246
2171
|
|
|
2247
|
-
const hasMetaExport = metaEntries.length > 0
|
|
2248
|
-
code += `export const routeTree: RouteTree = { root: tree, ${hasMetaExport ? "meta, " : "meta: {}, "}handlers }\n`
|
|
2249
|
-
|
|
2250
2172
|
return code
|
|
2251
2173
|
}
|
|
2252
2174
|
|
package/src/tree.ts
CHANGED
|
@@ -108,6 +108,399 @@ 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
|
+
|
|
111
504
|
function splitSegments(path: string): string[] {
|
|
112
505
|
return path.split("/").filter((s) => s.length > 0)
|
|
113
506
|
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structural intern for generated route-tree modules.
|
|
3
|
-
*
|
|
4
|
-
* Handler objects stay unique (`.routeTree()` patches `fn`/`mw`/`iv`/`os` onto each
|
|
5
|
-
* `H*`). Values they point at — JSON Schema subtrees, meta objects, selector strings,
|
|
6
|
-
* error-key arrays — are shared by identity when their JSON is identical.
|
|
7
|
-
*/
|
|
8
|
-
export type ForcedPrefix = "I" | "M" | "O" | "P";
|
|
9
|
-
export declare class InternPool {
|
|
10
|
-
private readonly counts;
|
|
11
|
-
private readonly firstSeen;
|
|
12
|
-
private readonly forced;
|
|
13
|
-
private readonly forcedPrefix;
|
|
14
|
-
private readonly ids;
|
|
15
|
-
private readonly prefixCounters;
|
|
16
|
-
private readonly values;
|
|
17
|
-
private sealed;
|
|
18
|
-
count(v: unknown): void;
|
|
19
|
-
force(v: unknown, prefix: ForcedPrefix): void;
|
|
20
|
-
seal(): void;
|
|
21
|
-
id(v: unknown): string | undefined;
|
|
22
|
-
expr(v: unknown): string;
|
|
23
|
-
emitConstLines(): string[];
|
|
24
|
-
private shouldIntern;
|
|
25
|
-
private prefixFor;
|
|
26
|
-
private bump;
|
|
27
|
-
private printExpanded;
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=codegen-route-tree-intern.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codegen-route-tree-intern.d.ts","sourceRoot":"","sources":["../src/codegen-route-tree-intern.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,YAAY,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;AA4BhD,qBAAa,UAAU;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAC/D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA4B;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4B;IAC3D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,OAAO,CAAC,MAAM,CAAQ;IAEtB,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,CAsBtB;IAED,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CAU5C;IAED,IAAI,IAAI,IAAI,CAWX;IAED,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAGjC;IAED,IAAI,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAKvB;IAED,cAAc,IAAI,MAAM,EAAE,CAczB;IAED,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,SAAS;IASjB,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,aAAa;CAerB"}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structural intern for generated route-tree modules.
|
|
3
|
-
*
|
|
4
|
-
* Handler objects stay unique (`.routeTree()` patches `fn`/`mw`/`iv`/`os` onto each
|
|
5
|
-
* `H*`). Values they point at — JSON Schema subtrees, meta objects, selector strings,
|
|
6
|
-
* error-key arrays — are shared by identity when their JSON is identical.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export type ForcedPrefix = "I" | "M" | "O" | "P"
|
|
10
|
-
|
|
11
|
-
const STRING_MIN = 8
|
|
12
|
-
const NUMBER_MIN = 8
|
|
13
|
-
|
|
14
|
-
function canonical(v: unknown): string {
|
|
15
|
-
if (v === undefined) return "__undefined__"
|
|
16
|
-
return JSON.stringify(v) as string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function valueDepth(v: unknown): number {
|
|
20
|
-
if (v === null || typeof v !== "object") return 0
|
|
21
|
-
let max = 0
|
|
22
|
-
if (Array.isArray(v)) {
|
|
23
|
-
for (const x of v) {
|
|
24
|
-
const d = valueDepth(x)
|
|
25
|
-
if (d > max) max = d
|
|
26
|
-
}
|
|
27
|
-
return max + 1
|
|
28
|
-
}
|
|
29
|
-
for (const x of Object.values(v as Record<string, unknown>)) {
|
|
30
|
-
if (x === undefined) continue
|
|
31
|
-
const d = valueDepth(x)
|
|
32
|
-
if (d > max) max = d
|
|
33
|
-
}
|
|
34
|
-
return max + 1
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export class InternPool {
|
|
38
|
-
private readonly counts = new Map<string, number>()
|
|
39
|
-
private readonly firstSeen: string[] = []
|
|
40
|
-
private readonly forced = new Set<string>()
|
|
41
|
-
private readonly forcedPrefix = new Map<string, ForcedPrefix>()
|
|
42
|
-
private readonly ids = new Map<string, string>()
|
|
43
|
-
private readonly prefixCounters = new Map<string, number>()
|
|
44
|
-
private readonly values = new Map<string, unknown>()
|
|
45
|
-
private sealed = false
|
|
46
|
-
|
|
47
|
-
count(v: unknown): void {
|
|
48
|
-
if (v === null || v === undefined) return
|
|
49
|
-
const t = typeof v
|
|
50
|
-
if (t === "boolean") return
|
|
51
|
-
if (t === "number") {
|
|
52
|
-
if (Number.isFinite(v) && String(v).length >= NUMBER_MIN) this.bump(v)
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
if (t === "string") {
|
|
56
|
-
if ((v as string).length >= STRING_MIN) this.bump(v)
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
if (t === "object") {
|
|
60
|
-
this.bump(v)
|
|
61
|
-
if (Array.isArray(v)) {
|
|
62
|
-
for (const x of v) this.count(x)
|
|
63
|
-
return
|
|
64
|
-
}
|
|
65
|
-
for (const x of Object.values(v as Record<string, unknown>)) {
|
|
66
|
-
if (x !== undefined) this.count(x)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
force(v: unknown, prefix: ForcedPrefix): void {
|
|
72
|
-
if (v === null || v === undefined) return
|
|
73
|
-
const c = canonical(v)
|
|
74
|
-
if (!this.values.has(c)) {
|
|
75
|
-
this.values.set(c, v)
|
|
76
|
-
this.firstSeen.push(c)
|
|
77
|
-
this.counts.set(c, this.counts.get(c) ?? 1)
|
|
78
|
-
}
|
|
79
|
-
this.forced.add(c)
|
|
80
|
-
if (!this.forcedPrefix.has(c)) this.forcedPrefix.set(c, prefix)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
seal(): void {
|
|
84
|
-
if (this.sealed) return
|
|
85
|
-
this.sealed = true
|
|
86
|
-
for (const c of this.firstSeen) {
|
|
87
|
-
const v = this.values.get(c)
|
|
88
|
-
if (!this.shouldIntern(v)) continue
|
|
89
|
-
const prefix = this.prefixFor(c, v)
|
|
90
|
-
const n = this.prefixCounters.get(prefix) ?? 0
|
|
91
|
-
this.prefixCounters.set(prefix, n + 1)
|
|
92
|
-
this.ids.set(c, `${prefix}${n}`)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
id(v: unknown): string | undefined {
|
|
97
|
-
if (v === undefined) return undefined
|
|
98
|
-
return this.ids.get(canonical(v))
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
expr(v: unknown): string {
|
|
102
|
-
if (v === undefined) return "undefined"
|
|
103
|
-
const ref = this.ids.get(canonical(v))
|
|
104
|
-
if (ref !== undefined) return ref
|
|
105
|
-
return this.printExpanded(v)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
emitConstLines(): string[] {
|
|
109
|
-
const items: Array<{ c: string; depth: number; id: string; seen: number; v: unknown }> = []
|
|
110
|
-
for (const [c, id] of this.ids) {
|
|
111
|
-
const v = this.values.get(c)
|
|
112
|
-
items.push({ c, depth: valueDepth(v), id, seen: this.firstSeen.indexOf(c), v })
|
|
113
|
-
}
|
|
114
|
-
items.sort((a, b) => a.depth - b.depth || a.seen - b.seen || a.id.localeCompare(b.id))
|
|
115
|
-
return items.map((it) => {
|
|
116
|
-
const kind = this.forcedPrefix.get(it.c)
|
|
117
|
-
let rhs = this.printExpanded(it.v)
|
|
118
|
-
if (kind === "I") rhs += ' as unknown as RouteHandler["iv"]'
|
|
119
|
-
else if (kind === "O") rhs += ' as unknown as RouteHandler["os"]'
|
|
120
|
-
return `const ${it.id} = ${rhs}`
|
|
121
|
-
})
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
private shouldIntern(v: unknown): boolean {
|
|
125
|
-
if (v === null || v === undefined) return false
|
|
126
|
-
const c = canonical(v)
|
|
127
|
-
if (this.forced.has(c)) return true
|
|
128
|
-
const n = this.counts.get(c) ?? 0
|
|
129
|
-
if (n < 2) return false
|
|
130
|
-
const t = typeof v
|
|
131
|
-
if (t === "string") return (v as string).length >= STRING_MIN
|
|
132
|
-
if (t === "number") return Number.isFinite(v) && String(v).length >= NUMBER_MIN
|
|
133
|
-
if (Array.isArray(v) && v.length === 0) return false
|
|
134
|
-
return t === "object"
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private prefixFor(c: string, v: unknown): string {
|
|
138
|
-
const forced = this.forcedPrefix.get(c)
|
|
139
|
-
if (forced !== undefined) return forced
|
|
140
|
-
if (typeof v === "string") return "T"
|
|
141
|
-
if (typeof v === "number") return "U"
|
|
142
|
-
if (Array.isArray(v)) return "A"
|
|
143
|
-
return "J"
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private bump(v: unknown): void {
|
|
147
|
-
const c = canonical(v)
|
|
148
|
-
const n = (this.counts.get(c) ?? 0) + 1
|
|
149
|
-
this.counts.set(c, n)
|
|
150
|
-
if (n === 1) {
|
|
151
|
-
this.values.set(c, v)
|
|
152
|
-
this.firstSeen.push(c)
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
private printExpanded(v: unknown): string {
|
|
157
|
-
if (v === null) return "null"
|
|
158
|
-
if (v === true) return "true"
|
|
159
|
-
if (v === false) return "false"
|
|
160
|
-
const t = typeof v
|
|
161
|
-
if (t === "string") return JSON.stringify(v)
|
|
162
|
-
if (t === "number") return String(v)
|
|
163
|
-
if (Array.isArray(v)) return `[${v.map((x) => this.expr(x)).join(",")}]`
|
|
164
|
-
if (t === "object") {
|
|
165
|
-
const obj = v as Record<string, unknown>
|
|
166
|
-
const keys = Object.keys(obj).filter((k) => obj[k] !== undefined)
|
|
167
|
-
return `{${keys.map((k) => `${JSON.stringify(k)}:${this.expr(obj[k])}`).join(",")}}`
|
|
168
|
-
}
|
|
169
|
-
return JSON.stringify(v) ?? "undefined"
|
|
170
|
-
}
|
|
171
|
-
}
|