ts-procedures 8.5.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (635) hide show
  1. package/README.md +166 -101
  2. package/agent_config/claude-code/.claude-plugin/plugin.json +1 -1
  3. package/agent_config/claude-code/agents/ts-procedures-architect.md +11 -10
  4. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +25 -12
  5. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +10 -12
  6. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +141 -45
  7. package/agent_config/claude-code/skills/ts-procedures/checklist.md +7 -6
  8. package/agent_config/claude-code/skills/ts-procedures/patterns.md +45 -6
  9. package/agent_config/claude-code/skills/ts-procedures/templates/client.md +1 -1
  10. package/agent_config/claude-code/skills/ts-procedures/templates/hono.md +1 -1
  11. package/agent_config/copilot/copilot-instructions.md +50 -33
  12. package/agent_config/cursor/cursorrules +50 -33
  13. package/build/adapters/astro/astro-context.js.map +1 -0
  14. package/build/adapters/astro/create-handler.js.map +1 -0
  15. package/build/adapters/astro/index.js.map +1 -0
  16. package/build/{implementations/http → adapters}/astro/index.test.js +1 -1
  17. package/build/adapters/astro/index.test.js.map +1 -0
  18. package/build/adapters/astro/rewrite-request.js.map +1 -0
  19. package/build/adapters/hono/envelope-parity.test.js +98 -0
  20. package/build/adapters/hono/envelope-parity.test.js.map +1 -0
  21. package/build/{implementations/http → adapters}/hono/handlers/http-stream.d.ts +1 -1
  22. package/build/adapters/hono/handlers/http-stream.js +55 -0
  23. package/build/adapters/hono/handlers/http-stream.js.map +1 -0
  24. package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.js +1 -1
  25. package/build/adapters/hono/handlers/http-stream.test.js.map +1 -0
  26. package/build/{implementations/http → adapters}/hono/handlers/http.d.ts +1 -1
  27. package/build/adapters/hono/handlers/http.js +50 -0
  28. package/build/adapters/hono/handlers/http.js.map +1 -0
  29. package/build/{implementations/http → adapters}/hono/handlers/http.test.js +1 -1
  30. package/build/adapters/hono/handlers/http.test.js.map +1 -0
  31. package/build/{implementations/http → adapters}/hono/handlers/rpc.d.ts +2 -2
  32. package/build/adapters/hono/handlers/rpc.js +23 -0
  33. package/build/adapters/hono/handlers/rpc.js.map +1 -0
  34. package/build/{implementations/http → adapters}/hono/handlers/rpc.test.js +1 -1
  35. package/build/adapters/hono/handlers/rpc.test.js.map +1 -0
  36. package/build/adapters/hono/handlers/stream.d.ts +12 -0
  37. package/build/adapters/hono/handlers/stream.js +89 -0
  38. package/build/adapters/hono/handlers/stream.js.map +1 -0
  39. package/build/{implementations/http → adapters}/hono/handlers/stream.test.js +3 -2
  40. package/build/adapters/hono/handlers/stream.test.js.map +1 -0
  41. package/build/{implementations/http → adapters}/hono/index.d.ts +24 -12
  42. package/build/{implementations/http → adapters}/hono/index.js +19 -8
  43. package/build/adapters/hono/index.js.map +1 -0
  44. package/build/{implementations/http → adapters}/hono/index.test.js +2 -4
  45. package/build/adapters/hono/index.test.js.map +1 -0
  46. package/build/{implementations/http → adapters/hono}/on-request-error.test.js +2 -2
  47. package/build/adapters/hono/on-request-error.test.js.map +1 -0
  48. package/build/adapters/hono/request.d.ts +7 -0
  49. package/build/adapters/hono/request.js +22 -0
  50. package/build/adapters/hono/request.js.map +1 -0
  51. package/build/{implementations/http → adapters/hono}/route-errors.test.js +4 -4
  52. package/build/adapters/hono/route-errors.test.js.map +1 -0
  53. package/build/adapters/hono/types.d.ts +55 -0
  54. package/build/adapters/hono/types.js +19 -0
  55. package/build/adapters/hono/types.js.map +1 -0
  56. package/build/client/freeze.test.js +39 -0
  57. package/build/client/freeze.test.js.map +1 -0
  58. package/build/client/typed-error-dispatch.test.js +2 -2
  59. package/build/client/typed-error-dispatch.test.js.map +1 -1
  60. package/build/codegen/__fixtures__/make-envelope.d.ts +1 -1
  61. package/build/codegen/bin/cli.d.ts +5 -0
  62. package/build/codegen/bin/cli.js +139 -182
  63. package/build/codegen/bin/cli.js.map +1 -1
  64. package/build/codegen/bin/cli.test.js +12 -2
  65. package/build/codegen/bin/cli.test.js.map +1 -1
  66. package/build/codegen/bin/flag-specs.d.ts +9 -0
  67. package/build/codegen/bin/flag-specs.js +33 -31
  68. package/build/codegen/bin/flag-specs.js.map +1 -1
  69. package/build/codegen/bin/flag-specs.test.js +14 -1
  70. package/build/codegen/bin/flag-specs.test.js.map +1 -1
  71. package/build/codegen/collect-models.d.ts +1 -1
  72. package/build/codegen/emit/api-route.d.ts +8 -0
  73. package/build/codegen/emit/api-route.js +156 -0
  74. package/build/codegen/emit/api-route.js.map +1 -0
  75. package/build/codegen/emit/context.d.ts +30 -0
  76. package/build/codegen/emit/context.js +2 -0
  77. package/build/codegen/emit/context.js.map +1 -0
  78. package/build/codegen/emit/declarations.d.ts +24 -0
  79. package/build/codegen/emit/declarations.js +48 -0
  80. package/build/codegen/emit/declarations.js.map +1 -0
  81. package/build/codegen/emit/format-types.d.ts +61 -0
  82. package/build/codegen/emit/format-types.js +188 -0
  83. package/build/codegen/emit/format-types.js.map +1 -0
  84. package/build/codegen/emit/http-stream-route.d.ts +7 -0
  85. package/build/codegen/emit/http-stream-route.js +138 -0
  86. package/build/codegen/emit/http-stream-route.js.map +1 -0
  87. package/build/codegen/emit/route-shared.d.ts +35 -0
  88. package/build/codegen/emit/route-shared.js +88 -0
  89. package/build/codegen/emit/route-shared.js.map +1 -0
  90. package/build/codegen/emit/rpc-route.d.ts +7 -0
  91. package/build/codegen/emit/rpc-route.js +37 -0
  92. package/build/codegen/emit/rpc-route.js.map +1 -0
  93. package/build/codegen/emit/scope-file.d.ts +39 -0
  94. package/build/codegen/emit/scope-file.js +166 -0
  95. package/build/codegen/emit/scope-file.js.map +1 -0
  96. package/build/codegen/emit/stream-route.d.ts +7 -0
  97. package/build/codegen/emit/stream-route.js +62 -0
  98. package/build/codegen/emit/stream-route.js.map +1 -0
  99. package/build/codegen/emit-errors.d.ts +1 -1
  100. package/build/codegen/emit-errors.integration.test.js +1 -1
  101. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  102. package/build/codegen/emit-index.js +13 -0
  103. package/build/codegen/emit-index.js.map +1 -1
  104. package/build/codegen/emit-index.test.js +25 -0
  105. package/build/codegen/emit-index.test.js.map +1 -1
  106. package/build/codegen/emit-scope.d.ts +13 -30
  107. package/build/codegen/emit-scope.js +15 -807
  108. package/build/codegen/emit-scope.js.map +1 -1
  109. package/build/codegen/emit-scope.test.js +86 -4
  110. package/build/codegen/emit-scope.test.js.map +1 -1
  111. package/build/codegen/goldens.test.js +69 -0
  112. package/build/codegen/goldens.test.js.map +1 -0
  113. package/build/codegen/group-routes.d.ts +1 -1
  114. package/build/codegen/pipeline.d.ts +1 -1
  115. package/build/codegen/resolve-envelope.d.ts +1 -1
  116. package/build/codegen/targets/_shared/error-schemas.d.ts +1 -1
  117. package/build/codegen/targets/_shared/route-slots.d.ts +1 -1
  118. package/build/codegen/targets/_shared/target-run.d.ts +1 -1
  119. package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +1 -1
  120. package/build/codegen/targets/swift/emit-route-swift.d.ts +1 -1
  121. package/build/core/create-http-stream.d.ts +50 -0
  122. package/build/core/create-http-stream.js +108 -0
  123. package/build/core/create-http-stream.js.map +1 -0
  124. package/build/{create-http-stream.test.js → core/create-http-stream.test.js} +1 -1
  125. package/build/core/create-http-stream.test.js.map +1 -0
  126. package/build/core/create-http.d.ts +51 -0
  127. package/build/core/create-http.js +65 -0
  128. package/build/core/create-http.js.map +1 -0
  129. package/build/{create-http.test.js → core/create-http.test.js} +13 -4
  130. package/build/core/create-http.test.js.map +1 -0
  131. package/build/core/create-stream.d.ts +26 -0
  132. package/build/core/create-stream.js +80 -0
  133. package/build/core/create-stream.js.map +1 -0
  134. package/build/{create-stream.test.js → core/create-stream.test.js} +23 -28
  135. package/build/core/create-stream.test.js.map +1 -0
  136. package/build/core/create.d.ts +22 -0
  137. package/build/core/create.js +71 -0
  138. package/build/core/create.js.map +1 -0
  139. package/build/{create.test.js → core/create.test.js} +25 -46
  140. package/build/core/create.test.js.map +1 -0
  141. package/build/core/definition-site.d.ts +24 -0
  142. package/build/{stack-utils.js → core/definition-site.js} +20 -20
  143. package/build/core/definition-site.js.map +1 -0
  144. package/build/{stack-utils.test.js → core/definition-site.test.js} +12 -3
  145. package/build/core/definition-site.test.js.map +1 -0
  146. package/build/{errors.d.ts → core/errors.d.ts} +19 -8
  147. package/build/{errors.js → core/errors.js} +21 -26
  148. package/build/core/errors.js.map +1 -0
  149. package/build/core/errors.test.js.map +1 -0
  150. package/build/core/factory-options.test.js +82 -0
  151. package/build/core/factory-options.test.js.map +1 -0
  152. package/build/core/http-route.d.ts +13 -0
  153. package/build/core/http-route.js +54 -0
  154. package/build/core/http-route.js.map +1 -0
  155. package/build/core/internal.d.ts +72 -0
  156. package/build/core/internal.js +128 -0
  157. package/build/core/internal.js.map +1 -0
  158. package/build/{migration.test.js → core/migration.test.js} +17 -1
  159. package/build/core/migration.test.js.map +1 -0
  160. package/build/core/procedures.d.ts +143 -0
  161. package/build/core/procedures.js +64 -0
  162. package/build/core/procedures.js.map +1 -0
  163. package/build/{index.test.js → core/procedures.test.js} +14 -11
  164. package/build/core/procedures.test.js.map +1 -0
  165. package/build/core/types.d.ts +182 -0
  166. package/build/{schema → core}/types.js.map +1 -1
  167. package/build/exports.d.ts +31 -11
  168. package/build/exports.js +23 -8
  169. package/build/exports.js.map +1 -1
  170. package/build/schema/adapter.d.ts +35 -0
  171. package/build/schema/adapter.js +13 -0
  172. package/build/schema/adapter.js.map +1 -0
  173. package/build/schema/adapter.test.js +53 -0
  174. package/build/schema/adapter.test.js.map +1 -0
  175. package/build/schema/compile.d.ts +37 -0
  176. package/build/schema/compile.js +38 -0
  177. package/build/schema/compile.js.map +1 -0
  178. package/build/schema/compile.test.js +78 -0
  179. package/build/schema/compile.test.js.map +1 -0
  180. package/build/schema/compute-schema.d.ts +47 -37
  181. package/build/schema/compute-schema.js +86 -29
  182. package/build/schema/compute-schema.js.map +1 -1
  183. package/build/schema/compute-schema.test.js +158 -40
  184. package/build/schema/compute-schema.test.js.map +1 -1
  185. package/build/schema/json-schema.d.ts +17 -0
  186. package/build/schema/json-schema.js +2 -0
  187. package/build/schema/json-schema.js.map +1 -0
  188. package/build/schema/typebox.d.ts +11 -0
  189. package/build/schema/typebox.js +24 -0
  190. package/build/schema/typebox.js.map +1 -0
  191. package/build/schema/typebox.test.js +34 -0
  192. package/build/schema/typebox.test.js.map +1 -0
  193. package/build/server/context.d.ts +8 -0
  194. package/build/server/context.js +7 -0
  195. package/build/server/context.js.map +1 -0
  196. package/build/server/context.test.js +16 -0
  197. package/build/server/context.test.js.map +1 -0
  198. package/build/{doc-envelope.d.ts → server/doc-envelope.d.ts} +1 -1
  199. package/build/server/doc-envelope.js.map +1 -0
  200. package/build/server/doc-envelope.test.d.ts +1 -0
  201. package/build/server/doc-envelope.test.js.map +1 -0
  202. package/build/{implementations/http → server}/doc-registry.d.ts +7 -2
  203. package/build/{implementations/http → server}/doc-registry.js +9 -5
  204. package/build/server/doc-registry.js.map +1 -0
  205. package/build/server/doc-registry.test.d.ts +1 -0
  206. package/build/{implementations/http → server}/doc-registry.test.js +27 -24
  207. package/build/server/doc-registry.test.js.map +1 -0
  208. package/build/server/docs/docs.test.d.ts +1 -0
  209. package/build/server/docs/docs.test.js +237 -0
  210. package/build/server/docs/docs.test.js.map +1 -0
  211. package/build/{implementations/http/hono → server}/docs/http-doc.d.ts +2 -2
  212. package/build/{implementations/http/hono → server}/docs/http-doc.js +1 -1
  213. package/build/server/docs/http-doc.js.map +1 -0
  214. package/build/{implementations/http/hono → server}/docs/http-stream-doc.d.ts +2 -2
  215. package/build/{implementations/http/hono → server}/docs/http-stream-doc.js +1 -1
  216. package/build/server/docs/http-stream-doc.js.map +1 -0
  217. package/build/{implementations/http/hono → server}/docs/rpc-doc.d.ts +2 -2
  218. package/build/{implementations/http/hono → server}/docs/rpc-doc.js +1 -1
  219. package/build/server/docs/rpc-doc.js.map +1 -0
  220. package/build/{implementations/http/hono → server}/docs/stream-doc.d.ts +2 -2
  221. package/build/{implementations/http/hono → server}/docs/stream-doc.js +1 -1
  222. package/build/server/docs/stream-doc.js.map +1 -0
  223. package/build/server/errors/dispatch.d.ts +96 -0
  224. package/build/{implementations/http/error-dispatch.js → server/errors/dispatch.js} +20 -10
  225. package/build/server/errors/dispatch.js.map +1 -0
  226. package/build/server/errors/dispatch.test.d.ts +1 -0
  227. package/build/server/errors/dispatch.test.js +418 -0
  228. package/build/server/errors/dispatch.test.js.map +1 -0
  229. package/build/{implementations/http/error-taxonomy.d.ts → server/errors/taxonomy.d.ts} +8 -17
  230. package/build/{implementations/http/error-taxonomy.js → server/errors/taxonomy.js} +6 -15
  231. package/build/server/errors/taxonomy.js.map +1 -0
  232. package/build/server/errors/taxonomy.test.d.ts +1 -0
  233. package/build/{implementations/http/error-taxonomy.test.js → server/errors/taxonomy.test.js} +45 -39
  234. package/build/server/errors/taxonomy.test.js.map +1 -0
  235. package/build/server/index.d.ts +29 -0
  236. package/build/server/index.js +27 -0
  237. package/build/server/index.js.map +1 -0
  238. package/build/server/no-framework-imports.test.d.ts +1 -0
  239. package/build/server/no-framework-imports.test.js +40 -0
  240. package/build/server/no-framework-imports.test.js.map +1 -0
  241. package/build/{implementations/http/hono/path.d.ts → server/paths.d.ts} +2 -3
  242. package/build/{implementations/http/hono/path.js → server/paths.js} +1 -1
  243. package/build/server/paths.js.map +1 -0
  244. package/build/server/paths.test.d.ts +1 -0
  245. package/build/server/paths.test.js +111 -0
  246. package/build/server/paths.test.js.map +1 -0
  247. package/build/server/request/params.d.ts +29 -0
  248. package/build/server/request/params.js +43 -0
  249. package/build/server/request/params.js.map +1 -0
  250. package/build/server/request/params.test.d.ts +1 -0
  251. package/build/server/request/params.test.js +91 -0
  252. package/build/server/request/params.test.js.map +1 -0
  253. package/build/server/request/query.d.ts +9 -0
  254. package/build/server/request/query.js +22 -0
  255. package/build/server/request/query.js.map +1 -0
  256. package/build/server/request/query.test.d.ts +1 -0
  257. package/build/server/request/query.test.js +60 -0
  258. package/build/server/request/query.test.js.map +1 -0
  259. package/build/server/sse.d.ts +70 -0
  260. package/build/server/sse.js +94 -0
  261. package/build/server/sse.js.map +1 -0
  262. package/build/server/sse.test.d.ts +1 -0
  263. package/build/server/sse.test.js +98 -0
  264. package/build/server/sse.test.js.map +1 -0
  265. package/build/{implementations → server}/types.d.ts +17 -15
  266. package/build/{implementations → server}/types.js.map +1 -1
  267. package/docs/astro-adapter.md +8 -9
  268. package/docs/client-and-codegen.md +4 -4
  269. package/docs/client-error-handling.md +92 -5
  270. package/docs/codegen-kotlin.md +2 -3
  271. package/docs/codegen-swift.md +1 -2
  272. package/docs/core.md +135 -54
  273. package/docs/http-integrations.md +83 -6
  274. package/docs/migration-v8-to-v9.md +192 -0
  275. package/docs/plans/2026-06-09-v9-rewrite.md +130 -0
  276. package/docs/specs/2026-06-09-v9-rewrite-design.md +221 -0
  277. package/docs/streaming.md +12 -0
  278. package/package.json +23 -47
  279. package/src/{implementations/http → adapters}/astro/index.test.ts +2 -2
  280. package/src/adapters/hono/__fixtures__/parity-envelope.json +389 -0
  281. package/src/adapters/hono/envelope-parity.test.ts +126 -0
  282. package/src/{implementations/http → adapters}/hono/handlers/http-stream.test.ts +1 -1
  283. package/src/adapters/hono/handlers/http-stream.ts +73 -0
  284. package/src/{implementations/http → adapters}/hono/handlers/http.test.ts +1 -1
  285. package/src/adapters/hono/handlers/http.ts +70 -0
  286. package/src/{implementations/http → adapters}/hono/handlers/rpc.test.ts +2 -2
  287. package/src/adapters/hono/handlers/rpc.ts +39 -0
  288. package/src/{implementations/http → adapters}/hono/handlers/stream.test.ts +4 -3
  289. package/src/{implementations/http → adapters}/hono/handlers/stream.ts +19 -92
  290. package/src/{implementations/http → adapters}/hono/index.test.ts +14 -16
  291. package/src/{implementations/http → adapters}/hono/index.ts +35 -30
  292. package/src/{implementations/http → adapters/hono}/on-request-error.test.ts +3 -3
  293. package/src/adapters/hono/request.ts +28 -0
  294. package/src/{implementations/http → adapters/hono}/route-errors.test.ts +5 -5
  295. package/src/{implementations/http → adapters}/hono/types.ts +43 -20
  296. package/src/client/freeze.test.ts +41 -0
  297. package/src/client/typed-error-dispatch.test.ts +3 -3
  298. package/src/codegen/__fixtures__/make-envelope.ts +1 -1
  299. package/src/codegen/__fixtures__/models-envelope.json +310 -0
  300. package/src/codegen/__fixtures__/users-envelope.json +9 -0
  301. package/src/codegen/__goldens__/MANIFEST.json +85 -0
  302. package/src/codegen/__goldens__/kotlin-default--models/Billing.kt +112 -0
  303. package/src/codegen/__goldens__/kotlin-default--models/BillingReports.kt +26 -0
  304. package/src/codegen/__goldens__/kotlin-default--models/Orders.kt +88 -0
  305. package/src/codegen/__goldens__/kotlin-default--users/Users.kt +189 -0
  306. package/src/codegen/__goldens__/swift-default--models/Billing.swift +97 -0
  307. package/src/codegen/__goldens__/swift-default--models/BillingReports.swift +20 -0
  308. package/src/codegen/__goldens__/swift-default--models/Orders.swift +81 -0
  309. package/src/codegen/__goldens__/swift-default--users/Users.swift +204 -0
  310. package/src/codegen/__goldens__/ts-default--models/_client.ts +1319 -0
  311. package/src/codegen/__goldens__/ts-default--models/_errors.ts +90 -0
  312. package/src/codegen/__goldens__/ts-default--models/_models.ts +10 -0
  313. package/src/codegen/__goldens__/ts-default--models/_types.ts +502 -0
  314. package/src/codegen/__goldens__/ts-default--models/billing-reports.ts +29 -0
  315. package/src/codegen/__goldens__/ts-default--models/billing.ts +67 -0
  316. package/src/codegen/__goldens__/ts-default--models/index.ts +48 -0
  317. package/src/codegen/__goldens__/ts-default--models/orders.ts +80 -0
  318. package/src/codegen/__goldens__/ts-default--users/_client.ts +1319 -0
  319. package/src/codegen/__goldens__/ts-default--users/_errors.ts +90 -0
  320. package/src/codegen/__goldens__/ts-default--users/_types.ts +502 -0
  321. package/src/codegen/__goldens__/ts-default--users/index.ts +38 -0
  322. package/src/codegen/__goldens__/ts-default--users/users.ts +169 -0
  323. package/src/codegen/__goldens__/ts-external-runtime--models/_errors.ts +90 -0
  324. package/src/codegen/__goldens__/ts-external-runtime--models/_models.ts +10 -0
  325. package/src/codegen/__goldens__/ts-external-runtime--models/billing-reports.ts +29 -0
  326. package/src/codegen/__goldens__/ts-external-runtime--models/billing.ts +67 -0
  327. package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +48 -0
  328. package/src/codegen/__goldens__/ts-external-runtime--models/orders.ts +80 -0
  329. package/src/codegen/__goldens__/ts-external-runtime--users/_errors.ts +90 -0
  330. package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +38 -0
  331. package/src/codegen/__goldens__/ts-external-runtime--users/users.ts +169 -0
  332. package/src/codegen/__goldens__/ts-flat--models/_client.ts +1319 -0
  333. package/src/codegen/__goldens__/ts-flat--models/_errors.ts +87 -0
  334. package/src/codegen/__goldens__/ts-flat--models/_models.ts +10 -0
  335. package/src/codegen/__goldens__/ts-flat--models/_types.ts +502 -0
  336. package/src/codegen/__goldens__/ts-flat--models/billing-reports.ts +28 -0
  337. package/src/codegen/__goldens__/ts-flat--models/billing.ts +51 -0
  338. package/src/codegen/__goldens__/ts-flat--models/index.ts +42 -0
  339. package/src/codegen/__goldens__/ts-flat--models/orders.ts +73 -0
  340. package/src/codegen/__goldens__/ts-flat--users/_client.ts +1319 -0
  341. package/src/codegen/__goldens__/ts-flat--users/_errors.ts +87 -0
  342. package/src/codegen/__goldens__/ts-flat--users/_types.ts +502 -0
  343. package/src/codegen/__goldens__/ts-flat--users/index.ts +34 -0
  344. package/src/codegen/__goldens__/ts-flat--users/users.ts +126 -0
  345. package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +1319 -0
  346. package/src/codegen/__goldens__/ts-no-share-models--models/_errors.ts +90 -0
  347. package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +502 -0
  348. package/src/codegen/__goldens__/ts-no-share-models--models/billing-reports.ts +29 -0
  349. package/src/codegen/__goldens__/ts-no-share-models--models/billing.ts +111 -0
  350. package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +48 -0
  351. package/src/codegen/__goldens__/ts-no-share-models--models/orders.ts +112 -0
  352. package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +1319 -0
  353. package/src/codegen/__goldens__/ts-no-share-models--users/_errors.ts +90 -0
  354. package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +502 -0
  355. package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +38 -0
  356. package/src/codegen/__goldens__/ts-no-share-models--users/users.ts +169 -0
  357. package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +1319 -0
  358. package/src/codegen/__goldens__/ts-shared-models-module--models/_errors.ts +90 -0
  359. package/src/codegen/__goldens__/ts-shared-models-module--models/_models.ts +7 -0
  360. package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +502 -0
  361. package/src/codegen/__goldens__/ts-shared-models-module--models/billing-reports.ts +29 -0
  362. package/src/codegen/__goldens__/ts-shared-models-module--models/billing.ts +67 -0
  363. package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +48 -0
  364. package/src/codegen/__goldens__/ts-shared-models-module--models/orders.ts +80 -0
  365. package/src/codegen/bin/cli.test.ts +13 -2
  366. package/src/codegen/bin/cli.ts +181 -144
  367. package/src/codegen/bin/flag-specs.test.ts +16 -1
  368. package/src/codegen/bin/flag-specs.ts +43 -31
  369. package/src/codegen/bundle-size.test.ts +1 -1
  370. package/src/codegen/collect-models.ts +1 -1
  371. package/src/codegen/e2e.test.ts +1 -1
  372. package/src/codegen/emit/api-route.ts +184 -0
  373. package/src/codegen/emit/context.ts +32 -0
  374. package/src/codegen/emit/declarations.ts +49 -0
  375. package/src/codegen/emit/format-types.ts +232 -0
  376. package/src/codegen/emit/http-stream-route.ts +162 -0
  377. package/src/codegen/emit/route-shared.ts +102 -0
  378. package/src/codegen/emit/rpc-route.ts +49 -0
  379. package/src/codegen/emit/scope-file.ts +226 -0
  380. package/src/codegen/emit/stream-route.ts +81 -0
  381. package/src/codegen/emit-errors.integration.test.ts +2 -2
  382. package/src/codegen/emit-errors.test.ts +1 -1
  383. package/src/codegen/emit-errors.ts +1 -1
  384. package/src/codegen/emit-index.test.ts +34 -0
  385. package/src/codegen/emit-index.ts +19 -0
  386. package/src/codegen/emit-scope.test.ts +96 -6
  387. package/src/codegen/emit-scope.ts +15 -1003
  388. package/src/codegen/goldens.test.ts +89 -0
  389. package/src/codegen/group-routes.test.ts +1 -1
  390. package/src/codegen/group-routes.ts +1 -1
  391. package/src/codegen/pipeline.test.ts +1 -1
  392. package/src/codegen/pipeline.ts +1 -1
  393. package/src/codegen/resolve-envelope.test.ts +1 -1
  394. package/src/codegen/resolve-envelope.ts +1 -1
  395. package/src/codegen/targets/_shared/error-schemas.test.ts +1 -1
  396. package/src/codegen/targets/_shared/error-schemas.ts +1 -1
  397. package/src/codegen/targets/_shared/route-slots.test.ts +1 -1
  398. package/src/codegen/targets/_shared/route-slots.ts +1 -1
  399. package/src/codegen/targets/_shared/target-run.ts +1 -1
  400. package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +6 -0
  401. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +1 -1
  402. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +1 -1
  403. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +1 -1
  404. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +6 -0
  405. package/src/codegen/targets/swift/access-level.test.ts +1 -1
  406. package/src/codegen/targets/swift/emit-route-swift.test.ts +1 -1
  407. package/src/codegen/targets/swift/emit-route-swift.ts +1 -1
  408. package/src/codegen/targets/swift/emit-scope-swift.test.ts +1 -1
  409. package/src/codegen/targets/ts/shared-models.test.ts +1 -1
  410. package/src/{create-http-stream.test.ts → core/create-http-stream.test.ts} +1 -1
  411. package/src/core/create-http-stream.ts +207 -0
  412. package/src/{create-http.test.ts → core/create-http.test.ts} +15 -4
  413. package/src/core/create-http.ts +126 -0
  414. package/src/{create-stream.test.ts → core/create-stream.test.ts} +28 -31
  415. package/src/core/create-stream.ts +142 -0
  416. package/src/{create.test.ts → core/create.test.ts} +25 -57
  417. package/src/core/create.ts +121 -0
  418. package/src/{stack-utils.test.ts → core/definition-site.test.ts} +14 -3
  419. package/src/{stack-utils.ts → core/definition-site.ts} +20 -23
  420. package/src/{errors.test.ts → core/errors.test.ts} +1 -1
  421. package/src/{errors.ts → core/errors.ts} +30 -28
  422. package/src/core/factory-options.test.ts +112 -0
  423. package/src/core/http-route.ts +73 -0
  424. package/src/core/internal.ts +203 -0
  425. package/src/{migration.test.ts → core/migration.test.ts} +23 -1
  426. package/src/{index.test.ts → core/procedures.test.ts} +13 -11
  427. package/src/core/procedures.ts +75 -0
  428. package/src/core/types.ts +195 -0
  429. package/src/exports.ts +60 -11
  430. package/src/schema/adapter.test.ts +58 -0
  431. package/src/schema/adapter.ts +45 -0
  432. package/src/schema/compile.test.ts +95 -0
  433. package/src/schema/compile.ts +64 -0
  434. package/src/schema/compute-schema.test.ts +222 -41
  435. package/src/schema/compute-schema.ts +145 -71
  436. package/src/schema/json-schema.ts +21 -0
  437. package/src/schema/typebox.test.ts +40 -0
  438. package/src/schema/typebox.ts +27 -0
  439. package/src/server/context.test.ts +22 -0
  440. package/src/server/context.ts +18 -0
  441. package/src/{doc-envelope.test.ts → server/doc-envelope.test.ts} +2 -2
  442. package/src/{doc-envelope.ts → server/doc-envelope.ts} +1 -1
  443. package/src/{implementations/http → server}/doc-registry.test.ts +32 -26
  444. package/src/{implementations/http → server}/doc-registry.ts +11 -7
  445. package/src/server/docs/docs.test.ts +287 -0
  446. package/src/{implementations/http/hono → server}/docs/http-doc.ts +3 -3
  447. package/src/{implementations/http/hono → server}/docs/http-stream-doc.ts +3 -3
  448. package/src/{implementations/http/hono → server}/docs/rpc-doc.ts +3 -3
  449. package/src/{implementations/http/hono → server}/docs/stream-doc.ts +3 -3
  450. package/src/server/errors/dispatch.test.ts +450 -0
  451. package/src/server/errors/dispatch.ts +189 -0
  452. package/src/{implementations/http/error-taxonomy.test.ts → server/errors/taxonomy.test.ts} +45 -39
  453. package/src/{implementations/http/error-taxonomy.ts → server/errors/taxonomy.ts} +8 -17
  454. package/src/server/index.ts +29 -0
  455. package/src/server/no-framework-imports.test.ts +43 -0
  456. package/src/server/paths.test.ts +141 -0
  457. package/src/{implementations/http/hono/path.ts → server/paths.ts} +2 -13
  458. package/src/server/request/params.test.ts +143 -0
  459. package/src/server/request/params.ts +68 -0
  460. package/src/server/request/query.test.ts +70 -0
  461. package/src/server/request/query.ts +24 -0
  462. package/src/server/sse.test.ts +113 -0
  463. package/src/server/sse.ts +117 -0
  464. package/src/{implementations → server}/types.ts +17 -16
  465. package/build/create-http-stream.d.ts +0 -58
  466. package/build/create-http-stream.js +0 -122
  467. package/build/create-http-stream.js.map +0 -1
  468. package/build/create-http-stream.test.js.map +0 -1
  469. package/build/create-http.d.ts +0 -49
  470. package/build/create-http.js +0 -108
  471. package/build/create-http.js.map +0 -1
  472. package/build/create-http.test.js.map +0 -1
  473. package/build/create-stream.d.ts +0 -35
  474. package/build/create-stream.js +0 -123
  475. package/build/create-stream.js.map +0 -1
  476. package/build/create-stream.test.js.map +0 -1
  477. package/build/create.d.ts +0 -28
  478. package/build/create.js +0 -82
  479. package/build/create.js.map +0 -1
  480. package/build/create.test.js.map +0 -1
  481. package/build/doc-envelope.js.map +0 -1
  482. package/build/doc-envelope.test.js.map +0 -1
  483. package/build/errors.js.map +0 -1
  484. package/build/errors.test.js.map +0 -1
  485. package/build/implementations/http/astro/astro-context.js.map +0 -1
  486. package/build/implementations/http/astro/create-handler.js.map +0 -1
  487. package/build/implementations/http/astro/index.js.map +0 -1
  488. package/build/implementations/http/astro/index.test.js.map +0 -1
  489. package/build/implementations/http/astro/rewrite-request.js.map +0 -1
  490. package/build/implementations/http/doc-registry.js.map +0 -1
  491. package/build/implementations/http/doc-registry.test.js.map +0 -1
  492. package/build/implementations/http/error-dispatch.d.ts +0 -76
  493. package/build/implementations/http/error-dispatch.js.map +0 -1
  494. package/build/implementations/http/error-dispatch.test.js +0 -254
  495. package/build/implementations/http/error-dispatch.test.js.map +0 -1
  496. package/build/implementations/http/error-taxonomy.js.map +0 -1
  497. package/build/implementations/http/error-taxonomy.test.js.map +0 -1
  498. package/build/implementations/http/hono/docs/http-doc.js.map +0 -1
  499. package/build/implementations/http/hono/docs/http-stream-doc.js.map +0 -1
  500. package/build/implementations/http/hono/docs/rpc-doc.js.map +0 -1
  501. package/build/implementations/http/hono/docs/stream-doc.js.map +0 -1
  502. package/build/implementations/http/hono/handlers/http-stream.js +0 -123
  503. package/build/implementations/http/hono/handlers/http-stream.js.map +0 -1
  504. package/build/implementations/http/hono/handlers/http-stream.test.js.map +0 -1
  505. package/build/implementations/http/hono/handlers/http.js +0 -110
  506. package/build/implementations/http/hono/handlers/http.js.map +0 -1
  507. package/build/implementations/http/hono/handlers/http.test.js.map +0 -1
  508. package/build/implementations/http/hono/handlers/rpc.js +0 -32
  509. package/build/implementations/http/hono/handlers/rpc.js.map +0 -1
  510. package/build/implementations/http/hono/handlers/rpc.test.js.map +0 -1
  511. package/build/implementations/http/hono/handlers/stream.d.ts +0 -23
  512. package/build/implementations/http/hono/handlers/stream.js +0 -147
  513. package/build/implementations/http/hono/handlers/stream.js.map +0 -1
  514. package/build/implementations/http/hono/handlers/stream.test.js.map +0 -1
  515. package/build/implementations/http/hono/index.js.map +0 -1
  516. package/build/implementations/http/hono/index.test.js.map +0 -1
  517. package/build/implementations/http/hono/path.js.map +0 -1
  518. package/build/implementations/http/hono/path.test.js +0 -83
  519. package/build/implementations/http/hono/path.test.js.map +0 -1
  520. package/build/implementations/http/hono/types.d.ts +0 -51
  521. package/build/implementations/http/hono/types.js.map +0 -1
  522. package/build/implementations/http/on-request-error.test.js.map +0 -1
  523. package/build/implementations/http/route-errors.test.js.map +0 -1
  524. package/build/index.d.ts +0 -175
  525. package/build/index.js +0 -47
  526. package/build/index.js.map +0 -1
  527. package/build/index.test.js.map +0 -1
  528. package/build/migration.test.js.map +0 -1
  529. package/build/schema/extract-json-schema.d.ts +0 -2
  530. package/build/schema/extract-json-schema.js +0 -12
  531. package/build/schema/extract-json-schema.js.map +0 -1
  532. package/build/schema/extract-json-schema.test.js +0 -23
  533. package/build/schema/extract-json-schema.test.js.map +0 -1
  534. package/build/schema/parser.d.ts +0 -36
  535. package/build/schema/parser.js +0 -210
  536. package/build/schema/parser.js.map +0 -1
  537. package/build/schema/parser.test.js +0 -120
  538. package/build/schema/parser.test.js.map +0 -1
  539. package/build/schema/resolve-schema-lib.d.ts +0 -12
  540. package/build/schema/resolve-schema-lib.js +0 -11
  541. package/build/schema/resolve-schema-lib.js.map +0 -1
  542. package/build/schema/resolve-schema-lib.test.js +0 -17
  543. package/build/schema/resolve-schema-lib.test.js.map +0 -1
  544. package/build/schema/types.d.ts +0 -8
  545. package/build/schema/types.js +0 -2
  546. package/build/stack-utils.d.ts +0 -25
  547. package/build/stack-utils.js.map +0 -1
  548. package/build/stack-utils.test.js.map +0 -1
  549. package/build/types.d.ts +0 -142
  550. package/build/types.js +0 -2
  551. package/build/types.js.map +0 -1
  552. package/docs/decisions/2026-06-02-monorepo-split-evaluation.md +0 -80
  553. package/docs/handoffs/ajsc-named-type-collision.md +0 -134
  554. package/docs/handoffs/ajsc-named-type-support.md +0 -181
  555. package/docs/handoffs/shared-models-auto-resolve-response.md +0 -181
  556. package/docs/npm-workspaces-migration-plan.md +0 -611
  557. package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +0 -886
  558. package/docs/superpowers/plans/2026-04-24-kotlin-codegen-target.md +0 -1265
  559. package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +0 -1993
  560. package/docs/superpowers/plans/2026-04-29-safe-result-api.md +0 -2293
  561. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +0 -1391
  562. package/docs/superpowers/plans/2026-05-08-create-http.md +0 -3355
  563. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +0 -3365
  564. package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +0 -1292
  565. package/docs/superpowers/plans/2026-06-06-shared-models-convention-and-diagnostics.md +0 -659
  566. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +0 -401
  567. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +0 -314
  568. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +0 -264
  569. package/docs/superpowers/specs/2026-04-29-safe-result-api-design.md +0 -324
  570. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +0 -252
  571. package/docs/superpowers/specs/2026-05-08-create-http-design.md +0 -409
  572. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +0 -411
  573. package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +0 -285
  574. package/src/create-http-stream.ts +0 -191
  575. package/src/create-http.ts +0 -210
  576. package/src/create-stream.ts +0 -228
  577. package/src/create.ts +0 -172
  578. package/src/implementations/http/README.md +0 -390
  579. package/src/implementations/http/error-dispatch.test.ts +0 -283
  580. package/src/implementations/http/error-dispatch.ts +0 -176
  581. package/src/implementations/http/hono/handlers/http-stream.ts +0 -152
  582. package/src/implementations/http/hono/handlers/http.ts +0 -145
  583. package/src/implementations/http/hono/handlers/rpc.ts +0 -54
  584. package/src/implementations/http/hono/path.test.ts +0 -96
  585. package/src/index.ts +0 -101
  586. package/src/schema/extract-json-schema.test.ts +0 -25
  587. package/src/schema/extract-json-schema.ts +0 -15
  588. package/src/schema/parser.test.ts +0 -182
  589. package/src/schema/parser.ts +0 -265
  590. package/src/schema/resolve-schema-lib.test.ts +0 -19
  591. package/src/schema/resolve-schema-lib.ts +0 -29
  592. package/src/schema/types.ts +0 -20
  593. package/src/types.ts +0 -133
  594. /package/build/{implementations/http → adapters}/astro/astro-context.d.ts +0 -0
  595. /package/build/{implementations/http → adapters}/astro/astro-context.js +0 -0
  596. /package/build/{implementations/http → adapters}/astro/create-handler.d.ts +0 -0
  597. /package/build/{implementations/http → adapters}/astro/create-handler.js +0 -0
  598. /package/build/{implementations/http → adapters}/astro/index.d.ts +0 -0
  599. /package/build/{implementations/http → adapters}/astro/index.js +0 -0
  600. /package/build/{implementations/http → adapters}/astro/index.test.d.ts +0 -0
  601. /package/build/{implementations/http → adapters}/astro/rewrite-request.d.ts +0 -0
  602. /package/build/{implementations/http → adapters}/astro/rewrite-request.js +0 -0
  603. /package/build/{create-http-stream.test.d.ts → adapters/hono/envelope-parity.test.d.ts} +0 -0
  604. /package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.d.ts +0 -0
  605. /package/build/{implementations/http → adapters}/hono/handlers/http.test.d.ts +0 -0
  606. /package/build/{implementations/http → adapters}/hono/handlers/rpc.test.d.ts +0 -0
  607. /package/build/{implementations/http → adapters}/hono/handlers/stream.test.d.ts +0 -0
  608. /package/build/{implementations/http → adapters}/hono/index.test.d.ts +0 -0
  609. /package/build/{implementations/http → adapters/hono}/on-request-error.test.d.ts +0 -0
  610. /package/build/{implementations/http → adapters/hono}/route-errors.test.d.ts +0 -0
  611. /package/build/{create-http.test.d.ts → client/freeze.test.d.ts} +0 -0
  612. /package/build/{create-stream.test.d.ts → codegen/goldens.test.d.ts} +0 -0
  613. /package/build/{create.test.d.ts → core/create-http-stream.test.d.ts} +0 -0
  614. /package/build/{doc-envelope.test.d.ts → core/create-http.test.d.ts} +0 -0
  615. /package/build/{errors.test.d.ts → core/create-stream.test.d.ts} +0 -0
  616. /package/build/{implementations/http/doc-registry.test.d.ts → core/create.test.d.ts} +0 -0
  617. /package/build/{implementations/http/error-dispatch.test.d.ts → core/definition-site.test.d.ts} +0 -0
  618. /package/build/{implementations/http/error-taxonomy.test.d.ts → core/errors.test.d.ts} +0 -0
  619. /package/build/{errors.test.js → core/errors.test.js} +0 -0
  620. /package/build/{implementations/http/hono/path.test.d.ts → core/factory-options.test.d.ts} +0 -0
  621. /package/build/{migration.test.d.ts → core/migration.test.d.ts} +0 -0
  622. /package/build/{index.test.d.ts → core/procedures.test.d.ts} +0 -0
  623. /package/build/{implementations/http/hono → core}/types.js +0 -0
  624. /package/build/schema/{extract-json-schema.test.d.ts → adapter.test.d.ts} +0 -0
  625. /package/build/schema/{parser.test.d.ts → compile.test.d.ts} +0 -0
  626. /package/build/schema/{resolve-schema-lib.test.d.ts → typebox.test.d.ts} +0 -0
  627. /package/build/{stack-utils.test.d.ts → server/context.test.d.ts} +0 -0
  628. /package/build/{doc-envelope.js → server/doc-envelope.js} +0 -0
  629. /package/build/{doc-envelope.test.js → server/doc-envelope.test.js} +0 -0
  630. /package/build/{implementations → server}/types.js +0 -0
  631. /package/src/{implementations/http → adapters}/astro/README.md +0 -0
  632. /package/src/{implementations/http → adapters}/astro/astro-context.ts +0 -0
  633. /package/src/{implementations/http → adapters}/astro/create-handler.ts +0 -0
  634. /package/src/{implementations/http → adapters}/astro/index.ts +0 -0
  635. /package/src/{implementations/http → adapters}/astro/rewrite-request.ts +0 -0
