@lovrozagar/honey 0.7.2 → 1.0.0-rc.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.
Files changed (1003) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -1969
  3. package/bin/honey.js +87 -27
  4. package/dist/adapters/bun/serve.d.ts +18 -0
  5. package/dist/adapters/bun/serve.js +89 -0
  6. package/dist/adapters/fetch-request.d.ts +20 -0
  7. package/dist/adapters/fetch-request.js +29 -0
  8. package/dist/adapters/node/headers.d.ts +27 -0
  9. package/dist/adapters/node/headers.js +86 -0
  10. package/dist/adapters/node/request.d.ts +16 -0
  11. package/dist/adapters/node/request.js +214 -0
  12. package/dist/adapters/node/response.d.ts +11 -0
  13. package/dist/adapters/node/response.js +126 -0
  14. package/dist/adapters/node/serve.d.ts +39 -0
  15. package/dist/adapters/node/serve.js +205 -0
  16. package/dist/adapters/node/url.d.ts +13 -0
  17. package/dist/adapters/node/url.js +87 -0
  18. package/dist/adapters/serve.d.ts +36 -0
  19. package/dist/adapters/serve.js +52 -0
  20. package/dist/build/artifacts.d.ts +34 -0
  21. package/dist/build/artifacts.js +123 -0
  22. package/dist/build/cli-args.d.ts +30 -0
  23. package/dist/build/cli-args.js +97 -0
  24. package/dist/build/cli.d.ts +11 -0
  25. package/dist/build/cli.js +150 -0
  26. package/dist/build/config.d.ts +102 -0
  27. package/dist/build/config.js +89 -0
  28. package/dist/build/generate.d.ts +19 -0
  29. package/dist/build/generate.js +80 -0
  30. package/dist/build/glob.d.ts +8 -0
  31. package/dist/build/glob.js +97 -0
  32. package/dist/build/index.d.ts +3 -58
  33. package/dist/build/index.js +3 -173
  34. package/dist/build/init.d.ts +3 -0
  35. package/dist/build/init.js +131 -0
  36. package/dist/build/loaders.d.ts +33 -0
  37. package/dist/build/loaders.js +105 -0
  38. package/dist/build/plugin.d.ts +52 -0
  39. package/dist/build/plugin.js +146 -0
  40. package/dist/build/source.d.ts +21 -0
  41. package/dist/build/source.js +100 -0
  42. package/dist/build/targets.d.ts +59 -0
  43. package/dist/build/targets.js +107 -0
  44. package/dist/context/context.d.ts +111 -0
  45. package/dist/context/context.js +213 -0
  46. package/dist/context/cookie-sign.d.ts +38 -0
  47. package/dist/context/cookie-sign.js +113 -0
  48. package/dist/context/cookie.d.ts +28 -0
  49. package/dist/context/cookie.js +142 -0
  50. package/dist/context/peer.d.ts +34 -0
  51. package/dist/context/peer.js +190 -0
  52. package/dist/errors/error.d.ts +60 -0
  53. package/dist/errors/error.js +84 -0
  54. package/dist/errors/errors.d.ts +45 -0
  55. package/dist/errors/errors.js +31 -0
  56. package/dist/errors/on-error.d.ts +10 -0
  57. package/dist/errors/on-error.js +204 -0
  58. package/dist/errors/problem-json.d.ts +14 -0
  59. package/dist/errors/problem-json.js +58 -0
  60. package/dist/errors/projector.d.ts +50 -0
  61. package/dist/errors/projector.js +107 -0
  62. package/dist/i18n/error-i18n.d.ts +26 -0
  63. package/dist/i18n/error-i18n.js +77 -0
  64. package/dist/i18n/i18n.d.ts +21 -0
  65. package/dist/i18n/i18n.js +40 -0
  66. package/dist/i18n/icu.d.ts +29 -0
  67. package/dist/i18n/icu.js +170 -0
  68. package/dist/i18n/index.d.ts +4 -0
  69. package/dist/i18n/index.js +3 -0
  70. package/dist/index.d.ts +30 -744
  71. package/dist/index.js +12 -2363
  72. package/dist/input/accepts.d.ts +5 -0
  73. package/dist/input/accepts.js +105 -0
  74. package/dist/input/binary.d.ts +20 -0
  75. package/dist/input/binary.js +40 -0
  76. package/dist/input/body-kind.d.ts +15 -0
  77. package/dist/input/body-kind.js +47 -0
  78. package/dist/input/body-limit.d.ts +21 -0
  79. package/dist/input/body-limit.js +99 -0
  80. package/dist/input/cookies.d.ts +7 -0
  81. package/dist/input/cookies.js +8 -0
  82. package/dist/input/form.d.ts +10 -0
  83. package/dist/input/form.js +24 -0
  84. package/dist/input/headers.d.ts +7 -0
  85. package/dist/input/headers.js +8 -0
  86. package/dist/input/input.d.ts +91 -0
  87. package/dist/input/input.js +88 -0
  88. package/dist/input/json.d.ts +10 -0
  89. package/dist/input/json.js +22 -0
  90. package/dist/input/params.d.ts +7 -0
  91. package/dist/input/params.js +8 -0
  92. package/dist/input/query.d.ts +10 -0
  93. package/dist/input/query.js +17 -0
  94. package/dist/mcp/mount.d.ts +116 -0
  95. package/dist/mcp/mount.js +45 -0
  96. package/dist/mcp/oauth.d.ts +14 -0
  97. package/dist/mcp/oauth.js +88 -0
  98. package/dist/mcp/uploads.d.ts +36 -0
  99. package/dist/mcp/uploads.js +171 -0
  100. package/dist/mcp/url-files.d.ts +32 -0
  101. package/dist/mcp/url-files.js +75 -0
  102. package/dist/meta/meta-spec-apply.d.ts +25 -0
  103. package/dist/meta/meta-spec-apply.js +83 -0
  104. package/dist/meta/meta-spec-merge.d.ts +103 -0
  105. package/dist/meta/meta-spec-merge.js +50 -0
  106. package/dist/meta/meta-spec-validate.d.ts +61 -0
  107. package/dist/meta/meta-spec-validate.js +166 -0
  108. package/dist/meta/meta-spec.d.ts +49 -0
  109. package/dist/meta/meta-spec.js +197 -0
  110. package/dist/middleware/compress.d.ts +15 -0
  111. package/dist/middleware/compress.js +93 -0
  112. package/dist/middleware/cors.d.ts +18 -0
  113. package/dist/middleware/cors.js +80 -0
  114. package/dist/middleware/csrf.d.ts +11 -0
  115. package/dist/middleware/csrf.js +65 -0
  116. package/dist/middleware/ip-restrict.d.ts +10 -0
  117. package/dist/middleware/ip-restrict.js +82 -0
  118. package/dist/middleware/middleware.d.ts +53 -0
  119. package/dist/middleware/middleware.js +112 -0
  120. package/dist/middleware/powered-by.d.ts +6 -0
  121. package/dist/middleware/powered-by.js +13 -0
  122. package/dist/middleware/rate-limit.d.ts +40 -0
  123. package/dist/middleware/rate-limit.js +90 -0
  124. package/dist/middleware/request-id.d.ts +25 -0
  125. package/dist/middleware/request-id.js +30 -0
  126. package/dist/middleware/secure-headers.d.ts +18 -0
  127. package/dist/middleware/secure-headers.js +36 -0
  128. package/dist/middleware/server-timing.d.ts +8 -0
  129. package/dist/middleware/server-timing.js +52 -0
  130. package/dist/middleware/timeout.d.ts +6 -0
  131. package/dist/middleware/timeout.js +29 -0
  132. package/dist/observability/curl-logger.d.ts +46 -0
  133. package/dist/observability/curl-logger.js +175 -0
  134. package/dist/observability/request-to-curl.d.ts +17 -0
  135. package/dist/observability/request-to-curl.js +47 -0
  136. package/dist/openapi/collect.d.ts +56 -18
  137. package/dist/openapi/collect.js +109 -23
  138. package/dist/openapi/components.d.ts +9 -0
  139. package/dist/openapi/components.js +90 -0
  140. package/dist/openapi/docs-page.d.ts +20 -18
  141. package/dist/openapi/docs-page.js +28 -46
  142. package/dist/openapi/document.d.ts +33 -26
  143. package/dist/openapi/document.js +21 -776
  144. package/dist/openapi/extract-schemas.d.ts +11 -0
  145. package/dist/openapi/extract-schemas.js +31 -0
  146. package/dist/openapi/generate.d.ts +47 -0
  147. package/dist/openapi/generate.js +180 -0
  148. package/dist/openapi/manifest.d.ts +41 -0
  149. package/dist/openapi/manifest.js +49 -0
  150. package/dist/openapi/output-keys.d.ts +6 -0
  151. package/dist/openapi/output-keys.js +24 -0
  152. package/dist/openapi/paths.d.ts +35 -0
  153. package/dist/openapi/paths.js +175 -0
  154. package/dist/openapi/register.d.ts +14 -3
  155. package/dist/openapi/register.js +13 -20
  156. package/dist/openapi/responses.d.ts +44 -0
  157. package/dist/openapi/responses.js +159 -0
  158. package/dist/openapi/scalar.d.ts +4 -14
  159. package/dist/openapi/scalar.js +5 -7
  160. package/dist/openapi/security.d.ts +4 -0
  161. package/dist/openapi/security.js +25 -0
  162. package/dist/openapi/serve.d.ts +25 -9
  163. package/dist/openapi/serve.js +108 -29
  164. package/dist/openapi/servers.d.ts +19 -0
  165. package/dist/openapi/servers.js +72 -0
  166. package/dist/openapi/swagger.d.ts +4 -14
  167. package/dist/openapi/swagger.js +5 -7
  168. package/dist/openapi/tags.d.ts +20 -0
  169. package/dist/openapi/tags.js +20 -0
  170. package/dist/openapi/webhooks.d.ts +19 -0
  171. package/dist/openapi/webhooks.js +70 -0
  172. package/dist/openapi/yaml.d.ts +8 -0
  173. package/dist/openapi/yaml.js +74 -0
  174. package/dist/proxy/headers.d.ts +30 -0
  175. package/dist/proxy/headers.js +86 -0
  176. package/dist/proxy/proxy.d.ts +39 -0
  177. package/dist/proxy/proxy.js +103 -0
  178. package/dist/proxy/upstream.d.ts +30 -0
  179. package/dist/proxy/upstream.js +116 -0
  180. package/dist/realtime/bus.d.ts +10 -13
  181. package/dist/realtime/bus.js +48 -93
  182. package/dist/realtime/invoke-user.d.ts +36 -0
  183. package/dist/realtime/invoke-user.js +103 -0
  184. package/dist/realtime/realtime.d.ts +7 -0
  185. package/dist/realtime/realtime.js +40 -0
  186. package/dist/realtime/route.d.ts +33 -27
  187. package/dist/realtime/route.js +27 -43
  188. package/dist/realtime/server.d.ts +24 -28
  189. package/dist/realtime/server.js +202 -225
  190. package/dist/response/binary.d.ts +18 -0
  191. package/dist/response/binary.js +10 -0
  192. package/dist/response/builder.d.ts +73 -0
  193. package/dist/response/builder.js +214 -0
  194. package/dist/response/cache-control.d.ts +30 -0
  195. package/dist/response/cache-control.js +74 -0
  196. package/dist/response/etag.d.ts +15 -0
  197. package/dist/response/etag.js +83 -0
  198. package/dist/response/media-type.d.ts +28 -0
  199. package/dist/response/media-type.js +97 -0
  200. package/dist/response/out-headers.d.ts +31 -0
  201. package/dist/response/out-headers.js +130 -0
  202. package/dist/response/pretty-json.d.ts +10 -0
  203. package/dist/response/pretty-json.js +44 -0
  204. package/dist/response/range.d.ts +19 -0
  205. package/dist/response/range.js +98 -0
  206. package/dist/response/response-headers.d.ts +11 -0
  207. package/dist/response/response-headers.js +21 -0
  208. package/dist/response/response.d.ts +69 -0
  209. package/dist/response/response.js +208 -0
  210. package/dist/response/sse.d.ts +41 -0
  211. package/dist/response/sse.js +73 -0
  212. package/dist/response/static.d.ts +20 -0
  213. package/dist/response/static.js +181 -0
  214. package/dist/response/status.d.ts +5 -0
  215. package/dist/response/status.js +68 -0
  216. package/dist/response/with-headers.d.ts +11 -0
  217. package/dist/response/with-headers.js +47 -0
  218. package/dist/routing/app-types.d.ts +181 -0
  219. package/dist/routing/app-types.js +1 -0
  220. package/dist/routing/app.d.ts +76 -0
  221. package/dist/routing/app.js +137 -0
  222. package/dist/routing/codegen-types.d.ts +17 -0
  223. package/dist/routing/codegen-types.js +1 -0
  224. package/dist/routing/delegate.d.ts +9 -0
  225. package/dist/routing/delegate.js +75 -0
  226. package/dist/routing/dispatch.d.ts +22 -0
  227. package/dist/routing/dispatch.js +255 -0
  228. package/dist/routing/finalize.d.ts +47 -0
  229. package/dist/routing/finalize.js +169 -0
  230. package/dist/routing/gateway-tree.d.ts +19 -0
  231. package/dist/routing/gateway-tree.js +74 -0
  232. package/dist/routing/invalidate-check.d.ts +58 -0
  233. package/dist/routing/invalidate-check.js +124 -0
  234. package/dist/routing/match.d.ts +22 -0
  235. package/dist/routing/match.js +108 -0
  236. package/dist/routing/middleware-chain.d.ts +16 -0
  237. package/dist/routing/middleware-chain.js +41 -0
  238. package/dist/routing/output-types.d.ts +91 -0
  239. package/dist/routing/output-types.js +1 -0
  240. package/dist/routing/pattern.d.ts +55 -0
  241. package/dist/routing/pattern.js +219 -0
  242. package/dist/routing/record.d.ts +18 -0
  243. package/dist/routing/record.js +4 -0
  244. package/dist/routing/register.d.ts +135 -0
  245. package/dist/routing/register.js +155 -0
  246. package/dist/routing/request-path.d.ts +30 -0
  247. package/dist/routing/request-path.js +173 -0
  248. package/dist/routing/route-builder.d.ts +160 -0
  249. package/dist/routing/route-builder.js +86 -0
  250. package/dist/routing/route-tree.d.ts +18 -0
  251. package/dist/routing/route-tree.js +91 -0
  252. package/dist/routing/settings-chain.d.ts +75 -0
  253. package/dist/routing/settings-chain.js +137 -0
  254. package/dist/routing/settings.d.ts +90 -0
  255. package/dist/routing/settings.js +44 -0
  256. package/dist/routing/tap.d.ts +31 -0
  257. package/dist/routing/tap.js +77 -0
  258. package/dist/routing/tree-merge.d.ts +7 -0
  259. package/dist/routing/tree-merge.js +77 -0
  260. package/dist/routing/tree.d.ts +85 -0
  261. package/dist/routing/tree.js +196 -0
  262. package/dist/routing/types.d.ts +20 -0
  263. package/dist/routing/types.js +1 -0
  264. package/dist/routing/ws-builder.d.ts +62 -0
  265. package/dist/routing/ws-builder.js +109 -0
  266. package/dist/runtime/detect-runtime.d.ts +16 -0
  267. package/dist/runtime/detect-runtime.js +11 -0
  268. package/dist/runtime/optional-peer.d.ts +10 -0
  269. package/dist/runtime/optional-peer.js +19 -0
  270. package/dist/schema/arktype.d.ts +7 -0
  271. package/dist/schema/arktype.js +13 -0
  272. package/dist/schema/canonicalize.d.ts +8 -0
  273. package/dist/schema/canonicalize.js +19 -0
  274. package/dist/schema/effect.d.ts +7 -0
  275. package/dist/schema/effect.js +4 -0
  276. package/dist/schema/naming.d.ts +31 -0
  277. package/dist/schema/naming.js +116 -0
  278. package/dist/schema/sanitize-spec.d.ts +15 -0
  279. package/dist/schema/sanitize-spec.js +43 -0
  280. package/dist/schema/slots.d.ts +15 -0
  281. package/dist/schema/slots.js +179 -0
  282. package/dist/schema/to-json-schema.d.ts +34 -0
  283. package/dist/schema/to-json-schema.js +94 -0
  284. package/dist/schema/valibot.d.ts +4 -0
  285. package/dist/schema/valibot.js +153 -0
  286. package/dist/schema/yup.d.ts +3 -0
  287. package/dist/schema/yup.js +57 -0
  288. package/dist/schema/zod.d.ts +6 -0
  289. package/dist/schema/zod.js +192 -0
  290. package/dist/security/crypto.d.ts +7 -0
  291. package/dist/security/crypto.js +30 -0
  292. package/dist/streaming/producer-stream.d.ts +45 -0
  293. package/dist/streaming/producer-stream.js +251 -0
  294. package/dist/telemetry/fields.d.ts +43 -0
  295. package/dist/telemetry/fields.js +64 -0
  296. package/dist/telemetry/log-format.d.ts +7 -0
  297. package/dist/telemetry/log-format.js +43 -0
  298. package/dist/telemetry/logger.d.ts +44 -0
  299. package/dist/telemetry/logger.js +122 -0
  300. package/dist/telemetry/otel-subpath.d.ts +7 -0
  301. package/dist/telemetry/otel-subpath.js +5 -0
  302. package/dist/telemetry/otel.d.ts +50 -57
  303. package/dist/telemetry/otel.js +54 -130
  304. package/dist/telemetry/request-log.d.ts +22 -0
  305. package/dist/telemetry/request-log.js +83 -0
  306. package/dist/telemetry/request-trace.d.ts +123 -0
  307. package/dist/telemetry/request-trace.js +199 -0
  308. package/dist/telemetry/span-lifecycle.d.ts +11 -0
  309. package/dist/telemetry/span-lifecycle.js +114 -0
  310. package/dist/telemetry/traceparent.d.ts +40 -0
  311. package/dist/telemetry/traceparent.js +73 -0
  312. package/dist/testing/testing.d.ts +42 -0
  313. package/dist/testing/testing.js +101 -0
  314. package/dist/validation/content-type.d.ts +21 -0
  315. package/dist/validation/content-type.js +42 -0
  316. package/dist/validation/standard-schema.d.ts +41 -0
  317. package/dist/validation/standard-schema.js +5 -0
  318. package/dist/validation/validate-input.d.ts +45 -0
  319. package/dist/validation/validate-input.js +174 -0
  320. package/dist/validation/validate-output.d.ts +34 -0
  321. package/dist/validation/validate-output.js +107 -0
  322. package/dist/ws/bun.d.ts +30 -25
  323. package/dist/ws/bun.js +42 -46
  324. package/dist/ws/cloudflare.d.ts +6 -75
  325. package/dist/ws/cloudflare.js +37 -104
  326. package/dist/ws/contract.d.ts +74 -0
  327. package/dist/ws/contract.js +83 -0
  328. package/dist/ws/node.d.ts +12 -21
  329. package/dist/ws/node.js +103 -151
  330. package/dist/ws/origin.d.ts +23 -0
  331. package/dist/ws/origin.js +48 -0
  332. package/dist/ws/route.d.ts +14 -0
  333. package/dist/ws/route.js +5 -0
  334. package/dist/ws/session.d.ts +15 -6
  335. package/dist/ws/session.js +22 -23
  336. package/dist/ws/shared.d.ts +23 -33
  337. package/dist/ws/shared.js +53 -39
  338. package/package.json +169 -251
  339. package/dist/accepts.d.ts +0 -12
  340. package/dist/accepts.d.ts.map +0 -1
  341. package/dist/accepts.js +0 -126
  342. package/dist/accepts.js.map +0 -1
  343. package/dist/body-kind.d.ts +0 -26
  344. package/dist/body-kind.d.ts.map +0 -1
  345. package/dist/body-kind.js +0 -70
  346. package/dist/body-kind.js.map +0 -1
  347. package/dist/body-limit.d.ts +0 -26
  348. package/dist/body-limit.d.ts.map +0 -1
  349. package/dist/body-limit.js +0 -126
  350. package/dist/body-limit.js.map +0 -1
  351. package/dist/build/index.d.ts.map +0 -1
  352. package/dist/build/index.js.map +0 -1
  353. package/dist/cli-args.d.ts +0 -33
  354. package/dist/cli-args.d.ts.map +0 -1
  355. package/dist/cli-args.js +0 -102
  356. package/dist/cli-args.js.map +0 -1
  357. package/dist/cli-go/auth.go +0 -26
  358. package/dist/cli-go/config.go +0 -192
  359. package/dist/cli-go/errors.go +0 -75
  360. package/dist/cli-go/multipart.go +0 -79
  361. package/dist/cli-go/output.go +0 -163
  362. package/dist/cli-go/root.go +0 -30
  363. package/dist/cli-go/stream.go +0 -88
  364. package/dist/cli-go/version.go +0 -5
  365. package/dist/cli.d.ts +0 -3
  366. package/dist/cli.d.ts.map +0 -1
  367. package/dist/cli.js +0 -209
  368. package/dist/cli.js.map +0 -1
  369. package/dist/client/defaults.d.ts +0 -12
  370. package/dist/client/defaults.d.ts.map +0 -1
  371. package/dist/client/defaults.js +0 -48
  372. package/dist/client/defaults.js.map +0 -1
  373. package/dist/client/error.d.ts +0 -49
  374. package/dist/client/error.d.ts.map +0 -1
  375. package/dist/client/error.js +0 -71
  376. package/dist/client/error.js.map +0 -1
  377. package/dist/client/http.d.ts +0 -155
  378. package/dist/client/http.d.ts.map +0 -1
  379. package/dist/client/http.js +0 -571
  380. package/dist/client/http.js.map +0 -1
  381. package/dist/client/index.d.ts +0 -23
  382. package/dist/client/index.d.ts.map +0 -1
  383. package/dist/client/index.js +0 -95
  384. package/dist/client/index.js.map +0 -1
  385. package/dist/client/path.d.ts +0 -26
  386. package/dist/client/path.d.ts.map +0 -1
  387. package/dist/client/path.js +0 -163
  388. package/dist/client/path.js.map +0 -1
  389. package/dist/client/redirect-policy.d.ts +0 -12
  390. package/dist/client/redirect-policy.d.ts.map +0 -1
  391. package/dist/client/redirect-policy.js +0 -20
  392. package/dist/client/redirect-policy.js.map +0 -1
  393. package/dist/client/sdk.d.ts +0 -70
  394. package/dist/client/sdk.d.ts.map +0 -1
  395. package/dist/client/sdk.js +0 -292
  396. package/dist/client/sdk.js.map +0 -1
  397. package/dist/client/sse.d.ts +0 -23
  398. package/dist/client/sse.d.ts.map +0 -1
  399. package/dist/client/sse.js +0 -129
  400. package/dist/client/sse.js.map +0 -1
  401. package/dist/client/types.d.ts +0 -124
  402. package/dist/client/types.d.ts.map +0 -1
  403. package/dist/client/types.js +0 -2
  404. package/dist/client/types.js.map +0 -1
  405. package/dist/client/ws.d.ts +0 -22
  406. package/dist/client/ws.d.ts.map +0 -1
  407. package/dist/client/ws.js +0 -112
  408. package/dist/client/ws.js.map +0 -1
  409. package/dist/client-go/errors.go +0 -236
  410. package/dist/client-go/export.go +0 -44
  411. package/dist/client-go/invalidation.go +0 -371
  412. package/dist/client-go/nullable.go +0 -62
  413. package/dist/client-go/realtime.go +0 -354
  414. package/dist/client-go/result.go +0 -20
  415. package/dist/client-go/runtime.go +0 -975
  416. package/dist/client-go/sse.go +0 -159
  417. package/dist/client-go/transport.go +0 -495
  418. package/dist/client-go/ws.go +0 -128
  419. package/dist/client-info.d.ts +0 -36
  420. package/dist/client-info.d.ts.map +0 -1
  421. package/dist/client-info.js +0 -53
  422. package/dist/client-info.js.map +0 -1
  423. package/dist/client-mcp/README.md +0 -10
  424. package/dist/client-mcp/server.ts +0 -221
  425. package/dist/client-mcp/types.ts +0 -19
  426. package/dist/client-python/_errors.py +0 -115
  427. package/dist/client-python/_invalidation.py +0 -494
  428. package/dist/client-python/_realtime.py +0 -179
  429. package/dist/client-python/_runtime.py +0 -860
  430. package/dist/client-python/_sse.py +0 -155
  431. package/dist/client-python/_transport.py +0 -366
  432. package/dist/client-python/_ws.py +0 -159
  433. package/dist/client-python/py.typed +0 -0
  434. package/dist/client-rust/errors.rs +0 -220
  435. package/dist/client-rust/invalidation.rs +0 -412
  436. package/dist/client-rust/invalidation_sync.rs +0 -93
  437. package/dist/client-rust/nullable.rs +0 -17
  438. package/dist/client-rust/realtime.rs +0 -702
  439. package/dist/client-rust/result.rs +0 -22
  440. package/dist/client-rust/runtime.rs +0 -980
  441. package/dist/client-rust/runtime_sync.rs +0 -484
  442. package/dist/client-rust/sse.rs +0 -188
  443. package/dist/client-rust/ws.rs +0 -167
  444. package/dist/codegen-go-cli.d.ts +0 -22
  445. package/dist/codegen-go-cli.d.ts.map +0 -1
  446. package/dist/codegen-go-cli.js +0 -964
  447. package/dist/codegen-go-cli.js.map +0 -1
  448. package/dist/codegen-go.d.ts +0 -41
  449. package/dist/codegen-go.d.ts.map +0 -1
  450. package/dist/codegen-go.js +0 -872
  451. package/dist/codegen-go.js.map +0 -1
  452. package/dist/codegen-hash.d.ts +0 -3
  453. package/dist/codegen-hash.d.ts.map +0 -1
  454. package/dist/codegen-hash.js +0 -9
  455. package/dist/codegen-hash.js.map +0 -1
  456. package/dist/codegen-ir.d.ts +0 -190
  457. package/dist/codegen-ir.d.ts.map +0 -1
  458. package/dist/codegen-ir.js +0 -661
  459. package/dist/codegen-ir.js.map +0 -1
  460. package/dist/codegen-lang.d.ts +0 -65
  461. package/dist/codegen-lang.d.ts.map +0 -1
  462. package/dist/codegen-lang.js +0 -526
  463. package/dist/codegen-lang.js.map +0 -1
  464. package/dist/codegen-load.d.ts +0 -31
  465. package/dist/codegen-load.d.ts.map +0 -1
  466. package/dist/codegen-load.js +0 -138
  467. package/dist/codegen-load.js.map +0 -1
  468. package/dist/codegen-loaders.d.ts +0 -12
  469. package/dist/codegen-loaders.d.ts.map +0 -1
  470. package/dist/codegen-loaders.js +0 -55
  471. package/dist/codegen-loaders.js.map +0 -1
  472. package/dist/codegen-mcp.d.ts +0 -13
  473. package/dist/codegen-mcp.d.ts.map +0 -1
  474. package/dist/codegen-mcp.js +0 -368
  475. package/dist/codegen-mcp.js.map +0 -1
  476. package/dist/codegen-python.d.ts +0 -33
  477. package/dist/codegen-python.d.ts.map +0 -1
  478. package/dist/codegen-python.js +0 -828
  479. package/dist/codegen-python.js.map +0 -1
  480. package/dist/codegen-route-tree-intern.d.ts +0 -40
  481. package/dist/codegen-route-tree-intern.d.ts.map +0 -1
  482. package/dist/codegen-route-tree-intern.js +0 -221
  483. package/dist/codegen-route-tree-intern.js.map +0 -1
  484. package/dist/codegen-rust.d.ts +0 -18
  485. package/dist/codegen-rust.d.ts.map +0 -1
  486. package/dist/codegen-rust.js +0 -1293
  487. package/dist/codegen-rust.js.map +0 -1
  488. package/dist/codegen-sanitize.d.ts +0 -3
  489. package/dist/codegen-sanitize.d.ts.map +0 -1
  490. package/dist/codegen-sanitize.js +0 -56
  491. package/dist/codegen-sanitize.js.map +0 -1
  492. package/dist/codegen-schema-naming.d.ts +0 -27
  493. package/dist/codegen-schema-naming.d.ts.map +0 -1
  494. package/dist/codegen-schema-naming.js +0 -150
  495. package/dist/codegen-schema-naming.js.map +0 -1
  496. package/dist/codegen-sdk-model.d.ts +0 -71
  497. package/dist/codegen-sdk-model.d.ts.map +0 -1
  498. package/dist/codegen-sdk-model.js +0 -179
  499. package/dist/codegen-sdk-model.js.map +0 -1
  500. package/dist/codegen.d.ts +0 -187
  501. package/dist/codegen.d.ts.map +0 -1
  502. package/dist/codegen.js +0 -4619
  503. package/dist/codegen.js.map +0 -1
  504. package/dist/context.d.ts +0 -86
  505. package/dist/context.d.ts.map +0 -1
  506. package/dist/context.js +0 -242
  507. package/dist/context.js.map +0 -1
  508. package/dist/cookie-sign.d.ts +0 -17
  509. package/dist/cookie-sign.d.ts.map +0 -1
  510. package/dist/cookie-sign.js +0 -104
  511. package/dist/cookie-sign.js.map +0 -1
  512. package/dist/cookie.d.ts +0 -24
  513. package/dist/cookie.d.ts.map +0 -1
  514. package/dist/cookie.js +0 -138
  515. package/dist/cookie.js.map +0 -1
  516. package/dist/cors.d.ts +0 -14
  517. package/dist/cors.d.ts.map +0 -1
  518. package/dist/cors.js +0 -87
  519. package/dist/cors.js.map +0 -1
  520. package/dist/crypto.d.ts +0 -7
  521. package/dist/crypto.d.ts.map +0 -1
  522. package/dist/crypto.js +0 -38
  523. package/dist/crypto.js.map +0 -1
  524. package/dist/csrf.d.ts +0 -28
  525. package/dist/csrf.d.ts.map +0 -1
  526. package/dist/csrf.js +0 -79
  527. package/dist/csrf.js.map +0 -1
  528. package/dist/curl-logger.d.ts +0 -44
  529. package/dist/curl-logger.d.ts.map +0 -1
  530. package/dist/curl-logger.js +0 -199
  531. package/dist/curl-logger.js.map +0 -1
  532. package/dist/detect-runtime.d.ts +0 -16
  533. package/dist/detect-runtime.d.ts.map +0 -1
  534. package/dist/detect-runtime.js +0 -13
  535. package/dist/detect-runtime.js.map +0 -1
  536. package/dist/dict.d.ts +0 -11
  537. package/dist/dict.d.ts.map +0 -1
  538. package/dist/dict.js +0 -13
  539. package/dist/dict.js.map +0 -1
  540. package/dist/error.d.ts +0 -21
  541. package/dist/error.d.ts.map +0 -1
  542. package/dist/error.js +0 -44
  543. package/dist/error.js.map +0 -1
  544. package/dist/errors.d.ts +0 -40
  545. package/dist/errors.d.ts.map +0 -1
  546. package/dist/errors.js +0 -39
  547. package/dist/errors.js.map +0 -1
  548. package/dist/etag.d.ts +0 -11
  549. package/dist/etag.d.ts.map +0 -1
  550. package/dist/etag.js +0 -82
  551. package/dist/etag.js.map +0 -1
  552. package/dist/feature-detect.d.ts +0 -25
  553. package/dist/feature-detect.d.ts.map +0 -1
  554. package/dist/feature-detect.js +0 -144
  555. package/dist/feature-detect.js.map +0 -1
  556. package/dist/feature-load.d.ts +0 -3
  557. package/dist/feature-load.d.ts.map +0 -1
  558. package/dist/feature-load.js +0 -36
  559. package/dist/feature-load.js.map +0 -1
  560. package/dist/feature-slots.d.ts +0 -44
  561. package/dist/feature-slots.d.ts.map +0 -1
  562. package/dist/feature-slots.js +0 -48
  563. package/dist/feature-slots.js.map +0 -1
  564. package/dist/fetch-request.d.ts +0 -10
  565. package/dist/fetch-request.d.ts.map +0 -1
  566. package/dist/fetch-request.js +0 -13
  567. package/dist/fetch-request.js.map +0 -1
  568. package/dist/gen-process.d.ts +0 -15
  569. package/dist/gen-process.d.ts.map +0 -1
  570. package/dist/gen-process.js +0 -43
  571. package/dist/gen-process.js.map +0 -1
  572. package/dist/gen-write.d.ts +0 -19
  573. package/dist/gen-write.d.ts.map +0 -1
  574. package/dist/gen-write.js +0 -120
  575. package/dist/gen-write.js.map +0 -1
  576. package/dist/glob.d.ts +0 -21
  577. package/dist/glob.d.ts.map +0 -1
  578. package/dist/glob.js +0 -115
  579. package/dist/glob.js.map +0 -1
  580. package/dist/go-type-emitter.d.ts +0 -47
  581. package/dist/go-type-emitter.d.ts.map +0 -1
  582. package/dist/go-type-emitter.js +0 -594
  583. package/dist/go-type-emitter.js.map +0 -1
  584. package/dist/honey-response.d.ts +0 -82
  585. package/dist/honey-response.d.ts.map +0 -1
  586. package/dist/honey-response.js +0 -338
  587. package/dist/honey-response.js.map +0 -1
  588. package/dist/i18n-slot.d.ts +0 -15
  589. package/dist/i18n-slot.d.ts.map +0 -1
  590. package/dist/i18n-slot.js +0 -14
  591. package/dist/i18n-slot.js.map +0 -1
  592. package/dist/i18n.d.ts +0 -29
  593. package/dist/i18n.d.ts.map +0 -1
  594. package/dist/i18n.js +0 -250
  595. package/dist/i18n.js.map +0 -1
  596. package/dist/index.d.ts.map +0 -1
  597. package/dist/index.js.map +0 -1
  598. package/dist/init.d.ts +0 -5
  599. package/dist/init.d.ts.map +0 -1
  600. package/dist/init.js +0 -140
  601. package/dist/init.js.map +0 -1
  602. package/dist/input.d.ts +0 -6
  603. package/dist/input.d.ts.map +0 -1
  604. package/dist/input.js +0 -4
  605. package/dist/input.js.map +0 -1
  606. package/dist/invalidate-check.d.ts +0 -61
  607. package/dist/invalidate-check.d.ts.map +0 -1
  608. package/dist/invalidate-check.js +0 -163
  609. package/dist/invalidate-check.js.map +0 -1
  610. package/dist/invoke-user.d.ts +0 -35
  611. package/dist/invoke-user.d.ts.map +0 -1
  612. package/dist/invoke-user.js +0 -73
  613. package/dist/invoke-user.js.map +0 -1
  614. package/dist/ip-restrict.d.ts +0 -24
  615. package/dist/ip-restrict.d.ts.map +0 -1
  616. package/dist/ip-restrict.js +0 -60
  617. package/dist/ip-restrict.js.map +0 -1
  618. package/dist/ip.d.ts +0 -39
  619. package/dist/ip.d.ts.map +0 -1
  620. package/dist/ip.js +0 -209
  621. package/dist/ip.js.map +0 -1
  622. package/dist/logger.d.ts +0 -45
  623. package/dist/logger.d.ts.map +0 -1
  624. package/dist/logger.js +0 -113
  625. package/dist/logger.js.map +0 -1
  626. package/dist/media-type.d.ts +0 -30
  627. package/dist/media-type.d.ts.map +0 -1
  628. package/dist/media-type.js +0 -97
  629. package/dist/media-type.js.map +0 -1
  630. package/dist/meta-spec-merge.d.ts +0 -32
  631. package/dist/meta-spec-merge.d.ts.map +0 -1
  632. package/dist/meta-spec-merge.js +0 -68
  633. package/dist/meta-spec-merge.js.map +0 -1
  634. package/dist/meta-spec.d.ts +0 -94
  635. package/dist/meta-spec.d.ts.map +0 -1
  636. package/dist/meta-spec.js +0 -535
  637. package/dist/meta-spec.js.map +0 -1
  638. package/dist/middleware.d.ts +0 -77
  639. package/dist/middleware.d.ts.map +0 -1
  640. package/dist/middleware.js +0 -253
  641. package/dist/middleware.js.map +0 -1
  642. package/dist/node-request.d.ts +0 -104
  643. package/dist/node-request.d.ts.map +0 -1
  644. package/dist/node-request.js +0 -407
  645. package/dist/node-request.js.map +0 -1
  646. package/dist/node.d.ts +0 -30
  647. package/dist/node.d.ts.map +0 -1
  648. package/dist/node.js +0 -396
  649. package/dist/node.js.map +0 -1
  650. package/dist/openapi/collect.d.ts.map +0 -1
  651. package/dist/openapi/collect.js.map +0 -1
  652. package/dist/openapi/docs-page.d.ts.map +0 -1
  653. package/dist/openapi/docs-page.js.map +0 -1
  654. package/dist/openapi/document.d.ts.map +0 -1
  655. package/dist/openapi/document.js.map +0 -1
  656. package/dist/openapi/json-schema-slot.d.ts +0 -12
  657. package/dist/openapi/json-schema-slot.d.ts.map +0 -1
  658. package/dist/openapi/json-schema-slot.js +0 -38
  659. package/dist/openapi/json-schema-slot.js.map +0 -1
  660. package/dist/openapi/register.d.ts.map +0 -1
  661. package/dist/openapi/register.js.map +0 -1
  662. package/dist/openapi/scalar.d.ts.map +0 -1
  663. package/dist/openapi/scalar.js.map +0 -1
  664. package/dist/openapi/serve.d.ts.map +0 -1
  665. package/dist/openapi/serve.js.map +0 -1
  666. package/dist/openapi/spec-factory.d.ts +0 -65
  667. package/dist/openapi/spec-factory.d.ts.map +0 -1
  668. package/dist/openapi/spec-factory.js +0 -52
  669. package/dist/openapi/spec-factory.js.map +0 -1
  670. package/dist/openapi/spec.d.ts +0 -29
  671. package/dist/openapi/spec.d.ts.map +0 -1
  672. package/dist/openapi/spec.js +0 -50
  673. package/dist/openapi/spec.js.map +0 -1
  674. package/dist/openapi/swagger.d.ts.map +0 -1
  675. package/dist/openapi/swagger.js.map +0 -1
  676. package/dist/pattern.d.ts +0 -71
  677. package/dist/pattern.d.ts.map +0 -1
  678. package/dist/pattern.js +0 -239
  679. package/dist/pattern.js.map +0 -1
  680. package/dist/peer.d.ts +0 -17
  681. package/dist/peer.d.ts.map +0 -1
  682. package/dist/peer.js +0 -50
  683. package/dist/peer.js.map +0 -1
  684. package/dist/plugin.d.ts +0 -228
  685. package/dist/plugin.d.ts.map +0 -1
  686. package/dist/plugin.js +0 -666
  687. package/dist/plugin.js.map +0 -1
  688. package/dist/powered-by.d.ts +0 -7
  689. package/dist/powered-by.d.ts.map +0 -1
  690. package/dist/powered-by.js +0 -11
  691. package/dist/powered-by.js.map +0 -1
  692. package/dist/pretty-json.d.ts +0 -10
  693. package/dist/pretty-json.d.ts.map +0 -1
  694. package/dist/pretty-json.js +0 -47
  695. package/dist/pretty-json.js.map +0 -1
  696. package/dist/producer-stream.d.ts +0 -47
  697. package/dist/producer-stream.d.ts.map +0 -1
  698. package/dist/producer-stream.js +0 -267
  699. package/dist/producer-stream.js.map +0 -1
  700. package/dist/proxy.d.ts +0 -90
  701. package/dist/proxy.d.ts.map +0 -1
  702. package/dist/proxy.js +0 -274
  703. package/dist/proxy.js.map +0 -1
  704. package/dist/python-type-emitter.d.ts +0 -24
  705. package/dist/python-type-emitter.d.ts.map +0 -1
  706. package/dist/python-type-emitter.js +0 -157
  707. package/dist/python-type-emitter.js.map +0 -1
  708. package/dist/realtime/bus.d.ts.map +0 -1
  709. package/dist/realtime/bus.js.map +0 -1
  710. package/dist/realtime/register.d.ts +0 -3
  711. package/dist/realtime/register.d.ts.map +0 -1
  712. package/dist/realtime/register.js +0 -10
  713. package/dist/realtime/register.js.map +0 -1
  714. package/dist/realtime/route.d.ts.map +0 -1
  715. package/dist/realtime/route.js.map +0 -1
  716. package/dist/realtime/server.d.ts.map +0 -1
  717. package/dist/realtime/server.js.map +0 -1
  718. package/dist/request-id.d.ts +0 -19
  719. package/dist/request-id.d.ts.map +0 -1
  720. package/dist/request-id.js +0 -16
  721. package/dist/request-id.js.map +0 -1
  722. package/dist/request-limits.d.ts +0 -3
  723. package/dist/request-limits.d.ts.map +0 -1
  724. package/dist/request-limits.js +0 -3
  725. package/dist/request-limits.js.map +0 -1
  726. package/dist/request-path.d.ts +0 -33
  727. package/dist/request-path.d.ts.map +0 -1
  728. package/dist/request-path.js +0 -178
  729. package/dist/request-path.js.map +0 -1
  730. package/dist/request-to-curl.d.ts +0 -15
  731. package/dist/request-to-curl.d.ts.map +0 -1
  732. package/dist/request-to-curl.js +0 -48
  733. package/dist/request-to-curl.js.map +0 -1
  734. package/dist/response.d.ts +0 -86
  735. package/dist/response.d.ts.map +0 -1
  736. package/dist/response.js +0 -313
  737. package/dist/response.js.map +0 -1
  738. package/dist/rust-type-emitter.d.ts +0 -44
  739. package/dist/rust-type-emitter.d.ts.map +0 -1
  740. package/dist/rust-type-emitter.js +0 -463
  741. package/dist/rust-type-emitter.js.map +0 -1
  742. package/dist/secure-headers.d.ts +0 -16
  743. package/dist/secure-headers.d.ts.map +0 -1
  744. package/dist/secure-headers.js +0 -53
  745. package/dist/secure-headers.js.map +0 -1
  746. package/dist/serve-register.d.ts +0 -6
  747. package/dist/serve-register.d.ts.map +0 -1
  748. package/dist/serve-register.js +0 -9
  749. package/dist/serve-register.js.map +0 -1
  750. package/dist/serve-slot.d.ts +0 -9
  751. package/dist/serve-slot.d.ts.map +0 -1
  752. package/dist/serve-slot.js +0 -52
  753. package/dist/serve-slot.js.map +0 -1
  754. package/dist/serve.d.ts +0 -38
  755. package/dist/serve.d.ts.map +0 -1
  756. package/dist/serve.js +0 -157
  757. package/dist/serve.js.map +0 -1
  758. package/dist/server-timing.d.ts +0 -9
  759. package/dist/server-timing.d.ts.map +0 -1
  760. package/dist/server-timing.js +0 -51
  761. package/dist/server-timing.js.map +0 -1
  762. package/dist/static.d.ts +0 -21
  763. package/dist/static.d.ts.map +0 -1
  764. package/dist/static.js +0 -102
  765. package/dist/static.js.map +0 -1
  766. package/dist/telemetry/otel.d.ts.map +0 -1
  767. package/dist/telemetry/otel.js.map +0 -1
  768. package/dist/testing.d.ts +0 -36
  769. package/dist/testing.d.ts.map +0 -1
  770. package/dist/testing.js +0 -124
  771. package/dist/testing.js.map +0 -1
  772. package/dist/timeout.d.ts +0 -13
  773. package/dist/timeout.d.ts.map +0 -1
  774. package/dist/timeout.js +0 -36
  775. package/dist/timeout.js.map +0 -1
  776. package/dist/tree.d.ts +0 -193
  777. package/dist/tree.d.ts.map +0 -1
  778. package/dist/tree.js +0 -437
  779. package/dist/tree.js.map +0 -1
  780. package/dist/trust.d.ts +0 -21
  781. package/dist/trust.d.ts.map +0 -1
  782. package/dist/trust.js +0 -100
  783. package/dist/trust.js.map +0 -1
  784. package/dist/ts-type-emitter.d.ts +0 -8
  785. package/dist/ts-type-emitter.d.ts.map +0 -1
  786. package/dist/ts-type-emitter.js +0 -150
  787. package/dist/ts-type-emitter.js.map +0 -1
  788. package/dist/type-emitter.d.ts +0 -36
  789. package/dist/type-emitter.d.ts.map +0 -1
  790. package/dist/type-emitter.js +0 -729
  791. package/dist/type-emitter.js.map +0 -1
  792. package/dist/type-extractor.d.ts +0 -43
  793. package/dist/type-extractor.d.ts.map +0 -1
  794. package/dist/type-extractor.js +0 -819
  795. package/dist/type-extractor.js.map +0 -1
  796. package/dist/types.d.ts +0 -467
  797. package/dist/types.d.ts.map +0 -1
  798. package/dist/types.js +0 -96
  799. package/dist/types.js.map +0 -1
  800. package/dist/validation.d.ts +0 -31
  801. package/dist/validation.d.ts.map +0 -1
  802. package/dist/validation.js +0 -335
  803. package/dist/validation.js.map +0 -1
  804. package/dist/with-headers.d.ts +0 -15
  805. package/dist/with-headers.d.ts.map +0 -1
  806. package/dist/with-headers.js +0 -45
  807. package/dist/with-headers.js.map +0 -1
  808. package/dist/ws/bun.d.ts.map +0 -1
  809. package/dist/ws/bun.js.map +0 -1
  810. package/dist/ws/cloudflare.d.ts.map +0 -1
  811. package/dist/ws/cloudflare.js.map +0 -1
  812. package/dist/ws/deno.d.ts +0 -13
  813. package/dist/ws/deno.d.ts.map +0 -1
  814. package/dist/ws/deno.js +0 -133
  815. package/dist/ws/deno.js.map +0 -1
  816. package/dist/ws/node.d.ts.map +0 -1
  817. package/dist/ws/node.js.map +0 -1
  818. package/dist/ws/session.d.ts.map +0 -1
  819. package/dist/ws/session.js.map +0 -1
  820. package/dist/ws/shared.d.ts.map +0 -1
  821. package/dist/ws/shared.js.map +0 -1
  822. package/dist/ws-origin.d.ts +0 -20
  823. package/dist/ws-origin.d.ts.map +0 -1
  824. package/dist/ws-origin.js +0 -41
  825. package/dist/ws-origin.js.map +0 -1
  826. package/dist/yaml.d.ts +0 -18
  827. package/dist/yaml.d.ts.map +0 -1
  828. package/dist/yaml.js +0 -101
  829. package/dist/yaml.js.map +0 -1
  830. package/docs/api-ref/go.md +0 -399
  831. package/docs/api-ref/python.md +0 -399
  832. package/docs/api-ref/rust.md +0 -399
  833. package/docs/api-ref/typescript.md +0 -399
  834. package/docs/invalidate-spec.md +0 -333
  835. package/docs/meta-spec.md +0 -555
  836. package/docs/packaging.md +0 -104
  837. package/docs/regression-matrix/README.md +0 -32
  838. package/docs/regression-matrix/review.md +0 -44
  839. package/docs/regression-matrix/ws1-3.md +0 -97
  840. package/docs/regression-matrix/ws4-8.md +0 -107
  841. package/docs/regression-matrix/ws9-12.md +0 -266
  842. package/docs/sdk.md +0 -798
  843. package/src/accepts.ts +0 -136
  844. package/src/body-kind.ts +0 -67
  845. package/src/body-limit.ts +0 -152
  846. package/src/build/index.ts +0 -217
  847. package/src/cli-args.ts +0 -123
  848. package/src/cli-go/auth.go +0 -26
  849. package/src/cli-go/config.go +0 -192
  850. package/src/cli-go/errors.go +0 -75
  851. package/src/cli-go/multipart.go +0 -79
  852. package/src/cli-go/output.go +0 -163
  853. package/src/cli-go/root.go +0 -30
  854. package/src/cli-go/stream.go +0 -88
  855. package/src/cli-go/version.go +0 -5
  856. package/src/cli.ts +0 -209
  857. package/src/client/defaults.ts +0 -47
  858. package/src/client/error.ts +0 -82
  859. package/src/client/http.ts +0 -737
  860. package/src/client/index.ts +0 -157
  861. package/src/client/path.ts +0 -169
  862. package/src/client/redirect-policy.ts +0 -19
  863. package/src/client/sdk.ts +0 -351
  864. package/src/client/sse.ts +0 -128
  865. package/src/client/types.ts +0 -206
  866. package/src/client/ws.ts +0 -149
  867. package/src/client-go/errors.go +0 -236
  868. package/src/client-go/export.go +0 -44
  869. package/src/client-go/invalidation.go +0 -371
  870. package/src/client-go/nullable.go +0 -62
  871. package/src/client-go/realtime.go +0 -354
  872. package/src/client-go/result.go +0 -20
  873. package/src/client-go/runtime.go +0 -975
  874. package/src/client-go/sse.go +0 -159
  875. package/src/client-go/transport.go +0 -495
  876. package/src/client-go/ws.go +0 -128
  877. package/src/client-info.ts +0 -79
  878. package/src/client-mcp/README.md +0 -10
  879. package/src/client-mcp/server.ts +0 -221
  880. package/src/client-mcp/types.ts +0 -19
  881. package/src/client-python/_errors.py +0 -115
  882. package/src/client-python/_invalidation.py +0 -494
  883. package/src/client-python/_realtime.py +0 -179
  884. package/src/client-python/_runtime.py +0 -860
  885. package/src/client-python/_sse.py +0 -155
  886. package/src/client-python/_transport.py +0 -366
  887. package/src/client-python/_ws.py +0 -159
  888. package/src/client-python/py.typed +0 -0
  889. package/src/client-rust/errors.rs +0 -220
  890. package/src/client-rust/invalidation.rs +0 -412
  891. package/src/client-rust/invalidation_sync.rs +0 -93
  892. package/src/client-rust/nullable.rs +0 -17
  893. package/src/client-rust/realtime.rs +0 -702
  894. package/src/client-rust/result.rs +0 -22
  895. package/src/client-rust/runtime.rs +0 -980
  896. package/src/client-rust/runtime_sync.rs +0 -484
  897. package/src/client-rust/sse.rs +0 -188
  898. package/src/client-rust/ws.rs +0 -167
  899. package/src/codegen-go-cli.ts +0 -1066
  900. package/src/codegen-go.ts +0 -970
  901. package/src/codegen-hash.ts +0 -8
  902. package/src/codegen-ir.ts +0 -812
  903. package/src/codegen-lang.ts +0 -517
  904. package/src/codegen-load.ts +0 -150
  905. package/src/codegen-loaders.ts +0 -50
  906. package/src/codegen-mcp.ts +0 -445
  907. package/src/codegen-python.ts +0 -916
  908. package/src/codegen-route-tree-intern.ts +0 -198
  909. package/src/codegen-rust.ts +0 -1402
  910. package/src/codegen-sanitize.ts +0 -57
  911. package/src/codegen-schema-naming.ts +0 -165
  912. package/src/codegen-sdk-model.ts +0 -228
  913. package/src/codegen.ts +0 -5089
  914. package/src/context.ts +0 -325
  915. package/src/cookie-sign.ts +0 -119
  916. package/src/cookie.ts +0 -143
  917. package/src/cors.ts +0 -95
  918. package/src/crypto.ts +0 -38
  919. package/src/csrf.ts +0 -86
  920. package/src/curl-logger.ts +0 -258
  921. package/src/detect-runtime.ts +0 -17
  922. package/src/dict.ts +0 -12
  923. package/src/error.ts +0 -55
  924. package/src/errors.ts +0 -85
  925. package/src/etag.ts +0 -97
  926. package/src/feature-detect.ts +0 -147
  927. package/src/feature-load.ts +0 -23
  928. package/src/feature-slots.ts +0 -70
  929. package/src/fetch-request.ts +0 -13
  930. package/src/gen-process.ts +0 -42
  931. package/src/gen-write.ts +0 -127
  932. package/src/glob.ts +0 -109
  933. package/src/go-type-emitter.ts +0 -660
  934. package/src/honey-response.ts +0 -379
  935. package/src/i18n-slot.ts +0 -30
  936. package/src/i18n.ts +0 -300
  937. package/src/index.ts +0 -3829
  938. package/src/init.ts +0 -161
  939. package/src/input.ts +0 -8
  940. package/src/invalidate-check.ts +0 -205
  941. package/src/invoke-user.ts +0 -95
  942. package/src/ip-restrict.ts +0 -79
  943. package/src/ip.ts +0 -194
  944. package/src/logger.ts +0 -178
  945. package/src/media-type.ts +0 -104
  946. package/src/meta-spec-merge.ts +0 -80
  947. package/src/meta-spec.ts +0 -718
  948. package/src/middleware.ts +0 -331
  949. package/src/node-request.ts +0 -431
  950. package/src/node.ts +0 -454
  951. package/src/openapi/collect.ts +0 -50
  952. package/src/openapi/docs-page.ts +0 -89
  953. package/src/openapi/document.ts +0 -893
  954. package/src/openapi/json-schema-slot.ts +0 -53
  955. package/src/openapi/register.ts +0 -23
  956. package/src/openapi/scalar.ts +0 -34
  957. package/src/openapi/serve.ts +0 -39
  958. package/src/openapi/spec-factory.ts +0 -100
  959. package/src/openapi/spec.ts +0 -74
  960. package/src/openapi/swagger.ts +0 -35
  961. package/src/pattern.ts +0 -245
  962. package/src/peer.ts +0 -53
  963. package/src/plugin.ts +0 -864
  964. package/src/powered-by.ts +0 -18
  965. package/src/pretty-json.ts +0 -56
  966. package/src/producer-stream.ts +0 -296
  967. package/src/proxy.ts +0 -370
  968. package/src/python-type-emitter.ts +0 -181
  969. package/src/realtime/bus.ts +0 -140
  970. package/src/realtime/register.ts +0 -13
  971. package/src/realtime/route.ts +0 -153
  972. package/src/realtime/server.ts +0 -298
  973. package/src/request-id.ts +0 -32
  974. package/src/request-limits.ts +0 -2
  975. package/src/request-path.ts +0 -165
  976. package/src/request-to-curl.ts +0 -52
  977. package/src/response.ts +0 -411
  978. package/src/rust-type-emitter.ts +0 -548
  979. package/src/secure-headers.ts +0 -74
  980. package/src/serve-register.ts +0 -12
  981. package/src/serve-slot.ts +0 -58
  982. package/src/serve.ts +0 -220
  983. package/src/server-timing.ts +0 -71
  984. package/src/static.ts +0 -112
  985. package/src/telemetry/otel.ts +0 -156
  986. package/src/testing.ts +0 -167
  987. package/src/timeout.ts +0 -45
  988. package/src/tree.ts +0 -554
  989. package/src/trust.ts +0 -117
  990. package/src/ts-type-emitter.ts +0 -168
  991. package/src/type-emitter.ts +0 -760
  992. package/src/type-extractor.ts +0 -855
  993. package/src/types.ts +0 -756
  994. package/src/validation.ts +0 -413
  995. package/src/with-headers.ts +0 -45
  996. package/src/ws/bun.ts +0 -120
  997. package/src/ws/cloudflare.ts +0 -192
  998. package/src/ws/deno.ts +0 -188
  999. package/src/ws/node.ts +0 -240
  1000. package/src/ws/session.ts +0 -73
  1001. package/src/ws/shared.ts +0 -140
  1002. package/src/ws-origin.ts +0 -53
  1003. package/src/yaml.ts +0 -103
