ts-procedures 8.6.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 (627) 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-scope.d.ts +13 -30
  103. package/build/codegen/emit-scope.js +15 -844
  104. package/build/codegen/emit-scope.js.map +1 -1
  105. package/build/codegen/goldens.test.js +69 -0
  106. package/build/codegen/goldens.test.js.map +1 -0
  107. package/build/codegen/group-routes.d.ts +1 -1
  108. package/build/codegen/pipeline.d.ts +1 -1
  109. package/build/codegen/resolve-envelope.d.ts +1 -1
  110. package/build/codegen/targets/_shared/error-schemas.d.ts +1 -1
  111. package/build/codegen/targets/_shared/route-slots.d.ts +1 -1
  112. package/build/codegen/targets/_shared/target-run.d.ts +1 -1
  113. package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +1 -1
  114. package/build/codegen/targets/swift/emit-route-swift.d.ts +1 -1
  115. package/build/core/create-http-stream.d.ts +50 -0
  116. package/build/core/create-http-stream.js +108 -0
  117. package/build/core/create-http-stream.js.map +1 -0
  118. package/build/{create-http-stream.test.js → core/create-http-stream.test.js} +1 -1
  119. package/build/core/create-http-stream.test.js.map +1 -0
  120. package/build/core/create-http.d.ts +51 -0
  121. package/build/core/create-http.js +65 -0
  122. package/build/core/create-http.js.map +1 -0
  123. package/build/{create-http.test.js → core/create-http.test.js} +13 -4
  124. package/build/core/create-http.test.js.map +1 -0
  125. package/build/core/create-stream.d.ts +26 -0
  126. package/build/core/create-stream.js +80 -0
  127. package/build/core/create-stream.js.map +1 -0
  128. package/build/{create-stream.test.js → core/create-stream.test.js} +23 -28
  129. package/build/core/create-stream.test.js.map +1 -0
  130. package/build/core/create.d.ts +22 -0
  131. package/build/core/create.js +71 -0
  132. package/build/core/create.js.map +1 -0
  133. package/build/{create.test.js → core/create.test.js} +25 -46
  134. package/build/core/create.test.js.map +1 -0
  135. package/build/core/definition-site.d.ts +24 -0
  136. package/build/{stack-utils.js → core/definition-site.js} +20 -20
  137. package/build/core/definition-site.js.map +1 -0
  138. package/build/{stack-utils.test.js → core/definition-site.test.js} +12 -3
  139. package/build/core/definition-site.test.js.map +1 -0
  140. package/build/{errors.d.ts → core/errors.d.ts} +19 -8
  141. package/build/{errors.js → core/errors.js} +21 -26
  142. package/build/core/errors.js.map +1 -0
  143. package/build/core/errors.test.js.map +1 -0
  144. package/build/core/factory-options.test.js +82 -0
  145. package/build/core/factory-options.test.js.map +1 -0
  146. package/build/core/http-route.d.ts +13 -0
  147. package/build/core/http-route.js +54 -0
  148. package/build/core/http-route.js.map +1 -0
  149. package/build/core/internal.d.ts +72 -0
  150. package/build/core/internal.js +128 -0
  151. package/build/core/internal.js.map +1 -0
  152. package/build/{migration.test.js → core/migration.test.js} +17 -1
  153. package/build/core/migration.test.js.map +1 -0
  154. package/build/core/procedures.d.ts +143 -0
  155. package/build/core/procedures.js +64 -0
  156. package/build/core/procedures.js.map +1 -0
  157. package/build/{index.test.js → core/procedures.test.js} +14 -11
  158. package/build/core/procedures.test.js.map +1 -0
  159. package/build/core/types.d.ts +182 -0
  160. package/build/{schema → core}/types.js.map +1 -1
  161. package/build/exports.d.ts +31 -11
  162. package/build/exports.js +23 -8
  163. package/build/exports.js.map +1 -1
  164. package/build/schema/adapter.d.ts +35 -0
  165. package/build/schema/adapter.js +13 -0
  166. package/build/schema/adapter.js.map +1 -0
  167. package/build/schema/adapter.test.js +53 -0
  168. package/build/schema/adapter.test.js.map +1 -0
  169. package/build/schema/compile.d.ts +37 -0
  170. package/build/schema/compile.js +38 -0
  171. package/build/schema/compile.js.map +1 -0
  172. package/build/schema/compile.test.js +78 -0
  173. package/build/schema/compile.test.js.map +1 -0
  174. package/build/schema/compute-schema.d.ts +47 -37
  175. package/build/schema/compute-schema.js +86 -29
  176. package/build/schema/compute-schema.js.map +1 -1
  177. package/build/schema/compute-schema.test.js +158 -40
  178. package/build/schema/compute-schema.test.js.map +1 -1
  179. package/build/schema/json-schema.d.ts +17 -0
  180. package/build/schema/json-schema.js +2 -0
  181. package/build/schema/json-schema.js.map +1 -0
  182. package/build/schema/typebox.d.ts +11 -0
  183. package/build/schema/typebox.js +24 -0
  184. package/build/schema/typebox.js.map +1 -0
  185. package/build/schema/typebox.test.js +34 -0
  186. package/build/schema/typebox.test.js.map +1 -0
  187. package/build/server/context.d.ts +8 -0
  188. package/build/server/context.js +7 -0
  189. package/build/server/context.js.map +1 -0
  190. package/build/server/context.test.js +16 -0
  191. package/build/server/context.test.js.map +1 -0
  192. package/build/{doc-envelope.d.ts → server/doc-envelope.d.ts} +1 -1
  193. package/build/server/doc-envelope.js.map +1 -0
  194. package/build/server/doc-envelope.test.d.ts +1 -0
  195. package/build/server/doc-envelope.test.js.map +1 -0
  196. package/build/{implementations/http → server}/doc-registry.d.ts +7 -2
  197. package/build/{implementations/http → server}/doc-registry.js +9 -5
  198. package/build/server/doc-registry.js.map +1 -0
  199. package/build/server/doc-registry.test.d.ts +1 -0
  200. package/build/{implementations/http → server}/doc-registry.test.js +27 -24
  201. package/build/server/doc-registry.test.js.map +1 -0
  202. package/build/server/docs/docs.test.d.ts +1 -0
  203. package/build/server/docs/docs.test.js +237 -0
  204. package/build/server/docs/docs.test.js.map +1 -0
  205. package/build/{implementations/http/hono → server}/docs/http-doc.d.ts +2 -2
  206. package/build/{implementations/http/hono → server}/docs/http-doc.js +1 -1
  207. package/build/server/docs/http-doc.js.map +1 -0
  208. package/build/{implementations/http/hono → server}/docs/http-stream-doc.d.ts +2 -2
  209. package/build/{implementations/http/hono → server}/docs/http-stream-doc.js +1 -1
  210. package/build/server/docs/http-stream-doc.js.map +1 -0
  211. package/build/{implementations/http/hono → server}/docs/rpc-doc.d.ts +2 -2
  212. package/build/{implementations/http/hono → server}/docs/rpc-doc.js +1 -1
  213. package/build/server/docs/rpc-doc.js.map +1 -0
  214. package/build/{implementations/http/hono → server}/docs/stream-doc.d.ts +2 -2
  215. package/build/{implementations/http/hono → server}/docs/stream-doc.js +1 -1
  216. package/build/server/docs/stream-doc.js.map +1 -0
  217. package/build/server/errors/dispatch.d.ts +96 -0
  218. package/build/{implementations/http/error-dispatch.js → server/errors/dispatch.js} +20 -10
  219. package/build/server/errors/dispatch.js.map +1 -0
  220. package/build/server/errors/dispatch.test.d.ts +1 -0
  221. package/build/server/errors/dispatch.test.js +418 -0
  222. package/build/server/errors/dispatch.test.js.map +1 -0
  223. package/build/{implementations/http/error-taxonomy.d.ts → server/errors/taxonomy.d.ts} +8 -17
  224. package/build/{implementations/http/error-taxonomy.js → server/errors/taxonomy.js} +6 -15
  225. package/build/server/errors/taxonomy.js.map +1 -0
  226. package/build/server/errors/taxonomy.test.d.ts +1 -0
  227. package/build/{implementations/http/error-taxonomy.test.js → server/errors/taxonomy.test.js} +45 -39
  228. package/build/server/errors/taxonomy.test.js.map +1 -0
  229. package/build/server/index.d.ts +29 -0
  230. package/build/server/index.js +27 -0
  231. package/build/server/index.js.map +1 -0
  232. package/build/server/no-framework-imports.test.d.ts +1 -0
  233. package/build/server/no-framework-imports.test.js +40 -0
  234. package/build/server/no-framework-imports.test.js.map +1 -0
  235. package/build/{implementations/http/hono/path.d.ts → server/paths.d.ts} +2 -3
  236. package/build/{implementations/http/hono/path.js → server/paths.js} +1 -1
  237. package/build/server/paths.js.map +1 -0
  238. package/build/server/paths.test.d.ts +1 -0
  239. package/build/server/paths.test.js +111 -0
  240. package/build/server/paths.test.js.map +1 -0
  241. package/build/server/request/params.d.ts +29 -0
  242. package/build/server/request/params.js +43 -0
  243. package/build/server/request/params.js.map +1 -0
  244. package/build/server/request/params.test.d.ts +1 -0
  245. package/build/server/request/params.test.js +91 -0
  246. package/build/server/request/params.test.js.map +1 -0
  247. package/build/server/request/query.d.ts +9 -0
  248. package/build/server/request/query.js +22 -0
  249. package/build/server/request/query.js.map +1 -0
  250. package/build/server/request/query.test.d.ts +1 -0
  251. package/build/server/request/query.test.js +60 -0
  252. package/build/server/request/query.test.js.map +1 -0
  253. package/build/server/sse.d.ts +70 -0
  254. package/build/server/sse.js +94 -0
  255. package/build/server/sse.js.map +1 -0
  256. package/build/server/sse.test.d.ts +1 -0
  257. package/build/server/sse.test.js +98 -0
  258. package/build/server/sse.test.js.map +1 -0
  259. package/build/{implementations → server}/types.d.ts +17 -15
  260. package/build/{implementations → server}/types.js.map +1 -1
  261. package/docs/astro-adapter.md +8 -9
  262. package/docs/client-and-codegen.md +4 -4
  263. package/docs/client-error-handling.md +5 -5
  264. package/docs/codegen-kotlin.md +2 -3
  265. package/docs/codegen-swift.md +1 -2
  266. package/docs/core.md +135 -54
  267. package/docs/http-integrations.md +58 -6
  268. package/docs/migration-v8-to-v9.md +192 -0
  269. package/docs/plans/2026-06-09-v9-rewrite.md +130 -0
  270. package/docs/specs/2026-06-09-v9-rewrite-design.md +221 -0
  271. package/docs/streaming.md +12 -0
  272. package/package.json +23 -47
  273. package/src/{implementations/http → adapters}/astro/index.test.ts +2 -2
  274. package/src/adapters/hono/__fixtures__/parity-envelope.json +389 -0
  275. package/src/adapters/hono/envelope-parity.test.ts +126 -0
  276. package/src/{implementations/http → adapters}/hono/handlers/http-stream.test.ts +1 -1
  277. package/src/adapters/hono/handlers/http-stream.ts +73 -0
  278. package/src/{implementations/http → adapters}/hono/handlers/http.test.ts +1 -1
  279. package/src/adapters/hono/handlers/http.ts +70 -0
  280. package/src/{implementations/http → adapters}/hono/handlers/rpc.test.ts +2 -2
  281. package/src/adapters/hono/handlers/rpc.ts +39 -0
  282. package/src/{implementations/http → adapters}/hono/handlers/stream.test.ts +4 -3
  283. package/src/{implementations/http → adapters}/hono/handlers/stream.ts +19 -92
  284. package/src/{implementations/http → adapters}/hono/index.test.ts +14 -16
  285. package/src/{implementations/http → adapters}/hono/index.ts +35 -30
  286. package/src/{implementations/http → adapters/hono}/on-request-error.test.ts +3 -3
  287. package/src/adapters/hono/request.ts +28 -0
  288. package/src/{implementations/http → adapters/hono}/route-errors.test.ts +5 -5
  289. package/src/{implementations/http → adapters}/hono/types.ts +43 -20
  290. package/src/client/freeze.test.ts +41 -0
  291. package/src/client/typed-error-dispatch.test.ts +3 -3
  292. package/src/codegen/__fixtures__/make-envelope.ts +1 -1
  293. package/src/codegen/__fixtures__/models-envelope.json +310 -0
  294. package/src/codegen/__goldens__/MANIFEST.json +85 -0
  295. package/src/codegen/__goldens__/kotlin-default--models/Billing.kt +112 -0
  296. package/src/codegen/__goldens__/kotlin-default--models/BillingReports.kt +26 -0
  297. package/src/codegen/__goldens__/kotlin-default--models/Orders.kt +88 -0
  298. package/src/codegen/__goldens__/kotlin-default--users/Users.kt +189 -0
  299. package/src/codegen/__goldens__/swift-default--models/Billing.swift +97 -0
  300. package/src/codegen/__goldens__/swift-default--models/BillingReports.swift +20 -0
  301. package/src/codegen/__goldens__/swift-default--models/Orders.swift +81 -0
  302. package/src/codegen/__goldens__/swift-default--users/Users.swift +204 -0
  303. package/src/codegen/__goldens__/ts-default--models/_client.ts +1319 -0
  304. package/src/codegen/__goldens__/ts-default--models/_errors.ts +90 -0
  305. package/src/codegen/__goldens__/ts-default--models/_models.ts +10 -0
  306. package/src/codegen/__goldens__/ts-default--models/_types.ts +502 -0
  307. package/src/codegen/__goldens__/ts-default--models/billing-reports.ts +29 -0
  308. package/src/codegen/__goldens__/ts-default--models/billing.ts +67 -0
  309. package/src/codegen/__goldens__/ts-default--models/index.ts +48 -0
  310. package/src/codegen/__goldens__/ts-default--models/orders.ts +80 -0
  311. package/src/codegen/__goldens__/ts-default--users/_client.ts +1319 -0
  312. package/src/codegen/__goldens__/ts-default--users/_errors.ts +90 -0
  313. package/src/codegen/__goldens__/ts-default--users/_types.ts +502 -0
  314. package/src/codegen/__goldens__/ts-default--users/index.ts +38 -0
  315. package/src/codegen/__goldens__/ts-default--users/users.ts +169 -0
  316. package/src/codegen/__goldens__/ts-external-runtime--models/_errors.ts +90 -0
  317. package/src/codegen/__goldens__/ts-external-runtime--models/_models.ts +10 -0
  318. package/src/codegen/__goldens__/ts-external-runtime--models/billing-reports.ts +29 -0
  319. package/src/codegen/__goldens__/ts-external-runtime--models/billing.ts +67 -0
  320. package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +48 -0
  321. package/src/codegen/__goldens__/ts-external-runtime--models/orders.ts +80 -0
  322. package/src/codegen/__goldens__/ts-external-runtime--users/_errors.ts +90 -0
  323. package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +38 -0
  324. package/src/codegen/__goldens__/ts-external-runtime--users/users.ts +169 -0
  325. package/src/codegen/__goldens__/ts-flat--models/_client.ts +1319 -0
  326. package/src/codegen/__goldens__/ts-flat--models/_errors.ts +87 -0
  327. package/src/codegen/__goldens__/ts-flat--models/_models.ts +10 -0
  328. package/src/codegen/__goldens__/ts-flat--models/_types.ts +502 -0
  329. package/src/codegen/__goldens__/ts-flat--models/billing-reports.ts +28 -0
  330. package/src/codegen/__goldens__/ts-flat--models/billing.ts +51 -0
  331. package/src/codegen/__goldens__/ts-flat--models/index.ts +42 -0
  332. package/src/codegen/__goldens__/ts-flat--models/orders.ts +73 -0
  333. package/src/codegen/__goldens__/ts-flat--users/_client.ts +1319 -0
  334. package/src/codegen/__goldens__/ts-flat--users/_errors.ts +87 -0
  335. package/src/codegen/__goldens__/ts-flat--users/_types.ts +502 -0
  336. package/src/codegen/__goldens__/ts-flat--users/index.ts +34 -0
  337. package/src/codegen/__goldens__/ts-flat--users/users.ts +126 -0
  338. package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +1319 -0
  339. package/src/codegen/__goldens__/ts-no-share-models--models/_errors.ts +90 -0
  340. package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +502 -0
  341. package/src/codegen/__goldens__/ts-no-share-models--models/billing-reports.ts +29 -0
  342. package/src/codegen/__goldens__/ts-no-share-models--models/billing.ts +111 -0
  343. package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +48 -0
  344. package/src/codegen/__goldens__/ts-no-share-models--models/orders.ts +112 -0
  345. package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +1319 -0
  346. package/src/codegen/__goldens__/ts-no-share-models--users/_errors.ts +90 -0
  347. package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +502 -0
  348. package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +38 -0
  349. package/src/codegen/__goldens__/ts-no-share-models--users/users.ts +169 -0
  350. package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +1319 -0
  351. package/src/codegen/__goldens__/ts-shared-models-module--models/_errors.ts +90 -0
  352. package/src/codegen/__goldens__/ts-shared-models-module--models/_models.ts +7 -0
  353. package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +502 -0
  354. package/src/codegen/__goldens__/ts-shared-models-module--models/billing-reports.ts +29 -0
  355. package/src/codegen/__goldens__/ts-shared-models-module--models/billing.ts +67 -0
  356. package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +48 -0
  357. package/src/codegen/__goldens__/ts-shared-models-module--models/orders.ts +80 -0
  358. package/src/codegen/bin/cli.test.ts +13 -2
  359. package/src/codegen/bin/cli.ts +181 -144
  360. package/src/codegen/bin/flag-specs.test.ts +16 -1
  361. package/src/codegen/bin/flag-specs.ts +43 -31
  362. package/src/codegen/bundle-size.test.ts +1 -1
  363. package/src/codegen/collect-models.ts +1 -1
  364. package/src/codegen/e2e.test.ts +1 -1
  365. package/src/codegen/emit/api-route.ts +184 -0
  366. package/src/codegen/emit/context.ts +32 -0
  367. package/src/codegen/emit/declarations.ts +49 -0
  368. package/src/codegen/emit/format-types.ts +232 -0
  369. package/src/codegen/emit/http-stream-route.ts +162 -0
  370. package/src/codegen/emit/route-shared.ts +102 -0
  371. package/src/codegen/emit/rpc-route.ts +49 -0
  372. package/src/codegen/emit/scope-file.ts +226 -0
  373. package/src/codegen/emit/stream-route.ts +81 -0
  374. package/src/codegen/emit-errors.integration.test.ts +2 -2
  375. package/src/codegen/emit-errors.test.ts +1 -1
  376. package/src/codegen/emit-errors.ts +1 -1
  377. package/src/codegen/emit-scope.test.ts +2 -2
  378. package/src/codegen/emit-scope.ts +15 -1048
  379. package/src/codegen/goldens.test.ts +89 -0
  380. package/src/codegen/group-routes.test.ts +1 -1
  381. package/src/codegen/group-routes.ts +1 -1
  382. package/src/codegen/pipeline.test.ts +1 -1
  383. package/src/codegen/pipeline.ts +1 -1
  384. package/src/codegen/resolve-envelope.test.ts +1 -1
  385. package/src/codegen/resolve-envelope.ts +1 -1
  386. package/src/codegen/targets/_shared/error-schemas.test.ts +1 -1
  387. package/src/codegen/targets/_shared/error-schemas.ts +1 -1
  388. package/src/codegen/targets/_shared/route-slots.test.ts +1 -1
  389. package/src/codegen/targets/_shared/route-slots.ts +1 -1
  390. package/src/codegen/targets/_shared/target-run.ts +1 -1
  391. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +1 -1
  392. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +1 -1
  393. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +1 -1
  394. package/src/codegen/targets/swift/access-level.test.ts +1 -1
  395. package/src/codegen/targets/swift/emit-route-swift.test.ts +1 -1
  396. package/src/codegen/targets/swift/emit-route-swift.ts +1 -1
  397. package/src/codegen/targets/swift/emit-scope-swift.test.ts +1 -1
  398. package/src/codegen/targets/ts/shared-models.test.ts +1 -1
  399. package/src/{create-http-stream.test.ts → core/create-http-stream.test.ts} +1 -1
  400. package/src/core/create-http-stream.ts +207 -0
  401. package/src/{create-http.test.ts → core/create-http.test.ts} +15 -4
  402. package/src/core/create-http.ts +126 -0
  403. package/src/{create-stream.test.ts → core/create-stream.test.ts} +28 -31
  404. package/src/core/create-stream.ts +142 -0
  405. package/src/{create.test.ts → core/create.test.ts} +25 -57
  406. package/src/core/create.ts +121 -0
  407. package/src/{stack-utils.test.ts → core/definition-site.test.ts} +14 -3
  408. package/src/{stack-utils.ts → core/definition-site.ts} +20 -23
  409. package/src/{errors.test.ts → core/errors.test.ts} +1 -1
  410. package/src/{errors.ts → core/errors.ts} +30 -28
  411. package/src/core/factory-options.test.ts +112 -0
  412. package/src/core/http-route.ts +73 -0
  413. package/src/core/internal.ts +203 -0
  414. package/src/{migration.test.ts → core/migration.test.ts} +23 -1
  415. package/src/{index.test.ts → core/procedures.test.ts} +13 -11
  416. package/src/core/procedures.ts +75 -0
  417. package/src/core/types.ts +195 -0
  418. package/src/exports.ts +60 -11
  419. package/src/schema/adapter.test.ts +58 -0
  420. package/src/schema/adapter.ts +45 -0
  421. package/src/schema/compile.test.ts +95 -0
  422. package/src/schema/compile.ts +64 -0
  423. package/src/schema/compute-schema.test.ts +222 -41
  424. package/src/schema/compute-schema.ts +145 -71
  425. package/src/schema/json-schema.ts +21 -0
  426. package/src/schema/typebox.test.ts +40 -0
  427. package/src/schema/typebox.ts +27 -0
  428. package/src/server/context.test.ts +22 -0
  429. package/src/server/context.ts +18 -0
  430. package/src/{doc-envelope.test.ts → server/doc-envelope.test.ts} +2 -2
  431. package/src/{doc-envelope.ts → server/doc-envelope.ts} +1 -1
  432. package/src/{implementations/http → server}/doc-registry.test.ts +32 -26
  433. package/src/{implementations/http → server}/doc-registry.ts +11 -7
  434. package/src/server/docs/docs.test.ts +287 -0
  435. package/src/{implementations/http/hono → server}/docs/http-doc.ts +3 -3
  436. package/src/{implementations/http/hono → server}/docs/http-stream-doc.ts +3 -3
  437. package/src/{implementations/http/hono → server}/docs/rpc-doc.ts +3 -3
  438. package/src/{implementations/http/hono → server}/docs/stream-doc.ts +3 -3
  439. package/src/server/errors/dispatch.test.ts +450 -0
  440. package/src/server/errors/dispatch.ts +189 -0
  441. package/src/{implementations/http/error-taxonomy.test.ts → server/errors/taxonomy.test.ts} +45 -39
  442. package/src/{implementations/http/error-taxonomy.ts → server/errors/taxonomy.ts} +8 -17
  443. package/src/server/index.ts +29 -0
  444. package/src/server/no-framework-imports.test.ts +43 -0
  445. package/src/server/paths.test.ts +141 -0
  446. package/src/{implementations/http/hono/path.ts → server/paths.ts} +2 -13
  447. package/src/server/request/params.test.ts +143 -0
  448. package/src/server/request/params.ts +68 -0
  449. package/src/server/request/query.test.ts +70 -0
  450. package/src/server/request/query.ts +24 -0
  451. package/src/server/sse.test.ts +113 -0
  452. package/src/server/sse.ts +117 -0
  453. package/src/{implementations → server}/types.ts +17 -16
  454. package/build/create-http-stream.d.ts +0 -58
  455. package/build/create-http-stream.js +0 -122
  456. package/build/create-http-stream.js.map +0 -1
  457. package/build/create-http-stream.test.js.map +0 -1
  458. package/build/create-http.d.ts +0 -49
  459. package/build/create-http.js +0 -108
  460. package/build/create-http.js.map +0 -1
  461. package/build/create-http.test.js.map +0 -1
  462. package/build/create-stream.d.ts +0 -35
  463. package/build/create-stream.js +0 -123
  464. package/build/create-stream.js.map +0 -1
  465. package/build/create-stream.test.js.map +0 -1
  466. package/build/create.d.ts +0 -28
  467. package/build/create.js +0 -82
  468. package/build/create.js.map +0 -1
  469. package/build/create.test.js.map +0 -1
  470. package/build/doc-envelope.js.map +0 -1
  471. package/build/doc-envelope.test.js.map +0 -1
  472. package/build/errors.js.map +0 -1
  473. package/build/errors.test.js.map +0 -1
  474. package/build/implementations/http/astro/astro-context.js.map +0 -1
  475. package/build/implementations/http/astro/create-handler.js.map +0 -1
  476. package/build/implementations/http/astro/index.js.map +0 -1
  477. package/build/implementations/http/astro/index.test.js.map +0 -1
  478. package/build/implementations/http/astro/rewrite-request.js.map +0 -1
  479. package/build/implementations/http/doc-registry.js.map +0 -1
  480. package/build/implementations/http/doc-registry.test.js.map +0 -1
  481. package/build/implementations/http/error-dispatch.d.ts +0 -76
  482. package/build/implementations/http/error-dispatch.js.map +0 -1
  483. package/build/implementations/http/error-dispatch.test.js +0 -254
  484. package/build/implementations/http/error-dispatch.test.js.map +0 -1
  485. package/build/implementations/http/error-taxonomy.js.map +0 -1
  486. package/build/implementations/http/error-taxonomy.test.js.map +0 -1
  487. package/build/implementations/http/hono/docs/http-doc.js.map +0 -1
  488. package/build/implementations/http/hono/docs/http-stream-doc.js.map +0 -1
  489. package/build/implementations/http/hono/docs/rpc-doc.js.map +0 -1
  490. package/build/implementations/http/hono/docs/stream-doc.js.map +0 -1
  491. package/build/implementations/http/hono/handlers/http-stream.js +0 -123
  492. package/build/implementations/http/hono/handlers/http-stream.js.map +0 -1
  493. package/build/implementations/http/hono/handlers/http-stream.test.js.map +0 -1
  494. package/build/implementations/http/hono/handlers/http.js +0 -110
  495. package/build/implementations/http/hono/handlers/http.js.map +0 -1
  496. package/build/implementations/http/hono/handlers/http.test.js.map +0 -1
  497. package/build/implementations/http/hono/handlers/rpc.js +0 -32
  498. package/build/implementations/http/hono/handlers/rpc.js.map +0 -1
  499. package/build/implementations/http/hono/handlers/rpc.test.js.map +0 -1
  500. package/build/implementations/http/hono/handlers/stream.d.ts +0 -23
  501. package/build/implementations/http/hono/handlers/stream.js +0 -147
  502. package/build/implementations/http/hono/handlers/stream.js.map +0 -1
  503. package/build/implementations/http/hono/handlers/stream.test.js.map +0 -1
  504. package/build/implementations/http/hono/index.js.map +0 -1
  505. package/build/implementations/http/hono/index.test.js.map +0 -1
  506. package/build/implementations/http/hono/path.js.map +0 -1
  507. package/build/implementations/http/hono/path.test.js +0 -83
  508. package/build/implementations/http/hono/path.test.js.map +0 -1
  509. package/build/implementations/http/hono/types.d.ts +0 -51
  510. package/build/implementations/http/hono/types.js.map +0 -1
  511. package/build/implementations/http/on-request-error.test.js.map +0 -1
  512. package/build/implementations/http/route-errors.test.js.map +0 -1
  513. package/build/index.d.ts +0 -175
  514. package/build/index.js +0 -47
  515. package/build/index.js.map +0 -1
  516. package/build/index.test.js.map +0 -1
  517. package/build/migration.test.js.map +0 -1
  518. package/build/schema/extract-json-schema.d.ts +0 -2
  519. package/build/schema/extract-json-schema.js +0 -12
  520. package/build/schema/extract-json-schema.js.map +0 -1
  521. package/build/schema/extract-json-schema.test.js +0 -23
  522. package/build/schema/extract-json-schema.test.js.map +0 -1
  523. package/build/schema/parser.d.ts +0 -36
  524. package/build/schema/parser.js +0 -210
  525. package/build/schema/parser.js.map +0 -1
  526. package/build/schema/parser.test.js +0 -120
  527. package/build/schema/parser.test.js.map +0 -1
  528. package/build/schema/resolve-schema-lib.d.ts +0 -12
  529. package/build/schema/resolve-schema-lib.js +0 -11
  530. package/build/schema/resolve-schema-lib.js.map +0 -1
  531. package/build/schema/resolve-schema-lib.test.js +0 -17
  532. package/build/schema/resolve-schema-lib.test.js.map +0 -1
  533. package/build/schema/types.d.ts +0 -8
  534. package/build/schema/types.js +0 -2
  535. package/build/stack-utils.d.ts +0 -25
  536. package/build/stack-utils.js.map +0 -1
  537. package/build/stack-utils.test.js.map +0 -1
  538. package/build/types.d.ts +0 -142
  539. package/build/types.js +0 -2
  540. package/build/types.js.map +0 -1
  541. package/docs/decisions/2026-06-02-monorepo-split-evaluation.md +0 -80
  542. package/docs/handoffs/2026-06-08-dx-round2-declines.md +0 -45
  543. package/docs/handoffs/ajsc-named-type-collision.md +0 -134
  544. package/docs/handoffs/ajsc-named-type-support.md +0 -181
  545. package/docs/handoffs/shared-models-auto-resolve-response.md +0 -181
  546. package/docs/npm-workspaces-migration-plan.md +0 -611
  547. package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +0 -886
  548. package/docs/superpowers/plans/2026-04-24-kotlin-codegen-target.md +0 -1265
  549. package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +0 -1993
  550. package/docs/superpowers/plans/2026-04-29-safe-result-api.md +0 -2293
  551. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +0 -1391
  552. package/docs/superpowers/plans/2026-05-08-create-http.md +0 -3355
  553. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +0 -3365
  554. package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +0 -1292
  555. package/docs/superpowers/plans/2026-06-06-shared-models-convention-and-diagnostics.md +0 -659
  556. package/docs/superpowers/plans/2026-06-08-codegen-dx-surfacing.md +0 -428
  557. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +0 -401
  558. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +0 -314
  559. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +0 -264
  560. package/docs/superpowers/specs/2026-04-29-safe-result-api-design.md +0 -324
  561. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +0 -252
  562. package/docs/superpowers/specs/2026-05-08-create-http-design.md +0 -409
  563. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +0 -411
  564. package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +0 -285
  565. package/docs/superpowers/specs/2026-06-08-dx-feedback-round-2-design.md +0 -376
  566. package/src/create-http-stream.ts +0 -191
  567. package/src/create-http.ts +0 -210
  568. package/src/create-stream.ts +0 -228
  569. package/src/create.ts +0 -172
  570. package/src/implementations/http/README.md +0 -390
  571. package/src/implementations/http/error-dispatch.test.ts +0 -283
  572. package/src/implementations/http/error-dispatch.ts +0 -176
  573. package/src/implementations/http/hono/handlers/http-stream.ts +0 -152
  574. package/src/implementations/http/hono/handlers/http.ts +0 -145
  575. package/src/implementations/http/hono/handlers/rpc.ts +0 -54
  576. package/src/implementations/http/hono/path.test.ts +0 -96
  577. package/src/index.ts +0 -101
  578. package/src/schema/extract-json-schema.test.ts +0 -25
  579. package/src/schema/extract-json-schema.ts +0 -15
  580. package/src/schema/parser.test.ts +0 -182
  581. package/src/schema/parser.ts +0 -265
  582. package/src/schema/resolve-schema-lib.test.ts +0 -19
  583. package/src/schema/resolve-schema-lib.ts +0 -29
  584. package/src/schema/types.ts +0 -20
  585. package/src/types.ts +0 -133
  586. /package/build/{implementations/http → adapters}/astro/astro-context.d.ts +0 -0
  587. /package/build/{implementations/http → adapters}/astro/astro-context.js +0 -0
  588. /package/build/{implementations/http → adapters}/astro/create-handler.d.ts +0 -0
  589. /package/build/{implementations/http → adapters}/astro/create-handler.js +0 -0
  590. /package/build/{implementations/http → adapters}/astro/index.d.ts +0 -0
  591. /package/build/{implementations/http → adapters}/astro/index.js +0 -0
  592. /package/build/{implementations/http → adapters}/astro/index.test.d.ts +0 -0
  593. /package/build/{implementations/http → adapters}/astro/rewrite-request.d.ts +0 -0
  594. /package/build/{implementations/http → adapters}/astro/rewrite-request.js +0 -0
  595. /package/build/{create-http-stream.test.d.ts → adapters/hono/envelope-parity.test.d.ts} +0 -0
  596. /package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.d.ts +0 -0
  597. /package/build/{implementations/http → adapters}/hono/handlers/http.test.d.ts +0 -0
  598. /package/build/{implementations/http → adapters}/hono/handlers/rpc.test.d.ts +0 -0
  599. /package/build/{implementations/http → adapters}/hono/handlers/stream.test.d.ts +0 -0
  600. /package/build/{implementations/http → adapters}/hono/index.test.d.ts +0 -0
  601. /package/build/{implementations/http → adapters/hono}/on-request-error.test.d.ts +0 -0
  602. /package/build/{implementations/http → adapters/hono}/route-errors.test.d.ts +0 -0
  603. /package/build/{create-http.test.d.ts → client/freeze.test.d.ts} +0 -0
  604. /package/build/{create-stream.test.d.ts → codegen/goldens.test.d.ts} +0 -0
  605. /package/build/{create.test.d.ts → core/create-http-stream.test.d.ts} +0 -0
  606. /package/build/{doc-envelope.test.d.ts → core/create-http.test.d.ts} +0 -0
  607. /package/build/{errors.test.d.ts → core/create-stream.test.d.ts} +0 -0
  608. /package/build/{implementations/http/doc-registry.test.d.ts → core/create.test.d.ts} +0 -0
  609. /package/build/{implementations/http/error-dispatch.test.d.ts → core/definition-site.test.d.ts} +0 -0
  610. /package/build/{implementations/http/error-taxonomy.test.d.ts → core/errors.test.d.ts} +0 -0
  611. /package/build/{errors.test.js → core/errors.test.js} +0 -0
  612. /package/build/{implementations/http/hono/path.test.d.ts → core/factory-options.test.d.ts} +0 -0
  613. /package/build/{migration.test.d.ts → core/migration.test.d.ts} +0 -0
  614. /package/build/{index.test.d.ts → core/procedures.test.d.ts} +0 -0
  615. /package/build/{implementations/http/hono → core}/types.js +0 -0
  616. /package/build/schema/{extract-json-schema.test.d.ts → adapter.test.d.ts} +0 -0
  617. /package/build/schema/{parser.test.d.ts → compile.test.d.ts} +0 -0
  618. /package/build/schema/{resolve-schema-lib.test.d.ts → typebox.test.d.ts} +0 -0
  619. /package/build/{stack-utils.test.d.ts → server/context.test.d.ts} +0 -0
  620. /package/build/{doc-envelope.js → server/doc-envelope.js} +0 -0
  621. /package/build/{doc-envelope.test.js → server/doc-envelope.test.js} +0 -0
  622. /package/build/{implementations → server}/types.js +0 -0
  623. /package/src/{implementations/http → adapters}/astro/README.md +0 -0
  624. /package/src/{implementations/http → adapters}/astro/astro-context.ts +0 -0
  625. /package/src/{implementations/http → adapters}/astro/create-handler.ts +0 -0
  626. /package/src/{implementations/http → adapters}/astro/index.ts +0 -0
  627. /package/src/{implementations/http → adapters}/astro/rewrite-request.ts +0 -0