@@ -0,0 +1,91 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { BODY_METHODS, defaultSuccessStatus, extractReqChannels } from './params.js';
3
+ import { parseQueryNative } from './query.js';
4
+ function makeSource(overrides) {
5
+ return {
6
+ pathParams: () => ({ id: '42' }),
7
+ url: () => 'http://localhost/users/42?limit=10&tag=a&tag=b',
8
+ json: async () => ({ name: 'Ada' }),
9
+ headers: () => ({ 'x-api-key': 'secret' }),
10
+ ...overrides,
11
+ };
12
+ }
13
+ describe('extractReqChannels', () => {
14
+ test('extracts only the declared channels', async () => {
15
+ const params = await extractReqChannels(makeSource(), 'get', { query: {} }, parseQueryNative);
16
+ expect(Object.keys(params)).toEqual(['query']);
17
+ expect(params.query).toEqual({ limit: '10', tag: ['a', 'b'] });
18
+ });
19
+ test('extracts pathParams channel', async () => {
20
+ const params = await extractReqChannels(makeSource(), 'get', { pathParams: {} }, parseQueryNative);
21
+ expect(params).toEqual({ pathParams: { id: '42' } });
22
+ });
23
+ test('extracts headers channel (lowercased keys come from the source)', async () => {
24
+ const params = await extractReqChannels(makeSource(), 'get', { headers: {} }, parseQueryNative);
25
+ expect(params).toEqual({ headers: { 'x-api-key': 'secret' } });
26
+ });
27
+ test('extracts all four channels for a body-carrying method', async () => {
28
+ const params = await extractReqChannels(makeSource(), 'post', { pathParams: {}, query: {}, body: {}, headers: {} }, parseQueryNative);
29
+ expect(params).toEqual({
30
+ pathParams: { id: '42' },
31
+ query: { limit: '10', tag: ['a', 'b'] },
32
+ body: { name: 'Ada' },
33
+ headers: { 'x-api-key': 'secret' },
34
+ });
35
+ });
36
+ test.each(['post', 'put', 'patch'])('parses the body for %s', async (method) => {
37
+ const params = await extractReqChannels(makeSource(), method, { body: {} }, parseQueryNative);
38
+ expect(params.body).toEqual({ name: 'Ada' });
39
+ });
40
+ test.each(['get', 'head', 'delete'])('skips the body for %s (never calls source.json)', async (method) => {
41
+ let jsonCalled = false;
42
+ const source = makeSource({
43
+ json: async () => {
44
+ jsonCalled = true;
45
+ return {};
46
+ },
47
+ });
48
+ const params = await extractReqChannels(source, method, { body: {} }, parseQueryNative);
49
+ expect(jsonCalled).toBe(false);
50
+ expect('body' in params).toBe(false);
51
+ });
52
+ test('JSON parse failure yields {} so validation reports the missing fields', async () => {
53
+ const source = makeSource({
54
+ json: async () => {
55
+ throw new SyntaxError('Unexpected token');
56
+ },
57
+ });
58
+ const params = await extractReqChannels(source, 'post', { body: {} }, parseQueryNative);
59
+ expect(params.body).toEqual({});
60
+ });
61
+ test('unknown channel is set to undefined (key present, no extraction)', async () => {
62
+ const params = await extractReqChannels(makeSource(), 'get', { cookies: {} }, parseQueryNative);
63
+ expect('cookies' in params).toBe(true);
64
+ expect(params.cookies).toBeUndefined();
65
+ });
66
+ test('empty schema extracts nothing', async () => {
67
+ const params = await extractReqChannels(makeSource(), 'post', {}, parseQueryNative);
68
+ expect(params).toEqual({});
69
+ });
70
+ test('custom query parser is used for the query channel', async () => {
71
+ const params = await extractReqChannels(makeSource(), 'get', { query: {} }, (raw) => ({ raw }));
72
+ expect(params.query).toEqual({ raw: 'limit=10&tag=a&tag=b' });
73
+ });
74
+ });
75
+ describe('BODY_METHODS', () => {
76
+ test('contains exactly post, put, patch', () => {
77
+ expect(BODY_METHODS).toEqual(['post', 'put', 'patch']);
78
+ });
79
+ });
80
+ describe('defaultSuccessStatus', () => {
81
+ test('post → 201', () => {
82
+ expect(defaultSuccessStatus('post')).toBe(201);
83
+ });
84
+ test('delete → 204', () => {
85
+ expect(defaultSuccessStatus('delete')).toBe(204);
86
+ });
87
+ test.each(['get', 'put', 'patch', 'head'])('%s → 200', (method) => {
88
+ expect(defaultSuccessStatus(method)).toBe(200);
89
+ });
90
+ });
91
+ //# sourceMappingURL=params.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.test.js","sourceRoot":"","sources":["../../../src/server/request/params.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /** Parses a raw query string into a params record. */
2
+ export type QueryParser = (queryString: string) => Record<string, unknown>;
3
+ /**
4
+ * Default query parser using URLSearchParams. Multi-value keys become arrays;
5
+ * single-value keys remain scalars (matches browser-native behavior).
6
+ */
7
+ export declare function parseQueryNative(queryString: string): Record<string, unknown>;
8
+ /** Extracts and parses the query string portion of a URL (empty object when none). */
9
+ export declare function extractQuery(url: string, parser: QueryParser): Record<string, unknown>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Default query parser using URLSearchParams. Multi-value keys become arrays;
3
+ * single-value keys remain scalars (matches browser-native behavior).
4
+ */
5
+ export function parseQueryNative(queryString) {
6
+ const sp = new URLSearchParams(queryString);
7
+ const result = {};
8
+ for (const key of new Set(sp.keys())) {
9
+ const values = sp.getAll(key);
10
+ result[key] = values.length > 1 ? values : values[0];
11
+ }
12
+ return result;
13
+ }
14
+ /** Extracts and parses the query string portion of a URL (empty object when none). */
15
+ export function extractQuery(url, parser) {
16
+ const q = url.indexOf('?');
17
+ if (q === -1)
18
+ return {};
19
+ const raw = url.slice(q + 1);
20
+ return raw ? parser(raw) : {};
21
+ }
22
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../../../src/server/request/query.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,MAAM,EAAE,GAAG,IAAI,eAAe,CAAC,WAAW,CAAC,CAAA;IAC3C,MAAM,MAAM,GAA4B,EAAE,CAAA;IAC1C,KAAK,MAAM,GAAG,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC7B,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,MAAmB;IAC3D,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAC1B,IAAI,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAA;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC5B,OAAO,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AAC/B,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,60 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { extractQuery, parseQueryNative } from './query.js';
3
+ describe('parseQueryNative', () => {
4
+ test('single-value keys remain scalars', () => {
5
+ expect(parseQueryNative('a=1&b=two')).toEqual({ a: '1', b: 'two' });
6
+ });
7
+ test('multi-value keys become arrays', () => {
8
+ expect(parseQueryNative('tag=a&tag=b&tag=c')).toEqual({ tag: ['a', 'b', 'c'] });
9
+ });
10
+ test('mixes scalars and arrays', () => {
11
+ expect(parseQueryNative('limit=10&tag=a&tag=b')).toEqual({ limit: '10', tag: ['a', 'b'] });
12
+ });
13
+ test('empty string parses to an empty object', () => {
14
+ expect(parseQueryNative('')).toEqual({});
15
+ });
16
+ test('decodes URL-encoded values (URLSearchParams semantics)', () => {
17
+ expect(parseQueryNative('q=hello%20world&plus=a+b')).toEqual({
18
+ q: 'hello world',
19
+ plus: 'a b',
20
+ });
21
+ });
22
+ test('key without a value yields an empty string', () => {
23
+ expect(parseQueryNative('flag')).toEqual({ flag: '' });
24
+ });
25
+ });
26
+ describe('extractQuery', () => {
27
+ test('parses the query portion of a URL', () => {
28
+ expect(extractQuery('http://localhost/users?limit=10&tag=a', parseQueryNative)).toEqual({
29
+ limit: '10',
30
+ tag: 'a',
31
+ });
32
+ });
33
+ test('returns {} when the URL has no "?"', () => {
34
+ expect(extractQuery('http://localhost/users', parseQueryNative)).toEqual({});
35
+ });
36
+ test('returns {} for a trailing "?" with an empty query', () => {
37
+ expect(extractQuery('http://localhost/users?', parseQueryNative)).toEqual({});
38
+ });
39
+ test('custom parser receives the raw query string and its result passes through', () => {
40
+ let receivedRaw;
41
+ const custom = (raw) => {
42
+ receivedRaw = raw;
43
+ return { parsed: true };
44
+ };
45
+ const result = extractQuery('http://localhost/p?a=1&b=2', custom);
46
+ expect(receivedRaw).toBe('a=1&b=2');
47
+ expect(result).toEqual({ parsed: true });
48
+ });
49
+ test('custom parser is NOT invoked when there is no query string', () => {
50
+ let called = false;
51
+ const custom = (raw) => {
52
+ called = true;
53
+ return { raw };
54
+ };
55
+ expect(extractQuery('http://localhost/p', custom)).toEqual({});
56
+ expect(extractQuery('http://localhost/p?', custom)).toEqual({});
57
+ expect(called).toBe(false);
58
+ });
59
+ });
60
+ //# sourceMappingURL=query.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.test.js","sourceRoot":"","sources":["../../../src/server/request/query.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * SSE metadata attachment, shared by every server adapter's stream handlers.
3
+ */
4
+ export type SSEOptions = {
5
+ event?: string;
6
+ id?: string;
7
+ retry?: number;
8
+ };
9
+ /**
10
+ * Marks an object yield as an SSE event with custom metadata. Stream handlers
11
+ * read this metadata to set the SSE `event:`, `id:`, and `retry:` fields:
12
+ *
13
+ * ```ts
14
+ * yield sse({ progress: 0.5 }, { event: 'progress', id: 'p-1' })
15
+ * ```
16
+ *
17
+ * The value is returned unchanged — metadata rides in a WeakMap, never on
18
+ * the payload.
19
+ */
20
+ export declare function sse<T extends object>(data: T, options?: SSEOptions): T;
21
+ /** Reads metadata attached via {@link sse}. Undefined for plain values. */
22
+ export declare function getSSEMeta(value: unknown): SSEOptions | undefined;
23
+ /** One wire-ready SSE event, as handed to the adapter's write function. */
24
+ export type SseEvent = {
25
+ data: string;
26
+ event: string;
27
+ id: string;
28
+ retry?: number;
29
+ };
30
+ /** Adapter-provided sink (e.g. Hono's `stream.writeSSE`). */
31
+ export type SseWrite = (event: SseEvent) => void | Promise<void>;
32
+ /** Yield payloads: strings pass through, `null`/`undefined` become empty data. */
33
+ export declare function serializeSseValue(value: unknown): string;
34
+ /**
35
+ * The SSE wire protocol shared by every stream handler: auto-incrementing
36
+ * event ids, `sse()` metadata overrides, the `event: 'return'` envelope for
37
+ * the generator's return value, and the error-event shape after mid-stream
38
+ * dispatch. Adapters supply only the framework write function.
39
+ */
40
+ export declare class SseEventSequencer {
41
+ private readonly write;
42
+ /** Event name for yields without `sse()` metadata — the procedure name. */
43
+ private readonly defaultEvent;
44
+ private eventId;
45
+ constructor(write: SseWrite,
46
+ /** Event name for yields without `sse()` metadata — the procedure name. */
47
+ defaultEvent: string);
48
+ /** Writes one yielded value; `sse()` metadata overrides event/id/retry. */
49
+ writeYield(value: unknown): Promise<void>;
50
+ /**
51
+ * Writes the generator's return value as the `event: 'return'` payload
52
+ * (clients resolve it via `TypedStream.result`). Skipped for `undefined` —
53
+ * a `void` generator produces no return event.
54
+ */
55
+ writeReturn(value: unknown): Promise<void>;
56
+ /**
57
+ * Writes a dispatched mid-stream error. `sse()` metadata on the payload
58
+ * (attachable inside `onMidStreamError`) wins over the dispatcher's event.
59
+ */
60
+ writeError(dispatched: {
61
+ data: unknown;
62
+ sseEvent?: string;
63
+ }): Promise<void>;
64
+ /**
65
+ * Drives a complete stream: every yield, then the return event. Errors from
66
+ * the iterator propagate to the caller, which dispatches them and writes the
67
+ * result via {@link writeError} (the id sequence continues across the two).
68
+ */
69
+ pump(iterator: AsyncIterator<unknown, unknown>): Promise<void>;
70
+ }
@@ -0,0 +1,94 @@
1
+ const sseMetadata = new WeakMap();
2
+ /**
3
+ * Marks an object yield as an SSE event with custom metadata. Stream handlers
4
+ * read this metadata to set the SSE `event:`, `id:`, and `retry:` fields:
5
+ *
6
+ * ```ts
7
+ * yield sse({ progress: 0.5 }, { event: 'progress', id: 'p-1' })
8
+ * ```
9
+ *
10
+ * The value is returned unchanged — metadata rides in a WeakMap, never on
11
+ * the payload.
12
+ */
13
+ export function sse(data, options) {
14
+ sseMetadata.set(data, options ?? {});
15
+ return data;
16
+ }
17
+ /** Reads metadata attached via {@link sse}. Undefined for plain values. */
18
+ export function getSSEMeta(value) {
19
+ if (typeof value === 'object' && value !== null) {
20
+ return sseMetadata.get(value);
21
+ }
22
+ return undefined;
23
+ }
24
+ /** Yield payloads: strings pass through, `null`/`undefined` become empty data. */
25
+ export function serializeSseValue(value) {
26
+ if (typeof value === 'string')
27
+ return value;
28
+ return value != null ? JSON.stringify(value) : '';
29
+ }
30
+ /**
31
+ * The SSE wire protocol shared by every stream handler: auto-incrementing
32
+ * event ids, `sse()` metadata overrides, the `event: 'return'` envelope for
33
+ * the generator's return value, and the error-event shape after mid-stream
34
+ * dispatch. Adapters supply only the framework write function.
35
+ */
36
+ export class SseEventSequencer {
37
+ write;
38
+ defaultEvent;
39
+ eventId = 0;
40
+ constructor(write,
41
+ /** Event name for yields without `sse()` metadata — the procedure name. */
42
+ defaultEvent) {
43
+ this.write = write;
44
+ this.defaultEvent = defaultEvent;
45
+ }
46
+ /** Writes one yielded value; `sse()` metadata overrides event/id/retry. */
47
+ async writeYield(value) {
48
+ const meta = getSSEMeta(value);
49
+ await this.write({
50
+ data: serializeSseValue(value),
51
+ event: meta?.event ?? this.defaultEvent,
52
+ id: meta?.id ?? String(this.eventId++),
53
+ ...(meta?.retry !== undefined && { retry: meta.retry }),
54
+ });
55
+ }
56
+ /**
57
+ * Writes the generator's return value as the `event: 'return'` payload
58
+ * (clients resolve it via `TypedStream.result`). Skipped for `undefined` —
59
+ * a `void` generator produces no return event.
60
+ */
61
+ async writeReturn(value) {
62
+ if (value === undefined)
63
+ return;
64
+ const data = typeof value === 'string' ? value : JSON.stringify(value);
65
+ await this.write({ data, event: 'return', id: String(this.eventId++) });
66
+ }
67
+ /**
68
+ * Writes a dispatched mid-stream error. `sse()` metadata on the payload
69
+ * (attachable inside `onMidStreamError`) wins over the dispatcher's event.
70
+ */
71
+ async writeError(dispatched) {
72
+ const meta = getSSEMeta(dispatched.data);
73
+ await this.write({
74
+ data: serializeSseValue(dispatched.data),
75
+ event: meta?.event ?? dispatched.sseEvent ?? 'error',
76
+ id: meta?.id ?? String(this.eventId++),
77
+ ...(meta?.retry !== undefined && { retry: meta.retry }),
78
+ });
79
+ }
80
+ /**
81
+ * Drives a complete stream: every yield, then the return event. Errors from
82
+ * the iterator propagate to the caller, which dispatches them and writes the
83
+ * result via {@link writeError} (the id sequence continues across the two).
84
+ */
85
+ async pump(iterator) {
86
+ let result = await iterator.next();
87
+ while (!result.done) {
88
+ await this.writeYield(result.value);
89
+ result = await iterator.next();
90
+ }
91
+ await this.writeReturn(result.value);
92
+ }
93
+ }
94
+ //# sourceMappingURL=sse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/server/sse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,98 @@
1
+ import { describe, expect, it, test } from 'vitest';
2
+ import { SseEventSequencer, getSSEMeta, serializeSseValue, sse } from './sse.js';
3
+ describe('sse', () => {
4
+ test('returns the value unchanged (same reference)', () => {
5
+ const payload = { progress: 0.5 };
6
+ const result = sse(payload, { event: 'progress' });
7
+ expect(result).toBe(payload);
8
+ // Metadata rides in a WeakMap — never on the payload itself.
9
+ expect(Object.keys(result)).toEqual(['progress']);
10
+ });
11
+ test('getSSEMeta round-trips the attached options', () => {
12
+ const payload = sse({ progress: 0.5 }, { event: 'progress', id: 'p-1', retry: 3000 });
13
+ expect(getSSEMeta(payload)).toEqual({ event: 'progress', id: 'p-1', retry: 3000 });
14
+ });
15
+ test('defaults to {} when no options are given', () => {
16
+ const payload = sse({ done: true });
17
+ expect(getSSEMeta(payload)).toEqual({});
18
+ });
19
+ test('metadata is per-object — two payloads keep separate options', () => {
20
+ const a = sse({ n: 1 }, { event: 'a' });
21
+ const b = sse({ n: 2 }, { event: 'b' });
22
+ expect(getSSEMeta(a)).toEqual({ event: 'a' });
23
+ expect(getSSEMeta(b)).toEqual({ event: 'b' });
24
+ });
25
+ });
26
+ describe('getSSEMeta', () => {
27
+ test('returns undefined for plain (undecorated) objects', () => {
28
+ expect(getSSEMeta({ progress: 0.5 })).toBeUndefined();
29
+ });
30
+ test('returns undefined for primitives', () => {
31
+ expect(getSSEMeta('text')).toBeUndefined();
32
+ expect(getSSEMeta(42)).toBeUndefined();
33
+ expect(getSSEMeta(true)).toBeUndefined();
34
+ expect(getSSEMeta(undefined)).toBeUndefined();
35
+ });
36
+ test('returns undefined for null', () => {
37
+ expect(getSSEMeta(null)).toBeUndefined();
38
+ });
39
+ });
40
+ describe('SseEventSequencer', () => {
41
+ function collector() {
42
+ const written = [];
43
+ return { written, write: (e) => void written.push(e) };
44
+ }
45
+ async function* gen(values, ret) {
46
+ for (const v of values)
47
+ yield v;
48
+ return ret;
49
+ }
50
+ it('writes yields with the default event and auto-incrementing ids', async () => {
51
+ const { written, write } = collector();
52
+ await new SseEventSequencer(write, 'Watch').pump(gen([{ a: 1 }, { a: 2 }]));
53
+ expect(written).toEqual([
54
+ { data: '{"a":1}', event: 'Watch', id: '0' },
55
+ { data: '{"a":2}', event: 'Watch', id: '1' },
56
+ ]);
57
+ });
58
+ it('sse() metadata overrides event/id/retry on yields', async () => {
59
+ const { written, write } = collector();
60
+ const tagged = sse({ p: 1 }, { event: 'progress', id: 'p-1', retry: 5 });
61
+ await new SseEventSequencer(write, 'Watch').pump(gen([tagged, { p: 2 }]));
62
+ expect(written[0]).toEqual({ data: '{"p":1}', event: 'progress', id: 'p-1', retry: 5 });
63
+ // counter not consumed by the custom id — next auto id is still 0
64
+ expect(written[1]).toEqual({ data: '{"p":2}', event: 'Watch', id: '0' });
65
+ });
66
+ it('emits the return value as event: return and skips undefined returns', async () => {
67
+ const { written, write } = collector();
68
+ await new SseEventSequencer(write, 'W').pump(gen([1], { total: 1 }));
69
+ expect(written[1]).toEqual({ data: '{"total":1}', event: 'return', id: '1' });
70
+ const second = collector();
71
+ await new SseEventSequencer(second.write, 'W').pump(gen([1]));
72
+ expect(second.written).toHaveLength(1);
73
+ });
74
+ it('writeError continues the id sequence and honors dispatched/meta events', async () => {
75
+ const { written, write } = collector();
76
+ const seq = new SseEventSequencer(write, 'W');
77
+ await seq.writeYield('x');
78
+ await seq.writeError({ data: { error: 'boom' }, sseEvent: 'error' });
79
+ expect(written[1]).toEqual({ data: '{"error":"boom"}', event: 'error', id: '1' });
80
+ await seq.writeError({ data: sse({ msg: 'm' }, { event: 'custom-fail' }) });
81
+ expect(written[2].event).toBe('custom-fail');
82
+ });
83
+ it('serializeSseValue: strings pass through, null/undefined become empty', () => {
84
+ expect(serializeSseValue('raw')).toBe('raw');
85
+ expect(serializeSseValue(null)).toBe('');
86
+ expect(serializeSseValue(undefined)).toBe('');
87
+ expect(serializeSseValue(7)).toBe('7');
88
+ });
89
+ it('propagates iterator errors to the caller (dispatch happens outside)', async () => {
90
+ const { write } = collector();
91
+ async function* boom() {
92
+ yield 1;
93
+ throw new Error('mid');
94
+ }
95
+ await expect(new SseEventSequencer(write, 'W').pump(boom())).rejects.toThrow('mid');
96
+ });
97
+ });
98
+ //# sourceMappingURL=sse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse.test.js","sourceRoot":"","sources":["../../src/server/sse.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,UAAU,CAAA;AAEhF,QAAQ,CAAC,KAAK,EAAE,GAAG,EAAE;IACnB,IAAI,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACxD,MAAM,OAAO,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAA;QACjC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC5B,6DAA6D;QAC7D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACvD,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QACrF,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACpD,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QACnC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACvE,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QACvC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QACvC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;QAC7C,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,IAAI,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC7D,MAAM,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;IACvD,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC5C,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;QAC1C,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;QACtC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;QACxC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,IAAI,CAAC,4BAA4B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,SAAS,SAAS;QAChB,MAAM,OAAO,GAAuE,EAAE,CAAA;QACtF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAA2B,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;IAClF,CAAC;IAED,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,MAAiB,EAAE,GAAa;QAClD,KAAK,MAAM,CAAC,IAAI,MAAM;YAAE,MAAM,CAAC,CAAA;QAC/B,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;QACtC,MAAM,IAAI,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QAC3E,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YACtB,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE;YAC5C,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE;SAC7C,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QACxE,MAAM,IAAI,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;QACzE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QACvF,kEAAkE;QAClE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;QACtC,MAAM,IAAI,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QAE7E,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;QAC1B,MAAM,IAAI,iBAAiB,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7D,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;QACtC,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAC7C,MAAM,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QACzB,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;QACpE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QAEjF,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAA;QAC3E,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC/C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sEAAsE,EAAE,GAAG,EAAE;QAC9E,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC5C,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACxC,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC7C,MAAM,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,CAAA;QAC7B,KAAK,SAAS,CAAC,CAAC,IAAI;YAClB,MAAM,CAAC,CAAA;YACP,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAA;QACxB,CAAC;QACD,MAAM,MAAM,CAAC,IAAI,iBAAiB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IACrF,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1,5 +1,13 @@
1
- import type { Procedures } from '../index.js';
2
- import type { ErrorTaxonomy } from './http/error-taxonomy.js';
1
+ /**
2
+ * Transport-agnostic HTTP server types.
3
+ *
4
+ * The doc shapes here (`*RouteDoc`, `DocEnvelope`, `ErrorDoc`, `HeaderDoc`)
5
+ * are a FROZEN wire contract: they are the input to client codegen, and v9
6
+ * guarantees byte-identical generated output vs v8. Do not change field names,
7
+ * optionality, or nesting without re-validating the codegen goldens.
8
+ */
9
+ import type { ProcedureKind } from '../core/types.js';
10
+ import type { ErrorTaxonomy } from './errors/taxonomy.js';
3
11
  /**
4
12
  * @typeParam TErrorKey - Union of valid taxonomy keys. Defaults to `string`
5
13
  * (unconstrained). Narrow it by passing `keyof typeof yourTaxonomy & string`
@@ -15,10 +23,6 @@ export interface RPCConfig<TErrorKey extends string = string> {
15
23
  */
