@lovrozagar/honey 0.6.8 → 0.7.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 (674) hide show
  1. package/README.md +514 -192
  2. package/bin/honey.js +25 -0
  3. package/dist/accepts.d.ts +7 -1
  4. package/dist/accepts.d.ts.map +1 -1
  5. package/dist/accepts.js +126 -0
  6. package/dist/accepts.js.map +1 -0
  7. package/dist/body-kind.d.ts +26 -0
  8. package/dist/body-kind.d.ts.map +1 -0
  9. package/dist/body-kind.js +70 -0
  10. package/dist/body-kind.js.map +1 -0
  11. package/dist/body-limit.d.ts +5 -1
  12. package/dist/body-limit.d.ts.map +1 -1
  13. package/dist/body-limit.js +126 -0
  14. package/dist/body-limit.js.map +1 -0
  15. package/dist/build/index.d.ts +19 -3
  16. package/dist/build/index.d.ts.map +1 -1
  17. package/dist/build/index.js +173 -0
  18. package/dist/build/index.js.map +1 -0
  19. package/dist/cli-args.d.ts +33 -0
  20. package/dist/cli-args.d.ts.map +1 -0
  21. package/dist/cli-args.js +102 -0
  22. package/dist/cli-args.js.map +1 -0
  23. package/dist/cli-go/auth.go +26 -0
  24. package/dist/cli-go/config.go +192 -0
  25. package/dist/cli-go/errors.go +75 -0
  26. package/dist/cli-go/multipart.go +79 -0
  27. package/dist/cli-go/output.go +163 -0
  28. package/dist/cli-go/root.go +30 -0
  29. package/dist/cli-go/stream.go +88 -0
  30. package/dist/cli-go/version.go +5 -0
  31. package/dist/cli.d.ts +1 -1
  32. package/dist/cli.js +209 -0
  33. package/dist/cli.js.map +1 -0
  34. package/dist/client/defaults.js +48 -0
  35. package/dist/client/defaults.js.map +1 -0
  36. package/dist/client/error.d.ts +35 -0
  37. package/dist/client/error.d.ts.map +1 -1
  38. package/dist/client/error.js +71 -0
  39. package/dist/client/error.js.map +1 -0
  40. package/dist/client/http.d.ts +67 -8
  41. package/dist/client/http.d.ts.map +1 -1
  42. package/dist/client/http.js +571 -0
  43. package/dist/client/http.js.map +1 -0
  44. package/dist/client/index.d.ts +3 -2
  45. package/dist/client/index.d.ts.map +1 -1
  46. package/dist/client/index.js +95 -0
  47. package/dist/client/index.js.map +1 -0
  48. package/dist/client/path.d.ts +26 -0
  49. package/dist/client/path.d.ts.map +1 -0
  50. package/dist/client/path.js +163 -0
  51. package/dist/client/path.js.map +1 -0
  52. package/dist/client/redirect-policy.d.ts +12 -0
  53. package/dist/client/redirect-policy.d.ts.map +1 -0
  54. package/dist/client/redirect-policy.js +20 -0
  55. package/dist/client/redirect-policy.js.map +1 -0
  56. package/dist/client/sdk.d.ts +36 -0
  57. package/dist/client/sdk.d.ts.map +1 -1
  58. package/dist/client/sdk.js +292 -0
  59. package/dist/client/sdk.js.map +1 -0
  60. package/dist/client/sse.d.ts +13 -0
  61. package/dist/client/sse.d.ts.map +1 -1
  62. package/dist/client/sse.js +129 -0
  63. package/dist/client/sse.js.map +1 -0
  64. package/dist/client/types.js +2 -0
  65. package/dist/client/types.js.map +1 -0
  66. package/dist/client/ws.d.ts +9 -2
  67. package/dist/client/ws.d.ts.map +1 -1
  68. package/dist/client/ws.js +112 -0
  69. package/dist/client/ws.js.map +1 -0
  70. package/dist/client-go/errors.go +236 -0
  71. package/dist/client-go/export.go +44 -0
  72. package/dist/client-go/invalidation.go +371 -0
  73. package/dist/client-go/nullable.go +62 -0
  74. package/dist/client-go/realtime.go +354 -0
  75. package/dist/client-go/result.go +20 -0
  76. package/dist/client-go/runtime.go +975 -0
  77. package/dist/client-go/sse.go +159 -0
  78. package/dist/client-go/transport.go +495 -0
  79. package/dist/client-go/ws.go +128 -0
  80. package/dist/client-info.d.ts +36 -0
  81. package/dist/client-info.d.ts.map +1 -0
  82. package/dist/client-info.js +53 -0
  83. package/dist/client-info.js.map +1 -0
  84. package/dist/client-mcp/README.md +10 -0
  85. package/dist/client-mcp/server.ts +221 -0
  86. package/dist/client-mcp/types.ts +19 -0
  87. package/dist/client-python/_errors.py +115 -0
  88. package/dist/client-python/_invalidation.py +494 -0
  89. package/dist/client-python/_realtime.py +179 -0
  90. package/dist/client-python/_runtime.py +860 -0
  91. package/dist/client-python/_sse.py +155 -0
  92. package/dist/client-python/_transport.py +366 -0
  93. package/dist/client-python/_ws.py +159 -0
  94. package/dist/client-python/py.typed +0 -0
  95. package/dist/client-rust/errors.rs +220 -0
  96. package/dist/client-rust/invalidation.rs +412 -0
  97. package/dist/client-rust/invalidation_sync.rs +93 -0
  98. package/dist/client-rust/nullable.rs +17 -0
  99. package/dist/client-rust/realtime.rs +702 -0
  100. package/dist/client-rust/result.rs +22 -0
  101. package/dist/client-rust/runtime.rs +980 -0
  102. package/dist/client-rust/runtime_sync.rs +484 -0
  103. package/dist/client-rust/sse.rs +188 -0
  104. package/dist/client-rust/ws.rs +167 -0
  105. package/dist/codegen-go-cli.d.ts.map +1 -1
  106. package/dist/codegen-go-cli.js +964 -0
  107. package/dist/codegen-go-cli.js.map +1 -0
  108. package/dist/codegen-go.d.ts +15 -3
  109. package/dist/codegen-go.d.ts.map +1 -1
  110. package/dist/codegen-go.js +872 -0
  111. package/dist/codegen-go.js.map +1 -0
  112. package/dist/codegen-hash.js +9 -0
  113. package/dist/codegen-hash.js.map +1 -0
  114. package/dist/codegen-ir.d.ts +69 -2
  115. package/dist/codegen-ir.d.ts.map +1 -1
  116. package/dist/codegen-ir.js +661 -0
  117. package/dist/codegen-ir.js.map +1 -0
  118. package/dist/codegen-lang.d.ts +65 -0
  119. package/dist/codegen-lang.d.ts.map +1 -0
  120. package/dist/codegen-lang.js +526 -0
  121. package/dist/codegen-lang.js.map +1 -0
  122. package/dist/codegen-load.d.ts +31 -0
  123. package/dist/codegen-load.d.ts.map +1 -0
  124. package/dist/codegen-load.js +138 -0
  125. package/dist/codegen-load.js.map +1 -0
  126. package/dist/codegen-loaders.js +55 -0
  127. package/dist/codegen-loaders.js.map +1 -0
  128. package/dist/codegen-mcp.d.ts.map +1 -1
  129. package/dist/codegen-mcp.js +368 -0
  130. package/dist/codegen-mcp.js.map +1 -0
  131. package/dist/codegen-python.d.ts +13 -1
  132. package/dist/codegen-python.d.ts.map +1 -1
  133. package/dist/codegen-python.js +828 -0
  134. package/dist/codegen-python.js.map +1 -0
  135. package/dist/codegen-route-tree-intern.d.ts +15 -5
  136. package/dist/codegen-route-tree-intern.d.ts.map +1 -1
  137. package/dist/codegen-route-tree-intern.js +221 -0
  138. package/dist/codegen-route-tree-intern.js.map +1 -0
  139. package/dist/codegen-rust.d.ts.map +1 -1
  140. package/dist/codegen-rust.js +1293 -0
  141. package/dist/codegen-rust.js.map +1 -0
  142. package/dist/codegen-sanitize.d.ts.map +1 -1
  143. package/dist/codegen-sanitize.js +56 -0
  144. package/dist/codegen-sanitize.js.map +1 -0
  145. package/dist/codegen-schema-naming.d.ts +5 -0
  146. package/dist/codegen-schema-naming.d.ts.map +1 -1
  147. package/dist/codegen-schema-naming.js +150 -0
  148. package/dist/codegen-schema-naming.js.map +1 -0
  149. package/dist/codegen-sdk-model.d.ts +71 -0
  150. package/dist/codegen-sdk-model.d.ts.map +1 -0
  151. package/dist/codegen-sdk-model.js +179 -0
  152. package/dist/codegen-sdk-model.js.map +1 -0
  153. package/dist/codegen.d.ts +41 -23
  154. package/dist/codegen.d.ts.map +1 -1
  155. package/dist/codegen.js +4610 -0
  156. package/dist/codegen.js.map +1 -0
  157. package/dist/context.d.ts +36 -6
  158. package/dist/context.d.ts.map +1 -1
  159. package/dist/context.js +242 -0
  160. package/dist/context.js.map +1 -0
  161. package/dist/cookie-sign.d.ts +16 -2
  162. package/dist/cookie-sign.d.ts.map +1 -1
  163. package/dist/cookie-sign.js +104 -0
  164. package/dist/cookie-sign.js.map +1 -0
  165. package/dist/cookie.d.ts +12 -0
  166. package/dist/cookie.d.ts.map +1 -1
  167. package/dist/cookie.js +138 -0
  168. package/dist/cookie.js.map +1 -0
  169. package/dist/cors.d.ts +1 -0
  170. package/dist/cors.d.ts.map +1 -1
  171. package/dist/cors.js +87 -0
  172. package/dist/cors.js.map +1 -0
  173. package/dist/crypto.d.ts +6 -1
  174. package/dist/crypto.d.ts.map +1 -1
  175. package/dist/crypto.js +38 -0
  176. package/dist/crypto.js.map +1 -0
  177. package/dist/csrf.d.ts +19 -0
  178. package/dist/csrf.d.ts.map +1 -1
  179. package/dist/csrf.js +79 -0
  180. package/dist/csrf.js.map +1 -0
  181. package/dist/curl-logger.d.ts +14 -3
  182. package/dist/curl-logger.d.ts.map +1 -1
  183. package/dist/curl-logger.js +199 -0
  184. package/dist/curl-logger.js.map +1 -0
  185. package/dist/detect-runtime.js +13 -0
  186. package/dist/detect-runtime.js.map +1 -0
  187. package/dist/dict.d.ts +11 -0
  188. package/dist/dict.d.ts.map +1 -0
  189. package/dist/dict.js +13 -0
  190. package/dist/dict.js.map +1 -0
  191. package/dist/error.d.ts.map +1 -1
  192. package/dist/error.js +44 -0
  193. package/dist/error.js.map +1 -0
  194. package/dist/errors.js +39 -0
  195. package/dist/errors.js.map +1 -0
  196. package/dist/etag.d.ts +2 -0
  197. package/dist/etag.d.ts.map +1 -1
  198. package/dist/etag.js +82 -0
  199. package/dist/etag.js.map +1 -0
  200. package/dist/feature-detect.d.ts +25 -0
  201. package/dist/feature-detect.d.ts.map +1 -0
  202. package/dist/feature-detect.js +144 -0
  203. package/dist/feature-detect.js.map +1 -0
  204. package/dist/feature-load.js +36 -0
  205. package/dist/feature-load.js.map +1 -0
  206. package/dist/feature-slots.d.ts +44 -0
  207. package/dist/feature-slots.d.ts.map +1 -0
  208. package/dist/feature-slots.js +48 -0
  209. package/dist/feature-slots.js.map +1 -0
  210. package/dist/fetch-request.d.ts +10 -0
  211. package/dist/fetch-request.d.ts.map +1 -0
  212. package/dist/fetch-request.js +13 -0
  213. package/dist/fetch-request.js.map +1 -0
  214. package/dist/gen-process.d.ts +15 -0
  215. package/dist/gen-process.d.ts.map +1 -0
  216. package/dist/gen-process.js +43 -0
  217. package/dist/gen-process.js.map +1 -0
  218. package/dist/gen-write.d.ts +19 -0
  219. package/dist/gen-write.d.ts.map +1 -0
  220. package/dist/gen-write.js +120 -0
  221. package/dist/gen-write.js.map +1 -0
  222. package/dist/glob.d.ts +21 -0
  223. package/dist/glob.d.ts.map +1 -0
  224. package/dist/glob.js +115 -0
  225. package/dist/glob.js.map +1 -0
  226. package/dist/go-type-emitter.d.ts +18 -4
  227. package/dist/go-type-emitter.d.ts.map +1 -1
  228. package/dist/go-type-emitter.js +594 -0
  229. package/dist/go-type-emitter.js.map +1 -0
  230. package/dist/honey-response.d.ts.map +1 -1
  231. package/dist/honey-response.js +338 -0
  232. package/dist/honey-response.js.map +1 -0
  233. package/dist/i18n-slot.d.ts +8 -0
  234. package/dist/i18n-slot.d.ts.map +1 -1
  235. package/dist/i18n-slot.js +14 -0
  236. package/dist/i18n-slot.js.map +1 -0
  237. package/dist/i18n.d.ts +3 -0
  238. package/dist/i18n.d.ts.map +1 -1
  239. package/dist/i18n.js +250 -0
  240. package/dist/i18n.js.map +1 -0
  241. package/dist/index.d.ts +408 -148
  242. package/dist/index.d.ts.map +1 -1
  243. package/dist/index.js +2324 -0
  244. package/dist/index.js.map +1 -0
  245. package/dist/init.d.ts +3 -5
  246. package/dist/init.d.ts.map +1 -1
  247. package/dist/init.js +140 -0
  248. package/dist/init.js.map +1 -0
  249. package/dist/input.js +4 -0
  250. package/dist/input.js.map +1 -0
  251. package/dist/invalidate-check.d.ts +11 -0
  252. package/dist/invalidate-check.d.ts.map +1 -1
  253. package/dist/invalidate-check.js +163 -0
  254. package/dist/invalidate-check.js.map +1 -0
  255. package/dist/invoke-user.d.ts +35 -0
  256. package/dist/invoke-user.d.ts.map +1 -0
  257. package/dist/invoke-user.js +73 -0
  258. package/dist/invoke-user.js.map +1 -0
  259. package/dist/ip-restrict.d.ts +13 -1
  260. package/dist/ip-restrict.d.ts.map +1 -1
  261. package/dist/ip-restrict.js +60 -0
  262. package/dist/ip-restrict.js.map +1 -0
  263. package/dist/ip.d.ts +39 -0
  264. package/dist/ip.d.ts.map +1 -0
  265. package/dist/ip.js +209 -0
  266. package/dist/ip.js.map +1 -0
  267. package/dist/logger.d.ts.map +1 -1
  268. package/dist/logger.js +113 -0
  269. package/dist/logger.js.map +1 -0
  270. package/dist/media-type.d.ts +30 -0
  271. package/dist/media-type.d.ts.map +1 -0
  272. package/dist/media-type.js +97 -0
  273. package/dist/media-type.js.map +1 -0
  274. package/dist/meta-spec-merge.d.ts +32 -0
  275. package/dist/meta-spec-merge.d.ts.map +1 -0
  276. package/dist/meta-spec-merge.js +68 -0
  277. package/dist/meta-spec-merge.js.map +1 -0
  278. package/dist/meta-spec.d.ts +16 -3
  279. package/dist/meta-spec.d.ts.map +1 -1
  280. package/dist/meta-spec.js +535 -0
  281. package/dist/meta-spec.js.map +1 -0
  282. package/dist/middleware.d.ts +23 -6
  283. package/dist/middleware.d.ts.map +1 -1
  284. package/dist/middleware.js +253 -0
  285. package/dist/middleware.js.map +1 -0
  286. package/dist/node-request.d.ts +57 -12
  287. package/dist/node-request.d.ts.map +1 -1
  288. package/dist/node-request.js +407 -0
  289. package/dist/node-request.js.map +1 -0
  290. package/dist/node.d.ts +20 -3
  291. package/dist/node.d.ts.map +1 -1
  292. package/dist/node.js +396 -0
  293. package/dist/node.js.map +1 -0
  294. package/dist/openapi/collect.d.ts +6 -3
  295. package/dist/openapi/collect.d.ts.map +1 -1
  296. package/dist/openapi/collect.js +30 -0
  297. package/dist/openapi/collect.js.map +1 -0
  298. package/dist/openapi/docs-page.d.ts +42 -0
  299. package/dist/openapi/docs-page.d.ts.map +1 -0
  300. package/dist/openapi/docs-page.js +80 -0
  301. package/dist/openapi/docs-page.js.map +1 -0
  302. package/dist/openapi/document.d.ts +4 -0
  303. package/dist/openapi/document.d.ts.map +1 -1
  304. package/dist/openapi/document.js +785 -0
  305. package/dist/openapi/document.js.map +1 -0
  306. package/dist/openapi/json-schema-slot.d.ts +7 -0
  307. package/dist/openapi/json-schema-slot.d.ts.map +1 -1
  308. package/dist/openapi/json-schema-slot.js +38 -0
  309. package/dist/openapi/json-schema-slot.js.map +1 -0
  310. package/dist/openapi/register.d.ts.map +1 -1
  311. package/dist/openapi/register.js +20 -0
  312. package/dist/openapi/register.js.map +1 -0
  313. package/dist/openapi/scalar.d.ts +3 -1
  314. package/dist/openapi/scalar.d.ts.map +1 -1
  315. package/dist/openapi/scalar.js +21 -0
  316. package/dist/openapi/scalar.js.map +1 -0
  317. package/dist/openapi/serve.d.ts +9 -0
  318. package/dist/openapi/serve.d.ts.map +1 -0
  319. package/dist/openapi/serve.js +36 -0
  320. package/dist/openapi/serve.js.map +1 -0
  321. package/dist/openapi/spec-factory.d.ts +30 -1
  322. package/dist/openapi/spec-factory.d.ts.map +1 -1
  323. package/dist/openapi/spec-factory.js +52 -0
  324. package/dist/openapi/spec-factory.js.map +1 -0
  325. package/dist/openapi/spec.d.ts +14 -5
  326. package/dist/openapi/spec.d.ts.map +1 -1
  327. package/dist/openapi/spec.js +50 -0
  328. package/dist/openapi/spec.js.map +1 -0
  329. package/dist/openapi/swagger.d.ts +3 -1
  330. package/dist/openapi/swagger.d.ts.map +1 -1
  331. package/dist/openapi/swagger.js +22 -0
  332. package/dist/openapi/swagger.js.map +1 -0
  333. package/dist/pattern.d.ts +71 -0
  334. package/dist/pattern.d.ts.map +1 -0
  335. package/dist/pattern.js +239 -0
  336. package/dist/pattern.js.map +1 -0
  337. package/dist/peer.d.ts +17 -0
  338. package/dist/peer.d.ts.map +1 -0
  339. package/dist/peer.js +50 -0
  340. package/dist/peer.js.map +1 -0
  341. package/dist/plugin.d.ts +67 -16
  342. package/dist/plugin.d.ts.map +1 -1
  343. package/dist/plugin.js +649 -0
  344. package/dist/plugin.js.map +1 -0
  345. package/dist/powered-by.d.ts.map +1 -1
  346. package/dist/powered-by.js +11 -0
  347. package/dist/powered-by.js.map +1 -0
  348. package/dist/pretty-json.d.ts.map +1 -1
  349. package/dist/pretty-json.js +47 -0
  350. package/dist/pretty-json.js.map +1 -0
  351. package/dist/producer-stream.d.ts +47 -0
  352. package/dist/producer-stream.d.ts.map +1 -0
  353. package/dist/producer-stream.js +267 -0
  354. package/dist/producer-stream.js.map +1 -0
  355. package/dist/proxy.d.ts +47 -8
  356. package/dist/proxy.d.ts.map +1 -1
  357. package/dist/proxy.js +274 -0
  358. package/dist/proxy.js.map +1 -0
  359. package/dist/python-type-emitter.d.ts +14 -1
  360. package/dist/python-type-emitter.d.ts.map +1 -1
  361. package/dist/python-type-emitter.js +157 -0
  362. package/dist/python-type-emitter.js.map +1 -0
  363. package/dist/realtime/bus.d.ts +17 -1
  364. package/dist/realtime/bus.d.ts.map +1 -1
  365. package/dist/realtime/bus.js +112 -0
  366. package/dist/realtime/bus.js.map +1 -0
  367. package/dist/realtime/register.d.ts +3 -0
  368. package/dist/realtime/register.d.ts.map +1 -0
  369. package/dist/realtime/register.js +10 -0
  370. package/dist/realtime/register.js.map +1 -0
  371. package/dist/realtime/route.d.ts +65 -26
  372. package/dist/realtime/route.d.ts.map +1 -1
  373. package/dist/realtime/route.js +72 -0
  374. package/dist/realtime/route.js.map +1 -0
  375. package/dist/realtime/server.d.ts +43 -0
  376. package/dist/realtime/server.d.ts.map +1 -0
  377. package/dist/realtime/server.js +255 -0
  378. package/dist/realtime/server.js.map +1 -0
  379. package/dist/request-id.d.ts +7 -0
  380. package/dist/request-id.d.ts.map +1 -1
  381. package/dist/request-id.js +16 -0
  382. package/dist/request-id.js.map +1 -0
  383. package/dist/request-limits.d.ts +3 -0
  384. package/dist/request-limits.d.ts.map +1 -0
  385. package/dist/request-limits.js +3 -0
  386. package/dist/request-limits.js.map +1 -0
  387. package/dist/request-path.d.ts +33 -0
  388. package/dist/request-path.d.ts.map +1 -0
  389. package/dist/request-path.js +178 -0
  390. package/dist/request-path.js.map +1 -0
  391. package/dist/request-to-curl.d.ts +7 -1
  392. package/dist/request-to-curl.d.ts.map +1 -1
  393. package/dist/request-to-curl.js +48 -0
  394. package/dist/request-to-curl.js.map +1 -0
  395. package/dist/response.d.ts +25 -2
  396. package/dist/response.d.ts.map +1 -1
  397. package/dist/response.js +313 -0
  398. package/dist/response.js.map +1 -0
  399. package/dist/rust-type-emitter.d.ts +14 -2
  400. package/dist/rust-type-emitter.d.ts.map +1 -1
  401. package/dist/rust-type-emitter.js +463 -0
  402. package/dist/rust-type-emitter.js.map +1 -0
  403. package/dist/secure-headers.d.ts.map +1 -1
  404. package/dist/secure-headers.js +53 -0
  405. package/dist/secure-headers.js.map +1 -0
  406. package/dist/serve-register.d.ts +4 -0
  407. package/dist/serve-register.d.ts.map +1 -1
  408. package/dist/serve-register.js +9 -0
  409. package/dist/serve-register.js.map +1 -0
  410. package/dist/serve-slot.d.ts +3 -0
  411. package/dist/serve-slot.d.ts.map +1 -1
  412. package/dist/serve-slot.js +52 -0
  413. package/dist/serve-slot.js.map +1 -0
  414. package/dist/serve.d.ts +18 -1
  415. package/dist/serve.d.ts.map +1 -1
  416. package/dist/serve.js +157 -0
  417. package/dist/serve.js.map +1 -0
  418. package/dist/server-timing.d.ts.map +1 -1
  419. package/dist/server-timing.js +51 -0
  420. package/dist/server-timing.js.map +1 -0
  421. package/dist/static.d.ts +9 -0
  422. package/dist/static.d.ts.map +1 -1
  423. package/dist/static.js +102 -0
  424. package/dist/static.js.map +1 -0
  425. package/dist/telemetry/otel.d.ts +2 -0
  426. package/dist/telemetry/otel.d.ts.map +1 -1
  427. package/dist/telemetry/otel.js +135 -0
  428. package/dist/telemetry/otel.js.map +1 -0
  429. package/dist/testing.d.ts +12 -0
  430. package/dist/testing.d.ts.map +1 -1
  431. package/dist/testing.js +124 -0
  432. package/dist/testing.js.map +1 -0
  433. package/dist/timeout.d.ts +6 -0
  434. package/dist/timeout.d.ts.map +1 -1
  435. package/dist/timeout.js +36 -0
  436. package/dist/timeout.js.map +1 -0
  437. package/dist/tree.d.ts +133 -36
  438. package/dist/tree.d.ts.map +1 -1
  439. package/dist/tree.js +437 -0
  440. package/dist/tree.js.map +1 -0
  441. package/dist/trust.d.ts +21 -0
  442. package/dist/trust.d.ts.map +1 -0
  443. package/dist/trust.js +100 -0
  444. package/dist/trust.js.map +1 -0
  445. package/dist/ts-type-emitter.d.ts.map +1 -1
  446. package/dist/ts-type-emitter.js +150 -0
  447. package/dist/ts-type-emitter.js.map +1 -0
  448. package/dist/type-emitter.d.ts +16 -2
  449. package/dist/type-emitter.d.ts.map +1 -1
  450. package/dist/type-emitter.js +729 -0
  451. package/dist/type-emitter.js.map +1 -0
  452. package/dist/type-extractor.d.ts +8 -4
  453. package/dist/type-extractor.d.ts.map +1 -1
  454. package/dist/type-extractor.js +819 -0
  455. package/dist/type-extractor.js.map +1 -0
  456. package/dist/types.d.ts +7 -0
  457. package/dist/types.d.ts.map +1 -1
  458. package/dist/types.js +96 -0
  459. package/dist/types.js.map +1 -0
  460. package/dist/validation.d.ts +14 -2
  461. package/dist/validation.d.ts.map +1 -1
  462. package/dist/validation.js +335 -0
  463. package/dist/validation.js.map +1 -0
  464. package/dist/with-headers.d.ts +15 -0
  465. package/dist/with-headers.d.ts.map +1 -0
  466. package/dist/with-headers.js +45 -0
  467. package/dist/with-headers.js.map +1 -0
  468. package/dist/ws/bun.d.ts +11 -5
  469. package/dist/ws/bun.d.ts.map +1 -1
  470. package/dist/ws/bun.js +82 -0
  471. package/dist/ws/bun.js.map +1 -0
  472. package/dist/ws/cloudflare.d.ts +25 -3
  473. package/dist/ws/cloudflare.d.ts.map +1 -1
  474. package/dist/ws/cloudflare.js +117 -0
  475. package/dist/ws/cloudflare.js.map +1 -0
  476. package/dist/ws/deno.d.ts +4 -4
  477. package/dist/ws/deno.d.ts.map +1 -1
  478. package/dist/ws/deno.js +133 -0
  479. package/dist/ws/deno.js.map +1 -0
  480. package/dist/ws/node.d.ts +20 -3
  481. package/dist/ws/node.d.ts.map +1 -1
  482. package/dist/ws/node.js +173 -0
  483. package/dist/ws/node.js.map +1 -0
  484. package/dist/ws/session.d.ts +11 -0
  485. package/dist/ws/session.d.ts.map +1 -0
  486. package/dist/ws/session.js +60 -0
  487. package/dist/ws/session.js.map +1 -0
  488. package/dist/ws/shared.d.ts +65 -0
  489. package/dist/ws/shared.d.ts.map +1 -0
  490. package/dist/ws/shared.js +103 -0
  491. package/dist/ws/shared.js.map +1 -0
  492. package/dist/ws-origin.d.ts +20 -0
  493. package/dist/ws-origin.d.ts.map +1 -0
  494. package/dist/ws-origin.js +41 -0
  495. package/dist/ws-origin.js.map +1 -0
  496. package/dist/yaml.d.ts +15 -1
  497. package/dist/yaml.d.ts.map +1 -1
  498. package/dist/yaml.js +101 -0
  499. package/dist/yaml.js.map +1 -0
  500. package/docs/invalidate-spec.md +13 -1
  501. package/docs/meta-spec.md +36 -12
  502. package/docs/packaging.md +43 -24
  503. package/docs/regression-matrix/README.md +32 -0
  504. package/docs/regression-matrix/review.md +44 -0
  505. package/docs/regression-matrix/ws1-3.md +97 -0
  506. package/docs/regression-matrix/ws4-8.md +107 -0
  507. package/docs/regression-matrix/ws9-12.md +266 -0
  508. package/docs/sdk.md +102 -52
  509. package/package.json +183 -52
  510. package/src/accepts.ts +91 -33
  511. package/src/body-kind.ts +67 -0
  512. package/src/body-limit.ts +102 -87
  513. package/src/build/index.ts +104 -54
  514. package/src/cli-args.ts +123 -0
  515. package/src/cli-go/auth.go +12 -1
  516. package/src/cli-go/config.go +29 -2
  517. package/src/cli-go/errors.go +28 -10
  518. package/src/cli-go/multipart.go +51 -27
  519. package/src/cli-go/output.go +58 -4
  520. package/src/cli-go/root.go +1 -1
  521. package/src/cli-go/version.go +2 -2
  522. package/src/cli.ts +154 -148
  523. package/src/client/error.ts +56 -1
  524. package/src/client/http.ts +479 -256
  525. package/src/client/index.ts +55 -17
  526. package/src/client/path.ts +169 -0
  527. package/src/client/redirect-policy.ts +19 -0
  528. package/src/client/sdk.ts +180 -101
  529. package/src/client/sse.ts +92 -66
  530. package/src/client/ws.ts +67 -31
  531. package/src/client-go/errors.go +41 -12
  532. package/src/client-go/export.go +44 -0
  533. package/src/client-go/invalidation.go +52 -54
  534. package/src/client-go/nullable.go +62 -0
  535. package/src/client-go/realtime.go +147 -110
  536. package/src/client-go/runtime.go +646 -88
  537. package/src/client-go/sse.go +104 -94
  538. package/src/client-go/transport.go +67 -27
  539. package/src/client-go/ws.go +49 -25
  540. package/src/client-info.ts +79 -0
  541. package/src/client-mcp/server.ts +133 -3
  542. package/src/client-python/_invalidation.py +207 -291
  543. package/src/client-python/_realtime.py +63 -40
  544. package/src/client-python/_runtime.py +501 -119
  545. package/src/client-python/_sse.py +130 -74
  546. package/src/client-python/_transport.py +37 -9
  547. package/src/client-python/_ws.py +50 -22
  548. package/src/client-rust/errors.rs +21 -1
  549. package/src/client-rust/invalidation.rs +202 -231
  550. package/src/client-rust/invalidation_sync.rs +16 -229
  551. package/src/client-rust/nullable.rs +17 -0
  552. package/src/client-rust/realtime.rs +217 -217
  553. package/src/client-rust/runtime.rs +602 -177
  554. package/src/client-rust/runtime_sync.rs +169 -145
  555. package/src/client-rust/sse.rs +142 -121
  556. package/src/client-rust/ws.rs +61 -37
  557. package/src/codegen-go-cli.ts +607 -728
  558. package/src/codegen-go.ts +710 -770
  559. package/src/codegen-ir.ts +381 -75
  560. package/src/codegen-lang.ts +517 -0
  561. package/src/codegen-load.ts +150 -0
  562. package/src/codegen-mcp.ts +207 -108
  563. package/src/codegen-python.ts +684 -816
  564. package/src/codegen-route-tree-intern.ts +51 -25
  565. package/src/codegen-rust.ts +946 -1240
  566. package/src/codegen-sanitize.ts +0 -4
  567. package/src/codegen-schema-naming.ts +19 -6
  568. package/src/codegen-sdk-model.ts +228 -0
  569. package/src/codegen.ts +1488 -1140
  570. package/src/context.ts +130 -11
  571. package/src/cookie-sign.ts +85 -16
  572. package/src/cookie.ts +66 -11
  573. package/src/cors.ts +55 -54
  574. package/src/crypto.ts +27 -5
  575. package/src/csrf.ts +57 -25
  576. package/src/curl-logger.ts +155 -114
  577. package/src/dict.ts +12 -0
  578. package/src/error.ts +4 -2
  579. package/src/etag.ts +58 -34
  580. package/src/feature-detect.ts +147 -0
  581. package/src/feature-slots.ts +70 -0
  582. package/src/fetch-request.ts +13 -0
  583. package/src/gen-process.ts +42 -0
  584. package/src/gen-write.ts +127 -0
  585. package/src/glob.ts +109 -0
  586. package/src/go-type-emitter.ts +406 -155
  587. package/src/honey-response.ts +36 -9
  588. package/src/i18n-slot.ts +10 -0
  589. package/src/i18n.ts +98 -23
  590. package/src/index.ts +1887 -1756
  591. package/src/init.ts +40 -28
  592. package/src/invalidate-check.ts +42 -4
  593. package/src/invoke-user.ts +95 -0
  594. package/src/ip-restrict.ts +47 -161
  595. package/src/ip.ts +194 -0
  596. package/src/logger.ts +65 -36
  597. package/src/media-type.ts +104 -0
  598. package/src/meta-spec-merge.ts +80 -0
  599. package/src/meta-spec.ts +0 -0
  600. package/src/middleware.ts +112 -12
  601. package/src/node-request.ts +242 -52
  602. package/src/node.ts +318 -75
  603. package/src/openapi/collect.ts +19 -44
  604. package/src/openapi/docs-page.ts +89 -0
  605. package/src/openapi/document.ts +503 -224
  606. package/src/openapi/json-schema-slot.ts +40 -0
  607. package/src/openapi/register.ts +7 -2
  608. package/src/openapi/scalar.ts +11 -10
  609. package/src/openapi/serve.ts +39 -0
  610. package/src/openapi/spec-factory.ts +50 -1
  611. package/src/openapi/spec.ts +53 -30
  612. package/src/openapi/swagger.ts +12 -11
  613. package/src/pattern.ts +245 -0
  614. package/src/peer.ts +53 -0
  615. package/src/plugin.ts +270 -185
  616. package/src/powered-by.ts +2 -2
  617. package/src/pretty-json.ts +25 -9
  618. package/src/producer-stream.ts +296 -0
  619. package/src/proxy.ts +253 -55
  620. package/src/python-type-emitter.ts +68 -56
  621. package/src/realtime/bus.ts +56 -9
  622. package/src/realtime/register.ts +13 -0
  623. package/src/realtime/route.ts +129 -80
  624. package/src/realtime/server.ts +298 -0
  625. package/src/request-id.ts +13 -3
  626. package/src/request-limits.ts +2 -0
  627. package/src/request-path.ts +165 -0
  628. package/src/request-to-curl.ts +28 -7
  629. package/src/response.ts +143 -103
  630. package/src/rust-type-emitter.ts +265 -170
  631. package/src/secure-headers.ts +8 -4
  632. package/src/serve-register.ts +4 -0
  633. package/src/serve-slot.ts +38 -0
  634. package/src/serve.ts +113 -25
  635. package/src/server-timing.ts +11 -7
  636. package/src/static.ts +85 -32
  637. package/src/telemetry/otel.ts +29 -7
  638. package/src/testing.ts +76 -14
  639. package/src/timeout.ts +15 -7
  640. package/src/tree.ts +405 -333
  641. package/src/trust.ts +117 -0
  642. package/src/ts-type-emitter.ts +18 -12
  643. package/src/type-emitter.ts +227 -89
  644. package/src/type-extractor.ts +603 -423
  645. package/src/types.ts +8 -0
  646. package/src/validation.ts +221 -96
  647. package/src/with-headers.ts +45 -0
  648. package/src/ws/bun.ts +53 -15
  649. package/src/ws/cloudflare.ts +81 -19
  650. package/src/ws/deno.ts +124 -36
  651. package/src/ws/node.ts +173 -79
  652. package/src/ws/session.ts +73 -0
  653. package/src/ws/shared.ts +140 -0
  654. package/src/ws-origin.ts +53 -0
  655. package/src/yaml.ts +45 -22
  656. package/dist/client-mcp/server.d.ts +0 -10
  657. package/dist/client-mcp/server.d.ts.map +0 -1
  658. package/dist/client-mcp/types.d.ts +0 -16
  659. package/dist/client-mcp/types.d.ts.map +0 -1
  660. package/dist/cloudflare/realtime.d.ts +0 -30
  661. package/dist/cloudflare/realtime.d.ts.map +0 -1
  662. package/dist/realtime/buffer.d.ts +0 -18
  663. package/dist/realtime/buffer.d.ts.map +0 -1
  664. package/dist/realtime/longpoll.d.ts +0 -23
  665. package/dist/realtime/longpoll.d.ts.map +0 -1
  666. package/dist/realtime/protocol.d.ts +0 -50
  667. package/dist/realtime/protocol.d.ts.map +0 -1
  668. package/dist/realtime/runtime.d.ts +0 -74
  669. package/dist/realtime/runtime.d.ts.map +0 -1
  670. package/src/cloudflare/realtime.ts +0 -234
  671. package/src/realtime/buffer.ts +0 -101
  672. package/src/realtime/longpoll.ts +0 -148
  673. package/src/realtime/protocol.ts +0 -128
  674. package/src/realtime/runtime.ts +0 -427
