@lovrozagar/honey 0.4.1 → 0.5.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.
@@ -0,0 +1,29 @@
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
@@ -0,0 +1 @@
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 +1 @@
1
- {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovrozagar/honey",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Type-safe API framework built on Web Standards. Builder-pattern DX, precompiled radix tree in production.",
5
5
  "keywords": [
6
6
  "api",
@@ -0,0 +1,171 @@
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
+ }
package/src/codegen.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { InternPool } from "./codegen-route-tree-intern.ts"
1
2
  import { deriveErrorEnvelopeName, deriveSchemaName, isErrorEnvelope, shortHash } from "./codegen-schema-naming.ts"
2
3
  import type { SchemaNameContext } from "./codegen-schema-naming.ts"
3
4
  import { effectJsonSchemaFn, loadEffectJsonSchema, loadToJSONSchema, toJSONSchemaFn } from "./codegen-loaders.ts"
@@ -2009,7 +2010,7 @@ function serializeNode(node: TreeBuild): string {
2009
2010
  const staticEntries = Object.entries(node.children)
2010
2011
  const sExpr =
2011
2012
  staticEntries.length > 0
2012
- ? `Object.assign(Object.create(null), { ${staticEntries.map(([k, v]) => `${JSON.stringify(k)}: ${serializeNode(v)}`).join(", ")} })`
2013
+ ? `S({ ${staticEntries.map(([k, v]) => `${JSON.stringify(k)}: ${serializeNode(v)}`).join(", ")} })`
2013
2014
  : "E"
2014
2015
 
2015
2016
  const dExpr = node.dynamic
@@ -2023,163 +2024,207 @@ function serializeNode(node: TreeBuild): string {
2023
2024
  const mExpr =
2024
2025
  node.handlers.length > 0 ? `{ ${node.handlers.map((h) => `${h.method}: ${h.handler}`).join(", ")} }` : "null"
2025
2026
 
2026
- return `{ s: ${sExpr}, d: ${dExpr}, w: ${wExpr}, m: ${mExpr}, ws: null }`
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)
2033
+ }
2034
+ }
2035
+ return `N(${args.join(", ")})`
2027
2036
  }
2028
2037
 
