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
package/README.md CHANGED
@@ -48,13 +48,75 @@ const user = await GetUser({}, { userId: '123' })
48
48
  const user2 = await procedure({}, { userId: '456' })
49
49
  ```
50
50
 
51
+ ## v8 Migration — Unified `HonoAppBuilder`
52
+
53
+ The three Hono builders (`HonoRPCAppBuilder`, `HonoAPIAppBuilder`, `HonoStreamAppBuilder`) are replaced in v8 by a single `HonoAppBuilder` that accepts any `Procedures<>()` factory and dispatches all four procedure kinds (`rpc`, `rpc-stream`, `http`, `http-stream`) by `procedure.kind` from a single `register()` call.
54
+
55
+ ```typescript
56
+ // Before (v7)
57
+ const rpc = new HonoRPCAppBuilder({ app, errors }).register(F1, ctx1)
58
+ const api = new HonoAPIAppBuilder({ app, errors, queryParser }).register(F2, ctx2)
59
+ const stream = new HonoStreamAppBuilder({ app, errors, onMidStreamError }).register(F3, ctx3)
60
+
61
+ // After (v8)
62
+ const builder = new HonoAppBuilder({
63
+ app,
64
+ errors,
65
+ api: { queryParser },
66
+ stream: { onMidStreamError },
67
+ }).register(F1, ctx1).register(F2, ctx2).register(F3, ctx3)
68
+ ```
69
+
70
+ Kind-specific config knobs are stratified into `rpc.*`, `api.*`, and `stream.*` blocks. Single-app users can call `builder.toDocEnvelope()` directly (no `DocRegistry` needed). `DocRegistry` remains for multi-app aggregation.
71
+
72
+ Subpath imports change from `ts-procedures/hono-rpc`, `ts-procedures/hono-api`, `ts-procedures/hono-stream` to `ts-procedures/hono`.
73
+
74
+ ## HTTP Routes (v8) — `CreateHttp`
75
+
76
+ v8 introduces `CreateHttp` and `CreateHttpStream` as first-class HTTP creators. HTTP fields (`path`, `method`, `scope`, `errors`) live on the creator config directly; no factory type parameter is required.
77
+
78
+ ```typescript
79
+ import { Procedures } from 'ts-procedures'
80
+ import { HonoAppBuilder } from 'ts-procedures/hono'
81
+ import { Type } from 'typebox'
82
+
83
+ type AppContext = { userId: string }
84
+ const API = Procedures<AppContext>()
85
+
86
+ // Input channels: pathParams, query, body, headers (schema.req)
87
+ // Response: schema.res.body (docs) + schema.res.headers (makes handler return { body, headers })
88
+ API.CreateHttp('GetUser', {
89
+ path: '/users/:id',
90
+ method: 'get',
91
+ schema: {
92
+ req: { pathParams: Type.Object({ id: Type.String() }) },
93
+ res: { body: Type.Object({ id: Type.String(), name: Type.String() }) },
94
+ },
95
+ }, async (ctx, { pathParams }) => fetchUser(pathParams.id))
96
+
97
+ API.CreateHttp('CreateUser', {
98
+ path: '/users',
99
+ method: 'post',
100
+ schema: {
101
+ req: { body: Type.Object({ name: Type.String(), email: Type.String() }) },
102
+ },
103
+ }, async (ctx, { body }) => createUser(body))
104
+
105
+ const app = new HonoAppBuilder({ pathPrefix: '/api' })
106
+ .register(API, (c) => ({ userId: c.req.header('x-user-id') || 'anonymous' }))
107
+ .build()
108
+ // GET /api/users/:id → 200, POST /api/users → 201
109
+ ```
110
+
111
+ **Migrating from v7?** Replace `Procedures<Ctx, APIConfig>()` → `Procedures<Ctx>()`, `.Create(` → `.CreateHttp(`, and `schema.input` → `schema.req`. Then re-run `npx ts-procedures-codegen`. See `CHANGELOG.md` for the full breaking-changes list.
112
+
51
113
  ## Features
52
114
 
53
- - **[Core Procedures](docs/core.md)** — Type-safe procedure definitions with `Procedures()`, `Create`, and `CreateStream`. Includes schema validation with TypeBox, error handling, generics, testing patterns, and the full API reference.
115
+ - **[Core Procedures](docs/core.md)** — Type-safe procedure definitions with `Procedures()`, `Create`, `CreateHttp`, and `CreateStream`. Includes schema validation with TypeBox, error handling, generics, testing patterns, and the full API reference.
54
116
 
55
- - **[Streaming](docs/streaming.md)** — Async generator procedures with yield validation, abort signal integration, SSE examples, and stream error handling.
117
+ - **[Streaming](docs/streaming.md)** — Async generator procedures with yield validation, abort signal integration, SSE examples, and stream error handling. `CreateHttpStream` supports response headers via `TypedStream.headers`.
56
118
 
57
- - **[HTTP Integrations](docs/http-integrations.md)** — Express and Hono builders with lifecycle hooks, route documentation, `DocRegistry` for composing docs, and per-channel input validation.
119
+ - **[HTTP Integrations](docs/http-integrations.md)** — `HonoAppBuilder` with lifecycle hooks, route documentation, `DocRegistry` for composing docs, and per-channel input validation via `schema.req`.
58
120
 
59
121
  - **[Client Code Generation](docs/client-and-codegen.md)** — Generate type-safe client SDKs from your server's `DocRegistry`. CLI and programmatic API, adapters, hooks, streaming support, and self-contained mode.
60
122
 
@@ -22,7 +22,7 @@ When asked to plan an API or procedure set:
22
22
  3. **List procedures** — name, type (Create vs CreateStream), description
23
23
  4. **Design schemas** — params (validated), returnType/yieldType (documented)
24
24
  5. **Design context** — what each handler needs from the request
25
- 6. **Choose HTTP implementation** — Express, Hono RPC, Hono Stream, Hono API, or combination
25
+ 6. **Choose HTTP implementation** — `HonoAppBuilder` covers all four procedure kinds (rpc, rpc-stream, http, http-stream); pick which kinds the app needs
26
26
  7. **Plan error handling** — which layer for each error type
27
27
  8. **Map route structure** — scope + version for RPC routes, path + method for API routes
28
28
 
@@ -109,19 +109,17 @@ type AuthContext = { userId: string; requestId: string; db: Database }
109
109
  ```
110
110
 
111
111
  ### HTTP Setup
112
- - ExpressRPCAppBuilder or HonoRPCAppBuilder for standard RPC
113
- - HonoStreamAppBuilder for streaming (SSE mode)
114
- - HonoAPIAppBuilder for REST-style endpoints
115
- - DocRegistry to compose docs from all builders
112
+ - HonoAppBuilder for RPC, streams (SSE/text), and REST endpoints
113
+ - DocRegistry to compose docs across multiple builders (or `builder.toDocEnvelope()` for single-app)
116
114
  - Path prefix: /api
117
115
 
118
116
  ### Route Map
119
117
  - POST /api/health/health-check/1
120
118
  - POST /api/users/get-user/1
121
119
  - GET|POST /api/activity/stream-activity/1
122
- - GET /api/users/:id (HonoAPIAppBuilder)
123
- - POST /api/users (HonoAPIAppBuilder, 201)
124
- - DELETE /api/users/:id (HonoAPIAppBuilder, 204)
120
+ - GET /api/users/:id (HonoAppBuilder)
121
+ - POST /api/users (HonoAppBuilder, 201)
122
+ - DELETE /api/users/:id (HonoAppBuilder, 204)
125
123
 
126
124
  ### Error Handling (pick a mode, optionally combine)
127
125
  - **Declarative mode (recommended for structured apps)**: `defineErrorTaxonomy({ AuthError: {class, 401}, NotFoundError: {class, 404}, ... })` wired via `errors` config. Drives typed client dispatch + DocEnvelope.
@@ -66,7 +66,7 @@ Uses **TypeBox** for schema definitions (`import { Type } from 'typebox'`):
66
66
  | `schema.params` | **Validated at runtime** via AJV |
67
67
  | `schema.returnType` | **Documentation only**, never validated |
68
68
  | `schema.yieldType` | Validated only if `validateYields: true` in CreateStream config |
69
- | `schema.input` | Structured multi-channel input — alternative to `schema.params`, mutually exclusive |
69
+ | `schema.req` | Structured multi-channel HTTP input (`pathParams`, `query`, `body`, `headers`) available on `CreateHttp` / `CreateHttpStream` only |
70
70
 
71
71
  AJV config: `allErrors: true`, `coerceTypes: true`, `removeAdditional: true`
72
72
 
@@ -94,7 +94,7 @@ const appErrors = defineErrorTaxonomy({
94
94
  UseCaseError: { class: UseCaseError, statusCode: 422, toResponse: (e) => ({ message: e.externalMsg }) },
95
95
  })
96
96
 
97
- new HonoAPIAppBuilder({ errors: appErrors, unknownError: { toResponse: () => ({ error: '...' }) } })
97
+ new HonoAppBuilder({ errors: appErrors, unknownError: { toResponse: () => ({ error: '...' }) } })
98
98
  ```
99
99
 
100
100
  Per-route narrowing: `APIConfig<keyof typeof appErrors & string>` / `RPCConfig<keyof typeof appErrors & string>` with a `errors: [...]` array on the config. Generated `_errors.ts` emits runtime classes — clients catch with `instanceof ${Service}Errors.${Name}` when using `create${Service}Client`.
@@ -103,13 +103,10 @@ Full contract: `docs/http-integrations.md § Error Handling` (canonical) and `ap
103
103
 
104
104
  ## HTTP Implementations
105
105
 
106
- | Builder | Import | Transport |
107
- |---------|--------|-----------|
108
- | `ExpressRPCAppBuilder` | `ts-procedures/express-rpc` | POST JSON |
109
- | `HonoRPCAppBuilder` | `ts-procedures/hono-rpc` | POST JSON |
110
- | `HonoStreamAppBuilder` | `ts-procedures/hono-stream` | SSE or newline-delimited JSON |
111
- | `HonoAPIAppBuilder` | `ts-procedures/hono-api` | REST-style with per-channel input |
112
- | `DocRegistry` | `ts-procedures/http-docs` | Compose route docs from multiple builders |
106
+ | Builder | Import | Handles |
107
+ |---------|--------|---------|
108
+ | `HonoAppBuilder` | `ts-procedures/hono` | RPC, REST-style HTTP, and streaming (SSE / newline-JSON) — one builder dispatches all four procedure kinds |
109
+ | `DocRegistry` | `ts-procedures/http-docs` | Compose route docs from multiple builders (single-app users can also call `builder.toDocEnvelope()`) |
113
110
 
114
111
  ### Route Path Format (RPC)
115
112
 
@@ -122,24 +119,28 @@ Example: `Create('GetUser', { scope: 'users', version: 1 }, ...)` --> `POST /use
122
119
  ### Builder Pattern
123
120
 
124
121
  ```typescript
125
- const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
126
- .register(factory, (req) => ({ /* context */ }))
122
+ const app = new HonoAppBuilder({ pathPrefix: '/api' })
123
+ .register(factory, (c) => ({ /* context */ }))
127
124
  .build()
128
125
  ```
129
126
 
130
127
  ### Lifecycle Hooks (HTTP builders)
131
128
 
132
- | Hook | When |
133
- |------|------|
134
- | `onRequestStart` | Before context resolution |
135
- | `onRequestEnd` | After response sent |
136
- | `onSuccess` | After successful handler execution |
137
- | `onError` | Imperative error callback first-class peer of the declarative `errors` taxonomy |
138
- | `onStreamStart` | Before first yield (HonoStreamAppBuilder) |
139
- | `onStreamEnd` | After stream closes (HonoStreamAppBuilder) |
140
- | `onError` (HonoStream) | Imperative pre-stream error callback peer of `errors` taxonomy |
141
- | `onRequestError` | Cross-cutting observer fires for every caught error before dispatch |
142
- | `onMidStreamError` | Error during streaming (return data to yield as final event) |
129
+ For `HonoAppBuilder` (v8), hooks are stratified: cross-cutting hooks live at the top level, kind-specific hooks live inside `rpc:` / `api:` / `stream:` blocks.
130
+
131
+ | Hook | Block | When |
132
+ |------|-------|------|
133
+ | `onRequestStart` | top level | Before context resolution (every kind) |
134
+ | `onRequestEnd` | top level | After response sent (every kind) |
135
+ | `onError` | top level | Imperative pre-stream / unary error callback — first-class peer of the declarative `errors` taxonomy |
136
+ | `onRequestError` | top level | Cross-cutting observer — fires for every caught error before dispatch |
137
+ | `rpc.onSuccess` | `rpc` block | After successful `Create` handler execution |
138
+ | `api.onSuccess` | `api` block | After successful `CreateHttp` handler execution |
139
+ | `api.queryParser` | `api` block | Custom query string parser for `CreateHttp` routes |
140
+ | `stream.defaultStreamMode` | `stream` block | Default mode for streaming routes (`'sse'` or `'text'`) |
141
+ | `stream.onStreamStart` | `stream` block | Before first yield |
142
+ | `stream.onStreamEnd` | `stream` block | After stream closes |
143
+ | `stream.onMidStreamError` | `stream` block | Error during streaming (return data to yield as final event — the only mid-stream path) |
143
144
 
144
145
  ## Decision Framework
145
146
 
@@ -148,17 +149,13 @@ const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
148
149
  - Request --> multiple values over time --> **CreateStream**
149
150
 
150
151
  **Which schema approach?**
151
- - RPC-style (single `params` object, POST-only) --> `schema.params`
152
- - REST-style (multiple HTTP input sources) --> `schema.input`
153
- - `schema.params` and `schema.input` are **mutually exclusive**
152
+ - RPC-style (single `params` object, POST-only) --> `Create` / `CreateStream` with `schema.params`
153
+ - REST-style (multiple HTTP input sources: pathParams, query, body, headers) --> `CreateHttp` / `CreateHttpStream` with `schema.req`
154
154
 
155
155
  **Which HTTP implementation?**
156
- - Express app --> **ExpressRPCAppBuilder**
157
- - Hono app (standard RPC) --> **HonoRPCAppBuilder**
158
- - Hono app (streaming) --> **HonoStreamAppBuilder**
159
- - Hono app (REST-style) --> **HonoAPIAppBuilder**
160
- - SSE with browser EventSource --> `streamMode: 'sse'`
161
- - Simple text streaming --> `streamMode: 'text'`
156
+ - Hono app (any combination of RPC / REST / streaming) --> **HonoAppBuilder** (one builder dispatches every kind)
157
+ - SSE with browser EventSource --> `stream.defaultStreamMode: 'sse'` on the builder, or `streamMode: 'sse'` per `register()` call
158
+ - Simple text streaming --> `stream.defaultStreamMode: 'text'`
162
159
 
163
160
  **How to group procedures?**
164
161
  - By domain: `UserProcedures`, `OrderProcedures`
@@ -171,9 +168,9 @@ The npm package ships user-facing documentation with narrative explanations and
171
168
 
172
169
  | File | Covers |
173
170
  |------|--------|
174
- | `docs/core.md` | Procedures factory, Create, CreateStream, schema.input, error handling |
171
+ | `docs/core.md` | Procedures factory, Create, CreateStream, schema.req, error handling |
175
172
  | `docs/streaming.md` | Streaming procedures, AbortSignal, SSE patterns |
176
- | `docs/http-integrations.md` | Express RPC, Hono RPC/Stream/API builders, **error taxonomy (canonical)**, DocRegistry (unified constructor, `.documentError()`) |
173
+ | `docs/http-integrations.md` | Hono unified builder (`HonoAppBuilder` — RPC + HTTP + streaming with stratified config), **error taxonomy (canonical)**, DocRegistry (unified constructor, `.documentError()`) |
177
174
  | `docs/client-and-codegen.md` | Client code generation, `createApiClient`/`createClient`, typed error dispatch, per-route `Errors` unions, per-call options, client-level defaults, typed RequestMeta augmentation, CLI options |
178
175
  | `docs/client-error-handling.md` | **Canonical guide** for 7.0+ client error surface: normalized error classes, `.safe()` Result API, `ClientErrorMap` augmentation, custom `ErrorClassifier`, migration from `ClientRequestError`. |
179
176
  | `CHANGELOG.md` | Release notes — see `[7.0.0]` for the safe-result API, new error classes, and `ClientRequestError` → `ClientHttpError` rename. See `[6.0.0]` for the peer error-handling model (taxonomy + `onError` + `onRequestError`). |
@@ -342,29 +342,37 @@ Create('GetUser', {}, async (ctx, params) => {
342
342
 
343
343
  ---
344
344
 
345
- ## 12. Registering Standard Procedures with HonoStreamAppBuilder
345
+ ## 12. Splitting Procedures Across Multiple HonoAppBuilder Instances
346
346
 
347
- **Problem:** Using `Create` procedures with `HonoStreamAppBuilder`it only handles `CreateStream` procedures.
347
+ **Problem:** Creating one `HonoAppBuilder` per procedure kind (RPC, stream, HTTP) the way v7 required duplicating cross-cutting config (errors, lifecycle hooks, context factories) in every instance.
348
348
 
349
349
  ```typescript
350
- // BAD — Create procedures are silently ignored
351
- const { Create, CreateStream } = Procedures<AppContext, RPCConfig>()
352
- Create('GetUser', { scope: 'users', version: 1 }, handler)
353
- CreateStream('StreamEvents', { scope: 'events', version: 1 }, streamHandler)
354
-
355
- new HonoStreamAppBuilder()
356
- .register(factory, ctx) // Only StreamEvents is registered
357
- .build()
350
+ // BAD — three builders, three copies of the same config
351
+ const rpcApp = new HonoAppBuilder({ errors: appErrors }).register(RPC, ctx).build()
352
+ const streamApp = new HonoAppBuilder({ errors: appErrors }).register(StreamRPC, ctx).build()
353
+ const apiApp = new HonoAppBuilder({ errors: appErrors }).register(API, ctx).build()
358
354
  ```
359
355
 
360
- **Fix:** Use `HonoRPCAppBuilder` or `ExpressRPCAppBuilder` for standard procedures. Use `HonoStreamAppBuilder` only for stream procedures.
356
+ **Fix:** In v8, `HonoAppBuilder` dispatches all four procedure kinds (`Create`, `CreateStream`, `CreateHttp`, `CreateHttpStream`) from a single `register()` call. One builder, one config block, all procedures.
361
357
 
362
358
  ```typescript
363
- // GOOD
364
- const rpcApp = new HonoRPCAppBuilder().register(RPC, ctx).build()
365
- const streamApp = new HonoStreamAppBuilder().register(StreamRPC, ctx).build()
359
+ // GOOD — one builder, all procedure kinds
360
+ const procs = Procedures<AppContext, RPCConfig>()
361
+ procs.Create('GetUser', { scope: 'users', version: 1 }, rpcHandler)
362
+ procs.CreateStream('StreamEvents', { scope: 'events', version: 1 }, streamHandler)
363
+ procs.CreateHttp('CreateUser', { path: '/users', method: 'post', schema: { /* ... */ } }, httpHandler)
364
+
365
+ const app = new HonoAppBuilder({
366
+ errors: appErrors,
367
+ unknownError: { toResponse: (err) => ({ error: (err as Error).message }) },
368
+ stream: { defaultStreamMode: 'sse' },
369
+ })
370
+ .register(procs, (c) => ({ /* ctx */ }))
371
+ .build()
366
372
  ```
367
373
 
374
+ **Why:** v8 collapsed v7's `HonoRPCAppBuilder` / `HonoStreamAppBuilder` / `HonoAPIAppBuilder` into one builder with stratified config (`rpc.{onSuccess}`, `api.{queryParser, onSuccess}`, `stream.{defaultStreamMode, onStreamStart, onStreamEnd, onMidStreamError}`). Cross-cutting config (`errors`, `unknownError`, `onError`, `onRequestError`, `onRequestStart`, `onRequestEnd`) lives at the top level and applies uniformly across kinds.
375
+
368
376
  ---
369
377
 
370
378
  ## 13. Missing Schema at Registration Time
@@ -398,9 +406,14 @@ Create('GetUser', {
398
406
  **Problem:** Using a single error handler for both validation errors (before streaming) and runtime errors (during streaming).
399
407
 
400
408
  ```typescript
401
- // BAD — onError doesn't apply to streaming
402
- new HonoStreamAppBuilder({
403
- onError: (proc, c, err) => { /* This doesn't exist */ },
409
+ // BAD — top-level onError fires for pre-stream errors only.
410
+ // Errors thrown after the first yield will NOT reach this callback.
411
+ new HonoAppBuilder({
412
+ onError: (proc, c, err) => {
413
+ // Catches pre-stream (validation / context) errors only.
414
+ // Mid-stream errors silently pass through — the HTTP status is already
415
+ // committed, so the response can't be rewritten here.
416
+ },
404
417
  })
405
418
  ```
406
419
 
@@ -410,15 +423,17 @@ new HonoStreamAppBuilder({
410
423
  // GOOD
411
424
  import { defineErrorTaxonomy } from 'ts-procedures/http-errors'
412
425
 
413
- new HonoStreamAppBuilder({
426
+ new HonoAppBuilder({
414
427
  // Taxonomy handles all pre-stream errors (validation, auth, context)
415
428
  errors: defineErrorTaxonomy({
416
429
  AuthError: { class: AuthError, statusCode: 401 },
417
430
  }),
418
431
  unknownError: { toResponse: (err) => ({ error: (err as Error).message }) },
419
- // Mid-stream still goes through onMidStreamError — the HTTP status is
420
- // already committed, so errors become yields, not responses.
421
- onMidStreamError: (proc, c, error) => ({ data: { error: error.message }, closeStream: true }),
432
+ // Mid-stream still goes through stream.onMidStreamError — the HTTP status
433
+ // is already committed, so errors become yields, not responses.
434
+ stream: {
435
+ onMidStreamError: (proc, c, error) => ({ data: { error: error.message }, closeStream: true }),
436
+ },
422
437
  })
423
438
  ```
424
439
 
@@ -516,75 +531,70 @@ const appErrors = defineErrorTaxonomy({
516
531
  },
517
532
  })
518
533
 
519
- const app = new ExpressRPCAppBuilder({
534
+ const app = new HonoAppBuilder({
520
535
  errors: appErrors,
521
536
  unknownError: { toResponse: () => ({ error: 'Internal server error' }) },
522
537
  })
523
- .register(factory, async (req) => {
524
- const user = await authenticate(req.headers.authorization)
538
+ .register(factory, async (c) => {
539
+ const user = await authenticate(c.req.header('authorization'))
525
540
  if (!user) throw new AuthError('invalid token')
526
541
  return { userId: user.id }
527
542
  })
528
543
  ```
529
544
 
530
- The imperative `onError: (procedure, req, res, error) => void` callback is a first-class peer — use it for apps that prefer a single response handler or when you want to handle the tail of errors the taxonomy doesn't cover.
545
+ The imperative `onError: (procedure, c, error) => Response` callback is a first-class peer — use it for apps that prefer a single response handler or when you want to handle the tail of errors the taxonomy doesn't cover.
531
546
 
532
547
  ---
533
548
 
534
- ## 18. Using Both schema.params and schema.input
549
+ ## 18. Mixing schema.params and schema.req on the same procedure
535
550
 
536
- **Problem:** Defining both `schema.params` and `schema.input` on the same procedure.
551
+ **Problem:** `schema.params` (RPC channel) and `schema.req` (HTTP channel) are mutually exclusive on `CreateHttp`. Using both throws at registration.
537
552
 
538
553
  ```typescript
539
554
  // BAD — throws ProcedureRegistrationError at registration
540
- Create('GetUser', {
555
+ API.CreateHttp('GetUser', {
541
556
  path: '/users/:id',
542
557
  method: 'get',
543
558
  schema: {
544
- params: Type.Object({ id: Type.String() }),
545
- input: {
559
+ params: Type.Object({ id: Type.String() }), // RPC-only field — invalid on CreateHttp
560
+ req: {
546
561
  pathParams: Type.Object({ id: Type.String() }),
547
562
  },
548
563
  },
549
564
  }, handler)
550
565
  ```
551
566
 
552
- **Fix:** Choose one. Use `schema.params` for flat RPC-style input, `schema.input` for structured multi-channel input.
567
+ **Fix:** Use `schema.req` for HTTP routes (`CreateHttp`). Use `schema.params` for RPC routes (`Create`). Never mix them.
553
568
 
554
569
  ```typescript
555
- // GOOD — schema.input for REST-style with per-channel validation
556
- Create('GetUser', {
570
+ // GOOD — CreateHttp with schema.req for per-channel validation
571
+ API.CreateHttp('GetUser', {
557
572
  path: '/users/:id',
558
573
  method: 'get',
559
574
  schema: {
560
- input: {
561
- pathParams: Type.Object({ id: Type.String() }),
562
- },
575
+ req: { pathParams: Type.Object({ id: Type.String() }) },
563
576
  },
564
577
  }, async (ctx, { pathParams }) => fetchUser(pathParams.id))
565
578
 
566
- // GOOD — schema.params for simple RPC-style
567
- Create('GetUser', {
568
- scope: 'users', version: 1,
579
+ // GOOD — Create with schema.params for flat RPC-style
580
+ const { GetUser } = Create('GetUser', {
569
581
  schema: { params: Type.Object({ id: Type.String() }) },
570
582
  }, async (ctx, params) => fetchUser(params.id))
571
583
  ```
572
584
 
573
- **Why:** `schema.params` and `schema.input` are mutually exclusive by design. They represent different input paradigms — flat (RPC) vs structured (HTTP API).
574
-
575
585
  ---
576
586
 
577
- ## 19. Mismatched Path Param Names in schema.input
587
+ ## 19. Mismatched Path Param Names in schema.req.pathParams
578
588
 
579
- **Problem:** Path template param names don't match `schema.input.pathParams` property names.
589
+ **Problem:** Path template param names don't match `schema.req.pathParams` property names.
580
590
 
581
591
  ```typescript
582
- // BAD — path has :id but schema declares userId — throws at build time
583
- Create('GetUser', {
592
+ // BAD — path has :id but schema declares userId — throws at registration
593
+ API.CreateHttp('GetUser', {
584
594
  path: '/users/:id',
585
595
  method: 'get',
586
596
  schema: {
587
- input: {
597
+ req: {
588
598
  pathParams: Type.Object({ userId: Type.String() }), // Wrong name!
589
599
  },
590
600
  },
@@ -595,18 +605,18 @@ Create('GetUser', {
595
605
 
596
606
  ```typescript
597
607
  // GOOD
598
- Create('GetUser', {
608
+ API.CreateHttp('GetUser', {
599
609
  path: '/users/:id',
600
610
  method: 'get',
601
611
  schema: {
602
- input: {
612
+ req: {
603
613
  pathParams: Type.Object({ id: Type.String() }), // Matches :id
604
614
  },
605
615
  },
606
616
  }, handler)
607
617
  ```
608
618
 
609
- **Why:** `HonoAPIAppBuilder` validates at build time that `:param` names in the path match schema properties. A mismatch would cause runtime validation failures with confusing error messages.
619
+ **Why:** `CreateHttp` validates at registration time that `:param` names in the path match `schema.req.pathParams` property names. A mismatch throws `ProcedureRegistrationError` immediately so you catch it at startup, not at runtime.
610
620
 
611
621
  ---
612
622
 
@@ -616,7 +626,7 @@ Create('GetUser', {
616
626
 
617
627
  ```typescript
618
628
  // BAD — duplicated across builders, invisible to generated clients
619
- new HonoAPIAppBuilder({
629
+ new HonoAppBuilder({
620
630
  onError: (procedure, c, error) => {
621
631
  if (error instanceof ValidationError) return c.json({ error: error.message }, 400)
622
632
  if (error instanceof AuthError) return c.json({ error: 'Unauthorized' }, 401)
@@ -642,7 +652,7 @@ const appErrors = defineErrorTaxonomy({
642
652
  },
643
653
  })
644
654
 
645
- new HonoAPIAppBuilder({
655
+ new HonoAppBuilder({
646
656
  errors: appErrors,
647
657
  unknownError: {
648
658
  toResponse: () => ({ error: 'Internal server error' }),
@@ -651,7 +661,7 @@ new HonoAPIAppBuilder({
651
661
  })
652
662
  ```
653
663
 
654
- The same `errors` / `unknownError` shape plugs into every builder (`HonoAPIAppBuilder`, `HonoRPCAppBuilder`, `ExpressRPCAppBuilder`, `HonoStreamAppBuilder` pre-stream only). `ctx.error()` still works and is caught by the default taxonomy at 500.
664
+ The same `errors` / `unknownError` shape plugs into `HonoAppBuilder` and applies uniformly across RPC, HTTP, and pre-stream paths. `ctx.error()` still works and is caught by the default taxonomy at 500.
655
665
 
656
666
  **The anti-pattern is the ladder, not `onError`.** `onError` is a first-class peer of the taxonomy — it's perfectly fine for simple apps or when you want full response control. The problem is writing `instanceof` ladders *inside* it to route by error class, because that's exactly what the taxonomy is designed to express declaratively.
657
667
 
@@ -729,6 +739,46 @@ const { Create: CreateInternal } = Procedures({
729
739
 
730
740
  ---
731
741
 
742
+ ## 23. Using `Create` for HTTP routes (v8+)
743
+
744
+ **Problem:** Using `Create` with HTTP-specific fields (`path`, `method`, `schema.input`) — this throws at registration time in v8.
745
+
746
+ ```typescript
747
+ // BAD — throws ProcedureRegistrationError in v8; Create is the RPC primitive only
748
+ const API = Procedures<Ctx, APIConfig>()
749
+
750
+ API.Create('GetUser', {
751
+ path: '/users/:id',
752
+ method: 'get',
753
+ schema: { input: { pathParams: Type.Object({ id: Type.String() }) } },
754
+ }, async (ctx, params) => { /* ... */ })
755
+ ```
756
+
757
+ **Fix:** Use `CreateHttp` for HTTP routes. `schema.input` is renamed `schema.req` in v8.
758
+
759
+ ```typescript
760
+ // GOOD — v8 HTTP surface
761
+ const API = Procedures<Ctx>()
762
+
763
+ API.CreateHttp('GetUser', {
764
+ path: '/users/:id',
765
+ method: 'get',
766
+ schema: { req: { pathParams: Type.Object({ id: Type.String() }) } },
767
+ }, async (ctx, { pathParams }) => fetchUser(pathParams.id))
768
+ ```
769
+
770
+ **Migration checklist:**
771
+
772
+ 1. Replace `Procedures<Ctx, APIConfig>()` with `Procedures<Ctx>()` for HTTP factories.
773
+ 2. Replace `.Create(` with `.CreateHttp(` for every HTTP route.
774
+ 3. Rename `schema.input` → `schema.req` (same channels: `pathParams`, `query`, `body`, `headers`).
775
+ 4. Move response type to `schema.res.body` (optional — `returnType` was docs-only anyway).
776
+ 5. Re-run `npx ts-procedures-codegen` to regenerate clients.
777
+
778
+ **Why:** `Create` is the RPC primitive (`params` / `returnType` only). HTTP routes with `path`, `method`, and per-channel input belong on `CreateHttp` (unary) or `CreateHttpStream` (streaming). Separating the surfaces makes the builder routing explicit and allows `CreateHttp` to support response headers (`schema.res.headers`) without leaking HTTP concepts into the RPC path.
779
+
780
+ ---
781
+
732
782
  ## Summary Table
733
783
 
734
784
  | # | Anti-Pattern | Risk | Severity |
@@ -744,7 +794,7 @@ const { Create: CreateInternal } = Procedures({
744
794
  | 9 | Manual type coercion | Unnecessary code, coercion mismatch | SUGGESTION |
745
795
  | 10 | Expecting extra fields to survive | Silent data loss | WARNING |
746
796
  | 11 | Missing context type | No type safety in handlers | WARNING |
747
- | 12 | Create with HonoStreamAppBuilder | Procedures silently ignored | CRITICAL |
797
+ | 12 | Splitting procedures across multiple HonoAppBuilder instances | Duplicated cross-cutting config; one builder dispatches all kinds in v8 | WARNING |
748
798
  | 13 | Plain JSON Schema objects instead of TypeBox | ProcedureRegistrationError | CRITICAL |
749
799
  | 14 | Wrong error handler for streams | Unhandled errors or wrong response format | WARNING |
750
800
  | 15 | Manual doc building instead of extendProcedureDoc | Fragile, incomplete documentation | SUGGESTION |
@@ -755,3 +805,4 @@ const { Create: CreateInternal } = Procedures({
755
805
  | 20 | Hand-writing onError instanceof ladders | Drifting response shapes, untyped client errors | WARNING |
756
806
  | 21 | Catching raw DOMException/TypeError from generated callables | Framework normalizes these; raw platform errors won't reach catch blocks after 7.0.0 | WARNING |
757
807
  | 22 | `noRuntimeValidation` on a public-facing factory | Untrusted wire data reaches handlers without AJV; coerceTypes/removeAdditional also disabled | CRITICAL |
808
+ | 23 | Using `Create` for HTTP routes (v8+) | ProcedureRegistrationError at startup; HTTP fields require `CreateHttp` / `CreateHttpStream` | CRITICAL |