package/dist/index.js CHANGED
@@ -1,2365 +1,14 @@
1
- import { bodyKind, headResponse, isProducedStream, rawBodyOf } from "./body-kind.js";
2
- import { clientInfo, HoneyContext } from "./context.js";
3
- import { dict } from "./dict.js";
4
- import { normalizePath, pathOfUrl, searchOfUrl } from "./request-path.js";
5
- import { BUN_URL_FROM_HOST, hasValidHost, TRUST_OFF } from "./client-info.js";
6
- import { loadFeature, requireFeature } from "./feature-slots.js";
7
- import { HoneyError } from "./error.js";
8
- import { ERROR_META } from "./errors.js";
9
- import { collectMiddlewareMeta, compileChain, RESERVED_CTX_KEYS } from "./middleware.js";
10
- import { createErrorResponse } from "./response.js";
11
- import { canonical, expandOptional, isStaticPattern, joinPatterns, normalizePattern, parsePattern, pathInScope, routeId, scopeCoverage, splitRouteId, } from "./pattern.js";
12
- import { assertTreeFormat, cloneTree, createNode, findLeaf, forEachLeaf, freezeTree, hasWsLeaf, insertLeaf, matchRoute, matchWsRoute, ROUTE_TREE_VERSION, } from "./tree.js";
13
- import { codeToStatusKey, EK, EMPTY_OBJ, SK } from "./types.js";
14
- import { assertBodySchemaAllowed, assertRequestContentType, validateInput, validateOutput } from "./validation.js";
15
- import { validateOriginPolicy } from "./ws-origin.js";
16
- import { loadHoneyFeature } from "./feature-load.js";
17
- import { getI18nRuntime } from "./i18n-slot.js";
18
- import { bindInternalHandler, epochCached, getOpenApiRuntime } from "./openapi/spec-factory.js";
19
- import { getServeRuntime, isCodegenProcess } from "./serve-slot.js";
20
- export { clientInfo, HoneyContext } from "./context.js";
21
- export { toFetchRequest } from "./fetch-request.js";
22
- export { HoneyError } from "./error.js";
23
- export { defineErrors, ERROR_META } from "./errors.js";
24
- export { createMiddleware, defineMiddleware } from "./middleware.js";
25
- export { createErrorResponse, HoneyRes } from "./response.js";
26
- export { mergeTree } from "./tree.js";
27
- export { detectRuntime } from "./detect-runtime.js";
28
- function createSettings() {
29
- return {
30
- customErrorFormatter: null,
31
- customErrorSchema: null,
32
- defaultBoundaryKey: null,
33
- defaultErrorKeys: new Set(),
34
- errorFactory: null,
35
- errorFormatter: defaultErrorFormatter,
36
- errorI18n: null,
37
- errorSchema: null,
38
- logger: null,
39
- onError: null,
40
- onMethodNotAllowed: null,
41
- onNotFound: null,
42
- outputValidation: null,
43
- stripPrefix: null,
44
- taps: null,
45
- telemetry: null,
46
- trailingSlash: "ignore",
47
- encodedSlashes: "reject",
48
- trust: TRUST_OFF,
49
- wsAdapter: null,
50
- };
51
- }
52
- /** Join a base path and a route or scope path into one canonical pattern. */
53
- function mergePath(base, path) {
54
- return joinPatterns(base, path);
55
- }
56
- function createGraph() {
57
- return {
58
- absorbedMetaSpecs: [],
59
- catchAll: new Map(),
60
- chains: [],
61
- epoch: 0,
62
- final: null,
63
- global: new Map(),
64
- hasWs: false,
65
- loaded: null,
66
- metaSpec: null,
67
- pending: new Set(),
68
- realtimeBus: null,
69
- realtimeCtx: null,
70
- realtimeRoutes: new Map(),
71
- records: new Map(),
72
- root: createNode(),
73
- rootShared: false,
74
- scoped: [],
75
- served: new Set(),
76
- settings: createSettings(),
77
- unexpected: new Set(),
78
- unloadIfStale: false,
79
- wsRecords: new Map(),
80
- };
81
- }
82
- /** Fresh copy of a record for another graph — sources are copied, resolved fields recomputed there. */
83
- function copyRecord(r) {
84
- const out = { ...r, ek: new Set(r.ek) };
85
- if (r.dk !== undefined)
86
- out.dk = new Set(r.dk);
87
- if (r.cm !== undefined)
88
- out.cm = [...r.cm];
89
- if (r.rm !== undefined)
90
- out.rm = [...r.rm];
91
- delete out.ca;
92
- return out;
93
- }
94
- /** Every leaf a pattern occupies: an optional last param places two. */
95
- function leafVariants(segments) {
96
- return expandOptional(segments);
97
- }
98
- /** Record the error behind an error response on `ctx.error` (read-only for user code). */
99
- function setCtxError(ctx, error) {
100
- ;
101
- ctx["error"] = error;
102
- }
103
- /** What `ctx.error` holds for a throw the boundary could not resolve: the 500 it became. */
104
- function asHoneyError(thrown) {
105
- return thrown instanceof HoneyError
106
- ? thrown
107
- : new HoneyError({ cause: thrown, errorKey: EK.internal_server_error, status: SK.internal_server_error });
108
- }
109
- function patternOf(id) {
110
- const { method, pattern } = splitRouteId(id);
111
- return { method, segments: parsePattern(pattern) };
112
- }
113
- /** `fn` of a tree leaf no handler serves — dispatch answers 404, codegen still documents it. */
114
- const NOT_SERVED = () => {
115
- throw new Error("honey: unserved route reached its handler");
116
- };
117
- function isRootWildcard(segments) {
118
- return segments.length === 1 && segments[0].k === "wildcard";
119
- }
120
- const EMPTY_PARAMS = EMPTY_OBJ;
121
- function requestIsWsUpgrade(request) {
122
- try {
123
- return request.headers.get("upgrade")?.toLowerCase() === "websocket";
124
- }
125
- catch {
126
- /* Deno closes the Request after upgradeWebSocket */
127
- return false;
128
- }
129
- }
130
- /** The info object `Deno.serve` passes as the second handler argument. */
131
- function isDenoServeInfo(env) {
132
- return env !== null && typeof env === "object" && env.remoteAddr !== undefined;
133
- }
134
- /** `obj[key]` for an own key only; `undefined` for inherited names such as `constructor`. */
135
- function safeFire(fn, logger) {
136
- if (fn === undefined)
137
- return;
138
- try {
139
- const result = fn();
140
- if (result && typeof result === "object" && "catch" in result) {
141
- ;
142
- result.catch((e) => {
143
- logger?.warn?.({ err: e }, "telemetry callback failed");
144
- });
145
- }
146
- }
147
- catch (e) {
148
- logger?.warn?.({ err: e }, "telemetry callback failed");
149
- }
150
- }
151
- function requestWithHeaders(req, headers) {
152
- return new Proxy(req, {
153
- get(target, prop) {
154
- if (prop === "headers")
155
- return headers;
156
- const value = Reflect.get(target, prop, target);
157
- return typeof value === "function" ? value.bind(target) : value;
158
- },
159
- });
160
- }
161
- function ctxRequest(fc) {
162
- if (!fc.headerSnap)
163
- return fc.request;
164
- try {
165
- void fc.request.headers.get("upgrade");
166
- return fc.request;
167
- }
168
- catch {
169
- return requestWithHeaders(fc.request, fc.headerSnap);
170
- }
171
- }
172
- function defaultErrorFormatter(_error, defaultShape) {
173
- return defaultShape;
174
- }
175
- /* errorKeys the framework throws on its own behalf — input/output validation, content negotiation,
176
- * routing, and the shipped middleware. Always passes the boundary check; users never declare these via .errors(). */
177
- const FRAMEWORK_EKS = new Set([
178
- EK.validation_failed,
179
- EK.output_validation_failed,
180
- EK.output_content_type_mismatch,
181
- EK.unsupported_media_type,
182
- EK.content_too_large,
183
- EK.method_not_allowed,
184
- EK.not_found,
185
- EK.too_many_requests,
186
- EK.request_timeout,
187
- EK.gateway_timeout,
188
- EK.bad_gateway,
189
- EK.forbidden,
190
- EK.bad_request,
191
- EK.malformed_body,
192
- ]);
193
- function shouldValidateOutput(mode) {
194
- if (mode === "always")
195
- return true;
196
- if (mode === "off")
197
- return false;
198
- return globalThis.process?.env?.NODE_ENV !== "production";
199
- }
200
- /** The scoped middleware behind a request-path check: runs only when the path is inside the scope. */
201
- function scopeGuard(segs, mw) {
202
- const guard = (ctx, next) => (pathInScope(ctx["path"], segs) ? mw(ctx, next) : next());
203
- Object.defineProperty(guard, "name", { configurable: true, value: mw.name });
204
- const tagged = mw;
205
- if (tagged.errors)
206
- Object.defineProperty(guard, "errors", { value: tagged.errors });
207
- if (tagged.meta)
208
- Object.defineProperty(guard, "meta", { value: tagged.meta });
209
- return guard;
210
- }
211
- /** Wrap a middleware so telemetry sees its own duration and its own throw. Built once at finalize. */
212
- function timedMiddleware(mw, onMw, log) {
213
- const name = mw.name || "anonymous";
214
- return async (ctx, next) => {
215
- const start = performance.now();
216
- try {
217
- const res = await mw(ctx, next);
218
- safeFire(() => onMw({ duration: performance.now() - start, name }), log);
219
- return res;
220
- }
221
- catch (error) {
222
- safeFire(() => onMw({ duration: performance.now() - start, error, name }), log);
223
- throw error;
224
- }
225
- };
226
- }
227
- function errorsOf(mw) {
228
- return mw.errors;
229
- }
230
- /** Longest run of middleware every record starts its chain with — what 404 and 405 run. */
231
- function commonPrefix(chains) {
232
- if (chains.length === 0)
233
- return [];
234
- let out = [...chains[0]];
235
- for (let i = 1; i < chains.length && out.length > 0; i++) {
236
- const c = chains[i];
237
- let n = 0;
238
- while (n < out.length && n < c.length && out[n] === c[n])
239
- n++;
240
- out = out.slice(0, n);
241
- }
242
- return out;
243
- }
244
- function describeMw(mw) {
245
- return mw.name ? `"${mw.name}"` : "an anonymous middleware";
246
- }
247
- export class Honey {
248
- /* view state — what routes registered through this handle capture */
249
- _basePath;
250
- _chain;
251
- _chainMeta;
252
- _contextValues;
253
- _graph;
254
- /** the `use(mw)` call that created this chain — null on the root handle */
255
- _node;
256
- constructor(opts) {
257
- this._basePath = "/";
258
- this._chain = [];
259
- this._chainMeta = null;
260
- this._contextValues = null;
261
- this._graph = opts?.graph ?? createGraph();
262
- this._node = null;
263
- }
264
- get _s() {
265
- return this._graph.settings;
266
- }
267
- /**
268
- * @internal — read by codegen through `metaSpecOf()`: the declared policy and every mounted
269
- * sub-app's, unmerged. Merged on read, so `metaSpec()` may come before or after `route(sub)`;
270
- * the merge lives with codegen so a served app never loads it.
271
- */
272
- get _metaSpecSource() {
273
- return { absorbed: this._graph.absorbedMetaSpecs, declared: this._graph.metaSpec };
274
- }
275
- /** @internal — read by codegen and OpenAPI */
276
- get _errorFactory() {
277
- return this._graph.settings.errorFactory;
278
- }
279
- set _errorFactory(factory) {
280
- this._graph.settings.errorFactory = factory;
281
- this._bumpEpoch();
282
- }
283
- /** @internal — read by OpenAPI */
284
- get _errorSchema() {
285
- return this._graph.settings.errorSchema;
286
- }
287
- /** @internal — read by OpenAPI */
288
- get _customErrorSchema() {
289
- return this._graph.settings.customErrorSchema;
290
- }
291
- get _root() {
292
- return this._graph.root;
293
- }
294
- get _realtimeBus() {
295
- return this._graph.realtimeBus;
296
- }
297
- /** A new handle on the same graph, carrying this handle's view. */
298
- _derive(chain = this._chain) {
299
- const next = new Honey({ graph: this._graph });
300
- next._basePath = this._basePath;
301
- next._chain = chain;
302
- next._chainMeta = this._chainMeta;
303
- next._contextValues = this._contextValues;
304
- next._node = this._node;
305
- return next;
306
- }
307
- /** This handle registers, mounts or serves — every `use()` on its way here is in use. */
308
- _markUsed() {
309
- let node = this._node;
310
- while (node !== null && !node.used) {
311
- node.used = true;
312
- node = node.parent;
313
- }
314
- }
315
- /** @internal — used by RouteBuilder for pre-filtered error factory */
316
- get _factory() {
317
- return this._graph.settings.errorFactory;
318
- }
319
- /** @internal — used by runtime error boundary */
320
- get _boundaryKey() {
321
- return this._graph.settings.defaultBoundaryKey;
322
- }
323
- /** Convert an unknown thrown value to a plain error Response — no boundary, no onError. */
324
- _toErrorResponse(thrown) {
325
- const error = thrown instanceof HoneyError
326
- ? thrown
327
- : new HoneyError({
328
- cause: thrown,
329
- errorKey: EK.internal_server_error,
330
- status: SK.internal_server_error,
331
- });
332
- const s = this._s;
333
- return createErrorResponse(error, s.errorFormatter, s.customErrorFormatter);
334
- }
335
- _createBoundaryError(errorKey, cause, fac) {
336
- const factory = fac;
337
- const factoryFn = factory?.[errorKey];
338
- if (factoryFn) {
339
- /* check if this is a custom schema error via ERROR_META — boundary must use standard errors only */
340
- const meta = factory?.[ERROR_META];
341
- if (meta?.[errorKey]?.schema) {
342
- /* custom schema error — cannot be used as boundary, fall through to manual construction */
343
- }
344
- else {
345
- return factoryFn({ cause });
346
- }
347
- }
348
- return new HoneyError({
349
- cause,
350
- errorKey,
351
- status: SK.internal_server_error,
352
- });
353
- }
354
- _createError(errorKey, statusKey) {
355
- const factory = this._s.errorFactory;
356
- const factoryFn = factory?.[errorKey];
357
- if (factoryFn) {
358
- return factoryFn();
359
- }
360
- return new HoneyError({ errorKey, status: statusKey });
361
- }
362
- /**
363
- * The i18n-resolved copy of `honeyError`: message from the locale's template for its
364
- * errorKey, field paths from the locale's field names. Returns `honeyError` itself when
365
- * i18n is not configured or nothing matches. Never mutates it: an error instance can be
366
- * thrown again, on another request, in another locale.
367
- */
368
- async _resolveI18n(honeyError, ctx, env, request, log) {
369
- const i18n = this._s.errorI18n;
370
- if (!i18n)
371
- return honeyError;
372
- try {
373
- const locale = await i18n.resolveLocale({
374
- cookies: ctx.cookies,
375
- env,
376
- headers: ctx.headers,
377
- params: ctx.params,
378
- req: request,
379
- search: ctx.search,
380
- });
381
- await loadHoneyFeature("i18n");
382
- return getI18nRuntime().translateError(honeyError, i18n, locale);
383
- }
384
- catch (e) {
385
- log?.warn?.({ err: e }, "i18n resolution failed");
386
- return honeyError;
387
- }
388
- }
389
- /**
390
- * The error boundary of every `next()`: turns what a handler or middleware threw into the
391
- * Response that replaces it, so every middleware around it sees a Response. Never rejects.
392
- */
393
- _convertError(thrown, ctx) {
394
- const fc = ctx._rq;
395
- const plan = fc?.plan;
396
- if (fc === null || fc === undefined || plan === null || plan === undefined) {
397
- setCtxError(ctx, asHoneyError(thrown));
398
- return this._safeErrorResponse(thrown);
399
- }
400
- const fallback = (e) => {
401
- fc.log?.warn?.({ err: e }, "error response failed");
402
- setCtxError(ctx, asHoneyError(thrown));
403
- return this._safeErrorResponse(thrown);
404
- };
405
- try {
406
- return this._resolveErrorResponse(thrown, plan, fc, ctx).catch(fallback);
407
- }
408
- catch (e) {
409
- return fallback(e);
410
- }
411
- }
412
- /** Last resort when even the configured formatter throws. */
413
- _safeErrorResponse(thrown) {
414
- try {
415
- return this._toErrorResponse(thrown instanceof HoneyError ? thrown : undefined);
416
- }
417
- catch {
418
- return new Response(JSON.stringify({ error: { errorKey: EK.internal_server_error } }), {
419
- headers: { "content-type": "application/json" },
420
- status: 500,
421
- });
422
- }
423
- }
424
- /**
425
- * Convert thrown value into an error Response — resolves boundary wrapping, i18n
426
- * translation, the onError callback, and error telemetry. `onResponse` telemetry is not
427
- * fired here: the request fires it exactly once, on the way out.
428
- */
429
- async _resolveErrorResponse(thrown, plan, fc, ctx) {
430
- const { env, log, request, startTime, method, path } = fc;
431
- const s = this._s;
432
- const record = plan.r;
433
- const fac = (record.fac ?? null);
434
- let honeyError;
435
- const boundaryKey = record.bek;
436
- if (thrown instanceof HoneyError) {
437
- /* framework-managed errorKeys (input/output validation, content negotiation, etc.) are always allowed
438
- * regardless of the declared keys — users never declare them, the framework owns them. */
439
- if (plan.enf && !FRAMEWORK_EKS.has(thrown.errorKey) && !record.ek.has(thrown.errorKey)) {
440
- honeyError = boundaryKey
441
- ? this._createBoundaryError(boundaryKey, thrown, fac)
442
- : new HoneyError({ cause: thrown, errorKey: EK.internal_server_error, status: SK.internal_server_error });
443
- }
444
- else {
445
- honeyError = thrown;
446
- }
447
- }
448
- else {
449
- honeyError = boundaryKey
450
- ? this._createBoundaryError(boundaryKey, thrown, fac)
451
- : new HoneyError({ cause: thrown, errorKey: EK.internal_server_error, status: SK.internal_server_error });
452
- }
453
- honeyError = await this._resolveI18n(honeyError, ctx, env, request, log);
454
- if (s.onError) {
455
- try {
456
- const customResult = await s.onError(thrown, this._makeErrorCtx(fc));
457
- if (customResult instanceof HoneyError) {
458
- /* user-mapped boundary error — re-run i18n against new errorKey,
459
- * then fall through to the default response path */
460
- honeyError = await this._resolveI18n(customResult, ctx, env, request, log);
461
- }
462
- else if (customResult) {
463
- safeFire(() => s.telemetry?.onError?.({ duration: performance.now() - startTime, error: honeyError, method, path }), log);
464
- setCtxError(ctx, honeyError);
465
- ctx._isErrorResponse = true;
466
- return customResult;
467
- }
468
- /* customResult === undefined | void → fall through to default path */
469
- }
470
- catch (e) {
471
- log?.warn?.({ err: e }, "onError failed");
472
- }
473
- }
474
- safeFire(() => s.telemetry?.onError?.({ duration: performance.now() - startTime, error: honeyError, method, path }), log);
475
- setCtxError(ctx, honeyError);
476
- ctx._isErrorResponse = true;
477
- return this._makeErrorCtx(fc).jsonFromError(honeyError);
478
- }
479
- basePath(prefix) {
480
- const next = this._derive();
481
- next._basePath = mergePath(this._basePath, prefix);
482
- return next;
483
- }
484
- context(values) {
485
- for (const key in values) {
486
- if (RESERVED_CTX_KEYS.has(key)) {
487
- throw new Error(`context() cannot set reserved key "${key}"`);
488
- }
489
- }
490
- const next = this._derive();
491
- next._contextValues = this._contextValues ? { ...this._contextValues, ...values } : { ...values };
492
- return next;
493
- }
494
- logger(logger) {
495
- this._s.logger = logger;
496
- return this;
497
- }
498
- outputValidation(mode) {
499
- this._s.outputValidation = mode;
500
- this._bumpEpoch();
501
- return this;
502
- }
503
- trailingSlash(mode) {
504
- this._s.trailingSlash = mode;
505
- return this;
506
- }
507
- /**
508
- * Request paths containing an encoded `/` or `\` (`%2F`, `%5C`) answer 400 by default.
509
- * `"allow"` keeps them encoded in the path, so they decode into a param value
510
- * (`/repos/:id` with `/repos/group%2Fproject` gives `id === "group/project"`). Only allow
511
- * them when nothing downstream (a `proxy()` upstream, a file resolver) treats a decoded
512
- * slash as a separator.
513
- */
514
- encodedSlashes(mode) {
515
- this._s.encodedSlashes = mode;
516
- return this;
517
- }
518
- /**
519
- * Which reverse proxies in front of the app to believe. Decides `ctx.ip`, `clientInfo()`,
520
- * `ipRestrict`, and every other feature that needs the client's address, scheme or host.
521
- *
522
- * - `false` (default): the peer address the runtime reports is the client; `X-Forwarded-*`
523
- * headers are ignored, since any client can send them.
524
- * - a hop count: exactly that many proxies, each appending its peer to `X-Forwarded-For`
525
- * (nginx `$proxy_add_x_forwarded_for`, most load balancers). The client is the entry the
526
- * outermost proxy wrote.
527
- * - addresses and CIDR ranges of your proxies: hops from those addresses are skipped; the
528
- * first other address is the client.
529
- *
530
- * A hop count or list needs `import "@lovrozagar/honey/trust"` in the app entry.
531
- */
532
- trustProxy(value) {
533
- this._s.trust =
534
- value === false || value === 0 ? TRUST_OFF : requireFeature("trust", "app.trustProxy()").compileTrust(value);
535
- return this;
536
- }
537
- /** Strip a URL path prefix before route matching — boundary-safe (won't strip partial segments), paths without the prefix pass through unchanged */
538
- stripPrefix(prefix) {
539
- let normalized = prefix.replace(/\/+$/, "");
540
- if (normalized.length > 0 && normalized.charCodeAt(0) !== 47) {
541
- normalized = `/${normalized}`;
542
- }
543
- this._s.stripPrefix = normalized === "" || normalized === "/" ? null : normalized;
544
- return this;
545
- }
546
- wsAdapter(adapter) {
547
- this._s.wsAdapter = adapter;
548
- return this;
549
- }
550
- /**
551
- * Serve this app's OpenAPI document at `${path}.json`, `.yaml` and `.yml` (default
552
- * `/openapi`), and optionally a docs UI. Each call serves its own document: two calls with
553
- * different options (say an internal and a public profile) never share a cache. Documents
554
- * are generated once per route change, serialized once, and sent with an `ETag` and
555
- * `Cache-Control: no-cache`. Pass `enabled: false` (for example in production) to mount
556
- * nothing while keeping the call in place.
557
- */
558
- openapi(options) {
559
- if (options.enabled === false)
560
- return this;
561
- const stem = options.path ?? "/openapi";
562
- const epochOf = () => this._graph.epoch;
563
- /* per call, not per app: each openapi() serves the document its own options describe */
564
- const document = epochCached(epochOf, async () => {
565
- await loadHoneyFeature("openapi");
566
- return getOpenApiRuntime().generateOpenApi(this, {
567
- filterRoutes: options.filterRoutes,
568
- info: { description: options.description, title: options.title, version: options.version },
569
- /* a served document is not an authoring moment — the check belongs to `honey generate` */
570
- invalidate: "off",
571
- profile: options.profile,
572
- securitySchemes: options.securitySchemes,
573
- });
574
- });
575
- /* the document first: it loads the runtime the serializers come from */
576
- const json = epochCached(epochOf, async () => {
577
- const doc = await document();
578
- return getOpenApiRuntime().toServedArtifact(JSON.stringify(doc), "application/json");
579
- });
580
- const yaml = epochCached(epochOf, async () => {
581
- const doc = await document();
582
- const runtime = getOpenApiRuntime();
583
- return runtime.toServedArtifact(runtime.toYaml(doc), "application/yaml; charset=utf-8");
584
- });
585
- const jsonPath = `${stem}.json`;
586
- this._mountArtifact("openapi", jsonPath, json);
587
- this._mountArtifact("openapi", `${stem}.yml`, yaml);
588
- this._mountArtifact("openapi", `${stem}.yaml`, yaml);
589
- if (options.docs) {
590
- const docs = options.docs;
591
- const specPath = mergePath(this._basePath, jsonPath);
592
- const ui = async (ctx) => {
593
- await loadHoneyFeature("openapi");
594
- /* the browser asks for the URL it sees: a stripped prefix is part of it */
595
- const prefix = this._s.stripPrefix ?? "";
596
- return getOpenApiRuntime().docsUi(docs, prefix + specPath)(ctx);
597
- };
598
- /* without an explicit docsPath, a user route at /docs moves the UI to /reference */
599
- const candidates = options.docsPath ? [options.docsPath] : ["/docs", "/reference"];
600
- let mounted = "user";
601
- let tried = candidates[0];
602
- for (const p of candidates) {
603
- tried = p;
604
- mounted = this._mountInternalGet(p, ui);
605
- if (mounted !== "user")
606
- break;
607
- }
608
- if (mounted !== "mounted") {
609
- const at = mergePath(this._basePath, tried);
610
- throw new Error(mounted === "internal"
611
- ? `Honey.openapi({ docs }) cannot mount at ${at}: an earlier openapi() or manifest() serves it. Pass docsPath.`
612
- : `Honey.openapi({ docs }) cannot mount at ${at}: a route already owns it. Pass docsPath.`);
613
- }
614
- }
615
- return this;
616
- }
617
- /**
618
- * Serve the route manifest at `path` (default `/manifest.json`), filtered by the same
619
- * visibility policy as the OpenAPI document. Cached per route change, sent with an `ETag`.
620
- * `enabled: false` mounts nothing.
621
- */
622
- manifest(options) {
623
- if (options?.enabled === false)
624
- return this;
625
- const epochOf = () => this._graph.epoch;
626
- const artifact = epochCached(epochOf, async () => {
627
- await loadHoneyFeature("openapi");
628
- const runtime = getOpenApiRuntime();
629
- return runtime.toServedArtifact(JSON.stringify(await runtime.generateManifest(this)), "application/json");
630
- });
631
- this._mountArtifact("manifest", options?.path ?? "/manifest.json", artifact);
632
- return this;
633
- }
634
- /** Mount a served document; a path another route or an earlier call owns is an error. */
635
- _mountArtifact(owner, path, load) {
636
- const result = this._mountInternalGet(path, async (ctx) => {
637
- const c = ctx;
638
- const artifact = await load();
639
- return c.res.raw(getOpenApiRuntime().artifactResponse(c.req, artifact));
640
- });
641
- if (result === "mounted")
642
- return;
643
- const at = mergePath(this._basePath, path);
644
- throw new Error(result === "internal"
645
- ? `Honey.${owner}() cannot mount GET ${at}: an earlier openapi() or manifest() serves it. Pass a different path.`
646
- : `Honey.${owner}() cannot mount GET ${at}: a route already owns it. Pass a different path.`);
647
- }
648
- async serve(options) {
649
- await loadHoneyFeature("serve");
650
- return getServeRuntime()(this, options);
651
- }
652
- /**
653
- * Mount an internal GET (spec, docs, manifest). Reports who owns the path when it cannot:
654
- * a user route (`"user"`) or an earlier internal mount (`"internal"`). Only an exact leaf
655
- * counts: a `/:slug` or `/*rest` route does not block a static internal path, which wins
656
- * over it on precedence, with backtracking, in both the runtime and a loaded tree.
657
- */
658
- _mountInternalGet(path, fn) {
659
- const fullPath = mergePath(this._basePath, path);
660
- const segments = parsePattern(fullPath);
661
- const id = routeId("GET", fullPath);
662
- const g = this._graph;
663
- const existing = g.records.get(id);
664
- if (existing)
665
- return existing._skip === true ? "internal" : "user";
666
- const leaf = findLeaf(g.root, segments, "GET");
667
- if (leaf !== undefined && leaf !== id)
668
- return "user";
669
- if (findLeaf(g.root, segments, "ALL") !== undefined)
670
- return "user";
671
- /* a leaf the loaded tree holds for a user route the app has yet to register */
672
- if (leaf === id && g.loaded?.has(id))
673
- return "user";
674
- const routeHandler = {
675
- _skip: true,
676
- bek: null,
677
- cm: [...this._chain],
678
- cv: this._contextValues,
679
- dk: new Set(),
680
- ek: new Set(),
681
- fn: (ctx) => fn(ctx),
682
- iv: null,
683
- mt: null,
684
- mw: [],
685
- os: null,
686
- ov: null,
687
- own: g.settings,
688
- rb: null,
689
- rm: [],
690
- xm: null,
691
- };
692
- this._markUsed();
693
- this._addRoute("GET", segments, routeHandler);
694
- return "mounted";
695
- }
696
- _bumpEpoch() {
697
- this._graph.epoch++;
698
- }
699
- /** Place `id` at every leaf of `segments`, copying a shared (loaded) root first. */
700
- _placeLeaves(segments, method, id) {
701
- const g = this._graph;
702
- const variants = leafVariants(segments);
703
- if (variants.every((v) => findLeaf(g.root, v, method) === id))
704
- return;
705
- if (g.rootShared) {
706
- g.root = cloneTree(g.root);
707
- g.rootShared = false;
708
- }
709
- for (const v of variants)
710
- insertLeaf(g.root, v, method, id);
711
- }
712
- /**
713
- * @internal — register one route record. Over a loaded tree the record binds to the leaf
714
- * the tree already holds for its id; a root wildcard the tree lacks becomes the gateway
715
- * catch-all; any other unknown route marks the tree as stale (reported at finalize).
716
- */
717
- _addRoute(method, segments, record) {
718
- const pattern = canonical(segments);
719
- const id = routeId(method, pattern);
720
- const g = this._graph;
721
- if (g.records.has(id) || (isRootWildcard(segments) && g.catchAll.has(method))) {
722
- throw new Error(`Duplicate route: ${id}`);
723
- }
724
- record.id = id;
725
- record.rp = pattern;
726
- if (g.loaded !== null && record._skip !== true) {
727
- const known = leafVariants(segments).every((v) => findLeaf(g.root, v, method) === id);
728
- if (!known) {
729
- if (isRootWildcard(segments)) {
730
- record.ca = true;
731
- g.catchAll.set(method, record);
732
- this._bumpEpoch();
733
- return;
734
- }
735
- g.unexpected.add(id);
736
- }
737
- }
738
- this._placeLeaves(segments, method, id);
739
- g.records.set(id, record);
740
- this._bumpEpoch();
741
- }
742
- /** @internal — register one websocket (or realtime) route record. */
743
- _addWsRoute(segments, record) {
744
- const pattern = canonical(segments);
745
- const id = routeId("WS", pattern);
746
- const g = this._graph;
747
- if (g.wsRecords.has(id))
748
- throw new Error(`Duplicate WebSocket route: ${pattern}`);
749
- record.id = id;
750
- record.rp = pattern;
751
- if (g.loaded !== null && leafVariants(segments).some((v) => findLeaf(g.root, v, "WS") !== id)) {
752
- g.unexpected.add(id);
753
- }
754
- this._placeLeaves(segments, "WS", id);
755
- g.wsRecords.set(id, record);
756
- g.hasWs = true;
757
- this._bumpEpoch();
758
- }
759
- /**
760
- * Resolve what this graph serves: registered records, live records carried by a loaded
761
- * snapshot, and delegated leaves the gateway catch-all serves. Then resolve every record —
762
- * its full chain (`chain → scoped → route → input validation`), error keys, meta and error
763
- * factory — and compile it once. Re-runs whenever the graph's epoch moved. Throws, naming
764
- * every route, when a loaded tree and the registered routes disagree (the generated file is
765
- * stale), and when a `use(mw)` handle or a route builder was left unused (the middleware or
766
- * route would silently be missing).
767
- */
768
- _finalize() {
769
- const g = this._graph;
770
- if (g.final !== null && g.final.epoch === g.epoch)
771
- return g.final;
772
- this._assertNothingDiscarded();
773
- const byId = new Map();
774
- const wsById = new Map();
775
- for (const [id, r] of g.records)
776
- byId.set(id, r);
777
- for (const [id, r] of g.wsRecords)
778
- wsById.set(id, r);
779
- const problems = [];
780
- if (g.loaded !== null) {
781
- for (const id of g.unexpected)
782
- problems.push(`${id} is registered but missing from the loaded route tree`);
783
- let delegated = 0;
784
- for (const [id, entry] of g.loaded) {
785
- const { method, pattern } = splitRouteId(id);
786
- if (method === "WS") {
787
- if (wsById.has(id))
788
- continue;
789
- if (entry.h !== undefined) {
790
- const live = copyRecord(entry.h);
791
- live.id = id;
792
- live.rp = pattern;
793
- wsById.set(id, live);
794
- }
795
- /* a websocket leaf nothing serves is not upgraded: the request falls through to HTTP */
796
- continue;
797
- }
798
- if (byId.has(id))
799
- continue;
800
- if (entry.h !== undefined) {
801
- const live = copyRecord(entry.h);
802
- live.id = id;
803
- live.rp = pattern;
804
- byId.set(id, live);
805
- continue;
806
- }
807
- const ca = g.catchAll.get(method) ?? g.catchAll.get("ALL");
808
- if (ca !== undefined) {
809
- const dl = copyRecord(ca);
810
- dl.dl = true;
811
- dl.id = id;
812
- dl.rp = pattern;
813
- dl.xm = entry.mt ? { ...entry.mt } : null;
814
- dl.iv = entry.iv ?? null;
815
- dl.os = entry.os ?? null;
816
- dl.dk = new Set([...(ca.dk ?? []), ...(entry.ek ?? [])]);
817
- if (entry.bek !== undefined && entry.bek !== null)
818
- dl.rb = entry.bek;
819
- byId.set(id, dl);
820
- delegated++;
821
- continue;
822
- }
823
- /* no handler anywhere: documented (served specs list it) but answered with 404 */
824
- byId.set(id, {
825
- bek: null,
826
- cm: [],
827
- dk: new Set(entry.ek ?? []),
828
- dl: true,
829
- ek: new Set(),
830
- fn: NOT_SERVED,
831
- id,
832
- iv: entry.iv ?? null,
833
- mt: null,
834
- mw: [],
835
- os: entry.os ?? null,
836
- rb: entry.bek ?? null,
837
- rm: [],
838
- rp: pattern,
839
- xm: entry.mt ? { ...entry.mt } : null,
840
- });
841
- }
842
- if (g.catchAll.size > 0 && delegated === 0) {
843
- for (const id of g.catchAll.keys()) {
844
- problems.push(`ALL root wildcard (${g.catchAll.get(id)?.id}) is missing from the loaded route tree`);
845
- }
846
- }
847
- }
848
- if (problems.length > 0) {
849
- /* generation rewrites this file from the registered routes; serving it stale is the error */
850
- if (g.unloadIfStale) {
851
- this._unloadTree();
852
- return this._finalize();
853
- }
854
- throw new Error(`Route tree out of date — regenerate it (\`honey generate\`):\n ${problems.join("\n ")}`);
855
- }
856
- const convert = (thrown, ctx) => this._convertError(thrown, ctx);
857
- const plans = new Map();
858
- const wsPlans = new Map();
859
- const statics = Object.create(null);
860
- const userChains = [];
861
- for (const [id, r] of byId) {
862
- const plan = this._planRoute(r, convert);
863
- plans.set(id, plan);
864
- if (r._skip !== true && r.dl !== true)
865
- userChains.push(r.cm ?? []);
866
- const { method, segments } = patternOf(id);
867
- for (const v of leafVariants(segments)) {
868
- if (isStaticPattern(v))
869
- statics[`${method} ${canonical(v)}`] = plan;
870
- }
871
- }
872
- for (const [id, r] of wsById) {
873
- wsPlans.set(id, this._planWs(r, convert));
874
- userChains.push(r.cm ?? []);
875
- }
876
- /* an app with no routes (static files only) has nothing but the handles that serve it */
877
- if (userChains.length === 0)
878
- for (const chain of g.served)
879
- userChains.push(chain);
880
- const miss = this._planMiss(commonPrefix(userChains), convert);
881
- g.final = { byId, convert, epoch: g.epoch, miss, plans, statics, wsById, wsPlans };
882
- return g.final;
883
- }
884
- /** `use(mw)` handles that never registered, mounted or served, and builders without `.handler()`. */
885
- _assertNothingDiscarded() {
886
- const g = this._graph;
887
- const problems = [];
888
- for (const node of g.chains) {
889
- if (node.used)
890
- continue;
891
- problems.push(`app.use(${describeMw(node.mw)}) returned a handle that never registers a route, so the middleware runs nowhere. ` +
892
- "use() does not change the handle it is called on: keep the returned value and register routes on it " +
893
- "(`const authed = app.use(auth); authed.get(...)`), or chain it (`honey().use(mw).get(...)`).");
894
- }
895
- for (const p of g.pending) {
896
- problems.push(`${p.id} was declared but never got a .handler() (or .proxy()), so the route is not registered.`);
897
- }
898
- if (problems.length > 0)
899
- throw new Error(`honey: ${problems.join("\n ")}`);
900
- }
901
- /**
902
- * Resolve a record against this graph: chain = captured chain, the scopes that cover its
903
- * pattern (behind a request-path check where only some of its paths are inside), then its
904
- * route middleware. Error keys and contributed meta come from that chain, in run order.
905
- * The error factory, default errors and boundary come from the app the route was
906
- * registered on when that app has a factory, else from this one.
907
- */
908
- _resolve(r, everyScope = false) {
909
- const s = this._graph.settings;
910
- const own = r.own ?? s;
911
- const src = own.errorFactory !== null ? own : s;
912
- const segments = parsePattern(r.rp ?? "/");
913
- const scoped = [];
914
- for (const entry of this._graph.scoped) {
915
- if (everyScope) {
916
- scoped.push(entry.guard);
917
- continue;
918
- }
919
- const cov = scopeCoverage(segments, entry.segs);
920
- if (cov === "all")
921
- scoped.push(entry.mw);
922
- else if (cov === "some")
923
- scoped.push(entry.guard);
924
- }
925
- const mw = [...this._graph.global.values(), ...(r.cm ?? []), ...scoped, ...(r.rm ?? [])];
926
- /* app defaults, then what the middleware declares in run order, then the route's own */
927
- const ek = new Set(src.defaultErrorKeys);
928
- for (const m of mw) {
929
- const errs = errorsOf(m);
930
- if (errs)
931
- for (const k of errs)
932
- ek.add(k);
933
- }
934
- if (r.dk !== undefined)
935
- for (const k of r.dk)
936
- ek.add(k);
937
- const bek = r.rb ?? src.defaultBoundaryKey;
938
- if (bek !== null)
939
- ek.add(bek);
940
- const enf = ek.size > 0;
941
- const fac = src.errorFactory;
942
- let ef = fac;
943
- if (fac !== null && enf) {
944
- const subset = Object.create(null);
945
- for (const key of ek) {
946
- if (key in fac)
947
- subset[key] = fac[key];
948
- }
949
- ef = Object.freeze(subset);
950
- }
951
- r.mw = mw;
952
- r.ek = ek;
953
- r.bek = bek;
954
- r.fac = fac;
955
- r.ef = ef;
956
- r.mt = mergeContributedMeta(collectMiddlewareMeta([mw]), r.xm ? { ...r.xm } : null);
957
- /* the serving app's taps win; a route from another app keeps that app's for the rest */
958
- const taps = own === s || own.taps === null ? s.taps : s.taps === null ? own.taps : new Map([...own.taps, ...s.taps]);
959
- return { enf, own, taps };
960
- }
961
- /** Wrap each middleware for `telemetry.onMiddleware`, once per finalize. */
962
- _timed(chain) {
963
- const onMw = this._graph.settings.telemetry?.onMiddleware;
964
- if (onMw === undefined)
965
- return chain;
966
- const log = this._graph.settings.logger ?? undefined;
967
- return chain.map((m) => timedMiddleware(m, onMw, log));
968
- }
969
- _planRoute(r, convert) {
970
- const { enf, own, taps } = this._resolve(r);
971
- const s = this._graph.settings;
972
- const ovm = own.outputValidation ?? s.outputValidation ?? "off";
973
- const base = this._timed(r.mw);
974
- const chain = [...base];
975
- /* a delegated route's schemas document it; the body is forwarded, never validated here */
976
- const iv = r.iv;
977
- if (iv && r.dl !== true) {
978
- chain.push((ctx, next) => validateInput(iv, ctx["req"], ctx["params"], ctx).then((validated) => {
979
- ctx["input"] = validated;
980
- return next();
981
- }));
982
- }
983
- const fn = r.fn;
984
- const handler = r.os && ovm !== "off"
985
- ? (ctx) => {
986
- const res = fn(ctx);
987
- if (!shouldValidateOutput(ovm))
988
- return res;
989
- return res instanceof Promise
990
- ? res.then((v) => this._validateOutput(r, ctx, v))
991
- : this._validateOutput(r, ctx, res);
992
- }
993
- : fn;
994
- return {
995
- cv: r.cv ?? null,
996
- enf,
997
- pf: null,
998
- pfChain: base,
999
- r,
1000
- rt: null,
1001
- run: compileChain(chain, handler, convert),
1002
- taps,
1003
- };
1004
- }
1005
- _planWs(r, convert) {
1006
- const { enf } = this._resolve(r);
1007
- const rt = this._graph.realtimeRoutes.get(r.rp) ?? null;
1008
- const chain = this._timed(r.mw);
1009
- const iv = r.iv;
1010
- if (iv) {
1011
- chain.push((ctx, next) => validateInput(iv, ctx["req"], ctx["params"], ctx).then((validated) => {
1012
- ctx["input"] = validated;
1013
- return next();
1014
- }));
1015
- }
1016
- const terminal = rt !== null
1017
- ? (ctx) => this._realtimeUpgrade(ctx, rt)
1018
- : (ctx) => this._wsUpgrade(ctx);
1019
- return {
1020
- cv: r.cv ?? null,
1021
- enf,
1022
- pf: null,
1023
- pfChain: [],
1024
- r,
1025
- rt,
1026
- run: compileChain(chain, terminal, convert),
1027
- taps: null,
1028
- };
1029
- }
1030
- /**
1031
- * 404 and 405 run through the same pipeline as a route: the middleware every route of this
1032
- * graph starts with (with no routes: every handle that served a request), then every scope
1033
- * (behind its request-path check), then the 404/405 answer. So a logger or CORS policy on the whole app also covers unknown paths, and a
1034
- * scope's guard answers before "not found" leaks what exists under it.
1035
- */
1036
- _planMiss(prefix, convert) {
1037
- const r = {
1038
- bek: null,
1039
- cm: prefix,
1040
- dk: new Set(),
1041
- ek: new Set(),
1042
- fn: (ctx) => {
1043
- const fc = ctx._rq;
1044
- return fc.allowed !== null ? this._make405(fc, fc.allowed) : this._make404(fc);
1045
- },
1046
- mt: null,
1047
- mw: [],
1048
- rm: [],
1049
- rp: "",
1050
- xm: null,
1051
- };
1052
- /* every scope, each behind its path check — the request path decides */
1053
- const { enf } = this._resolve(r, true);
1054
- return {
1055
- cv: null,
1056
- enf,
1057
- pf: null,
1058
- pfChain: [],
1059
- r,
1060
- rt: null,
1061
- run: compileChain(this._timed(r.mw), r.fn, convert),
1062
- taps: null,
1063
- };
1064
- }
1065
- /**
1066
- * @internal — every served route as one entry per leaf (an optional param yields two
1067
- * paths), in tree order. Codegen and OpenAPI read routes through this.
1068
- */
1069
- _collectRoutes(includeSkipped = false) {
1070
- const final = this._finalize();
1071
- const out = [];
1072
- forEachLeaf(this._root, (method, path, id) => {
1073
- if (method === "WS")
1074
- return;
1075
- const handler = final.byId.get(id);
1076
- if (handler === undefined)
1077
- return;
1078
- if (handler._skip && !includeSkipped)
1079
- return;
1080
- out.push({ handler, method, path });
1081
- });
1082
- return out;
1083
- }
1084
- /** @internal — websocket routes, one entry per leaf. */
1085
- _collectWsRoutes() {
1086
- const final = this._finalize();
1087
- const out = [];
1088
- forEachLeaf(this._root, (method, path, id) => {
1089
- if (method !== "WS")
1090
- return;
1091
- const handler = final.wsById.get(id);
1092
- if (handler !== undefined)
1093
- out.push({ handler, path });
1094
- });
1095
- return out;
1096
- }
1097
- /** @internal — the route-graph epoch; served documents cache against it. */
1098
- get _epoch() {
1099
- return this._graph.epoch;
1100
- }
1101
- defaultErrorFormatter(schemaOrFn, maybeFn) {
1102
- const s = this._s;
1103
- if (typeof schemaOrFn === "function") {
1104
- s.errorSchema = null;
1105
- s.errorFormatter = schemaOrFn;
1106
- }
1107
- else {
1108
- s.errorSchema = schemaOrFn;
1109
- const mapper = maybeFn;
1110
- s.errorFormatter = (error) => mapper(error);
1111
- }
1112
- return this;
1113
- }
1114
- customErrorFormatter(schemaOrFn, maybeFn) {
1115
- const s = this._s;
1116
- if (typeof schemaOrFn === "function") {
1117
- s.customErrorSchema = null;
1118
- s.customErrorFormatter = schemaOrFn;
1119
- }
1120
- else {
1121
- s.customErrorSchema = schemaOrFn;
1122
- const mapper = maybeFn;
1123
- s.customErrorFormatter = (error, data) => mapper(error, data);
1124
- }
1125
- return this;
1126
- }
1127
- errorI18n(config) {
1128
- this._s.errorI18n = config;
1129
- return this;
1130
- }
1131
- onError(handler) {
1132
- this._s.onError = handler;
1133
- return this;
1134
- }
1135
- onMethodNotAllowed(handler) {
1136
- this._s.onMethodNotAllowed = handler;
1137
- return this;
1138
- }
1139
- onNotFound(handler) {
1140
- this._s.onNotFound = handler;
1141
- return this;
1142
- }
1143
- /** Register a tap handler keyed by name — fires after successful handler response */
1144
- tap(key, handler) {
1145
- const s = this._s;
1146
- if (s.taps === null)
1147
- s.taps = new Map();
1148
- s.taps.set(key, handler);
1149
- this._bumpEpoch();
1150
- return this;
1151
- }
1152
- telemetry(adapter) {
1153
- this._s.telemetry = adapter;
1154
- /* onMiddleware wraps the compiled chains */
1155
- this._bumpEpoch();
1156
- return this;
1157
- }
1158
- /**
1159
- * Load a route tree — a generated `routes.gen.ts`, an `app.toRouteTree()` snapshot, or a
1160
- * `mergeTree()` of either. The tree supplies the router topology; what each route runs
1161
- * comes from the routes this app registers afterwards (bound by `RouteId`), from live
1162
- * records in a snapshot, or — for leaves with neither — from a root wildcard the app
1163
- * registers as its gateway catch-all. Must be called before any route is registered.
1164
- */
1165
- routeTree(tree) {
1166
- /* `honey generate` loads the app that imports the very file it is about to rewrite: a tree
1167
- from an older honey is ignored there, and the routes the app registers are used instead */
1168
- const generating = isCodegenProcess();
1169
- if (generating) {
1170
- try {
1171
- assertTreeFormat(tree);
1172
- }
1173
- catch {
1174
- return this;
1175
- }
1176
- }
1177
- assertTreeFormat(tree);
1178
- const g = this._graph;
1179
- if (g.loaded !== null)
1180
- throw new Error("routeTree() was already called on this app");
1181
- for (const r of g.records.values()) {
1182
- if (r._skip !== true)
1183
- throw new Error(`routeTree() must be called before routes are registered (${r.id} is)`);
1184
- }
1185
- if (g.wsRecords.size > 0 || g.catchAll.size > 0) {
1186
- throw new Error("routeTree() must be called before routes are registered");
1187
- }
1188
- forEachLeaf(tree.root, (method, path, id) => {
1189
- if (!(id in tree.routes))
1190
- throw new Error(`routeTree(): leaf ${method} ${path} has no route entry (${id})`);
1191
- });
1192
- const internals = [...g.records.values()];
1193
- g.records.clear();
1194
- g.root = freezeTree(tree.root);
1195
- g.rootShared = true;
1196
- g.loaded = new Map();
1197
- g.unloadIfStale = generating;
1198
- for (const id of Object.keys(tree.routes))
1199
- g.loaded.set(id, { ...tree.routes[id] });
1200
- if (hasWsLeaf(g.root))
1201
- g.hasWs = true;
1202
- /* internal routes mounted before the tree was loaded move onto the loaded topology */
1203
- for (const r of internals) {
1204
- const { method, segments } = patternOf(r.id);
1205
- this._addRoute(method, segments, r);
1206
- }
1207
- this._bumpEpoch();
1208
- return this;
1209
- }
1210
- /**
1211
- * Snapshot this app's routes as a tree: a copy of the topology plus, per route, its data
1212
- * and its live record. Internal routes (spec, docs, manifest) are left out. Loading the
1213
- * snapshot into another app serves these records; nothing in it is shared with this app.
1214
- * Each record keeps this app's settings (error factory, defaults, boundary) and context
1215
- * values, and carries the scoped middleware that covers it here as part of its chain —
1216
- * scopes themselves do not travel in a tree.
1217
- */
1218
- toRouteTree() {
1219
- this._markUsed();
1220
- const final = this._finalize();
1221
- const routes = Object.create(null);
1222
- const keep = new Set();
1223
- for (const [id, r] of final.byId) {
1224
- if (r._skip)
1225
- continue;
1226
- keep.add(id);
1227
- routes[id] = {
1228
- bek: r.bek,
1229
- ek: [...r.ek],
1230
- h: this._bake(r),
1231
- iv: r.iv ?? null,
1232
- mt: r.mt,
1233
- os: r.os ?? null,
1234
- };
1235
- }
1236
- for (const [id, r] of final.wsById) {
1237
- keep.add(id);
1238
- routes[id] = { bek: r.bek, ek: [...r.ek], h: this._bake(r), iv: r.iv, mt: r.mt };
1239
- }
1240
- const root = createNode();
1241
- forEachLeaf(this._root, (method, path, id) => {
1242
- if (keep.has(id))
1243
- insertLeaf(root, parsePattern(path), method, id);
1244
- });
1245
- return { meta: {}, root, routes, v: ROUTE_TREE_VERSION };
1246
- }
1247
- /** A resolved record as a standalone source: its resolved chain minus route middleware becomes its chain. */
1248
- _bake(r) {
1249
- const h = copyRecord(r);
1250
- const rm = r.rm ?? [];
1251
- /* app-wide middleware stays with the app; scopes travel as part of the chain */
1252
- h.cm = r.mw.slice(this._graph.global.size, r.mw.length - rm.length);
1253
- h.rm = [...rm];
1254
- h.dk = new Set(r.ek);
1255
- h.rb = r.bek;
1256
- h.xm = r.mt ? { ...r.mt } : null;
1257
- h.own = r.own ?? this._graph.settings;
1258
- return h;
1259
- }
1260
- /**
1261
- * @internal — generate-time: copy input/output schemas from `source` onto this app's
1262
- * routes that lack them (a gateway serves its generated tree, which carries none).
1263
- */
1264
- _overlaySchemas(source) {
1265
- const g = this._graph;
1266
- for (const [id, entry] of Object.entries(source.routes)) {
1267
- const iv = entry.iv ?? entry.h?.iv ?? null;
1268
- const os = entry.os ?? entry.h?.os ?? null;
1269
- if (iv === null && os === null)
1270
- continue;
1271
- const record = g.records.get(id);
1272
- if (record !== undefined) {
1273
- record.iv ??= iv;
1274
- record.os ??= os;
1275
- continue;
1276
- }
1277
- const loaded = g.loaded?.get(id);
1278
- if (loaded !== undefined) {
1279
- loaded.iv ??= iv;
1280
- loaded.os ??= os;
1281
- }
1282
- }
1283
- this._bumpEpoch();
1284
- }
1285
- /**
1286
- * @internal — generate-time: the route tree a gateway serves. `source` is the merged
1287
- * downstream tree (`codegen.mergeTree`); the gateway's own registered routes join it as
1288
- * ordinary leaves, while its root wildcards stay out of the tree — they are the catch-all
1289
- * the downstream leaves delegate to. An own route that is also a downstream route, or
1290
- * whose topology conflicts with one, throws here instead of at request time. The app is
1291
- * rebound to the result, so codegen that runs next (OpenAPI, manifest) sees what it serves.
1292
- */
1293
- _gatewayTree(source) {
1294
- assertTreeFormat(source);
1295
- const g = this._graph;
1296
- const root = cloneTree(source.root);
1297
- const routes = dict();
1298
- for (const id of Object.keys(source.routes)) {
1299
- const { bek, ek, i, mt } = source.routes[id];
1300
- routes[id] = { bek, ek, i, mt };
1301
- }
1302
- const own = [];
1303
- /* every route id this app serves, root wildcards included */
1304
- const served = new Set();
1305
- for (const r of [...g.records.values(), ...g.catchAll.values(), ...g.wsRecords.values()]) {
1306
- if (r._skip === true)
1307
- continue;
1308
- const id = r.id;
1309
- served.add(id);
1310
- const { method, segments } = patternOf(id);
1311
- if (!isRootWildcard(segments))
1312
- own.push({ id, method, segments });
1313
- }
1314
- const overlap = own.filter((o) => o.id in routes);
1315
- /* a merge source built from this app itself (`app.toRouteTree()`) holds exactly the routes
1316
- this app serves; anything else that overlaps is a gateway route shadowing a downstream
1317
- one — judged by the route sets, never by how many routes overlap */
1318
- const sourceIds = Object.keys(routes);
1319
- const isSelf = own.length > 0 && overlap.length === own.length && sourceIds.every((id) => served.has(id));
1320
- if (overlap.length > 0 && !isSelf) {
1321
- throw new Error(`Gateway routes are also downstream routes in the merged tree: ${overlap.map((o) => o.id).join(", ")}`);
1322
- }
1323
- if (isSelf)
1324
- own.length = 0;
1325
- for (const { id, method, segments } of own) {
1326
- for (const v of leafVariants(segments))
1327
- insertLeaf(root, v, method, id);
1328
- routes[id] = {};
1329
- }
1330
- this._replaceLoadedTree({ meta: { ...source.meta }, root, routes, v: ROUTE_TREE_VERSION });
1331
- /* own routes resolved over the rebound tree carry their final error keys and meta */
1332
- const snapshot = this.toRouteTree();
1333
- for (const { id } of own) {
1334
- const { bek, ek, mt } = snapshot.routes[id];
1335
- routes[id] = { bek, ek, mt };
1336
- }
1337
- const tree = { meta: { ...source.meta }, root, routes, v: ROUTE_TREE_VERSION };
1338
- this._replaceLoadedTree(tree);
1339
- return tree;
1340
- }
1341
- /** @internal — drop the loaded tree and route by the registered routes alone. */
1342
- _unloadTree() {
1343
- const g = this._graph;
1344
- const http = [...g.records.values(), ...g.catchAll.values()];
1345
- const ws = [...g.wsRecords.values()];
1346
- g.records.clear();
1347
- g.catchAll.clear();
1348
- g.wsRecords.clear();
1349
- g.unexpected.clear();
1350
- g.loaded = null;
1351
- g.unloadIfStale = false;
1352
- g.root = createNode();
1353
- g.rootShared = false;
1354
- g.hasWs = false;
1355
- for (const r of http) {
1356
- delete r.ca;
1357
- const { method, segments } = patternOf(r.id);
1358
- this._addRoute(method, segments, r);
1359
- }
1360
- for (const r of ws)
1361
- this._addWsRoute(patternOf(r.id).segments, r);
1362
- this._bumpEpoch();
1363
- }
1364
- /** @internal — swap the loaded tree, re-binding every registered route to it. */
1365
- _replaceLoadedTree(tree) {
1366
- const g = this._graph;
1367
- const http = [...g.records.values(), ...g.catchAll.values()];
1368
- const ws = [...g.wsRecords.values()];
1369
- g.records.clear();
1370
- g.catchAll.clear();
1371
- g.wsRecords.clear();
1372
- g.unexpected.clear();
1373
- g.loaded = null;
1374
- g.root = createNode();
1375
- g.rootShared = false;
1376
- g.hasWs = false;
1377
- this.routeTree(tree);
1378
- for (const r of http) {
1379
- delete r.ca;
1380
- const { method, segments } = patternOf(r.id);
1381
- this._addRoute(method, segments, r);
1382
- }
1383
- for (const r of ws)
1384
- this._addWsRoute(patternOf(r.id).segments, r);
1385
- }
1386
- /**
1387
- * Set the app's error factory. Like every app setting it applies to every handle of this
1388
- * app, whenever it is called; routes mounted from another app keep that app's factory.
1389
- */
1390
- errorFactory(factory) {
1391
- this._s.errorFactory = factory;
1392
- this._bumpEpoch();
1393
- return this;
1394
- }
1395
- /** Error keys every route of this app declares — applies to routes registered before and after the call. */
1396
- defaultErrors(...keys) {
1397
- for (const k of keys)
1398
- this._s.defaultErrorKeys.add(k);
1399
- this._bumpEpoch();
1400
- return this;
1401
- }
1402
- defaultBoundary(key) {
1403
- this._s.defaultBoundaryKey = key;
1404
- this._s.defaultErrorKeys.add(key);
1405
- this._bumpEpoch();
1406
- return this;
1407
- }
1408
- meta(values) {
1409
- if (values === undefined) {
1410
- /* phantom overload — type-only, no runtime effect */
1411
- return this;
1412
- }
1413
- /* chain-level meta — copy-on-write */
1414
- const next = this._derive();
1415
- next._chainMeta = this._chainMeta ? { ...this._chainMeta, ...values } : { ...values };
1416
- return next;
1417
- }
1418
- /**
1419
- * Declare what flows from route meta and route schemas into the OpenAPI document.
1420
- * Codegen-time only — never consulted on the request path. See docs/meta-spec.md.
1421
- */
1422
- metaSpec(spec) {
1423
- if (this._graph.metaSpec !== null) {
1424
- throw new Error("metaSpec() was already declared on this app — declare the whole policy in one call");
1425
- }
1426
- this._graph.metaSpec = spec;
1427
- return this;
1428
- }
1429
- /** Declare tap payload types — auto-extends meta with Partial<T> for meta-driven taps */
1430
- taps() {
1431
- return this;
1432
- }
1433
- /* oxlint-disable-next-line typescript/no-explicit-any -- overload impl requires erased types */
1434
- use(pathOrMw, maybeMw) {
1435
- if (typeof pathOrMw !== "string") {
1436
- /*
1437
- * Chain middleware: a new handle whose routes run `mw`. This handle is unchanged —
1438
- * a handle that never registers a route is reported at finalize.
1439
- */
1440
- const mw = pathOrMw;
1441
- const node = { mw, parent: this._node, used: false };
1442
- this._graph.chains.push(node);
1443
- const next = this._derive([...this._chain, mw]);
1444
- next._node = node;
1445
- return next;
1446
- }
1447
- /* scoped: guards every request path under the prefix, whichever handle registered the route */
1448
- const prefix = mergePath(this._basePath, normalizePattern(pathOrMw));
1449
- const mw = maybeMw;
1450
- const segs = parsePattern(prefix);
1451
- this._graph.scoped.push({
1452
- errors: errorsOf(mw) ? [...errorsOf(mw)] : undefined,
1453
- guard: scopeGuard(segs, mw),
1454
- mw,
1455
- prefix,
1456
- segs,
1457
- });
1458
- this._bumpEpoch();
1459
- return this._derive();
1460
- }
1461
- route(prefixOrSub, maybeSub) {
1462
- if (typeof prefixOrSub === "string") {
1463
- if (!(maybeSub instanceof Honey))
1464
- throw new TypeError("honey: route(prefix, sub) needs the sub-app");
1465
- this._markUsed();
1466
- this.basePath(prefixOrSub)._mount(maybeSub);
1467
- return this;
1468
- }
1469
- return this._mount(prefixOrSub);
1470
- }
1471
- _mount(sub) {
1472
- this._markUsed();
1473
- /* skip self-merge: .handler() already registered into the shared graph */
1474
- if (sub._graph !== this._graph) {
1475
- /*
1476
- * Re-register the sub's records under this handle: this handle's chain runs first,
1477
- * its context values and chain meta apply under the sub's own. Nothing is shared by
1478
- * reference, so routes the sub registers later stay its own, and two parents
1479
- * mounting one sub each get their own records. Each record keeps the settings of
1480
- * the sub (error factory, defaults, boundary, output validation). Internal routes
1481
- * (spec, docs, manifest) never travel.
1482
- */
1483
- sub._markUsed();
1484
- const subFinal = sub._finalize();
1485
- const subSettings = sub._graph.settings;
1486
- const mount = (r) => {
1487
- const c = copyRecord(r);
1488
- c.cm = [...this._chain, ...(r.cm ?? [])];
1489
- if (this._contextValues)
1490
- c.cv = { ...this._contextValues, ...r.cv };
1491
- if (this._chainMeta)
1492
- c.xm = { ...this._chainMeta, ...r.xm };
1493
- c.own = r.own ?? subSettings;
1494
- return c;
1495
- };
1496
- /* the sub's paths land under this handle's basePath, like Hono's `route("/v1", sub)` */
1497
- const base = this._basePath;
1498
- const at = (pattern) => (base === "/" ? pattern : mergePath(base, pattern));
1499
- for (const [id, r] of subFinal.byId) {
1500
- if (r._skip)
1501
- continue;
1502
- const { method, pattern } = splitRouteId(id);
1503
- this._addRoute(method, parsePattern(at(pattern)), mount(r));
1504
- }
1505
- for (const [id, r] of subFinal.wsById) {
1506
- const { pattern } = splitRouteId(id);
1507
- this._addWsRoute(parsePattern(at(pattern)), mount(r));
1508
- }
1509
- /* merged when codegen reads the policy (see `metaSpecOf`): the parent wins
1510
- * conflicts and keeps its resolved strictness, a sub's `false` still hides */
1511
- const subSource = sub._metaSpecSource;
1512
- this._graph.absorbedMetaSpecs.push({ absorbed: [...subSource.absorbed], declared: subSource.declared });
1513
- /* the sub's scopes guard the paths it brought — appended after this app's own */
1514
- const g = this._graph;
1515
- for (const entry of sub._graph.scoped) {
1516
- if (base === "/") {
1517
- if (!g.scoped.includes(entry))
1518
- g.scoped.push(entry);
1519
- continue;
1520
- }
1521
- const prefix = at(entry.prefix);
1522
- if (g.scoped.some((e) => e.mw === entry.mw && e.prefix === prefix))
1523
- continue;
1524
- const segs = parsePattern(prefix);
1525
- g.scoped.push({ errors: entry.errors, guard: scopeGuard(segs, entry.mw), mw: entry.mw, prefix, segs });
1526
- }
1527
- for (const [subPath, cfg] of sub._graph.realtimeRoutes) {
1528
- const path = at(subPath);
1529
- if (g.realtimeRoutes.has(path)) {
1530
- throw new Error(`Duplicate realtime route: ${path}`);
1531
- }
1532
- /* a default namespace is the route's full path, so it follows the mount; a named one is kept */
1533
- g.realtimeRoutes.set(path, { ...cfg, namespace: cfg.namespaceExplicit ? cfg.namespace : path, path });
1534
- }
1535
- if (!g.realtimeBus && sub._graph.realtimeBus) {
1536
- this._setBus(sub._graph.realtimeBus);
1537
- }
1538
- if (subSettings.taps !== null) {
1539
- const s = this._graph.settings;
1540
- if (s.taps === null)
1541
- s.taps = new Map();
1542
- for (const [key, fn] of subSettings.taps) {
1543
- if (!s.taps.has(key))
1544
- s.taps.set(key, fn);
1545
- }
1546
- }
1547
- this._bumpEpoch();
1548
- }
1549
- return this;
1550
- }
1551
- _setBus(bus) {
1552
- const g = this._graph;
1553
- g.realtimeBus = bus;
1554
- g.realtimeCtx = requireFeature("realtime", "app.realtime()").createRealtimePublisher(bus, () => [...g.realtimeRoutes.values()].map((cfg) => cfg.namespace));
1555
- return bus;
1556
- }
1557
- _registerRoute(method, path, extraMethods) {
1558
- const fullPath = mergePath(this._basePath, path);
1559
- const pending = { id: `${[method, ...(extraMethods ?? [])].join(",")} ${fullPath}` };
1560
- this._graph.pending.add(pending);
1561
- return new RouteBuilder({
1562
- boundaryErrorKey: null,
1563
- errorKeys: new Set(),
1564
- extraMethods: extraMethods ?? null,
1565
- inputSchemas: null,
1566
- meta: this._chainMeta ? { ...this._chainMeta } : null,
1567
- method,
1568
- middlewares: [],
1569
- outputSchemas: null,
1570
- parent: this,
1571
- path: fullPath,
1572
- pending,
1573
- });
1574
- }
1575
- /** @internal — set (or clear, with null) one app-wide middleware; used by `serve()` */
1576
- _setGlobal(key, mw) {
1577
- if (mw === null) {
1578
- if (!this._graph.global.delete(key))
1579
- return;
1580
- }
1581
- else {
1582
- this._graph.global.set(key, mw);
1583
- }
1584
- this._bumpEpoch();
1585
- }
1586
- /** @internal — what a route registered through this handle captures */
1587
- _view() {
1588
- return { chain: this._chain, cv: this._contextValues, own: this._graph.settings };
1589
- }
1590
- /** @internal — a builder got its handler (or was abandoned on purpose) */
1591
- _settle(pending) {
1592
- this._graph.pending.delete(pending);
1593
- this._markUsed();
1594
- }
1595
- on(methods, path) {
1596
- const [first, ...rest] = methods;
1597
- return this._registerRoute(first, path, rest.length > 0 ? rest : undefined);
1598
- }
1599
- all(path) {
1600
- return this._registerRoute("ALL", path);
1601
- }
1602
- delete(path) {
1603
- return this._registerRoute("DELETE", path);
1604
- }
1605
- get(path) {
1606
- return this._registerRoute("GET", path);
1607
- }
1608
- head(path) {
1609
- return this._registerRoute("HEAD", path);
1610
- }
1611
- options(path) {
1612
- return this._registerRoute("OPTIONS", path);
1613
- }
1614
- patch(path) {
1615
- return this._registerRoute("PATCH", path);
1616
- }
1617
- post(path) {
1618
- return this._registerRoute("POST", path);
1619
- }
1620
- put(path) {
1621
- return this._registerRoute("PUT", path);
1622
- }
1623
- ws(path) {
1624
- const fullPath = mergePath(this._basePath, path);
1625
- const pending = { id: `WS ${fullPath}` };
1626
- this._graph.pending.add(pending);
1627
- return new WSRouteBuilder({
1628
- errorKeys: new Set(),
1629
- inputSchemas: null,
1630
- meta: this._chainMeta ? { ...this._chainMeta } : null,
1631
- middlewares: [],
1632
- origins: null,
1633
- parent: this,
1634
- path: fullPath,
1635
- pending,
1636
- });
1637
- }
1638
- realtime(path, opts) {
1639
- const fullPath = mergePath(this._basePath, path);
1640
- const g = this._graph;
1641
- const rt = requireFeature("realtime", "app.realtime()");
1642
- const config = rt.resolveRealtimeConfig(fullPath, opts);
1643
- if (g.realtimeRoutes.has(fullPath)) {
1644
- throw new Error(`Duplicate realtime route: ${fullPath}`);
1645
- }
1646
- if (!g.realtimeBus)
1647
- this._setBus(rt.createBus());
1648
- g.realtimeRoutes.set(fullPath, config);
1649
- this._markUsed();
1650
- this._addWsRoute(parsePattern(fullPath), {
1651
- bek: null,
1652
- cm: [...this._chain],
1653
- cv: this._contextValues,
1654
- dk: new Set(),
1655
- ek: new Set(),
1656
- fn: Object.create(null),
1657
- iv: null,
1658
- mt: null,
1659
- mw: [],
1660
- own: g.settings,
1661
- rb: null,
1662
- rm: (opts.use ?? []).map((fn) => fn),
1663
- rp: fullPath,
1664
- xm: this._chainMeta ? { ...this._chainMeta } : null,
1665
- });
1666
- return this;
1667
- }
1668
- /**
1669
- * Deno must call `Deno.upgradeWebSocket` in the same turn as the serve
1670
- * callback. When the adapter implements `preUpgrade`, we do that here
1671
- * and return the 101 response before any middleware Promise.
1672
- */
1673
- fetch(request, env, executionCtx) {
1674
- if (!this._graph.served.has(this._chain)) {
1675
- this._markUsed();
1676
- this._graph.served.add(this._chain);
1677
- this._bumpEpoch();
1678
- }
1679
- const wsAdapter = this._graph.settings.wsAdapter;
1680
- const path = normalizePath(pathOfUrl(request.url), this._graph.settings.encodedSlashes);
1681
- if (path === null)
1682
- return this._badRequestTarget();
1683
- /* Deno and Bun before 1.4 build request.url by concatenating Host and the target, so a
1684
- * `Host: x/admin?` would choose the routed path. `serve()` checks Host on Deno; this covers
1685
- * `Deno.serve(app.fetch)`, which passes its serve info as env, and every Bun entry point on
1686
- * an affected version. Node's adapter checks it; Bun 1.4+ routes on the target. */
1687
- if ((BUN_URL_FROM_HOST || isDenoServeInfo(env)) && !hasValidHost(request))
1688
- return this._badRequestTarget();
1689
- /* an adapter alone (serve() always installs one) does not need the websocket path */
1690
- if (!this._graph.hasWs) {
1691
- return this._doFetch(request, env, executionCtx, path);
1692
- }
1693
- const isWsUpgrade = request.headers.get("upgrade")?.toLowerCase() === "websocket";
1694
- const canPreUpgrade = isWsUpgrade &&
1695
- wsAdapter?.preUpgrade !== undefined &&
1696
- !this.trailingSlashRedirects(path) &&
1697
- this._matchWs(this._finalize(), this.pathAfterPrefix(path)) !== null;
1698
- /* Deno closes the Request in preUpgrade: snapshot the headers the chain will read first */
1699
- const headerSnap = canPreUpgrade ? new Headers(request.headers) : undefined;
1700
- let pre;
1701
- try {
1702
- pre = canPreUpgrade ? wsAdapter?.preUpgrade?.(request) : undefined;
1703
- }
1704
- catch (err) {
1705
- /* the runtime refused the handshake: answer through the normal path, which fails the upgrade */
1706
- this._graph.settings.logger?.warn?.({ err }, "websocket preUpgrade failed");
1707
- pre = undefined;
1708
- }
1709
- /* After Deno.upgradeWebSocket the Request is closed. A sync throw here
1710
- * used to be boxed by async _doFetch; keep 101 returning either way. */
1711
- let work;
1712
- try {
1713
- work = this._doFetch(request, env, executionCtx, path, isWsUpgrade === true, headerSnap);
1714
- }
1715
- catch (err) {
1716
- work = Promise.reject(err);
1717
- }
1718
- if (!pre)
1719
- return work;
1720
- void Promise.resolve(work)
1721
- .then((res) => {
1722
- if (res.status === 101)
1723
- return;
1724
- const code = res.status === 401 ? 4401 : 1008;
1725
- const reason = res.status === 401 ? "unauthorized" : "upgrade rejected";
1726
- const reject = () => {
1727
- try {
1728
- pre.socket.close(code, reason);
1729
- }
1730
- catch {
1731
- /* already closed */
1732
- }
1733
- };
1734
- if (pre.whenOpen)
1735
- pre.whenOpen(reject);
1736
- else
1737
- reject();
1738
- })
1739
- .catch(() => {
1740
- try {
1741
- pre.socket.close(1011, "internal error");
1742
- }
1743
- catch {
1744
- /* already closed */
1745
- }
1746
- });
1747
- return pre.response;
1748
- }
1749
- /** @internal 400 for a request path the normalization policy rejects (see `normalizePath`), or an invalid `Host`. */
1750
- _badRequestTarget() {
1751
- return this._toErrorResponse(this._createError(EK.bad_request, SK.bad_request));
1752
- }
1753
- trailingSlashRedirects(path) {
1754
- if (path.length <= 1)
1755
- return false;
1756
- const mode = this._graph.settings.trailingSlash;
1757
- if (mode === "strip" && path.endsWith("/"))
1758
- return true;
1759
- if (mode === "enforce" && !path.endsWith("/"))
1760
- return true;
1761
- return false;
1762
- }
1763
- pathAfterPrefix(path) {
1764
- const prefix = this._graph.settings.stripPrefix;
1765
- if (prefix === null)
1766
- return path;
1767
- if (path === prefix)
1768
- return "/";
1769
- if (path.startsWith(prefix) && path.charCodeAt(prefix.length) === 47) {
1770
- return path.slice(prefix.length);
1771
- }
1772
- return path;
1773
- }
1774
- _doFetch(request, env, executionCtx, fullPath, knownWsUpgrade = false, headerSnap) {
1775
- const startTime = performance.now();
1776
- const final = this._finalize();
1777
- const s = this._graph.settings;
1778
- const rawUrl = request.url;
1779
- /* lazily create URL only when actually needed (search params, redirects) */
1780
- let _url;
1781
- const getUrl = () => {
1782
- if (_url === undefined)
1783
- _url = new URL(rawUrl);
1784
- return _url;
1785
- };
1786
- const log = s.logger ?? undefined;
1787
- const method = request.method.toUpperCase();
1788
- const fc = {
1789
- allowed: null,
1790
- env,
1791
- executionCtx,
1792
- headerSnap,
1793
- log,
1794
- method,
1795
- path: fullPath,
1796
- plan: null,
1797
- request,
1798
- startTime,
1799
- trust: s.trust,
1800
- url: getUrl,
1801
- ws: null,
1802
- wsUpgrade: knownWsUpgrade,
1803
- };
1804
- if (s.telemetry === null)
1805
- return this._route(fc, final, fullPath, rawUrl, knownWsUpgrade);
1806
- safeFire(() => s.telemetry?.onRequest?.({ env, req: request }), log);
1807
- /* every exit after onRequest — redirects, 426, upgrades, misses, preflights, handlers —
1808
- * fires onResponse exactly once, here */
1809
- return this._withOnResponse(fc, this._route(fc, final, fullPath, rawUrl, knownWsUpgrade));
1810
- }
1811
- _route(fc, final, fullPath, rawUrl, knownWsUpgrade) {
1812
- const s = this._graph.settings;
1813
- const { method, request } = fc;
1814
- /* trailing slash handling — a relative Location: the scheme, host and port the client
1815
- * used are the ones it keeps, whatever proxy terminated TLS in front of the app */
1816
- if (this.trailingSlashRedirects(fullPath)) {
1817
- const target = s.trailingSlash === "strip" ? fullPath.slice(0, -1) : `${fullPath}/`;
1818
- return new Response(null, {
1819
- headers: { location: target + searchOfUrl(rawUrl) },
1820
- status: 308,
1821
- });
1822
- }
1823
- /* prefix stripping — must run AFTER trailing slash so redirects preserve the full prefixed URL */
1824
- const path = this.pathAfterPrefix(fullPath);
1825
- fc.path = path;
1826
- const root = this._graph.root;
1827
- /* WebSocket route check — do not re-read headers after Deno.upgradeWebSocket */
1828
- const isWsUpgrade = knownWsUpgrade || requestIsWsUpgrade(request);
1829
- if (isWsUpgrade) {
1830
- const wsMatch = this._matchWs(final, path);
1831
- if (wsMatch !== null) {
1832
- return this._handleWs(fc, wsMatch);
1833
- }
1834
- }
1835
- /* O(1) static route lookup — patterns without params or wildcards only */
1836
- const staticHit = final.statics[`${method} ${path}`] ?? (method === "HEAD" ? final.statics[`GET ${path}`] : undefined);
1837
- if (staticHit !== undefined) {
1838
- return this._dispatchRecord(fc, staticHit, EMPTY_PARAMS);
1839
- }
1840
- const result = matchRoute(root, method, path);
1841
- if (result === null) {
1842
- /* no HTTP route: a websocket or realtime route on this path asks for an upgrade */
1843
- if (!isWsUpgrade && this._graph.hasWs) {
1844
- const wsMatch = this._matchWs(final, path);
1845
- if (wsMatch !== null) {
1846
- if (this._graph.realtimeRoutes.has(wsMatch.handler.rp)) {
1847
- return new Response(null, { headers: { upgrade: "websocket" }, status: 426 });
1848
- }
1849
- return new Response("Upgrade Required", {
1850
- headers: { connection: "Upgrade", upgrade: "websocket" },
1851
- status: 426,
1852
- });
1853
- }
1854
- }
1855
- return this._handleMiss(fc, null);
1856
- }
1857
- if (!result.matched) {
1858
- if (method === "OPTIONS") {
1859
- const requested = request.headers.get("access-control-request-method");
1860
- if (requested) {
1861
- /* a preflight asks about one method: run that route's own chain */
1862
- const hit = matchRoute(root, requested.trim().toUpperCase(), path);
1863
- const plan = hit?.matched ? final.plans.get(hit.id) : undefined;
1864
- if (hit?.matched && plan !== undefined && plan.r.fn !== NOT_SERVED) {
1865
- return this._handlePreflight(fc, plan, hit.params, result.allowed);
1866
- }
1867
- }
1868
- }
1869
- return this._handleMiss(fc, result.allowed);
1870
- }
1871
- const plan = final.plans.get(result.id);
1872
- if (plan === undefined)
1873
- return this._handleMiss(fc, null);
1874
- return this._dispatchRecord(fc, plan, result.params);
1875
- }
1876
- _matchWs(final, path) {
1877
- const hit = matchWsRoute(this._graph.root, path);
1878
- if (hit === null)
1879
- return null;
1880
- const handler = final.wsById.get(hit.id);
1881
- return handler === undefined ? null : { handler, params: hit.params };
1882
- }
1883
- _dispatchRecord(fc, plan, params) {
1884
- const record = plan.r;
1885
- if (record.fn === NOT_SERVED)
1886
- return this._handleMiss(fc, null);
1887
- /* a delegated route keeps its own input schemas for docs and the 415 check; the body
1888
- * itself belongs to whatever the catch-all forwards it to */
1889
- if (record.dl === true && record.iv) {
1890
- try {
1891
- assertRequestContentType(record.iv, fc.request);
1892
- }
1893
- catch (thrown) {
1894
- return this._toErrorResponse(thrown);
1895
- }
1896
- }
1897
- return this._handleMatched(fc, plan, params);
1898
- }
1899
- _makeErrorCtx(fc, allowed) {
1900
- const s = this._s;
1901
- return {
1902
- env: fc.env,
1903
- jsonFromError: (err) => createErrorResponse(err, s.errorFormatter, s.customErrorFormatter),
1904
- req: fc.request,
1905
- ...(allowed ? { allowed } : {}),
1906
- };
1907
- }
1908
- /** A request context for `plan`: route data, context values, `ctx.errors`, `ctx.realtime`. */
1909
- _newCtx(fc, plan, params, req) {
1910
- fc.plan = plan;
1911
- const r = plan.r;
1912
- const ctx = new HoneyContext({
1913
- env: fc.env,
1914
- executionCtx: fc.executionCtx,
1915
- meta: r.mt ?? undefined,
1916
- params,
1917
- path: fc.path,
1918
- req: req ?? fc.request,
1919
- routePattern: r.rp ?? "",
1920
- urlFn: fc.url,
1921
- });
1922
- if (plan.cv !== null)
1923
- Object.assign(ctx, plan.cv);
1924
- const rt = this._graph.realtimeCtx;
1925
- if (rt !== null)
1926
- ctx.realtime = rt;
1927
- if (r.ef)
1928
- ctx._setErrors(r.ef);
1929
- ctx._rq = fc;
1930
- return ctx;
1931
- }
1932
- _handleWs(fc, wsMatch) {
1933
- const plan = this._finalize().wsPlans.get(wsMatch.handler.id);
1934
- if (plan === undefined)
1935
- return this._handleMiss(fc, null);
1936
- const isUpgrade = fc.wsUpgrade === true || requestIsWsUpgrade(fc.request);
1937
- if (!isUpgrade) {
1938
- return new Response(null, {
1939
- headers: { upgrade: "websocket" },
1940
- status: 426,
1941
- });
1942
- }
1943
- if (!this._graph.settings.wsAdapter) {
1944
- fc.log?.warn?.("WebSocket adapter not configured — call .wsAdapter()");
1945
- return this._toErrorResponse(this._createError(EK.internal_server_error, SK.internal_server_error));
1946
- }
1947
- fc.ws = wsMatch;
1948
- const ctx = this._newCtx(fc, plan, wsMatch.params, ctxRequest(fc));
1949
- return plan.run(ctx);
1950
- }
1951
- /** Reject a cross-origin upgrade the route's origin policy does not allow (403). */
1952
- /** The websocket session runtime; a cross-origin upgrade the route does not allow is a 403. */
1953
- async _wsSession(finalCtx, policy) {
1954
- const ws = await loadFeature("ws", "a websocket route");
1955
- const headers = finalCtx.req.headers;
1956
- const origin = headers.get("origin");
1957
- if (origin === null || policy === "*")
1958
- return ws;
1959
- const credentialed = headers.has("cookie") || headers.has("authorization");
1960
- if (!ws.originAllowed(policy, origin, clientInfo(finalCtx).host, credentialed)) {
1961
- throw this._createError(EK.forbidden, SK.forbidden);
1962
- }
1963
- return ws;
1964
- }
1965
- async _wsUpgrade(finalCtx) {
1966
- const fc = finalCtx._rq;
1967
- const wsMatch = fc.ws;
1968
- const ws = await this._wsSession(finalCtx, wsMatch.handler.og ?? null);
1969
- const wsAdapter = this._graph.settings.wsAdapter;
1970
- const handler = ws.createWsSession({
1971
- callbacks: wsMatch.handler.fn,
1972
- ctx: finalCtx,
1973
- log: (this._graph.settings.logger ?? null),
1974
- reconnectToken: fc.url().searchParams.get("reconnect_token"),
1975
- route: wsMatch.handler.rp,
1976
- });
1977
- const upgradeResult = await wsAdapter.upgrade(fc.request, fc.env, handler);
1978
- return upgradeResult.response;
1979
- }
1980
- /** Terminal of a realtime route's chain: identify, upgrade, and attach the connection to the bus. */
1981
- async _realtimeUpgrade(finalCtx, config) {
1982
- const fc = finalCtx._rq;
1983
- await this._wsSession(finalCtx, config.allowedOrigins);
1984
- const wsAdapter = this._graph.settings.wsAdapter;
1985
- const rt = requireFeature("realtime", "app.realtime()");
1986
- const bus = this._graph.realtimeBus ?? this._setBus(rt.createBus());
1987
- /* a throwing identify rejects the upgrade through the chain's error boundary */
1988
- const userId = config.identify === null ? null : ((await config.identify(finalCtx)) ?? null);
1989
- const session = rt.createRealtimeSession({ bus, config, ctx: finalCtx, log: fc.log, userId });
1990
- const upgradeResult = await wsAdapter.upgrade(fc.request, fc.env, session.handler);
1991
- /* Node/CF return an open socket from upgrade(); Bun and Deno deliver it through onOpen */
1992
- if (upgradeResult.socket && upgradeResult.socket.readyState === 1)
1993
- session.attach(upgradeResult.socket);
1994
- return upgradeResult.response;
1995
- }
1996
- /**
1997
- * 404 (`allowed === null`) and 405: one pipeline with a synthetic record — full context,
1998
- * the app-wide middleware and the scopes covering the path run once, telemetry fires once.
1999
- */
2000
- _handleMiss(fc, allowed) {
2001
- const s = this._graph.settings;
2002
- const { method, path, request } = fc;
2003
- if (allowed === null) {
2004
- safeFire(() => s.telemetry?.onNotFound?.({ method, path, req: request }), fc.log);
2005
- }
2006
- else {
2007
- safeFire(() => s.telemetry?.onMethodNotAllowed?.({ allowed, method, path, req: request }), fc.log);
2008
- }
2009
- fc.allowed = allowed;
2010
- const plan = this._finalize().miss;
2011
- const ctx = this._newCtx(fc, plan, EMPTY_PARAMS);
2012
- return plan.run(ctx);
2013
- }
2014
- /** Fire `onResponse` once for the request's one exit and return. A dispatch that rejects
2015
- * (an adapter failure past every error boundary) still ends the request: it reports 500. */
2016
- _withOnResponse(fc, res) {
2017
- const s = this._graph.settings;
2018
- if (s.telemetry?.onResponse === undefined)
2019
- return res;
2020
- const fire = (status) => {
2021
- safeFire(() => s.telemetry?.onResponse?.({ duration: performance.now() - fc.startTime, req: fc.request, status }), fc.log);
2022
- };
2023
- if (!(res instanceof Promise)) {
2024
- fire(res.status);
2025
- return res;
2026
- }
2027
- return res.then((r) => {
2028
- fire(r.status);
2029
- return r;
2030
- }, (error) => {
2031
- fire(500);
2032
- throw error;
2033
- });
2034
- }
2035
- _make404(fc) {
2036
- const s = this._s;
2037
- if (s.onNotFound)
2038
- return s.onNotFound(this._makeErrorCtx(fc));
2039
- return this._makeErrorCtx(fc).jsonFromError(this._createError(EK.not_found, SK.not_found));
2040
- }
2041
- async _make405(fc, allowed) {
2042
- const s = this._s;
2043
- const res = s.onMethodNotAllowed
2044
- ? await s.onMethodNotAllowed(this._makeErrorCtx(fc, allowed))
2045
- : this._makeErrorCtx(fc).jsonFromError(this._createError(EK.method_not_allowed, SK.method_not_allowed));
2046
- const responseHeaders = new Headers(res.headers);
2047
- responseHeaders.set("allow", allowed.join(", "));
2048
- return new Response(res.body, {
2049
- headers: responseHeaders,
2050
- status: res.status,
2051
- });
2052
- }
2053
- /**
2054
- * CORS preflight for a path that has no OPTIONS route: run the chain of the route the
2055
- * preflight asks about (`Access-Control-Request-Method`) — chain, scoped and route
2056
- * middleware, never input validation or the handler. Middleware that answers the
2057
- * preflight (cors) short-circuits; otherwise the answer is the 405 with `Allow`.
2058
- */
2059
- _handlePreflight(fc, plan, params, allowed) {
2060
- fc.allowed = allowed;
2061
- const ctx = this._newCtx(fc, plan, params);
2062
- const final = this._finalize();
2063
- plan.pf ??= compileChain(plan.pfChain, (c) => {
2064
- const rq = c._rq;
2065
- return this._make405(rq, rq.allowed ?? []);
2066
- }, final.convert);
2067
- return plan.pf(ctx);
2068
- }
2069
- _handleMatched(fc, plan, params) {
2070
- const ctx = this._newCtx(fc, plan, params);
2071
- const telemetry = this._graph.settings.telemetry;
2072
- if (telemetry !== null && telemetry.onRoute !== undefined) {
2073
- try {
2074
- telemetry.onRoute({ method: fc.method, params, path: fc.path, req: fc.request, route: plan.r.rp ?? "" });
2075
- }
2076
- catch {
2077
- /* telemetry must not crash request */
2078
- }
2079
- }
2080
- const res = plan.run(ctx);
2081
- if (res instanceof Promise)
2082
- return res.then((r) => this._finishMatched(fc, plan, ctx, r));
2083
- return this._finishMatched(fc, plan, ctx, res);
2084
- }
2085
- /** Output validation, inside the chain: an invalid body becomes an error response the middleware sees. */
2086
- async _validateOutput(handler, ctx, response) {
2087
- if (response === undefined || response === null || ctx._isErrorResponse)
2088
- return response;
2089
- /* read the creation tag, never `response.body`: on Node that would build a stream per response */
2090
- const kind = bodyKind(response);
2091
- if (kind === "empty")
2092
- return response;
2093
- const ct = response.headers.get("content-type");
2094
- /* content-type mismatch check */
2095
- if (ct && handler.os) {
2096
- const declaredTypes = Object.keys(handler.os);
2097
- const matches = declaredTypes.some((t) => ct.startsWith(t));
2098
- if (!matches) {
2099
- throw new HoneyError({
2100
- errorKey: EK.output_content_type_mismatch,
2101
- status: SK.internal_server_error,
2102
- });
2103
- }
2104
- }
2105
- /* JSON schema validation. A body Honey built from a string is validated from that string
2106
- * (no stream, no tee); anything else is read from a clone (Bun clone() drains the original).
2107
- * A stream Honey created (sse, stream, generate) is never buffered: it may never end. */
2108
- if (ct?.startsWith("application/json") && handler.ov && !isProducedStream(response)) {
2109
- const sk = codeToStatusKey[response.status];
2110
- if (sk) {
2111
- const raw = rawBodyOf(response);
2112
- if (raw !== null) {
2113
- const text = typeof raw === "string" ? raw : new TextDecoder().decode(raw);
2114
- await handler.ov(sk, text.length === 0 ? null : JSON.parse(text));
2115
- return response;
2116
- }
2117
- const forReturn = response.clone();
2118
- const data = await response.json();
2119
- await handler.ov(sk, data);
2120
- return forReturn;
2121
- }
2122
- }
2123
- return response;
2124
- }
2125
- _finishMatched(fc, plan, ctx, response) {
2126
- const s = this._graph.settings;
2127
- const handler = plan.r;
2128
- /* taps — fire after successful handler, non-blocking */
2129
- if (plan.taps !== null && !ctx._isErrorResponse) {
2130
- const taps = plan.taps;
2131
- const log = fc.log;
2132
- /* meta-driven taps — fire for each registered key found in route meta */
2133
- if (handler.mt !== null) {
2134
- for (const [key, tapFn] of taps) {
2135
- const metaValue = handler.mt[key];
2136
- if (metaValue !== undefined) {
2137
- ctx.background(Promise.resolve()
2138
- .then(() => tapFn(ctx, metaValue))
2139
- .catch((e) => log?.warn?.({ err: e, tap: key }, "tap failed")));
2140
- }
2141
- }
2142
- }
2143
- /* dynamic taps — fire for each c.tap() call */
2144
- if (ctx._pendingTaps !== null) {
2145
- for (const pending of ctx._pendingTaps) {
2146
- const tapFn = taps.get(pending.key);
2147
- if (tapFn !== undefined) {
2148
- ctx.background(Promise.resolve()
2149
- .then(() => tapFn(ctx, pending.payload))
2150
- .catch((e) => log?.warn?.({ err: e, tap: pending.key }, "tap failed")));
2151
- }
2152
- }
2153
- ctx._pendingTaps = null;
2154
- }
2155
- }
2156
- if (s.telemetry !== null) {
2157
- try {
2158
- const duration = performance.now() - fc.startTime;
2159
- s.telemetry.onHandler?.({
2160
- duration,
2161
- method: fc.method,
2162
- path: fc.path,
2163
- route: handler.rp ?? "",
2164
- status: response.status,
2165
- });
2166
- }
2167
- catch {
2168
- /* telemetry must never crash the response path */
2169
- }
2170
- }
2171
- if (fc.method === "HEAD")
2172
- return headResponse(response);
2173
- return response;
2174
- }
2175
- }
2176
1
  /**
2177
- * Route meta = middleware-contributed meta, overlaid by everything stated explicitly
2178
- * (chain `.meta()`, then route `.meta()`). Explicit always wins.
2
+ * `@lovrozagar/honey`: the app (`honey()`), its context, errors, middleware and responses, the tree merge, and the
3
+ * types an app is read through. Everything optional is its own subpath; nothing here registers itself (H23).
2179
4
  */