2029
- function toTsLiteral(v: unknown): string {
2030
- if (v === null) return "null"
2031
- if (v === true) return "true"
2032
- if (v === false) return "false"
2033
- if (Array.isArray(v)) return "unknown[]"
2034
- if (typeof v === "string") return JSON.stringify(v)
2035
- if (typeof v === "number") return String(v)
2036
- if (typeof v === "object") return "Record<string, unknown>"
2037
- return typeof v
2038
+ function nodeHasStatic(node: TreeBuild): boolean {
2039
+ if (Object.keys(node.children).length > 0) return true
2040
+ if (node.dynamic !== null) return nodeHasStatic(node.dynamic.child)
2041
+ return false
2038
2042
  }
2039
2043
 
2040
- export function generateRouteTree(routes: RouteConfig[]): string {
2041
- const lines: string[] = []
2042
- lines.push('import type { TreeNode, RouteHandler, RouteTree } from "@lovrozagar/honey/tree"')
2043
- lines.push("")
2044
- lines.push("const E = Object.create(null) as Record<string, TreeNode>")
2045
- lines.push("")
2044
+ function selectorOf(route: RouteConfig): string {
2045
+ return `${route.method} ${route.path}`
2046
+ }
2046
2047
 
2047
- /* unique handler per route — no dedup, patching shared handlers would corrupt */
2048
- const handlerEntries: Array<{ index: number; route: RouteConfig }> = []
2049
- for (let i = 0; i < routes.length; i++) {
2050
- handlerEntries.push({ index: i, route: routes[i] })
2051
- }
2052
-
2053
- /* emit handler configs with pre-built ek and mt */
2054
- for (const { index, route } of handlerEntries) {
2055
- const mwList = "[]"
2056
- const bekExpr = route.boundaryErrorKey !== null ? JSON.stringify(route.boundaryErrorKey) : "null"
2057
- const ekSet = route.errorKeys.length > 0 ? `new Set(${JSON.stringify(route.errorKeys)})` : "new Set()"
2058
- const mtExpr = route.meta !== null ? JSON.stringify(route.meta) : "null"
2059
- const ivExpr =
2060
- route.inputSchemas !== null ? `${JSON.stringify(route.inputSchemas)} as unknown as RouteHandler["iv"]` : "null"
2061
- const osExpr =
2062
- route.outputSchemas !== null ? `${JSON.stringify(route.outputSchemas)} as unknown as RouteHandler["os"]` : "null"
2063
- lines.push(
2064
- `const H${index}: RouteHandler = { bek: ${bekExpr}, ef: null, fn: null as unknown as RouteHandler["fn"], mw: ${mwList}, ek: ${ekSet}, iv: ${ivExpr}, os: ${osExpr}, mt: ${mtExpr}, ov: null, rp: "" }`,
2065
- )
2066
- }
2048
+ function mapKeyExpr(intern: InternPool, selector: string): string {
2049
+ const id = intern.id(selector)
2050
+ return id !== undefined ? `[${id}]` : JSON.stringify(selector)
2051
+ }
2067
2052
 
2068
- lines.push("")
2053
+ function buildInternPool(routes: RouteConfig[]): InternPool {
2054
+ const intern = new InternPool()
2055
+ for (const route of routes) {
2056
+ intern.count(route.boundaryErrorKey)
2057
+ intern.count(route.errorKeys)
2058
+ intern.count(route.inputSchemas)
2059
+ intern.count(route.outputSchemas)
2060
+ intern.count(route.meta)
2061
+ intern.count(selectorOf(route))
2062
+ }
2063
+ for (const route of routes) {
2064
+ intern.force(route.inputSchemas, "I")
2065
+ intern.force(route.outputSchemas, "O")
2066
+ intern.force(route.meta, "M")
2067
+ intern.force(selectorOf(route), "P")
2068
+ }
2069
+ intern.seal()
2070
+ return intern
2071
+ }
2069
2072
 
2070
- /* build tree structure */
2071
- const rootBuild = createTreeBuild()
2073
+ function insertHandler(rootBuild: TreeBuild, route: RouteConfig, hName: string): void {
2074
+ const segments = route.path.split("/").filter((s) => s.length > 0)
2075
+ let node = rootBuild
2072
2076
 
2073
- for (const { index, route } of handlerEntries) {
2074
- const hName = `H${index}`
2075
- const segments = route.path.split("/").filter((s) => s.length > 0)
2076
- let node = rootBuild
2077
-
2078
- for (let i = 0; i < segments.length; i++) {
2079
- const seg = segments[i]
2080
- if (seg.startsWith("*")) {
2081
- const name = seg.length > 1 ? seg.slice(1) : "*"
2082
- if (node.wildcard === null) {
2083
- node.wildcard = { handlers: [], name }
2084
- }
2085
- node.wildcard.handlers.push({ handler: hName, method: route.method })
2086
- break
2087
- }
2088
- if (seg.startsWith(":")) {
2089
- const name = seg.endsWith("?") ? seg.slice(1, -1) : seg.slice(1)
2090
- if (node.dynamic === null) {
2091
- node.dynamic = { child: createTreeBuild(), name }
2092
- }
2093
- if (i === segments.length - 1) {
2094
- node.dynamic.child.handlers.push({
2095
- handler: hName,
2096
- method: route.method,
2097
- })
2098
- } else {
2099
- node = node.dynamic.child
2100
- }
2101
- continue
2077
+ for (let i = 0; i < segments.length; i++) {
2078
+ const seg = segments[i]
2079
+ if (seg.startsWith("*")) {
2080
+ const name = seg.length > 1 ? seg.slice(1) : "*"
2081
+ if (node.wildcard === null) {
2082
+ node.wildcard = { handlers: [], name }
2102
2083
  }
2103
- if (node.children[seg] === undefined) {
2104
- node.children[seg] = createTreeBuild()
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 }
2105
2091
  }
2106
2092
  if (i === segments.length - 1) {
2107
- node.children[seg].handlers.push({
2093
+ node.dynamic.child.handlers.push({
2108
2094
  handler: hName,
2109
2095
  method: route.method,
2110
2096
  })
2111
2097
  } else {
2112
- node = node.children[seg]
2098
+ node = node.dynamic.child
2113
2099
  }
2100
+ continue
2114
2101
  }
2115
-
2116
- if (segments.length === 0) {
2117
- node.handlers.push({ handler: hName, method: route.method })
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]
2118
2112
  }
2119
2113
  }
2120
2114
 
2121
- lines.push(`export const tree: TreeNode = ${serializeNode(rootBuild)}`)
2122
- lines.push("")
2123
-
2124
- /* emit handler lookup map for .routeTree() patching */
2125
- const handlerMapEntries = handlerEntries.map(
2126
- ({ index, route }) => `\t${JSON.stringify(`${route.method} ${route.path}`)}: H${index}`,
2127
- )
2128
- lines.push(`export const handlers: Record<string, RouteHandler> = {\n${handlerMapEntries.join(",\n")}\n}`)
2129
- lines.push("")
2130
-
2131
- return lines.join("\n")
2132
- }
2133
-
2134
- function generateFromTreeRoot(root: TreeNode): string {
2135
- const routes: RouteConfig[] = []
2136
- collectRoutesForTree(root, "", routes)
2137
-
2138
- const collected: CollectedRoute[] = []
2139
- walkTree(root, "", collected)
2140
-
2141
- let code = generateRouteTree(routes)
2142
-
2143
- /* emit meta export — full meta for gateway/external consumers */
2144
- const metaEntries: string[] = []
2145
- for (const { handler, method, path } of collected) {
2146
- if (handler.mt === null || Object.keys(handler.mt).length === 0) continue
2147
- metaEntries.push(`\t${JSON.stringify(`${method} ${path}`)}: ${JSON.stringify(handler.mt)}`)
2115
+ if (segments.length === 0) {
2116
+ node.handlers.push({ handler: hName, method: route.method })
2148
2117
  }
2118
+ }
2149
2119
 
2150
- /* emit MetaShape type from handler metas — preserve literal types */
2120
+ function collectMetaShape(collected: CollectedRoute[]): {
2121
+ allKeys: Map<string, Set<string>>
2122
+ keyCount: Map<string, number>
2123
+ metaHandlerCount: number
2124
+ } {
2151
2125
  const allKeys = new Map<string, Set<string>>()
2126
+ const keyCount = new Map<string, number>()
2152
2127
  let metaHandlerCount = 0
2153
2128
  for (const { handler } of collected) {
2154
2129
  if (handler.mt === null) continue
2155
2130
  metaHandlerCount++
2156
2131
  for (const [k, v] of Object.entries(handler.mt)) {
2157
2132
  if (!allKeys.has(k)) allKeys.set(k, new Set())
2158
- allKeys.get(k)?.add(toTsLiteral(v))
2133
+ allKeys.get(k)?.add(emitLiteral(v))
2134
+ keyCount.set(k, (keyCount.get(k) ?? 0) + 1)
2159
2135
  }
2160
2136
  }
2137
+ return { allKeys, keyCount, metaHandlerCount }
2138
+ }
2161
2139
 
2162
- /* count per-key occurrences to determine optionality */
2163
- const keyCount = new Map<string, number>()
2164
- for (const { handler } of collected) {
2165
- if (handler.mt === null) continue
2166
- for (const k of Object.keys(handler.mt)) {
2167
- keyCount.set(k, (keyCount.get(k) ?? 0) + 1)
2140
+ function emitMetaShapeType(shape: ReturnType<typeof collectMetaShape>): string {
2141
+ if (shape.allKeys.size === 0) return ""
2142
+ const props = [...shape.allKeys.entries()]
2143
+ .sort(([a], [b]) => a.localeCompare(b))
2144
+ .map(([key, types]) => {
2145
+ const optional = (shape.keyCount.get(key) ?? 0) < shape.metaHandlerCount ? "?" : ""
2146
+ const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : `"${key}"`
2147
+ return `\t${safeKey}${optional}: ${[...types].join(" | ")}`
2148
+ })
2149
+ return `export type MetaShape = {\n${props.join("\n")}\n} & Record<string, unknown>\n`
2150
+ }
2151
+
2152
+ function emitRouteTree(routes: RouteConfig[], collected: CollectedRoute[] | null): string {
2153
+ const intern = buildInternPool(routes)
2154
+ const metaShape = collected !== null ? collectMetaShape(collected) : null
2155
+ const hasMetaShape = metaShape !== null && metaShape.allKeys.size > 0
2156
+ 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
+ lines.push(
2161
+ 'function N(s: Record<string, TreeNode>, m: Record<string, RouteHandler> | null = null, d: TreeNode["d"] = null, w: { n: string; m: Record<string, RouteHandler> } | null = null): TreeNode {',
2162
+ )
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)
2168
2187
  }
2169
2188
  }
2170
2189
 
2171
- if (allKeys.size > 0) {
2172
- const props = [...allKeys.entries()]
2173
- .sort(([a], [b]) => a.localeCompare(b))
2174
- .map(([key, types]) => {
2175
- const optional = (keyCount.get(key) ?? 0) < metaHandlerCount ? "?" : ""
2176
- const safeKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key) ? key : `"${key}"`
2177
- return `\t${safeKey}${optional}: ${[...types].join(" | ")}`
2178
- })
2179
- code += `\nexport type MetaShape = {\n${props.join("\n")}\n}\n\n`
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
+ lines.push("")
2207
+ lines.push(`export const tree: TreeNode = ${serializeNode(rootBuild)}`)
2208
+ lines.push("")
2209
+
2210
+ const handlerMapEntries = routes.map((route, index) => `\t${mapKeyExpr(intern, selectorOf(route))}: H${index}`)
2211
+ lines.push(`export const handlers: Record<string, RouteHandler> = {\n${handlerMapEntries.join(",\n")}\n}`)
2212
+ lines.push("")
2213
+
2214
+ let code = lines.join("\n")
2215
+ if (collected === null) return code
2216
+
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
+ if (hasMetaShape && metaShape !== null) {
2225
+ code += `\n${emitMetaShapeType(metaShape)}\n`
2180
2226
  }
2181
2227
 
2182
- /* emit RouteSelector union from route graph */
2183
2228
  const selectors = new Set<string>()
2184
2229
  for (const { handler, method, path } of collected) {
2185
2230
  if (handler._skip || isMetaInternal(handler)) continue
@@ -2187,21 +2232,36 @@ function generateFromTreeRoot(root: TreeNode): string {
2187
2232
  }
2188
2233
  if (selectors.size > 0) {
2189
2234
  const sorted = [...selectors].sort()
2190
- code += `\nexport type RouteSelector = ${sorted.map((s) => JSON.stringify(s)).join(" | ")}\n`
2235
+ const parts = sorted.map((s) => {
2236
+ const id = intern.id(s)
2237
+ return id !== undefined ? `typeof ${id}` : JSON.stringify(s)
2238
+ })
2239
+ code += `\nexport type RouteSelector = ${parts.join(" | ")}\n`
2191
2240
  }
2192
2241
 
2193
2242
  if (metaEntries.length > 0) {
2194
- const metaType = allKeys.size > 0 ? "Record<string, MetaShape>" : "Record<string, Record<string, unknown>>"
2243
+ const metaType = hasMetaShape ? "Record<string, MetaShape>" : "Record<string, Record<string, unknown>>"
2195
2244
  code += `export const meta: ${metaType} = {\n${metaEntries.join(",\n")}\n}\n`
2196
2245
  }
2197
2246
 
2198
- /* emit routeTree convenience export for .routeTree() */
2199
2247
  const hasMetaExport = metaEntries.length > 0
2200
2248
  code += `export const routeTree: RouteTree = { root: tree, ${hasMetaExport ? "meta, " : "meta: {}, "}handlers }\n`
2201
2249
 
2202
2250
  return code
2203
2251
  }
2204
2252
 
2253
+ export function generateRouteTree(routes: RouteConfig[]): string {
2254
+ return emitRouteTree(routes, null)
2255
+ }
2256
+
2257
+ function generateFromTreeRoot(root: TreeNode): string {
2258
+ const routes: RouteConfig[] = []
2259
+ collectRoutesForTree(root, "", routes)
2260
+ const collected: CollectedRoute[] = []
2261
+ walkTree(root, "", collected)
2262
+ return emitRouteTree(routes, collected)
2263
+ }
2264
+
2205
2265
  export function generateRouteTreeFromApp<TEnv, TCtx>(
2206
2266
  app: Honey<TEnv, TCtx, unknown, unknown, unknown, string, string>,
2207
2267
  ): string {