ts-procedures 7.3.0 → 8.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 (325) 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 +87 -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 +308 -47
  39. package/build/codegen/emit-scope.js.map +1 -1
  40. package/build/codegen/emit-scope.test.js +363 -110
  41. package/build/codegen/emit-scope.test.js.map +1 -1
  42. package/build/codegen/pipeline.test.js +7 -7
  43. package/build/codegen/pipeline.test.js.map +1 -1
  44. package/build/codegen/resolve-envelope.js +1 -1
  45. package/build/codegen/resolve-envelope.js.map +1 -1
  46. package/build/codegen/resolve-envelope.test.js +5 -5
  47. package/build/codegen/resolve-envelope.test.js.map +1 -1
  48. package/build/codegen/targets/_shared/route-slots.d.ts +8 -3
  49. package/build/codegen/targets/_shared/route-slots.js +49 -8
  50. package/build/codegen/targets/_shared/route-slots.js.map +1 -1
  51. package/build/codegen/targets/_shared/route-slots.test.js +99 -26
  52. package/build/codegen/targets/_shared/route-slots.test.js.map +1 -1
  53. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js +88 -17
  54. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js.map +1 -1
  55. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js +9 -6
  56. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js.map +1 -1
  57. package/build/codegen/targets/kotlin/integration.test.js +6 -0
  58. package/build/codegen/targets/kotlin/integration.test.js.map +1 -1
  59. package/build/codegen/targets/swift/access-level.test.js +8 -11
  60. package/build/codegen/targets/swift/access-level.test.js.map +1 -1
  61. package/build/codegen/targets/swift/emit-route-swift.test.js +91 -20
  62. package/build/codegen/targets/swift/emit-route-swift.test.js.map +1 -1
  63. package/build/codegen/targets/swift/emit-scope-swift.test.js +12 -9
  64. package/build/codegen/targets/swift/emit-scope-swift.test.js.map +1 -1
  65. package/build/codegen/targets/swift/integration.test.js +6 -0
  66. package/build/codegen/targets/swift/integration.test.js.map +1 -1
  67. package/build/create-http-stream.d.ts +58 -0
  68. package/build/create-http-stream.js +122 -0
  69. package/build/create-http-stream.js.map +1 -0
  70. package/build/create-http-stream.test.js +88 -0
  71. package/build/create-http-stream.test.js.map +1 -0
  72. package/build/create-http.d.ts +49 -0
  73. package/build/create-http.js +108 -0
  74. package/build/create-http.js.map +1 -0
  75. package/build/create-http.test.js +137 -0
  76. package/build/create-http.test.js.map +1 -0
  77. package/build/create-stream.d.ts +35 -0
  78. package/build/create-stream.js +123 -0
  79. package/build/create-stream.js.map +1 -0
  80. package/build/create-stream.test.js +428 -0
  81. package/build/create-stream.test.js.map +1 -0
  82. package/build/create.d.ts +28 -0
  83. package/build/create.js +82 -0
  84. package/build/create.js.map +1 -0
  85. package/build/create.test.js +483 -0
  86. package/build/create.test.js.map +1 -0
  87. package/build/exports.d.ts +2 -0
  88. package/build/implementations/http/astro/index.test.js +20 -12
  89. package/build/implementations/http/astro/index.test.js.map +1 -1
  90. package/build/implementations/http/doc-registry.js +1 -1
  91. package/build/implementations/http/doc-registry.js.map +1 -1
  92. package/build/implementations/http/doc-registry.test.js +36 -5
  93. package/build/implementations/http/doc-registry.test.js.map +1 -1
  94. package/build/implementations/http/error-dispatch.d.ts +76 -0
  95. package/build/implementations/http/error-dispatch.js +77 -0
  96. package/build/implementations/http/error-dispatch.js.map +1 -0
  97. package/build/implementations/http/error-dispatch.test.js +254 -0
  98. package/build/implementations/http/error-dispatch.test.js.map +1 -0
  99. package/build/implementations/http/error-taxonomy.d.ts +5 -5
  100. package/build/implementations/http/hono/docs/http-doc.d.ts +6 -0
  101. package/build/implementations/http/hono/docs/http-doc.js +42 -0
  102. package/build/implementations/http/hono/docs/http-doc.js.map +1 -0
  103. package/build/implementations/http/hono/docs/http-stream-doc.d.ts +6 -0
  104. package/build/implementations/http/hono/docs/http-stream-doc.js +40 -0
  105. package/build/implementations/http/hono/docs/http-stream-doc.js.map +1 -0
  106. package/build/implementations/http/hono/docs/rpc-doc.d.ts +6 -0
  107. package/build/implementations/http/hono/docs/rpc-doc.js +24 -0
  108. package/build/implementations/http/hono/docs/rpc-doc.js.map +1 -0
  109. package/build/implementations/http/hono/docs/stream-doc.d.ts +6 -0
  110. package/build/implementations/http/hono/docs/stream-doc.js +42 -0
  111. package/build/implementations/http/hono/docs/stream-doc.js.map +1 -0
  112. package/build/implementations/http/hono/handlers/http-stream.d.ts +10 -0
  113. package/build/implementations/http/hono/handlers/http-stream.js +123 -0
  114. package/build/implementations/http/hono/handlers/http-stream.js.map +1 -0
  115. package/build/implementations/http/hono/handlers/http-stream.test.js +128 -0
  116. package/build/implementations/http/hono/handlers/http-stream.test.js.map +1 -0
  117. package/build/implementations/http/hono/handlers/http.d.ts +10 -0
  118. package/build/implementations/http/hono/handlers/http.js +115 -0
  119. package/build/implementations/http/hono/handlers/http.js.map +1 -0
  120. package/build/implementations/http/hono/handlers/http.test.js +118 -0
  121. package/build/implementations/http/hono/handlers/http.test.js.map +1 -0
  122. package/build/implementations/http/hono/handlers/rpc.d.ts +11 -0
  123. package/build/implementations/http/hono/handlers/rpc.js +32 -0
  124. package/build/implementations/http/hono/handlers/rpc.js.map +1 -0
  125. package/build/implementations/http/hono/handlers/rpc.test.js +73 -0
  126. package/build/implementations/http/hono/handlers/rpc.test.js.map +1 -0
  127. package/build/implementations/http/hono/handlers/stream.d.ts +23 -0
  128. package/build/implementations/http/hono/handlers/stream.js +147 -0
  129. package/build/implementations/http/hono/handlers/stream.js.map +1 -0
  130. package/build/implementations/http/hono/handlers/stream.test.d.ts +1 -0
  131. package/build/implementations/http/hono/handlers/stream.test.js +177 -0
  132. package/build/implementations/http/hono/handlers/stream.test.js.map +1 -0
  133. package/build/implementations/http/hono/index.d.ts +57 -0
  134. package/build/implementations/http/hono/index.js +149 -0
  135. package/build/implementations/http/hono/index.js.map +1 -0
  136. package/build/implementations/http/hono/index.test.d.ts +1 -0
  137. package/build/implementations/http/hono/index.test.js +274 -0
  138. package/build/implementations/http/hono/index.test.js.map +1 -0
  139. package/build/implementations/http/hono/path.d.ts +17 -0
  140. package/build/implementations/http/hono/path.js +39 -0
  141. package/build/implementations/http/hono/path.js.map +1 -0
  142. package/build/implementations/http/hono/path.test.d.ts +1 -0
  143. package/build/implementations/http/hono/path.test.js +83 -0
  144. package/build/implementations/http/hono/path.test.js.map +1 -0
  145. package/build/implementations/http/hono/types.d.ts +51 -0
  146. package/build/implementations/http/hono/types.js.map +1 -0
  147. package/build/implementations/http/on-request-error.test.js +6 -96
  148. package/build/implementations/http/on-request-error.test.js.map +1 -1
  149. package/build/implementations/http/route-errors.test.js +11 -59
  150. package/build/implementations/http/route-errors.test.js.map +1 -1
  151. package/build/implementations/types.d.ts +43 -9
  152. package/build/index.d.ts +124 -124
  153. package/build/index.js +10 -221
  154. package/build/index.js.map +1 -1
  155. package/build/index.test.js +20 -919
  156. package/build/index.test.js.map +1 -1
  157. package/build/migration.test.d.ts +1 -0
  158. package/build/migration.test.js +34 -0
  159. package/build/migration.test.js.map +1 -0
  160. package/build/schema/compute-schema.d.ts +11 -3
  161. package/build/schema/compute-schema.js +13 -7
  162. package/build/schema/compute-schema.js.map +1 -1
  163. package/build/schema/parser.d.ts +11 -3
  164. package/build/schema/parser.js +49 -9
  165. package/build/schema/parser.js.map +1 -1
  166. package/build/stack-utils.js +8 -0
  167. package/build/stack-utils.js.map +1 -1
  168. package/build/types.d.ts +142 -0
  169. package/build/types.js.map +1 -0
  170. package/docs/astro-adapter.md +5 -5
  171. package/docs/core.md +15 -17
  172. package/docs/http-integrations.md +83 -170
  173. package/docs/streaming.md +3 -60
  174. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +2 -7
  175. package/docs/superpowers/plans/2026-05-08-create-http.md +3355 -0
  176. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +3365 -0
  177. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +1 -3
  178. package/docs/superpowers/specs/2026-05-08-create-http-design.md +409 -0
  179. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +411 -0
  180. package/package.json +4 -22
  181. package/src/client/call.test.ts +26 -0
  182. package/src/client/call.ts +4 -1
  183. package/src/client/fetch-adapter.test.ts +14 -1
  184. package/src/client/fetch-adapter.ts +3 -1
  185. package/src/client/index.test.ts +7 -7
  186. package/src/client/request-builder.ts +2 -2
  187. package/src/client/stream.test.ts +39 -7
  188. package/src/client/stream.ts +16 -2
  189. package/src/client/typed-error-dispatch.test.ts +7 -97
  190. package/src/client/types.ts +21 -3
  191. package/src/codegen/__fixtures__/users-envelope.json +119 -38
  192. package/src/codegen/e2e.test.ts +98 -24
  193. package/src/codegen/emit-errors.integration.test.ts +1 -1
  194. package/src/codegen/emit-scope.test.ts +395 -110
  195. package/src/codegen/emit-scope.ts +350 -55
  196. package/src/codegen/pipeline.test.ts +7 -7
  197. package/src/codegen/resolve-envelope.test.ts +5 -5
  198. package/src/codegen/resolve-envelope.ts +1 -1
  199. package/src/codegen/targets/_shared/route-slots.test.ts +109 -26
  200. package/src/codegen/targets/_shared/route-slots.ts +48 -11
  201. package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +73 -0
  202. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +100 -17
  203. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +9 -6
  204. package/src/codegen/targets/kotlin/integration.test.ts +19 -0
  205. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +79 -0
  206. package/src/codegen/targets/swift/access-level.test.ts +8 -11
  207. package/src/codegen/targets/swift/emit-route-swift.test.ts +103 -20
  208. package/src/codegen/targets/swift/emit-scope-swift.test.ts +12 -9
  209. package/src/codegen/targets/swift/integration.test.ts +17 -0
  210. package/src/create-http-stream.test.ts +97 -0
  211. package/src/create-http-stream.ts +191 -0
  212. package/src/create-http.test.ts +163 -0
  213. package/src/create-http.ts +211 -0
  214. package/src/create-stream.test.ts +565 -0
  215. package/src/create-stream.ts +228 -0
  216. package/src/create.test.ts +658 -0
  217. package/src/create.ts +172 -0
  218. package/src/exports.ts +2 -0
  219. package/src/implementations/http/README.md +135 -95
  220. package/src/implementations/http/astro/README.md +4 -5
  221. package/src/implementations/http/astro/index.test.ts +25 -18
  222. package/src/implementations/http/doc-registry.test.ts +42 -5
  223. package/src/implementations/http/doc-registry.ts +1 -1
  224. package/src/implementations/http/error-dispatch.test.ts +283 -0
  225. package/src/implementations/http/error-dispatch.ts +176 -0
  226. package/src/implementations/http/error-taxonomy.ts +5 -5
  227. package/src/implementations/http/hono/docs/http-doc.ts +43 -0
  228. package/src/implementations/http/hono/docs/http-stream-doc.ts +44 -0
  229. package/src/implementations/http/hono/docs/rpc-doc.ts +34 -0
  230. package/src/implementations/http/hono/docs/stream-doc.ts +53 -0
  231. package/src/implementations/http/hono/handlers/http-stream.test.ts +150 -0
  232. package/src/implementations/http/hono/handlers/http-stream.ts +152 -0
  233. package/src/implementations/http/hono/handlers/http.test.ts +130 -0
  234. package/src/implementations/http/hono/handlers/http.ts +147 -0
  235. package/src/implementations/http/hono/handlers/rpc.test.ts +81 -0
  236. package/src/implementations/http/hono/handlers/rpc.ts +54 -0
  237. package/src/implementations/http/hono/handlers/stream.test.ts +198 -0
  238. package/src/implementations/http/hono/handlers/stream.ts +208 -0
  239. package/src/implementations/http/hono/index.test.ts +329 -0
  240. package/src/implementations/http/hono/index.ts +204 -0
  241. package/src/implementations/http/hono/path.test.ts +96 -0
  242. package/src/implementations/http/hono/path.ts +59 -0
  243. package/src/implementations/http/hono/types.ts +93 -0
  244. package/src/implementations/http/on-request-error.test.ts +10 -116
  245. package/src/implementations/http/route-errors.test.ts +11 -77
  246. package/src/implementations/types.ts +44 -9
  247. package/src/index.test.ts +22 -1249
  248. package/src/index.ts +49 -485
  249. package/src/migration.test.ts +48 -0
  250. package/src/schema/compute-schema.ts +26 -12
  251. package/src/schema/parser.ts +62 -12
  252. package/src/stack-utils.ts +8 -0
  253. package/src/types.ts +133 -0
  254. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/express-rpc.md +0 -137
  255. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-api.md +0 -173
  256. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-rpc.md +0 -142
  257. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-stream.md +0 -147
  258. package/build/implementations/http/express-rpc/error-taxonomy.test.js +0 -83
  259. package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +0 -1
  260. package/build/implementations/http/express-rpc/index.d.ts +0 -125
  261. package/build/implementations/http/express-rpc/index.js +0 -216
  262. package/build/implementations/http/express-rpc/index.js.map +0 -1
  263. package/build/implementations/http/express-rpc/index.test.js +0 -684
  264. package/build/implementations/http/express-rpc/index.test.js.map +0 -1
  265. package/build/implementations/http/express-rpc/types.d.ts +0 -11
  266. package/build/implementations/http/express-rpc/types.js.map +0 -1
  267. package/build/implementations/http/hono-api/error-taxonomy.test.js +0 -137
  268. package/build/implementations/http/hono-api/error-taxonomy.test.js.map +0 -1
  269. package/build/implementations/http/hono-api/index.d.ts +0 -151
  270. package/build/implementations/http/hono-api/index.js +0 -344
  271. package/build/implementations/http/hono-api/index.js.map +0 -1
  272. package/build/implementations/http/hono-api/index.test.js +0 -992
  273. package/build/implementations/http/hono-api/index.test.js.map +0 -1
  274. package/build/implementations/http/hono-api/types.d.ts +0 -13
  275. package/build/implementations/http/hono-api/types.js.map +0 -1
  276. package/build/implementations/http/hono-rpc/error-taxonomy.test.js +0 -64
  277. package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +0 -1
  278. package/build/implementations/http/hono-rpc/index.d.ts +0 -130
  279. package/build/implementations/http/hono-rpc/index.js +0 -209
  280. package/build/implementations/http/hono-rpc/index.js.map +0 -1
  281. package/build/implementations/http/hono-rpc/index.test.js +0 -828
  282. package/build/implementations/http/hono-rpc/index.test.js.map +0 -1
  283. package/build/implementations/http/hono-rpc/types.d.ts +0 -11
  284. package/build/implementations/http/hono-rpc/types.js +0 -2
  285. package/build/implementations/http/hono-rpc/types.js.map +0 -1
  286. package/build/implementations/http/hono-stream/error-taxonomy.test.js +0 -159
  287. package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +0 -1
  288. package/build/implementations/http/hono-stream/index.d.ts +0 -171
  289. package/build/implementations/http/hono-stream/index.js +0 -415
  290. package/build/implementations/http/hono-stream/index.js.map +0 -1
  291. package/build/implementations/http/hono-stream/index.test.js +0 -1383
  292. package/build/implementations/http/hono-stream/index.test.js.map +0 -1
  293. package/build/implementations/http/hono-stream/types.d.ts +0 -15
  294. package/build/implementations/http/hono-stream/types.js +0 -2
  295. package/build/implementations/http/hono-stream/types.js.map +0 -1
  296. package/src/implementations/http/express-rpc/README.md +0 -280
  297. package/src/implementations/http/express-rpc/error-taxonomy.test.ts +0 -103
  298. package/src/implementations/http/express-rpc/index.test.ts +0 -957
  299. package/src/implementations/http/express-rpc/index.ts +0 -327
  300. package/src/implementations/http/express-rpc/types.ts +0 -16
  301. package/src/implementations/http/hono-api/README.md +0 -284
  302. package/src/implementations/http/hono-api/error-taxonomy.test.ts +0 -179
  303. package/src/implementations/http/hono-api/index.test.ts +0 -1341
  304. package/src/implementations/http/hono-api/index.ts +0 -519
  305. package/src/implementations/http/hono-api/types.ts +0 -16
  306. package/src/implementations/http/hono-rpc/README.md +0 -357
  307. package/src/implementations/http/hono-rpc/error-taxonomy.test.ts +0 -82
  308. package/src/implementations/http/hono-rpc/index.test.ts +0 -1107
  309. package/src/implementations/http/hono-rpc/index.ts +0 -320
  310. package/src/implementations/http/hono-rpc/types.ts +0 -16
  311. package/src/implementations/http/hono-stream/README.md +0 -559
  312. package/src/implementations/http/hono-stream/error-taxonomy.test.ts +0 -178
  313. package/src/implementations/http/hono-stream/index.test.ts +0 -1804
  314. package/src/implementations/http/hono-stream/index.ts +0 -622
  315. package/src/implementations/http/hono-stream/types.ts +0 -20
  316. /package/build/{implementations/http/express-rpc/error-taxonomy.test.d.ts → create-http-stream.test.d.ts} +0 -0
  317. /package/build/{implementations/http/express-rpc/index.test.d.ts → create-http.test.d.ts} +0 -0
  318. /package/build/{implementations/http/hono-api/error-taxonomy.test.d.ts → create-stream.test.d.ts} +0 -0
  319. /package/build/{implementations/http/hono-api/index.test.d.ts → create.test.d.ts} +0 -0
  320. /package/build/implementations/http/{hono-rpc/error-taxonomy.test.d.ts → error-dispatch.test.d.ts} +0 -0
  321. /package/build/implementations/http/{hono-rpc/index.test.d.ts → hono/handlers/http-stream.test.d.ts} +0 -0
  322. /package/build/implementations/http/{hono-stream/error-taxonomy.test.d.ts → hono/handlers/http.test.d.ts} +0 -0
  323. /package/build/implementations/http/{hono-stream/index.test.d.ts → hono/handlers/rpc.test.d.ts} +0 -0
  324. /package/build/implementations/http/{express-rpc → hono}/types.js +0 -0
  325. /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[]