@@ -1,283 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest'
2
- import { Hono } from 'hono'
3
- import { dispatchMidStreamError, dispatchPreStreamError } from './error-dispatch.js'
4
- import { defineErrorTaxonomy } from './error-taxonomy.js'
5
- import { ProcedureValidationError } from '../../errors.js'
6
-
7
- function makeContext() {
8
- return new Promise<import('hono').Context>((resolve) => {
9
- const app = new Hono()
10
- app.get('/', (c) => {
11
- resolve(c)
12
- return c.text('ok')
13
- })
14
- app.request('/')
15
- })
16
- }
17
-
18
- const dummyProcedure = {
19
- name: 'Test',
20
- kind: 'rpc',
21
- config: { scope: 'test', version: 1 },
22
- handler: async () => undefined,
23
- } as any
24
-
25
- describe('dispatchPreStreamError', () => {
26
- test('default taxonomy: ProcedureValidationError → 400', async () => {
27
- const c = await makeContext()
28
- const err = new ProcedureValidationError('Test', 'Validation error for Test', [
29
- { instancePath: '/x', message: 'expected number' } as any,
30
- ])
31
-
32
- const res = await dispatchPreStreamError({
33
- err,
34
- procedure: dummyProcedure,
35
- raw: c,
36
- cfg: {},
37
- })
38
-
39
- expect(res.status).toBe(400)
40
- const body = await res.json()
41
- expect(body.name).toBe('ProcedureValidationError')
42
- expect(body.procedureName).toBe('Test')
43
- })
44
-
45
- test('user taxonomy entry takes precedence', async () => {
46
- const c = await makeContext()
47
- class MyError extends Error {
48
- constructor(public reason: string) { super(reason) }
49
- }
50
- const errors = defineErrorTaxonomy({
51
- MyError: { class: MyError, statusCode: 422, toResponse: (e) => ({ name: 'MyError', reason: e.reason }) },
52
- })
53
-
54
- const res = await dispatchPreStreamError({
55
- err: new MyError('boom'),
56
- procedure: dummyProcedure,
57
- raw: c,
58
- cfg: { errors },
59
- })
60
-
61
- expect(res.status).toBe(422)
62
- expect(await res.json()).toEqual({ name: 'MyError', reason: 'boom' })
63
- })
64
-
65
- test('falls back to onError imperative callback', async () => {
66
- const c = await makeContext()
67
- const onError = vi.fn().mockResolvedValue(c.json({ ok: false }, 503))
68
-
69
- const res = await dispatchPreStreamError({
70
- err: new Error('unmatched'),
71
- procedure: dummyProcedure,
72
- raw: c,
73
- cfg: { onError: (proc, raw, e) => onError(proc, raw, e) },
74
- })
75
-
76
- expect(onError).toHaveBeenCalled()
77
- expect(res.status).toBe(503)
78
- })
79
-
80
- test('hard default 500 when nothing matches', async () => {
81
- const c = await makeContext()
82
- const res = await dispatchPreStreamError({
83
- err: new Error('boom'),
84
- procedure: dummyProcedure,
85
- raw: c,
86
- cfg: {},
87
- })
88
- expect(res.status).toBe(500)
89
- expect(await res.json()).toEqual({ error: 'boom' })
90
- })
91
-
92
- test('onRequestError observer fires before dispatch and is awaited', async () => {
93
- const c = await makeContext()
94
- const calls: string[] = []
95
- const onRequestError = vi.fn(async () => {
96
- calls.push('observer')
97
- })
98
- const errors = defineErrorTaxonomy({
99
- AnyError: {
100
- match: (e): e is Error => e instanceof Error,
101
- statusCode: 500,
102
- toResponse: () => {
103
- calls.push('toResponse')
104
- return { name: 'AnyError' }
105
- },
106
- },
107
- })
108
-
109
- await dispatchPreStreamError({
110
- err: new Error('x'),
111
- procedure: dummyProcedure,
112
- raw: c,
113
- cfg: { errors, onRequestError },
114
- })
115
-
116
- expect(calls).toEqual(['observer', 'toResponse'])
117
- expect(onRequestError).toHaveBeenCalledWith({ err: expect.any(Error), procedure: dummyProcedure, raw: c })
118
- })
119
-
120
- test('observer throw is swallowed and logged', async () => {
121
- const c = await makeContext()
122
- const consoleErr = vi.spyOn(console, 'error').mockImplementation(() => {})
123
- const onRequestError = vi.fn(() => { throw new Error('observer broke') })
124
-
125
- const res = await dispatchPreStreamError({
126
- err: new Error('x'),
127
- procedure: dummyProcedure,
128
- raw: c,
129
- cfg: { onRequestError },
130
- })
131
-
132
- expect(res.status).toBe(500)
133
- expect(consoleErr).toHaveBeenCalled()
134
- consoleErr.mockRestore()
135
- })
136
-
137
- test('taxonomy onCatch is fully awaited before the response body is written', async () => {
138
- const c = await makeContext()
139
- const calls: string[] = []
140
- class HookedError extends Error {}
141
- const errors = defineErrorTaxonomy({
142
- HookedError: {
143
- class: HookedError,
144
- statusCode: 500,
145
- toResponse: () => ({ name: 'HookedError' }),
146
- onCatch: async () => {
147
- // Awaiting an async setTimeout here means a non-awaiting dispatcher
148
- // would write the response BEFORE this push runs. The order we capture
149
- // in `calls` reveals which branch happened.
150
- await new Promise<void>((resolve) => setTimeout(resolve, 5))
151
- calls.push('oncatch-done')
152
- },
153
- },
154
- })
155
-
156
- // Spy on c.json: when the dispatcher writes the response, record where in
157
- // the timeline it happened relative to onCatch's push.
158
- const originalJson = c.json.bind(c) as (...args: any[]) => Response
159
- const jsonSpy = vi.fn((...args: any[]) => {
160
- calls.push('response-write')
161
- return originalJson(...args)
162
- })
163
- ;(c as any).json = jsonSpy
164
-
165
- const res = await dispatchPreStreamError({
166
- err: new HookedError('boom'),
167
- procedure: dummyProcedure,
168
- raw: c,
169
- cfg: { errors },
170
- })
171
-
172
- expect(res.status).toBe(500)
173
- expect(jsonSpy).toHaveBeenCalledTimes(1)
174
- // If the dispatcher awaits onCatch first, 'oncatch-done' precedes
175
- // 'response-write'. Without the await, the order would be reversed
176
- // (or 'oncatch-done' would land after the dispatcher returns).
177
- expect(calls).toEqual(['oncatch-done', 'response-write'])
178
- })
179
- })
180
-
181
- const streamProcedure = {
182
- name: 'Tail',
183
- kind: 'rpc-stream',
184
- config: { scope: 'logs', version: 1 },
185
- handler: async function* () {},
186
- } as any
187
-
188
- describe('dispatchMidStreamError', () => {
189
- test('uses taxonomy body when configured', async () => {
190
- const c = await makeContext()
191
- class MidErr extends Error {}
192
- const errors = defineErrorTaxonomy({
193
- MidErr: { class: MidErr, statusCode: 500, toResponse: () => ({ name: 'MidErr', detail: 'x' }) },
194
- })
195
-
196
- const result = await dispatchMidStreamError({
197
- err: new MidErr('mid'),
198
- procedure: streamProcedure,
199
- raw: c,
200
- cfg: { errors },
201
- })
202
-
203
- expect(result.data).toEqual({ name: 'MidErr', detail: 'x' })
204
- expect(result.sseEvent).toBe('error')
205
- expect(result.runOnCatch).toBeTypeOf('function')
206
- })
207
-
208
- test('falls back to onMidStreamError', async () => {
209
- const c = await makeContext()
210
- const result = await dispatchMidStreamError({
211
- err: new Error('boom'),
212
- procedure: streamProcedure,
213
- raw: c,
214
- cfg: {
215
- onMidStreamError: () => ({ data: { kind: 'fail', msg: 'boom' } }),
216
- },
217
- })
218
-
219
- expect(result.data).toEqual({ kind: 'fail', msg: 'boom' })
220
- expect(result.sseEvent).toBe('Tail') // procedure name override
221
- })
222
-
223
- test('hard default { error: msg } when nothing matches', async () => {
224
- const c = await makeContext()
225
- const result = await dispatchMidStreamError({
226
- err: new Error('plain'),
227
- procedure: streamProcedure,
228
- raw: c,
229
- cfg: {},
230
- })
231
-
232
- expect(result.data).toEqual({ error: 'plain' })
233
- expect(result.sseEvent).toBe('error')
234
- })
235
-
236
- test('onRequestError observer fires before dispatch (mid-stream form)', async () => {
237
- const c = await makeContext()
238
- const onRequestError = vi.fn(async () => {})
239
-
240
- await dispatchMidStreamError({
241
- err: new Error('x'),
242
- procedure: streamProcedure,
243
- raw: c,
244
- cfg: { onRequestError },
245
- })
246
-
247
- expect(onRequestError).toHaveBeenCalled()
248
- })
249
-
250
- test('returns a runOnCatch function that is invokable and awaits the taxonomy hook', async () => {
251
- const c = await makeContext()
252
- const calls: string[] = []
253
- class StreamErr extends Error {}
254
- const errors = defineErrorTaxonomy({
255
- StreamErr: {
256
- class: StreamErr,
257
- statusCode: 500,
258
- toResponse: () => ({ name: 'StreamErr' }),
259
- onCatch: async () => {
260
- await new Promise<void>((resolve) => setTimeout(resolve, 5))
261
- calls.push('oncatch-done')
262
- },
263
- },
264
- })
265
-
266
- // Mid-stream contract: the dispatcher does NOT call runOnCatch itself —
267
- // the caller (stream handler) decides when to invoke it. Verify the shape
268
- // and that awaiting it actually awaits the hook.
269
- const result = await dispatchMidStreamError({
270
- err: new StreamErr('mid'),
271
- procedure: streamProcedure,
272
- raw: c,
273
- cfg: { errors },
274
- })
275
-
276
- expect(result.runOnCatch).toBeTypeOf('function')
277
- // Hook has not yet run — caller hasn't invoked it.
278
- expect(calls).toEqual([])
279
-
280
- await result.runOnCatch!()
281
- expect(calls).toEqual(['oncatch-done'])
282
- })
283
- })
@@ -1,176 +0,0 @@
1
- import type { Context } from 'hono'
2
- import {
3
- resolveErrorResponse,
4
- type ErrorTaxonomy,
5
- type TAnyProcedureRegistration,
6
- type UnknownErrorConfig,
7
- } from './error-taxonomy.js'
8
- import type { TStreamProcedureRegistration, THttpStreamProcedureRegistration } from '../../types.js'
9
-
10
- /**
11
- * Public alias of {@link TAnyProcedureRegistration} — re-exported here so the
12
- * hono/ module can import it from one place without taking a direct dependency
13
- * on error-taxonomy internals. Single source of truth lives in
14
- * error-taxonomy.ts.
15
- */
16
- export type AnyProcedureRegistration = TAnyProcedureRegistration
17
-
18
- export type OnRequestErrorContext = {
19
- err: unknown
20
- procedure: AnyProcedureRegistration
21
- raw: Context
22
- }
23
-
24
- export type OnRequestErrorObserver = (
25
- ctx: OnRequestErrorContext,
26
- ) => void | Promise<void>
27
-
28
- export type PreStreamOnError = (
29
- procedure: AnyProcedureRegistration,
30
- raw: Context,
31
- err: Error,
32
- ) => Response | Promise<Response>
33
-
34
- export type PreStreamErrorConfig = {
35
- errors?: ErrorTaxonomy
36
- unknownError?: UnknownErrorConfig
37
- onError?: PreStreamOnError
38
- onRequestError?: OnRequestErrorObserver
39
- }
40
-
41
- /**
42
- * Used by rpc, http, and the pre-stream guard in stream / http-stream
43
- * handlers. Order: onRequestError observer (awaited, throws swallowed) →
44
- * taxonomy resolver → imperative onError → hard default 500.
45
- */
46
- export async function dispatchPreStreamError(params: {
47
- err: unknown
48
- procedure: AnyProcedureRegistration
49
- raw: Context
50
- cfg: PreStreamErrorConfig
51
- }): Promise<Response> {
52
- const { err, procedure, raw, cfg } = params
53
-
54
- if (cfg.onRequestError) {
55
- try {
56
- await cfg.onRequestError({ err, procedure, raw })
57
- } catch (observerErr) {
58
- console.error(
59
- '[ts-procedures hono] onRequestError threw — swallowed:',
60
- observerErr,
61
- )
62
- }
63
- }
64
-
65
- const resolved = resolveErrorResponse({
66
- err,
67
- userTaxonomy: cfg.errors,
68
- unknownError: cfg.unknownError,
69
- procedure,
70
- raw,
71
- })
72
- if (resolved) {
73
- await resolved.runOnCatch()
74
- return raw.json(resolved.body, resolved.statusCode as never)
75
- }
76
-
77
- if (cfg.onError) {
78
- return cfg.onError(procedure, raw, err as Error)
79
- }
80
-
81
- return raw.json({ error: (err as Error).message }, 500)
82
- }
83
-
84
- /**
85
- * Return shape of an `onMidStreamError` callback.
86
- *
87
- * - `data`: the value to write to the open stream as the error payload.
88
- * Decorate with the `sse(data, { event, id, retry })` helper from
89
- * `hono/handlers/stream` to attach SSE metadata; the stream handler
90
- * reads that metadata via `getSSEMeta` after dispatch.
91
- * - `closeStream`: reserved for future use. The stream currently always
92
- * closes naturally after the catch block returns; this flag is kept on
93
- * the public type for forward compatibility but the dispatcher does not
94
- * read it.
95
- */
96
- export type MidStreamErrorResult<TErrorData = unknown> = {
97
- data: TErrorData
98
- closeStream?: boolean
99
- }
100
-
101
- export type OnMidStreamError<TErrorData = unknown> = (
102
- procedure: TStreamProcedureRegistration | THttpStreamProcedureRegistration<any>,
103
- raw: Context,
104
- err: Error,
105
- ) => MidStreamErrorResult<TErrorData> | undefined
106
-
107
- export type MidStreamErrorConfig<TErrorData = unknown> = {
108
- errors?: ErrorTaxonomy
109
- unknownError?: UnknownErrorConfig
110
- onMidStreamError?: OnMidStreamError<TErrorData>
111
- onRequestError?: OnRequestErrorObserver
112
- }
113
-
114
- export type DispatchedMidStreamError = {
115
- data: unknown
116
- sseEvent?: string
117
- sseId?: string
118
- sseRetry?: number
119
- runOnCatch?: () => Promise<void>
120
- }
121
-
122
- /**
123
- * Used inside SSE / text-stream generator catch blocks. Returns the bytes
124
- * to write to the open stream — the HTTP status is already committed, so we
125
- * can't return a Response. Order matches dispatchPreStreamError: observer
126
- * (awaited, throws swallowed) → taxonomy → onMidStreamError → hard default.
127
- */
128
- export async function dispatchMidStreamError<TErrorData = unknown>(params: {
129
- err: unknown
130
- procedure: TStreamProcedureRegistration | THttpStreamProcedureRegistration<any>
131
- raw: Context
132
- cfg: MidStreamErrorConfig<TErrorData>
133
- }): Promise<DispatchedMidStreamError> {
134
- const { err, procedure, raw, cfg } = params
135
-
136
- if (cfg.onRequestError) {
137
- try {
138
- await cfg.onRequestError({ err, procedure, raw })
139
- } catch (observerErr) {
140
- console.error(
141
- '[ts-procedures hono] onRequestError (mid-stream) threw — swallowed:',
142
- observerErr,
143
- )
144
- }
145
- }
146
-
147
- const resolved = resolveErrorResponse({
148
- err,
149
- userTaxonomy: cfg.errors,
150
- unknownError: cfg.unknownError,
151
- procedure,
152
- raw,
153
- })
154
- if (resolved) {
155
- return {
156
- data: resolved.body,
157
- sseEvent: 'error',
158
- runOnCatch: resolved.runOnCatch,
159
- }
160
- }
161
-
162
- if (cfg.onMidStreamError) {
163
- const result = cfg.onMidStreamError(procedure, raw, err as Error)
164
- if (result?.data !== undefined) {
165
- return {
166
- data: result.data,
167
- sseEvent: procedure.name,
168
- }
169
- }
170
- }
171
-
172
- return {
173
- data: { error: (err as Error).message },
174
- sseEvent: 'error',
175
- }
176
- }
@@ -1,152 +0,0 @@
1
- import type { Context, Hono } from 'hono'
2
- import { streamSSE } from 'hono/streaming'
3
- import type { THttpStreamProcedureRegistration } from '../../../../types.js'
4
- import type { HttpMethod } from '../../../types.js'
5
- import { dispatchMidStreamError, dispatchPreStreamError } from '../../error-dispatch.js'
6
- import { buildHttpStreamRouteDoc } from '../docs/http-stream-doc.js'
7
- import type { DocAccumulator, HonoAppBuilderConfig, HonoFactoryItem, QueryParser } from '../types.js'
8
-
9
- const BODY_METHODS: HttpMethod[] = ['post', 'put', 'patch']
10
-
11
- function parseQueryNative(queryString: string): Record<string, unknown> {
12
- const sp = new URLSearchParams(queryString)
13
- const result: Record<string, unknown> = {}
14
- for (const key of new Set(sp.keys())) {
15
- const values = sp.getAll(key)
16
- result[key] = values.length > 1 ? values : values[0]
17
- }
18
- return result
19
- }
20
-
21
- function extractQuery(url: string, parser: QueryParser): Record<string, unknown> {
22
- const q = url.indexOf('?')
23
- if (q === -1) return {}
24
- const raw = url.slice(q + 1)
25
- return raw ? parser(raw) : {}
26
- }
27
-
28
- async function extractParams(
29
- c: Context,
30
- method: HttpMethod,
31
- reqSchema: Record<string, unknown>,
32
- parser: QueryParser,
33
- ): Promise<Record<string, unknown>> {
34
- const params: Record<string, unknown> = {}
35
- for (const channel of Object.keys(reqSchema)) {
36
- switch (channel) {
37
- case 'pathParams':
38
- params.pathParams = c.req.param()
39
- break
40
- case 'query':
41
- params.query = extractQuery(c.req.url, parser)
42
- break
43
- case 'body':
44
- if (BODY_METHODS.includes(method)) {
45
- params.body = await c.req.json().catch(() => ({}))
46
- }
47
- break
48
- case 'headers': {
49
- const obj: Record<string, string> = {}
50
- c.req.raw.headers.forEach((v, k) => { obj[k] = v })
51
- params.headers = obj
52
- break
53
- }
54
- default:
55
- params[channel] = undefined
56
- }
57
- }
58
- return params
59
- }
60
-
61
- export function installHttpStreamRoute(params: {
62
- app: Hono
63
- procedure: THttpStreamProcedureRegistration<any>
64
- factoryItem: HonoFactoryItem
65
- cfg: HonoAppBuilderConfig
66
- docs: DocAccumulator
67
- }): void {
68
- const { app, procedure, factoryItem, cfg, docs } = params
69
- const queryParser = cfg.api?.queryParser ?? parseQueryNative
70
-
71
- const route = buildHttpStreamRouteDoc(
72
- procedure,
73
- cfg.pathPrefix,
74
- factoryItem.extendProcedureDoc as any,
75
- )
76
- docs.push(route)
77
-
78
- const reqSchema = procedure.config.schema?.req
79
-
80
- app.on(procedure.config.method.toUpperCase(), route.fullPath, async (c: Context) => {
81
- try {
82
- const context =
83
- typeof factoryItem.factoryContext === 'function'
84
- ? await (factoryItem.factoryContext as (c: Context) => any)(c)
85
- : factoryItem.factoryContext
86
-
87
- const reqParams = reqSchema
88
- ? await extractParams(c, procedure.config.method, reqSchema as Record<string, unknown>, queryParser)
89
- : undefined
90
-
91
- const { stream: gen, initialHeaders } = await procedure.handler(
92
- { ...context, signal: c.req.raw.signal },
93
- reqParams,
94
- )
95
-
96
- if (initialHeaders) {
97
- for (const [k, v] of Object.entries(initialHeaders)) c.header(k, v)
98
- }
99
-
100
- cfg.stream?.onStreamStart?.(procedure, c, 'sse')
101
-
102
- return streamSSE(c, async (stream) => {
103
- let eventId = 0
104
- try {
105
- let it = await gen.next()
106
- while (!it.done) {
107
- const data = typeof it.value === 'string' ? it.value : JSON.stringify(it.value)
108
- await stream.writeSSE({ data, event: procedure.name, id: String(eventId++) })
109
- it = await gen.next()
110
- }
111
- if (it.value !== undefined) {
112
- const data = typeof it.value === 'string' ? it.value : JSON.stringify(it.value)
113
- await stream.writeSSE({ data, event: 'return', id: String(eventId++) })
114
- }
115
- } catch (error) {
116
- const dispatched = await dispatchMidStreamError({
117
- err: error,
118
- procedure,
119
- raw: c,
120
- cfg: {
121
- errors: cfg.errors,
122
- unknownError: cfg.unknownError,
123
- onMidStreamError: cfg.stream?.onMidStreamError,
124
- onRequestError: cfg.onRequestError,
125
- },
126
- })
127
- await stream.writeSSE({
128
- data: typeof dispatched.data === 'string' ? dispatched.data : JSON.stringify(dispatched.data),
129
- event: dispatched.sseEvent ?? 'error',
130
- id: String(eventId++),
131
- })
132
- if (dispatched.runOnCatch) await dispatched.runOnCatch()
133
- } finally {
134
- cfg.stream?.onStreamEnd?.(procedure, c, 'sse')
135
- cfg.onRequestEnd?.(c)
136
- }
137
- })
138
- } catch (error) {
139
- return dispatchPreStreamError({
140
- err: error,
141
- procedure,
142
- raw: c,
143
- cfg: {
144
- errors: cfg.errors,
145
- unknownError: cfg.unknownError,
146
- onError: cfg.onError,
147
- onRequestError: cfg.onRequestError,
148
- },
149
- })
150
- }
151
- })
152
- }