ts-procedures 7.3.0 → 8.1.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 (332) hide show
  1. package/README.md +65 -3
  2. package/agent_config/claude-code/agents/ts-procedures-architect.md +6 -8
  3. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +30 -33
  4. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +104 -53
  5. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +205 -232
  6. package/agent_config/claude-code/skills/ts-procedures/patterns.md +80 -153
  7. package/agent_config/claude-code/skills/ts-procedures-review/SKILL.md +1 -1
  8. package/agent_config/claude-code/skills/ts-procedures-review/checklist.md +4 -5
  9. package/agent_config/claude-code/skills/ts-procedures-scaffold/SKILL.md +4 -7
  10. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono.md +223 -0
  11. package/agent_config/copilot/copilot-instructions.md +34 -48
  12. package/agent_config/cursor/cursorrules +34 -48
  13. package/build/client/call.js +4 -1
  14. package/build/client/call.js.map +1 -1
  15. package/build/client/call.test.js +23 -0
  16. package/build/client/call.test.js.map +1 -1
  17. package/build/client/fetch-adapter.js +3 -1
  18. package/build/client/fetch-adapter.js.map +1 -1
  19. package/build/client/fetch-adapter.test.js +11 -1
  20. package/build/client/fetch-adapter.test.js.map +1 -1
  21. package/build/client/index.test.js +7 -7
  22. package/build/client/index.test.js.map +1 -1
  23. package/build/client/request-builder.d.ts +1 -1
  24. package/build/client/request-builder.js +2 -2
  25. package/build/client/request-builder.js.map +1 -1
  26. package/build/client/stream.js +13 -2
  27. package/build/client/stream.js.map +1 -1
  28. package/build/client/stream.test.js +32 -7
  29. package/build/client/stream.test.js.map +1 -1
  30. package/build/client/typed-error-dispatch.test.js +8 -92
  31. package/build/client/typed-error-dispatch.test.js.map +1 -1
  32. package/build/client/types.d.ts +21 -3
  33. package/build/codegen/bin/cli.js +0 -0
  34. package/build/codegen/e2e.test.js +418 -23
  35. package/build/codegen/e2e.test.js.map +1 -1
  36. package/build/codegen/emit-errors.integration.test.js +1 -1
  37. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  38. package/build/codegen/emit-scope.js +351 -55
  39. package/build/codegen/emit-scope.js.map +1 -1
  40. package/build/codegen/emit-scope.test.js +540 -110
  41. package/build/codegen/emit-scope.test.js.map +1 -1
  42. package/build/codegen/emit-types.d.ts +6 -2
  43. package/build/codegen/emit-types.js +81 -20
  44. package/build/codegen/emit-types.js.map +1 -1
  45. package/build/codegen/emit-types.test.js +70 -1
  46. package/build/codegen/emit-types.test.js.map +1 -1
  47. package/build/codegen/pipeline.test.js +7 -7
  48. package/build/codegen/pipeline.test.js.map +1 -1
  49. package/build/codegen/resolve-envelope.js +1 -1
  50. package/build/codegen/resolve-envelope.js.map +1 -1
  51. package/build/codegen/resolve-envelope.test.js +5 -5
  52. package/build/codegen/resolve-envelope.test.js.map +1 -1
  53. package/build/codegen/targets/_shared/route-slots.d.ts +8 -3
  54. package/build/codegen/targets/_shared/route-slots.js +49 -8
  55. package/build/codegen/targets/_shared/route-slots.js.map +1 -1
  56. package/build/codegen/targets/_shared/route-slots.test.js +99 -26
  57. package/build/codegen/targets/_shared/route-slots.test.js.map +1 -1
  58. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js +88 -17
  59. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js.map +1 -1
  60. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js +9 -6
  61. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js.map +1 -1
  62. package/build/codegen/targets/kotlin/integration.test.js +6 -0
  63. package/build/codegen/targets/kotlin/integration.test.js.map +1 -1
  64. package/build/codegen/targets/swift/access-level.test.js +8 -11
  65. package/build/codegen/targets/swift/access-level.test.js.map +1 -1
  66. package/build/codegen/targets/swift/emit-route-swift.test.js +91 -20
  67. package/build/codegen/targets/swift/emit-route-swift.test.js.map +1 -1
  68. package/build/codegen/targets/swift/emit-scope-swift.test.js +12 -9
  69. package/build/codegen/targets/swift/emit-scope-swift.test.js.map +1 -1
  70. package/build/codegen/targets/swift/integration.test.js +6 -0
  71. package/build/codegen/targets/swift/integration.test.js.map +1 -1
  72. package/build/create-http-stream.d.ts +58 -0
  73. package/build/create-http-stream.js +122 -0
  74. package/build/create-http-stream.js.map +1 -0
  75. package/build/create-http-stream.test.js +88 -0
  76. package/build/create-http-stream.test.js.map +1 -0
  77. package/build/create-http.d.ts +49 -0
  78. package/build/create-http.js +108 -0
  79. package/build/create-http.js.map +1 -0
  80. package/build/create-http.test.js +137 -0
  81. package/build/create-http.test.js.map +1 -0
  82. package/build/create-stream.d.ts +35 -0
  83. package/build/create-stream.js +123 -0
  84. package/build/create-stream.js.map +1 -0
  85. package/build/create-stream.test.js +428 -0
  86. package/build/create-stream.test.js.map +1 -0
  87. package/build/create.d.ts +28 -0
  88. package/build/create.js +82 -0
  89. package/build/create.js.map +1 -0
  90. package/build/create.test.js +483 -0
  91. package/build/create.test.js.map +1 -0
  92. package/build/exports.d.ts +2 -0
  93. package/build/implementations/http/astro/index.test.js +20 -12
  94. package/build/implementations/http/astro/index.test.js.map +1 -1
  95. package/build/implementations/http/doc-registry.js +1 -1
  96. package/build/implementations/http/doc-registry.js.map +1 -1
  97. package/build/implementations/http/doc-registry.test.js +36 -5
  98. package/build/implementations/http/doc-registry.test.js.map +1 -1
  99. package/build/implementations/http/error-dispatch.d.ts +76 -0
  100. package/build/implementations/http/error-dispatch.js +77 -0
  101. package/build/implementations/http/error-dispatch.js.map +1 -0
  102. package/build/implementations/http/error-dispatch.test.js +254 -0
  103. package/build/implementations/http/error-dispatch.test.js.map +1 -0
  104. package/build/implementations/http/error-taxonomy.d.ts +5 -5
  105. package/build/implementations/http/hono/docs/http-doc.d.ts +6 -0
  106. package/build/implementations/http/hono/docs/http-doc.js +42 -0
  107. package/build/implementations/http/hono/docs/http-doc.js.map +1 -0
  108. package/build/implementations/http/hono/docs/http-stream-doc.d.ts +6 -0
  109. package/build/implementations/http/hono/docs/http-stream-doc.js +40 -0
  110. package/build/implementations/http/hono/docs/http-stream-doc.js.map +1 -0
  111. package/build/implementations/http/hono/docs/rpc-doc.d.ts +6 -0
  112. package/build/implementations/http/hono/docs/rpc-doc.js +24 -0
  113. package/build/implementations/http/hono/docs/rpc-doc.js.map +1 -0
  114. package/build/implementations/http/hono/docs/stream-doc.d.ts +6 -0
  115. package/build/implementations/http/hono/docs/stream-doc.js +42 -0
  116. package/build/implementations/http/hono/docs/stream-doc.js.map +1 -0
  117. package/build/implementations/http/hono/handlers/http-stream.d.ts +10 -0
  118. package/build/implementations/http/hono/handlers/http-stream.js +123 -0
  119. package/build/implementations/http/hono/handlers/http-stream.js.map +1 -0
  120. package/build/implementations/http/hono/handlers/http-stream.test.js +128 -0
  121. package/build/implementations/http/hono/handlers/http-stream.test.js.map +1 -0
  122. package/build/implementations/http/hono/handlers/http.d.ts +10 -0
  123. package/build/implementations/http/hono/handlers/http.js +115 -0
  124. package/build/implementations/http/hono/handlers/http.js.map +1 -0
  125. package/build/implementations/http/hono/handlers/http.test.js +118 -0
  126. package/build/implementations/http/hono/handlers/http.test.js.map +1 -0
  127. package/build/implementations/http/hono/handlers/rpc.d.ts +11 -0
  128. package/build/implementations/http/hono/handlers/rpc.js +32 -0
  129. package/build/implementations/http/hono/handlers/rpc.js.map +1 -0
  130. package/build/implementations/http/hono/handlers/rpc.test.js +73 -0
  131. package/build/implementations/http/hono/handlers/rpc.test.js.map +1 -0
  132. package/build/implementations/http/hono/handlers/stream.d.ts +23 -0
  133. package/build/implementations/http/hono/handlers/stream.js +147 -0
  134. package/build/implementations/http/hono/handlers/stream.js.map +1 -0
  135. package/build/implementations/http/hono/handlers/stream.test.d.ts +1 -0
  136. package/build/implementations/http/hono/handlers/stream.test.js +177 -0
  137. package/build/implementations/http/hono/handlers/stream.test.js.map +1 -0
  138. package/build/implementations/http/hono/index.d.ts +57 -0
  139. package/build/implementations/http/hono/index.js +149 -0
  140. package/build/implementations/http/hono/index.js.map +1 -0
  141. package/build/implementations/http/hono/index.test.d.ts +1 -0
  142. package/build/implementations/http/hono/index.test.js +274 -0
  143. package/build/implementations/http/hono/index.test.js.map +1 -0
  144. package/build/implementations/http/hono/path.d.ts +17 -0
  145. package/build/implementations/http/hono/path.js +39 -0
  146. package/build/implementations/http/hono/path.js.map +1 -0
  147. package/build/implementations/http/hono/path.test.d.ts +1 -0
  148. package/build/implementations/http/hono/path.test.js +83 -0
  149. package/build/implementations/http/hono/path.test.js.map +1 -0
  150. package/build/implementations/http/hono/types.d.ts +51 -0
  151. package/build/implementations/http/hono/types.js.map +1 -0
  152. package/build/implementations/http/on-request-error.test.js +6 -96
  153. package/build/implementations/http/on-request-error.test.js.map +1 -1
  154. package/build/implementations/http/route-errors.test.js +11 -59
  155. package/build/implementations/http/route-errors.test.js.map +1 -1
  156. package/build/implementations/types.d.ts +43 -9
  157. package/build/index.d.ts +124 -124
  158. package/build/index.js +10 -221
  159. package/build/index.js.map +1 -1
  160. package/build/index.test.js +20 -919
  161. package/build/index.test.js.map +1 -1
  162. package/build/migration.test.d.ts +1 -0
  163. package/build/migration.test.js +34 -0
  164. package/build/migration.test.js.map +1 -0
  165. package/build/schema/compute-schema.d.ts +11 -3
  166. package/build/schema/compute-schema.js +13 -7
  167. package/build/schema/compute-schema.js.map +1 -1
  168. package/build/schema/parser.d.ts +11 -3
  169. package/build/schema/parser.js +49 -9
  170. package/build/schema/parser.js.map +1 -1
  171. package/build/stack-utils.js +8 -0
  172. package/build/stack-utils.js.map +1 -1
  173. package/build/types.d.ts +142 -0
  174. package/build/types.js.map +1 -0
  175. package/docs/astro-adapter.md +5 -5
  176. package/docs/core.md +15 -17
  177. package/docs/http-integrations.md +83 -170
  178. package/docs/streaming.md +3 -60
  179. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +2 -7
  180. package/docs/superpowers/plans/2026-05-08-create-http.md +3355 -0
  181. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +3365 -0
  182. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +1 -3
  183. package/docs/superpowers/specs/2026-05-08-create-http-design.md +409 -0
  184. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +411 -0
  185. package/package.json +4 -22
  186. package/src/client/call.test.ts +26 -0
  187. package/src/client/call.ts +4 -1
  188. package/src/client/fetch-adapter.test.ts +14 -1
  189. package/src/client/fetch-adapter.ts +3 -1
  190. package/src/client/index.test.ts +7 -7
  191. package/src/client/request-builder.ts +2 -2
  192. package/src/client/stream.test.ts +39 -7
  193. package/src/client/stream.ts +16 -2
  194. package/src/client/typed-error-dispatch.test.ts +7 -97
  195. package/src/client/types.ts +21 -3
  196. package/src/codegen/__fixtures__/users-envelope.json +119 -38
  197. package/src/codegen/e2e.test.ts +452 -24
  198. package/src/codegen/emit-errors.integration.test.ts +1 -1
  199. package/src/codegen/emit-scope.test.ts +581 -110
  200. package/src/codegen/emit-scope.ts +390 -61
  201. package/src/codegen/emit-types.test.ts +73 -1
  202. package/src/codegen/emit-types.ts +82 -21
  203. package/src/codegen/pipeline.test.ts +7 -7
  204. package/src/codegen/resolve-envelope.test.ts +5 -5
  205. package/src/codegen/resolve-envelope.ts +1 -1
  206. package/src/codegen/targets/_shared/route-slots.test.ts +109 -26
  207. package/src/codegen/targets/_shared/route-slots.ts +48 -11
  208. package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +73 -0
  209. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +100 -17
  210. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +9 -6
  211. package/src/codegen/targets/kotlin/integration.test.ts +19 -0
  212. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +79 -0
  213. package/src/codegen/targets/swift/access-level.test.ts +8 -11
  214. package/src/codegen/targets/swift/emit-route-swift.test.ts +103 -20
  215. package/src/codegen/targets/swift/emit-scope-swift.test.ts +12 -9
  216. package/src/codegen/targets/swift/integration.test.ts +17 -0
  217. package/src/create-http-stream.test.ts +97 -0
  218. package/src/create-http-stream.ts +191 -0
  219. package/src/create-http.test.ts +163 -0
  220. package/src/create-http.ts +211 -0
  221. package/src/create-stream.test.ts +565 -0
  222. package/src/create-stream.ts +228 -0
  223. package/src/create.test.ts +658 -0
  224. package/src/create.ts +172 -0
  225. package/src/exports.ts +2 -0
  226. package/src/implementations/http/README.md +135 -95
  227. package/src/implementations/http/astro/README.md +4 -5
  228. package/src/implementations/http/astro/index.test.ts +25 -18
  229. package/src/implementations/http/doc-registry.test.ts +42 -5
  230. package/src/implementations/http/doc-registry.ts +1 -1
  231. package/src/implementations/http/error-dispatch.test.ts +283 -0
  232. package/src/implementations/http/error-dispatch.ts +176 -0
  233. package/src/implementations/http/error-taxonomy.ts +5 -5
  234. package/src/implementations/http/hono/docs/http-doc.ts +43 -0
  235. package/src/implementations/http/hono/docs/http-stream-doc.ts +44 -0
  236. package/src/implementations/http/hono/docs/rpc-doc.ts +34 -0
  237. package/src/implementations/http/hono/docs/stream-doc.ts +53 -0
  238. package/src/implementations/http/hono/handlers/http-stream.test.ts +150 -0
  239. package/src/implementations/http/hono/handlers/http-stream.ts +152 -0
  240. package/src/implementations/http/hono/handlers/http.test.ts +130 -0
  241. package/src/implementations/http/hono/handlers/http.ts +147 -0
  242. package/src/implementations/http/hono/handlers/rpc.test.ts +81 -0
  243. package/src/implementations/http/hono/handlers/rpc.ts +54 -0
  244. package/src/implementations/http/hono/handlers/stream.test.ts +198 -0
  245. package/src/implementations/http/hono/handlers/stream.ts +208 -0
  246. package/src/implementations/http/hono/index.test.ts +329 -0
  247. package/src/implementations/http/hono/index.ts +204 -0
  248. package/src/implementations/http/hono/path.test.ts +96 -0
  249. package/src/implementations/http/hono/path.ts +59 -0
  250. package/src/implementations/http/hono/types.ts +93 -0
  251. package/src/implementations/http/on-request-error.test.ts +10 -116
  252. package/src/implementations/http/route-errors.test.ts +11 -77
  253. package/src/implementations/types.ts +44 -9
  254. package/src/index.test.ts +22 -1249
  255. package/src/index.ts +49 -485
  256. package/src/migration.test.ts +48 -0
  257. package/src/schema/compute-schema.ts +26 -12
  258. package/src/schema/parser.ts +62 -12
  259. package/src/stack-utils.ts +8 -0
  260. package/src/types.ts +133 -0
  261. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/express-rpc.md +0 -137
  262. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-api.md +0 -173
  263. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-rpc.md +0 -142
  264. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-stream.md +0 -147
  265. package/build/implementations/http/express-rpc/error-taxonomy.test.js +0 -83
  266. package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +0 -1
  267. package/build/implementations/http/express-rpc/index.d.ts +0 -125
  268. package/build/implementations/http/express-rpc/index.js +0 -216
  269. package/build/implementations/http/express-rpc/index.js.map +0 -1
  270. package/build/implementations/http/express-rpc/index.test.js +0 -684
  271. package/build/implementations/http/express-rpc/index.test.js.map +0 -1
  272. package/build/implementations/http/express-rpc/types.d.ts +0 -11
  273. package/build/implementations/http/express-rpc/types.js.map +0 -1
  274. package/build/implementations/http/hono-api/error-taxonomy.test.js +0 -137
  275. package/build/implementations/http/hono-api/error-taxonomy.test.js.map +0 -1
  276. package/build/implementations/http/hono-api/index.d.ts +0 -151
  277. package/build/implementations/http/hono-api/index.js +0 -344
  278. package/build/implementations/http/hono-api/index.js.map +0 -1
  279. package/build/implementations/http/hono-api/index.test.js +0 -992
  280. package/build/implementations/http/hono-api/index.test.js.map +0 -1
  281. package/build/implementations/http/hono-api/types.d.ts +0 -13
  282. package/build/implementations/http/hono-api/types.js.map +0 -1
  283. package/build/implementations/http/hono-rpc/error-taxonomy.test.js +0 -64
  284. package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +0 -1
  285. package/build/implementations/http/hono-rpc/index.d.ts +0 -130
  286. package/build/implementations/http/hono-rpc/index.js +0 -209
  287. package/build/implementations/http/hono-rpc/index.js.map +0 -1
  288. package/build/implementations/http/hono-rpc/index.test.js +0 -828
  289. package/build/implementations/http/hono-rpc/index.test.js.map +0 -1
  290. package/build/implementations/http/hono-rpc/types.d.ts +0 -11
  291. package/build/implementations/http/hono-rpc/types.js +0 -2
  292. package/build/implementations/http/hono-rpc/types.js.map +0 -1
  293. package/build/implementations/http/hono-stream/error-taxonomy.test.js +0 -159
  294. package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +0 -1
  295. package/build/implementations/http/hono-stream/index.d.ts +0 -171
  296. package/build/implementations/http/hono-stream/index.js +0 -415
  297. package/build/implementations/http/hono-stream/index.js.map +0 -1
  298. package/build/implementations/http/hono-stream/index.test.js +0 -1383
  299. package/build/implementations/http/hono-stream/index.test.js.map +0 -1
  300. package/build/implementations/http/hono-stream/types.d.ts +0 -15
  301. package/build/implementations/http/hono-stream/types.js +0 -2
  302. package/build/implementations/http/hono-stream/types.js.map +0 -1
  303. package/src/implementations/http/express-rpc/README.md +0 -280
  304. package/src/implementations/http/express-rpc/error-taxonomy.test.ts +0 -103
  305. package/src/implementations/http/express-rpc/index.test.ts +0 -957
  306. package/src/implementations/http/express-rpc/index.ts +0 -327
  307. package/src/implementations/http/express-rpc/types.ts +0 -16
  308. package/src/implementations/http/hono-api/README.md +0 -284
  309. package/src/implementations/http/hono-api/error-taxonomy.test.ts +0 -179
  310. package/src/implementations/http/hono-api/index.test.ts +0 -1341
  311. package/src/implementations/http/hono-api/index.ts +0 -519
  312. package/src/implementations/http/hono-api/types.ts +0 -16
  313. package/src/implementations/http/hono-rpc/README.md +0 -357
  314. package/src/implementations/http/hono-rpc/error-taxonomy.test.ts +0 -82
  315. package/src/implementations/http/hono-rpc/index.test.ts +0 -1107
  316. package/src/implementations/http/hono-rpc/index.ts +0 -320
  317. package/src/implementations/http/hono-rpc/types.ts +0 -16
  318. package/src/implementations/http/hono-stream/README.md +0 -559
  319. package/src/implementations/http/hono-stream/error-taxonomy.test.ts +0 -178
  320. package/src/implementations/http/hono-stream/index.test.ts +0 -1804
  321. package/src/implementations/http/hono-stream/index.ts +0 -622
  322. package/src/implementations/http/hono-stream/types.ts +0 -20
  323. /package/build/{implementations/http/express-rpc/error-taxonomy.test.d.ts → create-http-stream.test.d.ts} +0 -0
  324. /package/build/{implementations/http/express-rpc/index.test.d.ts → create-http.test.d.ts} +0 -0
  325. /package/build/{implementations/http/hono-api/error-taxonomy.test.d.ts → create-stream.test.d.ts} +0 -0
  326. /package/build/{implementations/http/hono-api/index.test.d.ts → create.test.d.ts} +0 -0
  327. /package/build/implementations/http/{hono-rpc/error-taxonomy.test.d.ts → error-dispatch.test.d.ts} +0 -0
  328. /package/build/implementations/http/{hono-rpc/index.test.d.ts → hono/handlers/http-stream.test.d.ts} +0 -0
  329. /package/build/implementations/http/{hono-stream/error-taxonomy.test.d.ts → hono/handlers/http.test.d.ts} +0 -0
  330. /package/build/implementations/http/{hono-stream/index.test.d.ts → hono/handlers/rpc.test.d.ts} +0 -0
  331. /package/build/implementations/http/{express-rpc → hono}/types.js +0 -0
  332. /package/build/{implementations/http/hono-api/types.js → types.js} +0 -0