package/src/logger.ts CHANGED
@@ -39,38 +39,61 @@ type CreateLoggerOptions = {
39
39
  write?: (line: string) => void
40
40
  }
41
41
 
42
- function createLogger(opts?: CreateLoggerOptions): LoggerInstance {
43
- const threshold = LEVELS[opts?.level ?? "info"]
44
- const write = opts?.write ?? ((line: string) => console.log(line))
45
- const base = opts?.base ?? {}
42
+ /* Methods live on the prototype: `logger()` makes a child per request, and a
43
+ * closure-per-level instance cost seven allocations each time. */
44
+ class Logger implements LoggerInstance {
45
+ level: LogLevel
46
+ #threshold: number
47
+ #write: (line: string) => void
48
+ #base: Record<string, unknown>
49
+
50
+ constructor(level: LogLevel, write: (line: string) => void, base: Record<string, unknown>) {
51
+ this.level = level
52
+ this.#threshold = LEVELS[level]
53
+ this.#write = write
54
+ this.#base = base
55
+ }
46
56
 
47
- function emit(level: number, first: Record<string, unknown> | string, second?: string): void {
48
- if (level < threshold) return
49
- const obj =
50
- typeof first === "string"
51
- ? { ...base, level, msg: first, time: Date.now() }
52
- : { ...base, ...first, level, msg: second ?? "", time: Date.now() }
53
- write(JSON.stringify(obj))
57
+ child(bindings: Record<string, unknown>): LoggerInstance {
58
+ return new Logger(this.level, this.#write, { ...this.#base, ...bindings })
59
+ }
60
+
61
+ trace(first: Record<string, unknown> | string, second?: string): void {
62
+ this.#emit(LEVELS.trace, first, second)
63
+ }
64
+
65
+ debug(first: Record<string, unknown> | string, second?: string): void {
66
+ this.#emit(LEVELS.debug, first, second)
67
+ }
68
+
69
+ info(first: Record<string, unknown> | string, second?: string): void {
70
+ this.#emit(LEVELS.info, first, second)
71
+ }
72
+
73
+ warn(first: Record<string, unknown> | string, second?: string): void {
74
+ this.#emit(LEVELS.warn, first, second)
75
+ }
76
+
77
+ error(first: Record<string, unknown> | string, second?: string): void {
78
+ this.#emit(LEVELS.error, first, second)
54
79
  }
55
80
 
56
- const instance: LoggerInstance = {
57
- child(bindings: Record<string, unknown>): LoggerInstance {
58
- return createLogger({
59
- base: { ...base, ...bindings },
60
- level: opts?.level,
61
- write,
62
- })
63
- },
64
- debug: (first: Record<string, unknown> | string, second?: string) => emit(LEVELS.debug, first, second),
65
- error: (first: Record<string, unknown> | string, second?: string) => emit(LEVELS.error, first, second),
66
- fatal: (first: Record<string, unknown> | string, second?: string) => emit(LEVELS.fatal, first, second),
67
- info: (first: Record<string, unknown> | string, second?: string) => emit(LEVELS.info, first, second),
68
- level: opts?.level ?? "info",
69
- trace: (first: Record<string, unknown> | string, second?: string) => emit(LEVELS.trace, first, second),
70
- warn: (first: Record<string, unknown> | string, second?: string) => emit(LEVELS.warn, first, second),
81
+ fatal(first: Record<string, unknown> | string, second?: string): void {
82
+ this.#emit(LEVELS.fatal, first, second)
83
+ }
84
+
85
+ #emit(level: number, first: Record<string, unknown> | string, second?: string): void {
86
+ if (level < this.#threshold) return
87
+ const obj =
88
+ typeof first === "string"
89
+ ? { ...this.#base, level, msg: first, time: Date.now() }
90
+ : { ...this.#base, ...first, level, msg: second ?? "", time: Date.now() }
91
+ this.#write(JSON.stringify(obj))
71
92
  }
93
+ }
72
94
 
73
- return instance
95
+ function createLogger(opts?: CreateLoggerOptions): LoggerInstance {
96
+ return new Logger(opts?.level ?? "info", opts?.write ?? ((line: string) => console.log(line)), opts?.base ?? {})
74
97
  }
75
98
 
76
99
  /* ── request lifecycle middleware ── */
@@ -116,8 +139,13 @@ function logger(options?: LoggerOptions): MiddlewareFn<{ path: string; req: Requ
116
139
  })
117
140
  : noopLogger
118
141
 
142
+ /* a failing sink never fails the request, on the way in or out */
119
143
  if (instance) {
120
- child.info(`--> ${method} ${path}`)
144
+ try {
145
+ child.info(`--> ${method} ${path}`)
146
+ } catch (err) {
147
+ console.error("logger: failed to log request", err)
148
+ }
121
149
  }
122
150
 
123
151
  const response = await next({ log: child })
@@ -131,14 +159,15 @@ function logger(options?: LoggerOptions): MiddlewareFn<{ path: string; req: Requ
131
159
  status: response.status,
132
160
  }
133
161
 
134
- if (skip?.(data)) {
135
- return response
136
- }
137
-
138
- if (instance) {
139
- child.info({ duration, status: response.status }, `<-- ${method} ${path}`)
140
- } else {
141
- log(data)
162
+ try {
163
+ if (skip?.(data)) return response
164
+ if (instance) {
165
+ child.info({ duration, status: response.status }, `<-- ${method} ${path}`)
166
+ } else {
167
+ log(data)
168
+ }
169
+ } catch (err) {
170
+ console.error("logger: failed to log request", err)
142
171
  }
143
172
 
144
173
  return response
@@ -0,0 +1,104 @@
1
+ /**
2
+ * One media-type parser (RFC 9110 §8.3.1) for every place that reads a `Content-Type`:
3
+ * input validation, `bodyLimit`, and the client. Type, subtype and parameter names are
4
+ * case-insensitive, so they are lowercased; parameter values keep their case.
5
+ *
6
+ * Pure and dependency-free: the client entry imports it too.
7
+ */
8
+
9
+ export type MediaType = {
10
+ /** `type/subtype`, lowercased, without parameters */
11
+ essence: string
12
+ /** parameters by lowercased name; a repeated name keeps the first value */
13
+ params: Record<string, string>
14
+ subtype: string
15
+ /** the structured-syntax suffix (`json` for `application/vnd.api+json`), or `null` */
16
+ suffix: string | null
17
+ type: string
18
+ }
19
+
20
+ /* RFC 9110 token characters */
21
+ const TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/
22
+
23
+ function isToken(s: string): boolean {
24
+ return s.length > 0 && TOKEN.test(s)
25
+ }
26
+
27
+ /**
28
+ * Parses a `Content-Type` (or any media type) value. Returns `null` for an absent or
29
+ * malformed value, so a caller never mistakes `application/jsonx` or `json` for JSON.
30
+ */
31
+ export function parseMediaType(value: string | null | undefined): MediaType | null {
32
+ if (value === null || value === undefined) return null
33
+ const semi = value.indexOf(";")
34
+ const head = (semi === -1 ? value : value.slice(0, semi)).trim()
35
+ const slash = head.indexOf("/")
36
+ if (slash === -1) return null
37
+ const type = head.slice(0, slash).toLowerCase()
38
+ const subtype = head.slice(slash + 1).toLowerCase()
39
+ if (!isToken(type) || !isToken(subtype)) return null
40
+ const plus = subtype.lastIndexOf("+")
41
+ const suffix = plus > 0 && plus < subtype.length - 1 ? subtype.slice(plus + 1) : null
42
+ const params = Object.create(null) as Record<string, string>
43
+ if (semi !== -1) parseParams(value, semi + 1, params)
44
+ return { essence: `${type}/${subtype}`, params, subtype, suffix, type }
45
+ }
46
+
47
+ /* `; name=value` pairs; value is a token or a quoted-string. Malformed pairs are skipped,
48
+ * as browsers and undici do, rather than rejecting the whole header. */
49
+ function parseParams(value: string, start: number, out: Record<string, string>): void {
50
+ let i = start
51
+ const n = value.length
52
+ while (i < n) {
53
+ while (i < n && (value[i] === " " || value[i] === "\t" || value[i] === ";")) i++
54
+ const eq = value.indexOf("=", i)
55
+ const nextSemi = value.indexOf(";", i)
56
+ if (eq === -1 || (nextSemi !== -1 && nextSemi < eq)) {
57
+ i = nextSemi === -1 ? n : nextSemi + 1
58
+ continue
59
+ }
60
+ const name = value.slice(i, eq).trim().toLowerCase()
61
+ i = eq + 1
62
+ let v: string
63
+ if (value[i] === '"') {
64
+ i++
65
+ let buf = ""
66
+ while (i < n && value[i] !== '"') {
67
+ if (value[i] === "\\" && i + 1 < n) i++
68
+ buf += value[i]
69
+ i++
70
+ }
71
+ v = buf
72
+ i++ /* closing quote */
73
+ const after = value.indexOf(";", i)
74
+ i = after === -1 ? n : after + 1
75
+ } else {
76
+ const end = value.indexOf(";", i)
77
+ v = (end === -1 ? value.slice(i) : value.slice(i, end)).trim()
78
+ i = end === -1 ? n : end + 1
79
+ }
80
+ if (isToken(name) && !(name in out)) out[name] = v
81
+ }
82
+ }
83
+
84
+ /** `application/json`, or any `+json` structured-syntax type (`application/problem+json`). */
85
+ export function isJsonMediaType(mt: MediaType | null): boolean {
86
+ return mt !== null && (mt.essence === "application/json" || mt.suffix === "json")
87
+ }
88
+
89
+ /** Text-like bodies: `text/*`, `application/xml`, and any `+xml` type. */
90
+ export function isTextMediaType(mt: MediaType | null): boolean {
91
+ return mt !== null && (mt.type === "text" || mt.essence === "application/xml" || mt.suffix === "xml")
92
+ }
93
+
94
+ export type BodyParser = "json" | "multipart" | "urlencoded"
95
+
96
+ /** Which body parser a request `Content-Type` selects, or `null` when none applies. */
97
+ export function bodyParserFor(contentType: string | null | undefined): BodyParser | null {
98
+ const mt = parseMediaType(contentType)
99
+ if (mt === null) return null
100
+ if (isJsonMediaType(mt)) return "json"
101
+ if (mt.essence === "multipart/form-data") return "multipart"
102
+ if (mt.essence === "application/x-www-form-urlencoded") return "urlencoded"
103
+ return null
104
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Composition of metaSpec policies across mounted sub-apps. Kept apart from the policy engine
3
+ * so the app core can merge policies without loading the engine.
4
+ */
5
+ import type { MetaSpecConfig, MetaSpecEntry, MetaSpecMergeConflict, MetaSpecStrictness } from "./types.ts"
6
+
7
+ /** The strictness a declared policy actually runs with: `"error"` unless it says otherwise. */
8
+ export function resolvedStrictness(config: MetaSpecConfig | null): MetaSpecStrictness {
9
+ return config?.strict ?? (config ? "error" : "off")
10
+ }
11
+
12
+ /**
13
+ * Merge a mounted sub-app's policy into a parent's.
14
+ *
15
+ * The parent wins on conflict, so one gateway keeps one answer for its aggregate document —
16
+ * with a single exception. A sub entry of `false` wins over anything the parent says, because
17
+ * hiding is a safety claim and the strictest claim has to survive composition: a worker that
18
+ * declares a field unpublishable must not have the gateway publish it. Wrongly hidden is a
19
+ * visible gap; wrongly published is a leak.
20
+ *
21
+ * Strictness is the parent's *resolved* setting: a parent that never wrote `strict` runs with
22
+ * `"error"`, and a sub-app's `"off"` must not downgrade it. Every other disagreement is
23
+ * recorded in `conflicts` and reported at codegen.
24
+ *
25
+ * Order-independent with respect to when the parent declares its own policy: callers may keep
26
+ * the absorbed sub policies and merge them in at codegen time.
27
+ */
28
+ export function mergeMetaSpec(own: MetaSpecConfig | null, sub: MetaSpecConfig | null): MetaSpecConfig | null {
29
+ if (!sub) return own
30
+ if (!own) return sub
31
+ const conflicts: MetaSpecMergeConflict[] = [...(own.conflicts ?? []), ...(sub.conflicts ?? [])]
32
+
33
+ const meta: Record<string, MetaSpecEntry> = { ...sub.meta, ...own.meta }
34
+ for (const [key, subEntry] of Object.entries(sub.meta ?? {})) {
35
+ const ownEntry = own.meta?.[key]
36
+ if (ownEntry === undefined || ownEntry === subEntry) continue
37
+ if (subEntry === false && ownEntry !== false) {
38
+ meta[key] = false
39
+ conflicts.push({ key, resolution: "hidden", section: "meta" })
40
+ continue
41
+ }
42
+ conflicts.push({ key, resolution: "parent", section: "meta" })
43
+ }
44
+
45
+ const recordOverlap = (section: "profiles" | "schema", subSide: object, ownSide: object): void => {
46
+ for (const [key, subEntry] of Object.entries(subSide)) {
47
+ const ownEntry = (ownSide as Record<string, unknown>)[key]
48
+ if (ownEntry === undefined || ownEntry === subEntry) continue
49
+ conflicts.push({ key, resolution: "parent", section })
50
+ }
51
+ }
52
+ recordOverlap("schema", sub.schema ?? {}, own.schema ?? {})
53
+ recordOverlap("profiles", sub.profiles ?? {}, own.profiles ?? {})
54
+
55
+ return {
56
+ conflicts,
57
+ meta,
58
+ profiles: { ...sub.profiles, ...own.profiles },
59
+ schema: { ...sub.schema, ...own.schema },
60
+ strict: resolvedStrictness(own),
61
+ }
62
+ }
63
+
64
+ /** A policy as an app holds it: its own declaration and each mounted sub-app's source, unmerged. */
65
+ export type MetaSpecSource = {
66
+ readonly declared: MetaSpecConfig | null
67
+ readonly absorbed: readonly MetaSpecSource[]
68
+ }
69
+
70
+ function resolveSource(source: MetaSpecSource): MetaSpecConfig | null {
71
+ let merged = source.declared
72
+ for (const sub of source.absorbed) merged = mergeMetaSpec(merged, resolveSource(sub))
73
+ return merged
74
+ }
75
+
76
+ /** The policy codegen applies to `app`: its own, with every mounted sub-app's merged in mount order. */
77
+ export function metaSpecOf(app: unknown): MetaSpecConfig | null {
78
+ const source = (app as { _metaSpecSource?: MetaSpecSource })._metaSpecSource
79
+ return source === undefined ? null : resolveSource(source)
80
+ }
package/src/meta-spec.ts CHANGED
Binary file
package/src/middleware.ts CHANGED
@@ -94,9 +94,8 @@ export function createMiddleware<TReqs = {}, TRet extends Promise<Response> = Pr
94
94
  }
95
95
 
96
96
  /**
97
- * Merge meta contributed by a middleware chain, in mount order. Resolved once at route
98
- * registration — never per request, because the precompiled route tree bakes `mt` as a literal
99
- * and a lazily-derived value would diverge from it.
97
+ * Merge meta contributed by a middleware chain, in run order (later wins). Resolved once when
98
+ * the app finalizes, from the chain the route runs — never per request.
100
99
  */
101
100
  export function collectMiddlewareMeta(
102
101
  groups: ReadonlyArray<ReadonlyArray<RuntimeMiddleware>>,
@@ -114,20 +113,71 @@ export function collectMiddlewareMeta(
114
113
  }
115
114
 
116
115
  /**
117
- * Context properties that middleware additions must not overwrite.
118
- * These are set by the framework during request construction.
119
- * TypeScript prevents this at compile time; this guard catches runtime bypasses.
116
+ * Every name the framework owns on a request context — fields, lazy getters, methods and
117
+ * internal backing state. `next({ ... })` additions and `.context()` values may not use them:
118
+ * an addition would silently replace framework state, and a value assigned over a getter-only
119
+ * field throws on every request. TypeScript prevents most of this at compile time; this set
120
+ * is the runtime guard.
120
121
  */
121
- const RESERVED_CTX_KEYS = new Set(["background", "cookies", "env", "headers", "params", "req", "res", "search"])
122
+ export const RESERVED_CTX_KEYS: ReadonlySet<string> = new Set([
123
+ "background",
124
+ "cookies",
125
+ "env",
126
+ "error",
127
+ "errors",
128
+ "executionCtx",
129
+ "headers",
130
+ "input",
131
+ "ip",
132
+ "meta",
133
+ "params",
134
+ "path",
135
+ "realtime",
136
+ "req",
137
+ "res",
138
+ "routePattern",
139
+ "search",
140
+ "searchAll",
141
+ "signal",
142
+ "tap",
143
+ "_ac",
144
+ "_errorToResponse",
145
+ "_isErrorResponse",
146
+ "_lzClient",
147
+ "_lzCookies",
148
+ "_lzHeaders",
149
+ "_lzSearch",
150
+ "_lzSearchAll",
151
+ "_lzUrlFn",
152
+ "_pendingTaps",
153
+ "_rq",
154
+ "_setErrors",
155
+ ])
122
156
 
123
157
  /**
124
- * Compile a middleware chain + handler into a single function at registration time.
125
- * Eliminates per-request recursive dispatch, closure allocation, and Promise.resolve wrapping.
158
+ * Turns a value thrown inside a chain into the Response that stands in for it. Supplied by
159
+ * the app; must not throw.
160
+ */
161
+ export type ChainErrorConverter = (thrown: unknown, ctx: object) => Response | Promise<Response>
162
+
163
+ const NO_RESPONSE_HANDLER = "handler must return a Response — did you forget 'return ctx.res...()'?"
164
+ const NO_RESPONSE_MIDDLEWARE = "middleware must return a Response — did you forget 'return next(...)'?"
165
+
166
+ /**
167
+ * Compile a middleware chain + handler into a single function, once.
168
+ *
169
+ * With `convert`, every `next()` boundary is an error boundary: whatever the handler or a
170
+ * middleware throws (or rejects with) becomes a Response at that layer, so the middleware
171
+ * around it always gets a Response back from `next()` and its post-`next()` code — headers,
172
+ * logging, timing — runs on error responses too. The compiled function never rejects as long
173
+ * as `convert` does not. Without `convert`, throws propagate (the bare executor).
126
174
  */
127
175
  export function compileChain(
128
176
  middlewares: RuntimeMiddleware[],
129
177
  handler: (ctx: object) => Response | Promise<Response>,
178
+ convert?: ChainErrorConverter,
130
179
  ): (ctx: object) => Response | Promise<Response> {
180
+ if (convert !== undefined) return compileConverting(middlewares, handler, convert)
131
181
  if (middlewares.length === 0) {
132
182
  /* sync fast path — avoids microtask overhead for sync handlers */
133
183
  return (ctx) => {
@@ -136,7 +186,7 @@ export function compileChain(
136
186
  return result.then(validateResponse)
137
187
  }
138
188
  if (result === undefined || result === null) {
139
- throw new Error("handler must return a Response — did you forget 'return ctx.res...()'?")
189
+ throw new Error(NO_RESPONSE_HANDLER)
140
190
  }
141
191
  return result
142
192
  }
@@ -165,6 +215,56 @@ export function compileChain(
165
215
  return (ctx) => executeChain(middlewares, ctx, handler)
166
216
  }
167
217
 
218
+ function compileConverting(
219
+ middlewares: readonly RuntimeMiddleware[],
220
+ handler: (ctx: object) => Response | Promise<Response>,
221
+ convert: ChainErrorConverter,
222
+ ): (ctx: object) => Response | Promise<Response> {
223
+ const n = middlewares.length
224
+
225
+ const runHandler = (ctx: object): Response | Promise<Response> => {
226
+ let result: Response | Promise<Response>
227
+ try {
228
+ result = handler(ctx)
229
+ } catch (thrown) {
230
+ return convert(thrown, ctx)
231
+ }
232
+ if (result instanceof Promise) {
233
+ return result.then(
234
+ (value) => (value === undefined || value === null ? convert(new Error(NO_RESPONSE_HANDLER), ctx) : value),
235
+ (thrown: unknown) => convert(thrown, ctx),
236
+ )
237
+ }
238
+ if (result === undefined || result === null) return convert(new Error(NO_RESPONSE_HANDLER), ctx)
239
+ return result
240
+ }
241
+
242
+ const step = (i: number, ctx: object): Response | Promise<Response> => {
243
+ if (i === n) return runHandler(ctx)
244
+ const mw = middlewares[i] as RuntimeMiddleware
245
+ let called = false
246
+ const next = (additions?: Record<string, unknown>): Promise<Response> => {
247
+ if (called) throw new Error("next() called multiple times")
248
+ called = true
249
+ if (additions) mergeAdditions(ctx, additions)
250
+ const downstream = step(i + 1, ctx)
251
+ return downstream instanceof Promise ? downstream : Promise.resolve(downstream)
252
+ }
253
+ let out: Promise<Response>
254
+ try {
255
+ out = mw(ctx as Record<string, unknown>, next)
256
+ } catch (thrown) {
257
+ return convert(thrown, ctx)
258
+ }
259
+ return Promise.resolve(out).then(
260
+ (value) => (value === undefined || value === null ? convert(new Error(NO_RESPONSE_MIDDLEWARE), ctx) : value),
261
+ (thrown: unknown) => convert(thrown, ctx),
262
+ )
263
+ }
264
+
265
+ return (ctx) => step(0, ctx)
266
+ }
267
+
168
268
  function mergeAdditions(ctx: object, additions: Record<string, unknown>): void {
169
269
  for (const key in additions) {
170
270
  if (!RESERVED_CTX_KEYS.has(key)) {
@@ -175,14 +275,14 @@ function mergeAdditions(ctx: object, additions: Record<string, unknown>): void {
175
275
 
176
276
  function validateResponse(result: Response): Response {
177
277
  if (result === undefined || result === null) {
178
- throw new Error("handler must return a Response — did you forget 'return ctx.res...()'?")
278
+ throw new Error(NO_RESPONSE_HANDLER)
179
279
  }
180
280
  return result
181
281
  }
182
282
 
183
283
  function validateMiddlewareResponse(result: Response): Response {
184
284
  if (result === undefined || result === null) {
185
- throw new Error("middleware must return a Response — did you forget 'return next(...)'?")
285
+ throw new Error(NO_RESPONSE_MIDDLEWARE)
186
286
  }
187
287
  return result
188
288
  }