16
24
  errors?: TErrorKey[];
17
25
  }
18
- export type FactoryItem<C> = {
19
- factory: ReturnType<typeof Procedures<C, RPCConfig>>;
20
- factoryContext: (req: Request) => C;
21
- };
22
26
  export interface RPCHttpRouteDoc extends RPCConfig {
23
27
  kind: 'rpc';
24
28
  name: string;
@@ -39,7 +43,7 @@ export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head';
39
43
  * typo protection on `errors`.
40
44
  */
41
45
  export interface APIConfig<TErrorKey extends string = string> {
42
- /** HTTP route path (supports Hono path params, e.g., '/users/:id') */
46
+ /** HTTP route path (supports path params, e.g., '/users/:id') */
43
47
  path: string;
44
48
  /** HTTP method for this endpoint */
45
49
  method: HttpMethod;
@@ -78,12 +82,12 @@ export interface APIHttpRouteDoc {
78
82
  };
79
83
  }
80
84
  /**
81
- * Constrains schema.input channel names to valid HTTP input sources.
82
- * Use with `satisfies` or as a type annotation to catch typos at compile time:
85
+ * Constrains `schema.req` channel names to valid HTTP input sources.
86
+ * Use with `satisfies` to catch typos at compile time:
83
87
  *
84
88
  * @example
85
89
  * schema: {
86
- * input: {
90
+ * req: {
87
91
  * pathParams: Type.Object({ id: Type.String() }),
88
92
  * qurey: Type.Object({ ... }), // TS error: 'qurey' not in APIInput
89
93
  * } satisfies APIInput
@@ -162,8 +166,7 @@ export type ExtractConfig<TFactory> = TFactory extends {
162
166
  export type ProceduresFactory = {
163
167
  getProcedures: () => Array<{
164
168
  name: string;
165
- kind?: import('../types.js').ProcedureKind;
166
- isStream?: boolean;
169
+ kind?: ProcedureKind;
167
170
  config: any;
168
171
  handler: (ctx: any, params?: any) => Promise<any> | AsyncGenerator<any, any, unknown>;
169
172
  }>;
@@ -177,9 +180,8 @@ export interface DocSource<T = AnyHttpRouteDoc> {
177
180
  readonly docs: T[];
178
181
  /**
179
182
  * Optional list of procedures that were registered with this builder but
180
- * couldn't be served by it (e.g. a streaming procedure registered with an
181
- * RPC builder). DocRegistry aggregates these across sources and warns at
182
- * `toJSON()` time so silently-dropped procedures don't slip through.
183
+ * couldn't be served by it. DocRegistry aggregates these across sources and
184
+ * warns at `toJSON()` time so silently-dropped procedures don't slip through.
183
185
  */
184
186
  readonly skippedProcedures?: {
185
187
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/implementations/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":""}
@@ -26,7 +26,6 @@ my-astro-app/
26
26
  ```ts
27
27
  // src/server/procedures/users.ts
28
28
  import { Procedures } from 'ts-procedures'
29
- import type { APIConfig } from 'ts-procedures/http'
30
29
  import { Type } from 'typebox'
31
30
 
32
31
  type UserContext = {
@@ -34,17 +33,17 @@ type UserContext = {
34
33
  currentUser: { id: string } | null
35
34
  }
36
35
 
37
- export const usersAPI = Procedures<UserContext, APIConfig>()
36
+ export const usersAPI = Procedures<UserContext>()
38
37
 
39
- usersAPI.Create(
38
+ usersAPI.CreateHttp(
40
39
  'GetUser',
41
40
  {
42
41
  path: '/users/:id',
43
42
  method: 'get',
44
43
  scope: 'users', // drives the generated client namespace: api.users.GetUser(...)
45
44
  schema: {
46
- input: { pathParams: Type.Object({ id: Type.String() }) },
47
- returnType: Type.Object({ id: Type.String(), name: Type.String() }),
45
+ req: { pathParams: Type.Object({ id: Type.String() }) },
46
+ res: { body: Type.Object({ id: Type.String(), name: Type.String() }) },
48
47
  },
49
48
  },
50
49
  async (ctx, { pathParams }) => {
@@ -128,8 +127,7 @@ The adapter does NOT couple to `DocRegistry`. Wire codegen separately, against t
128
127
 
129
128
  ```ts
130
129
  // scripts/build-docs.ts
131
- import { writeFileSync } from 'node:fs'
132
- import { DocRegistry } from 'ts-procedures/http-docs'
130
+ import { writeDocEnvelope } from 'ts-procedures'
133
131
  import { HonoAppBuilder } from 'ts-procedures/hono'
134
132
  import { usersAPI } from '../src/server/procedures/users'
135
133
 
@@ -138,10 +136,11 @@ import { usersAPI } from '../src/server/procedures/users'
138
136
  const builder = new HonoAppBuilder().register(usersAPI, () => ({} as never))
139
137
  builder.build()
140
138
 
141
- const envelope = new DocRegistry().from(builder).toEnvelope()
142
- writeFileSync('envelope.json', JSON.stringify(envelope, null, 2))
139
+ await writeDocEnvelope(builder, 'envelope.json')
143
140
  ```
144
141
 
142
+ `writeDocEnvelope` accepts a built `HonoAppBuilder` (it calls `toDocEnvelope()` for you), a `DocRegistry`, or a plain `DocEnvelope` object, and writes pretty JSON to disk.
143
+
145
144
  ### Wire it as an npm script
146
145
 
147
146
  ```jsonc