@@ -0,0 +1,93 @@
1
+ import type { Context, Hono } from 'hono'
2
+ import type { ErrorTaxonomy, UnknownErrorConfig } from '../error-taxonomy.js'
3
+ import type {
4
+ AnyProcedureRegistration,
5
+ OnRequestErrorObserver,
6
+ OnMidStreamError,
7
+ PreStreamOnError,
8
+ } from '../error-dispatch.js'
9
+ import type {
10
+ ProceduresFactory,
11
+ ExtractContext,
12
+ StreamMode,
13
+ AnyHttpRouteDoc,
14
+ RPCHttpRouteDoc,
15
+ APIHttpRouteDoc,
16
+ StreamHttpRouteDoc,
17
+ HttpStreamRouteDoc,
18
+ } from '../../types.js'
19
+ import type {
20
+ TProcedureRegistration,
21
+ TStreamProcedureRegistration,
22
+ THttpProcedureRegistration,
23
+ THttpStreamProcedureRegistration,
24
+ } from '../../../types.js'
25
+
26
+ export type { AnyProcedureRegistration } from '../error-dispatch.js'
27
+
28
+ /** Default query parser using URLSearchParams. */
29
+ export type QueryParser = (queryString: string) => Record<string, unknown>
30
+
31
+ export type OnRequestErrorContext = {
32
+ err: unknown
33
+ procedure: AnyProcedureRegistration
34
+ raw: Context
35
+ }
36
+
37
+ export type ExtendProcedureDoc = (params: {
38
+ base: RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc | HttpStreamRouteDoc
39
+ procedure: AnyProcedureRegistration
40
+ }) => Record<string, unknown>
41
+
42
+ export type HonoFactoryItem<TFactory extends ProceduresFactory = ProceduresFactory> = {
43
+ factory: TFactory
44
+ factoryContext:
45
+ | ExtractContext<TFactory>
46
+ | ((c: Context) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>)
47
+ streamMode?: StreamMode
48
+ extendProcedureDoc?: ExtendProcedureDoc
49
+ }
50
+
51
+ export type HonoAppBuilderConfig<TStreamErrorData = unknown> = {
52
+ /** Existing Hono app. If omitted, a new instance is created. */
53
+ app?: Hono
54
+ /** Path prefix applied to every route across all kinds. */
55
+ pathPrefix?: string
56
+
57
+ // Error handling — peers
58
+ errors?: ErrorTaxonomy
59
+ unknownError?: UnknownErrorConfig
60
+ onError?: PreStreamOnError
61
+ /** Cross-cutting observer — fires for every caught error before dispatch. */
62
+ onRequestError?: OnRequestErrorObserver
63
+
64
+ // Lifecycle (every kind)
65
+ onRequestStart?: (c: Context) => void
66
+ onRequestEnd?: (c: Context) => void
67
+
68
+ // Kind-specific blocks
69
+ rpc?: {
70
+ onSuccess?: (procedure: TProcedureRegistration, c: Context) => void
71
+ }
72
+ api?: {
73
+ queryParser?: QueryParser
74
+ onSuccess?: (procedure: THttpProcedureRegistration<any>, c: Context) => void
75
+ }
76
+ stream?: {
77
+ /** Default for both rpc-stream and http-stream. */
78
+ defaultStreamMode?: StreamMode
79
+ onStreamStart?: (
80
+ procedure: TStreamProcedureRegistration | THttpStreamProcedureRegistration<any>,
81
+ c: Context,
82
+ streamMode: StreamMode,
83
+ ) => void
84
+ onStreamEnd?: (
85
+ procedure: TStreamProcedureRegistration | THttpStreamProcedureRegistration<any>,
86
+ c: Context,
87
+ streamMode: StreamMode,
88
+ ) => void
89
+ onMidStreamError?: OnMidStreamError<TStreamErrorData>
90
+ }
91
+ }
92
+
93
+ export type DocAccumulator = AnyHttpRouteDoc[]
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * Cross-builder tests for the `onRequestError` observer hook.
4
4
  *