2180
- function mergeContributedMeta(contributed, explicit) {
2181
- if (!contributed)
2182
- return explicit ? Object.freeze(explicit) : null;
2183
- return Object.freeze(explicit ? { ...contributed, ...explicit } : { ...contributed });
2184
- }
2185
- class RouteBuilder {
2186
- _s;
2187
- constructor(state) {
2188
- this._s = state;
2189
- }
2190
- errors(...args) {
2191
- const keys = typeof args[0] === "object" && args[0] !== null ? args.slice(1) : args;
2192
- for (const k of keys) {
2193
- this._s.errorKeys.add(k);
2194
- }
2195
- return new RouteBuilder({
2196
- ...this._s,
2197
- errorKeys: this._s.errorKeys,
2198
- });
2199
- }
2200
- boundary(key) {
2201
- this._s.boundaryErrorKey = key;
2202
- this._s.errorKeys.add(key);
2203
- return new RouteBuilder({
2204
- ...this._s,
2205
- boundaryErrorKey: key,
2206
- errorKeys: this._s.errorKeys,
2207
- });
2208
- }
2209
- handler(fn) {
2210
- let ov = null;
2211
- const outputSchemas = this._s.outputSchemas;
2212
- if (outputSchemas) {
2213
- const jsonSchemas = outputSchemas["application/json"];
2214
- if (jsonSchemas) {
2215
- ov = async (statusKey, data) => {
2216
- const schema = jsonSchemas[statusKey];
2217
- if (schema) {
2218
- await validateOutput(schema, statusKey, data);
2219
- }
2220
- };
2221
- }
2222
- }
2223
- const isInternal = Symbol.for("honey.internal") in fn;
2224
- /* a bound copy per app: one `spec()` or docs handler may be mounted on several apps */
2225
- if (isInternal)
2226
- fn = bindInternalHandler(fn, this._s.parent);
2227
- const parent = this._s.parent;
2228
- const view = parent._view();
2229
- const base = {
2230
- _skip: isInternal || undefined,
2231
- bek: null,
2232
- cm: [...view.chain],
2233
- cv: view.cv,
2234
- dk: new Set(this._s.errorKeys),
2235
- /* provisional until finalize resolves scopes and app defaults */
2236
- ek: new Set(this._s.errorKeys),
2237
- fn: fn,
2238
- iv: this._s.inputSchemas,
2239
- mt: mergeContributedMeta(collectMiddlewareMeta([view.chain, this._s.middlewares]), this._s.meta),
2240
- mw: [],
2241
- os: this._s.outputSchemas,
2242
- ov,
2243
- own: view.own,
2244
- rb: this._s.boundaryErrorKey,
2245
- rm: [...this._s.middlewares],
2246
- xm: this._s.meta ? { ...this._s.meta } : null,
2247
- };
2248
- /* one record per method — `.on([...])` registers each under its own RouteId */
2249
- parent._settle(this._s.pending);
2250
- const segments = parsePattern(this._s.path);
2251
- const methods = [this._s.method, ...(this._s.extraMethods ?? [])];
2252
- for (const method of methods)
2253
- assertBodySchemaAllowed(this._s.inputSchemas, method, this._s.path);
2254
- for (let i = 0; i < methods.length; i++) {
2255
- parent._addRoute(methods[i], segments, i === 0 ? base : copyRecord(base));
2256
- }
2257
- return this._s.parent;
2258
- }
2259
- proxy(config) {
2260
- const proxyHandler = requireFeature("proxy", ".proxy()").createProxyHandler(config);
2261
- return this.handler(proxyHandler);
2262
- }
2263
- input(schemas) {
2264
- return new RouteBuilder({
2265
- ...this._s,
2266
- inputSchemas: schemas,
2267
- });
2268
- }
2269
- meta(meta) {
2270
- return new RouteBuilder({
2271
- ...this._s,
2272
- meta: (() => {
2273
- const merged = { ...this._s.meta, ...meta };
2274
- const inv = merged["invalidate"];
2275
- if (Array.isArray(inv) && inv.length > 1) {
2276
- merged["invalidate"] = [...new Set(inv)];
2277
- }
2278
- return merged;
2279
- })(),
2280
- });
2281
- }
2282
- output(_schemas) {
2283
- return new RouteBuilder({
2284
- ...this._s,
2285
- outputSchemas: _schemas,
2286
- });
2287
- }
2288
- use(mw) {
2289
- return new RouteBuilder({
2290
- ...this._s,
2291
- middlewares: [...this._s.middlewares, mw],
2292
- });
2293
- }
2294
- }
2295
- class WSRouteBuilder {
2296
- _s;
2297
- constructor(state) {
2298
- this._s = state;
2299
- }
2300
- errors(factory, ...keys) {
2301
- void factory;
2302
- for (const k of keys) {
2303
- this._s.errorKeys.add(k);
2304
- }
2305
- return new WSRouteBuilder({
2306
- ...this._s,
2307
- errorKeys: this._s.errorKeys,
2308
- });
2309
- }
2310
- handler(wsHandler) {
2311
- const parent = this._s.parent;
2312
- const view = parent._view();
2313
- const routeHandler = {
2314
- bek: null,
2315
- cm: [...view.chain],
2316
- cv: view.cv,
2317
- dk: new Set(this._s.errorKeys),
2318
- ek: new Set(),
2319
- fn: wsHandler,
2320
- iv: this._s.inputSchemas,
2321
- mt: null,
2322
- mw: [],
2323
- og: this._s.origins,
2324
- own: view.own,
2325
- rb: null,
2326
- rm: [...this._s.middlewares],
2327
- rp: this._s.path,
2328
- xm: this._s.meta ? { ...this._s.meta } : null,
2329
- };
2330
- parent._settle(this._s.pending);
2331
- parent._addWsRoute(parsePattern(this._s.path), routeHandler);
2332
- return this._s.parent;
2333
- }
2334
- input(schemas) {
2335
- return new WSRouteBuilder({
2336
- ...this._s,
2337
- inputSchemas: schemas,
2338
- });
2339
- }
2340
- meta(meta) {
2341
- this._s.meta = { ...this._s.meta, ...meta };
2342
- return this;
2343
- }
2344
- /**
2345
- * Browser origins allowed to open this socket: `"*"`, a list of origins
2346
- * (`https://app.example.com`), or a predicate. Same-origin always passes. Without it, a
2347
- * cross-origin upgrade that carries `Cookie` or `Authorization` gets 403.
2348
- */
2349
- origins(policy) {
2350
- return new WSRouteBuilder({
2351
- ...this._s,
2352
- origins: validateOriginPolicy(policy),
2353
- });
2354
- }
2355
- use(mw) {
2356
- return new WSRouteBuilder({
2357
- ...this._s,
2358
- middlewares: [...this._s.middlewares, mw],
2359
- });
2360
- }
2361
- }
2362
- export function honey() {
2363
- return new Honey();
2364
- }
2365
- //# sourceMappingURL=index.js.map
5
+ export { toFetchRequest } from "./adapters/fetch-request.js";
6
+ export { HoneyContext } from "./context/context.js";
7
+ export { HoneyError } from "./errors/error.js";
8
+ export { defineErrors, ERROR_META } from "./errors/errors.js";
9
+ export { createErrorResponse } from "./errors/projector.js";
10
+ export { createMiddleware, defineMiddleware } from "./middleware/middleware.js";
11
+ export { HoneyRes } from "./response/response.js";
12
+ export { Honey, honey } from "./routing/app.js";
13
+ export { mergeTree } from "./routing/tree-merge.js";
14
+ export { detectRuntime } from "./runtime/detect-runtime.js";