5
- * Invariants verified once per builder:
5
+ * Invariants verified per builder:
6
6
  * 1. Fires exactly once for every caught error.
7
7
  * 2. Runs BEFORE dispatch (taxonomy / onError / hard default).
8
8
  * 3. Is awaited — async observer work completes before the response is sent.
@@ -12,82 +12,13 @@
12
12
  * path still produces a response.
13
13
  */
14
14
  import { describe, expect, test, vi } from 'vitest'
15
- import request from 'supertest'
16
15
  import { Type } from 'typebox'
17
16
  import { Procedures } from '../../index.js'
18
- import { APIConfig, RPCConfig } from '../types.js'
19
- import { HonoAPIAppBuilder } from './hono-api/index.js'
20
- import { HonoRPCAppBuilder } from './hono-rpc/index.js'
21
- import { ExpressRPCAppBuilder } from './express-rpc/index.js'
22
- import { HonoStreamAppBuilder } from './hono-stream/index.js'
17
+ import { RPCConfig } from '../types.js'
18
+ import { HonoAppBuilder } from './hono/index.js'
23
19
 
24
- describe('onRequestError — HonoAPIAppBuilder', () => {
25
- function boomApp(config: ConstructorParameters<typeof HonoAPIAppBuilder>[0]) {
26
- const API = Procedures<{}, APIConfig>()
27
- API.Create(
28
- 'Boom',
29
- { path: '/boom', method: 'get', schema: { returnType: Type.Object({}) } },
30
- async () => {
31
- throw new TypeError('boom')
32
- }
33
- )
34
- return new HonoAPIAppBuilder(config).register(API, () => ({})).build()
35
- }
36
-
37
- test('fires exactly once and before dispatch', async () => {
38
- const order: string[] = []
39
- const onRequestError = vi.fn(() => {
40
- order.push('observer')
41
- })
42
- const onError = vi.fn((_p: any, c: any) => {
43
- order.push('onError')
44
- return c.json({ handled: true }, 418)
45
- })
46
-
47
- const app = boomApp({ onRequestError, onError })
48
- await app.request('/boom')
49
- expect(onRequestError).toHaveBeenCalledTimes(1)
50
- expect(order).toEqual(['observer', 'onError'])
51
- })
52
-
53
- test('is awaited — async work completes before response is sent', async () => {
54
- const log: string[] = []
55
- const onRequestError = async () => {
56
- await new Promise((r) => setTimeout(r, 5))
57
- log.push('observer-done')
58
- }
59
- const app = boomApp({
60
- onRequestError,
61
- onError: (_p, c) => {
62
- log.push('onError-called')
63
- return c.json({ ok: true }, 500)
64
- },
65
- })
66
- await app.request('/boom')
67
- expect(log).toEqual(['observer-done', 'onError-called'])
68
- })
69
-
70
- test('observer-thrown errors are swallowed — dispatch still produces a response', async () => {
71
- const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
72
- const app = boomApp({
73
- onRequestError: () => {
74
- throw new Error('observer exploded')
75
- },
76
- })
77
- const res = await app.request('/boom')
78
- expect(res.status).toBe(500)
79
- consoleSpy.mockRestore()
80
- })
81
-
82
- test('omitting observer preserves existing behavior', async () => {
83
- const app = boomApp({ onError: (_p, c) => c.json({ ok: true }, 418) })
84
- const res = await app.request('/boom')
85
- expect(res.status).toBe(418)
86
- })
87
- })
88
-
89
- describe('onRequestError — HonoRPCAppBuilder', () => {
90
- function boomApp(config: ConstructorParameters<typeof HonoRPCAppBuilder>[0]) {
20
+ describe('onRequestError — HonoAppBuilder (rpc kind)', () => {
21
+ function boomApp(config: ConstructorParameters<typeof HonoAppBuilder>[0]) {
91
22
  const RPC = Procedures<{}, RPCConfig>()
92
23
  RPC.Create(
93
24
  'Boom',
@@ -96,7 +27,7 @@ describe('onRequestError — HonoRPCAppBuilder', () => {
96
27
  throw new TypeError('boom')
97
28
  }
98
29
  )
99
- return new HonoRPCAppBuilder(config).register(RPC, () => ({})).build()
30
+ return new HonoAppBuilder(config).register(RPC, () => ({})).build()
100
31
  }
101
32
 
102
33
  test('fires once; runs before onError', async () => {
@@ -128,51 +59,13 @@ describe('onRequestError — HonoRPCAppBuilder', () => {
128
59
  })
129
60
  })
130
61
 
131
- describe('onRequestError — ExpressRPCAppBuilder', () => {
132
- function boomApp(config: ConstructorParameters<typeof ExpressRPCAppBuilder>[0]) {
133
- const RPC = Procedures<{}, RPCConfig>()
134
- RPC.Create(
135
- 'Boom',
136
- { scope: 'test', version: 1, schema: { params: Type.Object({}) } },
137
- async () => {
138
- throw new TypeError('boom')
139
- }
140
- )
141
- return new ExpressRPCAppBuilder(config).register(RPC, () => ({})).build()
142
- }
143
-
144
- test('fires once; raw is { req, res }', async () => {
145
- let rawSeen: any
146
- const app = boomApp({
147
- onRequestError: (ctx) => {
148
- rawSeen = ctx.raw
149
- },
150
- })
151
- await request(app).post('/test/boom/1').send({})
152
- expect(rawSeen.req).toBeDefined()
153
- expect(rawSeen.res).toBeDefined()
154
- })
155
-
156
- test('observer throws are swallowed', async () => {
157
- const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
158
- const app = boomApp({
159
- onRequestError: () => {
160
- throw new Error('observer bug')
161
- },
162
- })
163
- const res = await request(app).post('/test/boom/1').send({})
164
- expect(res.status).toBe(500)
165
- consoleSpy.mockRestore()
166
- })
167
- })
168
-
169
- describe('onRequestError — HonoStreamAppBuilder (pre-stream)', () => {
170
- function boomApp(config: ConstructorParameters<typeof HonoStreamAppBuilder>[0]) {
62
+ describe('onRequestError — HonoAppBuilder (rpc-stream pre-stream)', () => {
63
+ function boomApp(config: ConstructorParameters<typeof HonoAppBuilder>[0]) {
171
64
  const RPC = Procedures<{}, RPCConfig>()
172
65
  RPC.CreateStream('Stream', { scope: 'test', version: 1 }, async function* () {
173
66
  yield { ok: true }
174
67
  })
175
- return new HonoStreamAppBuilder(config)
68
+ return new HonoAppBuilder(config)
176
69
  .register(RPC, () => {
177
70
  throw new TypeError('context failed')
178
71
  })
@@ -199,3 +92,4 @@ describe('onRequestError — HonoStreamAppBuilder (pre-stream)', () => {
199
92
  consoleSpy.mockRestore()
200
93
  })
201
94
  })
95
+
@@ -3,10 +3,7 @@ import { describe, expect, test } from 'vitest'
3
3
  import { Type } from 'typebox'
4
4
  import { Procedures } from '../../index.js'
5
5
  import { APIConfig, RPCConfig } from '../types.js'
6
- import { HonoAPIAppBuilder } from './hono-api/index.js'
7
- import { HonoRPCAppBuilder } from './hono-rpc/index.js'
8
- import { ExpressRPCAppBuilder } from './express-rpc/index.js'
9
- import { HonoStreamAppBuilder } from './hono-stream/index.js'
6
+ import { HonoAppBuilder } from './hono/index.js'
10
7
  import { DocRegistry } from './doc-registry.js'
11
8
  import { defineErrorTaxonomy } from './error-taxonomy.js'
12
9
 
@@ -26,39 +23,13 @@ const appErrors = defineErrorTaxonomy({
26
23
  })
27
24
 
28
25
  describe('per-route errors declaration', () => {
29
- test('hono-api copies config.errors onto the route doc', () => {
30
- const API = Procedures<{}, APIConfig<keyof typeof appErrors & string>>()
31
- API.Create(
32
- 'GetUser',
33
- {
34
- path: '/users/:id',
35
- method: 'get',
36
- errors: ['UseCaseError', 'AuthError'],
37
- schema: {
38
- input: { pathParams: Type.Object({ id: Type.String() }) },
39
- returnType: Type.Object({}),
40
- },
41
- },
42
- async () => ({})
43
- )
44
- const builder = new HonoAPIAppBuilder().register(API, () => ({}))
45
- builder.build()
46
- expect(builder.docs[0]!.errors).toEqual(['UseCaseError', 'AuthError'])
47
- })
26
+ // migrated to schema.req in Phase 3+ (CreateHttp)
27
+ test.todo('hono-api copies config.errors onto the route doc')
48
28
 
49
- test('hono-api route doc omits errors when not declared', () => {
50
- const API = Procedures<{}, APIConfig>()
51
- API.Create(
52
- 'Health',
53
- { path: '/health', method: 'get', schema: { returnType: Type.Object({}) } },
54
- async () => ({})
55
- )
56
- const builder = new HonoAPIAppBuilder().register(API, () => ({}))
57
- builder.build()
58
- expect(builder.docs[0]!.errors).toBeUndefined()
59
- })
29
+ // migrated to schema.req in Phase 3+ (CreateHttp)
30
+ test.todo('hono-api route doc omits errors when not declared')
60
31
 
61
- test('hono-rpc copies config.errors onto the route doc', () => {
32
+ test('hono rpc copies config.errors onto the route doc', () => {
62
33
  const RPC = Procedures<{}, RPCConfig<keyof typeof appErrors & string>>()
63
34
  RPC.Create(
64
35
  'DoThing',
@@ -70,29 +41,12 @@ describe('per-route errors declaration', () => {
70
41
  },
71
42
  async () => ({})
72
43
  )
73
- const builder = new HonoRPCAppBuilder().register(RPC, () => ({}))
44
+ const builder = new HonoAppBuilder().register(RPC, () => ({}))
74
45
  builder.build()
75
46
  expect(builder.docs[0]!.errors).toEqual(['UseCaseError'])
76
47
  })
77
48
 
78
- test('express-rpc copies config.errors onto the route doc', () => {
79
- const RPC = Procedures<{}, RPCConfig<keyof typeof appErrors & string>>()
80
- RPC.Create(
81
- 'DoThing',
82
- {
83
- scope: 'things',
84
- version: 1,
85
- errors: ['AuthError'],
86
- schema: { params: Type.Object({}) },
87
- },
88
- async () => ({})
89
- )
90
- const builder = new ExpressRPCAppBuilder().register(RPC, () => ({}))
91
- builder.build()
92
- expect(builder.docs[0]!.errors).toEqual(['AuthError'])
93
- })
94
-
95
- test('hono-stream copies config.errors onto the route doc', () => {
49
+ test('hono stream copies config.errors onto the route doc', () => {
96
50
  const Stream = Procedures<{}, RPCConfig<keyof typeof appErrors & string>>()
97
51
  Stream.CreateStream(
98
52
  'Watch',
@@ -101,7 +55,7 @@ describe('per-route errors declaration', () => {
101
55
  yield { ok: true }
102
56
  }
103
57
  )
104
- const builder = new HonoStreamAppBuilder().register(Stream, () => ({}))
58
+ const builder = new HonoAppBuilder().register(Stream, () => ({}))
105
59
  builder.build()
106
60
  expect(builder.docs[0]!.errors).toEqual(['AuthError'])
107
61
  })
@@ -151,26 +105,6 @@ describe('DocRegistry with taxonomy input', () => {
151
105
  expect(count).toBe(1)
152
106
  })
153
107
 
154
- test('registered route errors survive DocRegistry composition', () => {
155
- const API = Procedures<{}, APIConfig<keyof typeof appErrors & string>>()
156
- API.Create(
157
- 'GetUser',
158
- {
159
- path: '/users/:id',
160
- method: 'get',
161
- errors: ['UseCaseError'],
162
- schema: {
163
- input: { pathParams: Type.Object({ id: Type.String() }) },
164
- returnType: Type.Object({}),
165
- },
166
- },
167
- async () => ({})
168
- )
169
- const app = new HonoAPIAppBuilder().register(API, () => ({}))
170
- app.build()
171
-
172
- const envelope = new DocRegistry({ errors: appErrors }).from(app).toJSON()
173
- const route = envelope.routes.find((r) => r.kind === 'api' && r.name === 'GetUser')
174
- expect(route?.errors).toEqual(['UseCaseError'])
175
- })
108
+ // migrated to schema.req in Phase 3+ (CreateHttp)
109
+ test.todo('registered route errors survive DocRegistry composition')
176
110
  })
@@ -66,20 +66,28 @@ export interface APIConfig<TErrorKey extends string = string> {
66
66
  errors?: TErrorKey[]
67
67
  }
68
68
 
69
- export interface APIHttpRouteDoc extends APIConfig {
69
+ export interface APIHttpRouteDoc {
70
70
  kind: 'api'
71
71
  name: string
72
+ scope?: string
73
+ path: string
74
+ method: HttpMethod
72
75
  /** Full resolved path including pathPrefix */
73
76
  fullPath: string
77
+ successStatus?: number
78
+ errors?: string[]
74
79
  jsonSchema: {
75
- pathParams?: Record<string, unknown>
76
- query?: Record<string, unknown>
77
- body?: Record<string, unknown>
78
- headers?: Record<string, unknown>
79
- response?: Record<string, unknown>
80
+ req?: {
81
+ pathParams?: Record<string, unknown>
82
+ query?: Record<string, unknown>
83
+ body?: Record<string, unknown>
84
+ headers?: Record<string, unknown>
85
+ }
86
+ res?: {
87
+ body?: Record<string, unknown>
88
+ headers?: Record<string, unknown>
89
+ }
80
90
  }
81
- /** Taxonomy keys for errors this route may emit. */
82
- errors?: string[]
83
91
  }
84
92
 
85
93
  /**
@@ -121,6 +129,30 @@ export interface StreamHttpRouteDoc extends RPCConfig {
121
129
  errors?: string[]
122
130
  }
123
131
 
132
+ export interface HttpStreamRouteDoc {
133
+ kind: 'http-stream'
134
+ name: string
135
+ scope?: string
136
+ path: string
137
+ method: HttpMethod
138
+ fullPath: string
139
+ streamMode: StreamMode
140
+ errors?: string[]
141
+ jsonSchema: {
142
+ req?: {
143
+ pathParams?: Record<string, unknown>
144
+ query?: Record<string, unknown>
145
+ body?: Record<string, unknown>
146
+ headers?: Record<string, unknown>
147
+ }
148
+ res?: {
149
+ headers?: Record<string, unknown>
150
+ }
151
+ yield?: Record<string, unknown>
152
+ returnType?: Record<string, unknown>
153
+ }
154
+ }
155
+
124
156
  // ================
125
157
  // Utility types
126
158
  // ================
@@ -152,19 +184,22 @@ export type ExtractConfig<TFactory> = TFactory extends {
152
184
  export type ProceduresFactory = {
153
185
  getProcedures: () => Array<{
154
186
  name: string
187
+ kind?: import('../types.js').ProcedureKind
155
188
  isStream?: boolean
156
189
  config: any
157
190
  handler: (ctx: any, params?: any) => Promise<any> | AsyncGenerator<any, any, unknown>
158
191
  }>
159
192
  Create: (...args: any[]) => any
160
193
  CreateStream?: (...args: any[]) => any
194
+ CreateHttp?: (...args: any[]) => any
195
+ CreateHttpStream?: (...args: any[]) => any
161
196
  }
162
197
 
163
198
  // ================
164
199
  // DocRegistry types
165
200
  // ================
166
201
 
167
- export type AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc
202
+ export type AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc | HttpStreamRouteDoc
168
203
 
169
204
  export interface DocSource<T = AnyHttpRouteDoc> {
170
205
  readonly docs: T[]