ts-procedures 7.2.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 +139 -53
  5. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +208 -231
  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 +36 -48
  12. package/agent_config/cursor/cursorrules +36 -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 +125 -115
  153. package/build/index.js +10 -222
  154. package/build/index.js.map +1 -1
  155. package/build/index.test.js +30 -822
  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 +34 -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 +35 -1091
  248. package/src/index.ts +50 -474
  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/docs/core.md CHANGED
@@ -10,6 +10,7 @@ The `Procedures()` function creates a factory for defining procedures. It accept
10
10
 
11
11
  ```typescript
12
12
  Procedures<TContext, TExtendedConfig>(builder?: {
13
+ config?: { noRuntimeValidation?: true }
13
14
  onCreate?: (procedure: TProcedureRegistration<TContext, TExtendedConfig>) => void
14
15
  })
15
16
  ```
@@ -18,6 +19,7 @@ Procedures<TContext, TExtendedConfig>(builder?: {
18
19
  |-----------|----------------------------------------------------------------------------|
19
20
  | `TContext` | The base context type passed to all handlers as the first parameter |
20
21
  | `TExtendedConfig` | Additional configuration properties for all procedures `config` properties |
22
+ | `builder.config.noRuntimeValidation` | When `true`, every procedure created by this factory skips AJV validation of `schema.params` and `schema.input` at call time. Applies to both `Create` and `CreateStream`. Default: validation runs. |
21
23
  | `builder.onCreate` | Optional callback invoked when each procedure is registered (runtime) |
22
24
 
23
25
  ## Create Function
@@ -91,7 +93,7 @@ async function* (ctx, params) => AsyncGenerator<TYield, TReturn | void>
91
93
  - `ctx.error(message, meta?)` - Create a ProcedureError
92
94
  - `ctx.signal?` - AbortSignal for cancellation support (optional for `Create`, always present for `CreateStream`)
93
95
 
94
- When using the built-in HTTP implementations (Hono, Express), `ctx.signal` is automatically injected from the HTTP request, so handlers can detect client disconnection. For direct usage without a server, `signal` is `undefined` unless you pass one in context.
96
+ When using the built-in HTTP implementation (Hono), `ctx.signal` is automatically injected from the HTTP request, so handlers can detect client disconnection. For direct usage without a server, `signal` is `undefined` unless you pass one in context.
95
97
 
96
98
  **Returns:**
97
99
  - `{ [name]: handler }` - Named generator export
@@ -221,6 +223,22 @@ AJV is configured with:
221
223
 
222
224
  **Note:** `schema.params` is validated at runtime. `schema.returnType` is for documentation/introspection only.
223
225
 
226
+ ### Disabling Runtime Validation
227
+
228
+ For trusted internal callers — for example, a back-of-house factory whose inputs are already type-checked at build time and whose handlers are never invoked from public HTTP — pass `config.noRuntimeValidation: true` when constructing the factory:
229
+
230
+ ```typescript
231
+ const { Create, CreateStream } = Procedures({
232
+ config: { noRuntimeValidation: true },
233
+ })
234
+ ```
235
+
236
+ When set, every procedure registered by this factory skips AJV validation of `schema.params` and `schema.input` on every call. JSON Schema is still computed at registration time (so `info.schema` and codegen are unaffected) — only the per-call validator runs are bypassed.
237
+
238
+ **Use sparingly.** Do not enable this for procedures that accept input from public clients, untyped JSON bodies, or anything you do not control end-to-end. The flag is shaped as `noRuntimeValidation?: true` (only `true` is accepted) to make the opt-out explicit at the call site.
239
+
240
+ This is independent of the per-call `ctx.isPrevalidated` escape hatch used by HTTP builders that have already validated upstream — both paths short-circuit the same validators.
241
+
224
242
  ## Error Handling
225
243
 
226
244
  ### Using ctx.error()
@@ -274,7 +292,7 @@ The taxonomy also drives typed `catch` blocks on generated clients and per-route
274
292
 
275
293
  ## Abort Signal
276
294
 
277
- For regular procedures, `ctx.signal` is available when the server implementation provides it. The built-in HTTP integrations (Hono RPC, Express RPC) inject the request's abort signal automatically:
295
+ For regular procedures, `ctx.signal` is available when the server implementation provides it. The built-in HTTP integration (`HonoAppBuilder`) injects the request's abort signal automatically:
278
296
 
279
297
  ```typescript
280
298
  const { Create } = Procedures<{ signal: AbortSignal }>()
@@ -292,7 +310,7 @@ const { LongQuery } = Create(
292
310
  )
293
311
  ```
294
312
 
295
- When using the Hono or Express implementations, `ctx.signal` aborts when the client disconnects, automatically cancelling in-flight `fetch()` calls, database queries, or any other signal-aware operation.
313
+ When using the Hono implementation, `ctx.signal` aborts when the client disconnects, automatically cancelling in-flight `fetch()` calls, database queries, or any other signal-aware operation.
296
314
 
297
315
  For streaming abort signal behavior (including `signal.reason` and consumer break detection), see [Streaming Procedures](./streaming.md#abort-signal-integration).
298
316
 
@@ -300,27 +318,25 @@ For streaming abort signal behavior (including `signal.reason` and consumer brea
300
318
 
301
319
  ### onCreate Callback
302
320
 
303
- Register procedures with your framework (Express, Fastify, etc.):
321
+ Register procedures with a custom framework via the `onCreate` callback. Each registration receives `{ name, handler, config }` so you can wire it into whatever router or framework you want:
304
322
 
305
323
  ```typescript
306
- import express from 'express'
324
+ import { Hono } from 'hono'
325
+ import { ProcedureError } from 'ts-procedures'
307
326
 
308
- const app = express()
309
- const routes: Map<string, Function> = new Map()
327
+ const app = new Hono()
310
328
 
311
- const { Create } = Procedures<{ req: Request; res: Response }>({
312
- onCreate: ({ name, handler, config }) => {
313
- // Register as Express route
314
- app.post(`/rpc/${name}`, async (req, res) => {
329
+ const { Create } = Procedures<{ raw: unknown }>({
330
+ onCreate: ({ name, handler }) => {
331
+ app.post(`/rpc/${name}`, async (c) => {
315
332
  try {
316
- const result = await handler({ req, res }, req.body)
317
- res.json(result)
333
+ const result = await handler({ raw: c }, await c.req.json())
334
+ return c.json(result)
318
335
  } catch (e) {
319
336
  if (e instanceof ProcedureError) {
320
- res.status(500).json({ error: e.message })
321
- } else {
322
- res.status(500).json({ error: 'Internal error' })
337
+ return c.json({ error: e.message }, 500)
323
338
  }
339
+ return c.json({ error: 'Internal error' }, 500)
324
340
  }
325
341
  })
326
342
  },
@@ -329,7 +345,7 @@ const { Create } = Procedures<{ req: Request; res: Response }>({
329
345
  // Procedures are automatically registered as /rpc/GetUser, /rpc/CreateUser, etc.
330
346
  ```
331
347
 
332
- For built-in HTTP framework integrations (Express RPC, Hono RPC, Hono API, Hono Stream), see [HTTP Integrations](./http-integrations.md).
348
+ For the built-in HTTP integration (RPC, RPC streams, REST, REST streams via `HonoAppBuilder`), see [HTTP Integrations](./http-integrations.md).
333
349
 
334
350
  ### Introspection with getProcedures()
335
351
 
@@ -419,6 +435,7 @@ describe('GetUser', () => {
419
435
  Creates a procedure factory.
420
436
 
421
437
  **Parameters:**
438
+ - `builder.config.noRuntimeValidation` - When `true`, every procedure registered through this factory skips AJV validation of `schema.params` and `schema.input` at call time. Default: validation runs. See [Disabling Runtime Validation](#disabling-runtime-validation).
422
439
  - `builder.onCreate` - Callback invoked when each procedure is registered
423
440
 
424
441
  **Returns:**
@@ -2,89 +2,38 @@
2
2
 
3
3
  # HTTP Framework Integrations
4
4
 
5
- ts-procedures includes built-in HTTP builders for Express and Hono that handle routing, context resolution, lifecycle hooks, abort signals, and automatic route documentation. Each builder uses the `onCreate` callback internally to register procedures as HTTP endpoints.
5
+ ts-procedures includes a built-in HTTP builder for Hono that handles routing, context resolution, lifecycle hooks, abort signals, and automatic route documentation. The builder reads procedures off the factory at registration time and mounts the matching routes when you call `build()`.
6
6
 
7
- For a full cross-framework comparison (config interfaces, path generation, context resolution, abort signal, lifecycle hooks, route documentation), see the [HTTP implementations overview](../src/implementations/http/README.md).
7
+ For a full reference (config interfaces, path generation, context resolution, abort signal, lifecycle hooks, route documentation), see the [HTTP implementations overview](../src/implementations/http/README.md).
8
8
 
9
9
  ## Integrations at a Glance
10
10
 
11
- | Integration | Export | Style | Guide |
12
- |-------------|--------|-------|-------|
13
- | Express RPC | `ts-procedures/express-rpc` | RPC (POST routes) | [README](../src/implementations/http/express-rpc/README.md) |
14
- | Hono RPC | `ts-procedures/hono-rpc` | RPC (POST routes) | [README](../src/implementations/http/hono-rpc/README.md) |
15
- | Hono Stream | `ts-procedures/hono-stream` | SSE/text streaming | [README](../src/implementations/http/hono-stream/README.md) |
16
- | Hono API | `ts-procedures/hono-api` | REST (method-based) | [README](../src/implementations/http/hono-api/README.md) |
11
+ | Integration | Export | Procedure kinds | Guide |
12
+ |-------------|--------|-----------------|-------|
13
+ | HonoAppBuilder | `ts-procedures/hono` | `rpc`, `rpc-stream`, `http`, `http-stream` | [HTTP implementations overview](../src/implementations/http/README.md) |
17
14
 
18
- ## Express RPC
15
+ ## Hono
19
16
 
20
- RPC-style HTTP integration for Express that creates POST routes at `/rpc/{name}/{version}` paths with automatic JSON schema documentation.
17
+ `HonoAppBuilder` is the single Hono integration. One builder dispatches all four procedure kinds — `rpc`, `rpc-stream`, `http`, `http-stream` — from one `register()` call. Works with Bun, Deno, Cloudflare Workers, and Node.js.
21
18
 
22
19
  ```typescript
23
- import { ExpressRPCAppBuilder, RPCConfig } from 'ts-procedures/express-rpc'
24
-
25
- const RPC = Procedures<AppContext, RPCConfig>()
26
-
27
- RPC.Create(
28
- 'GetUser',
29
- {
30
- scope: ['users', 'get'],
31
- version: 1,
32
- schema: {
33
- params: Type.Object({ id: Type.String() }),
34
- returnType: Type.Object({ id: Type.String(), name: Type.String() }),
35
- },
36
- },
37
- async (ctx, params) => {
38
- return { id: params.id, name: 'John Doe' }
39
- }
40
- )
41
-
42
- const app = new ExpressRPCAppBuilder()
43
- .register(RPC, (req) => ({ userId: req.headers['x-user-id'] as string }))
44
- .build()
45
-
46
- app.listen(3000)
47
- // Route created: POST /users/get/get-user/1
48
- ```
49
-
50
- See the [Express RPC Integration Guide](../src/implementations/http/express-rpc/README.md) for complete setup including lifecycle hooks, error handling, and route documentation.
51
-
52
- ## Hono RPC
53
-
54
- RPC-style HTTP integration for Hono with the same routing pattern as Express RPC. Works with Bun, Deno, Cloudflare Workers, and Node.js.
55
-
56
- ```typescript
57
- import { HonoRPCAppBuilder, RPCConfig } from 'ts-procedures/hono-rpc'
20
+ import { Procedures } from 'ts-procedures'
21
+ import { HonoAppBuilder } from 'ts-procedures/hono'
22
+ import type { RPCConfig } from 'ts-procedures/http'
23
+ import { Type } from 'typebox'
58
24
 
59
- const RPC = Procedures<AppContext, RPCConfig>()
25
+ type AppContext = { userId: string }
26
+ const procs = Procedures<AppContext, RPCConfig>()
60
27
 
61
- RPC.Create('GetUser', {
28
+ // 1. RPC procedure (Create) — POST /rpc/users/profile/get-user/1
29
+ procs.Create('GetUser', {
62
30
  scope: ['users', 'profile'],
63
31
  version: 1,
64
32
  schema: { params: Type.Object({ id: Type.String() }) },
65
- }, async (ctx, params) => {
66
- return { id: params.id, name: 'John Doe' }
67
- })
68
-
69
- const app = new HonoRPCAppBuilder({ pathPrefix: '/rpc' })
70
- .register(RPC, (c) => ({ userId: c.req.header('x-user-id') || 'anonymous' }))
71
- .build()
72
-
73
- // POST /rpc/users/profile/get-user/1
74
- ```
75
-
76
- See the [Hono RPC Integration Guide](../src/implementations/http/hono-rpc/README.md) for complete setup including context resolution, doc extension, abort signal, error handling, and runtime compatibility.
77
-
78
- ## Hono Stream
33
+ }, async (ctx, params) => ({ id: params.id, name: 'John Doe' }))
79
34
 
80
- Streaming/SSE integration for Hono that supports both SSE and text streaming modes with yield validation, lifecycle hooks, and client disconnect detection.
81
-
82
- ```typescript
83
- import { HonoStreamAppBuilder } from 'ts-procedures/hono-stream'
84
-
85
- const StreamRPC = Procedures<AppContext, RPCConfig>()
86
-
87
- StreamRPC.CreateStream('WatchNotifications', {
35
+ // 2. RPC stream (CreateStream) GET/POST /rpc/user/notifications/watch-notifications/1
36
+ procs.CreateStream('WatchNotifications', {
88
37
  scope: ['user', 'notifications'],
89
38
  version: 1,
90
39
  schema: { yieldType: Type.Object({ id: Type.Number(), message: Type.String() }) },
@@ -95,60 +44,43 @@ StreamRPC.CreateStream('WatchNotifications', {
95
44
  }
96
45
  })
97
46
 
98
- const app = new HonoStreamAppBuilder()
99
- .register(StreamRPC, (c) => ({ userId: c.req.header('x-user-id') || 'anonymous' }))
100
- .build()
101
- ```
102
-
103
- See the [Hono Stream Integration Guide](../src/implementations/http/hono-stream/README.md) for complete setup including SSE/text modes, the `sse()` helper, validation, error handling, and migration notes.
104
-
105
- ## Hono API Integration
106
-
107
- REST-style HTTP integration for Hono that routes by HTTP method with per-channel input validation via `schema.input`.
108
-
109
- ```typescript
110
- import { Procedures } from 'ts-procedures'
111
- import { HonoAPIAppBuilder } from 'ts-procedures/hono-api'
112
- import type { APIConfig } from 'ts-procedures/http'
113
- import { Type } from 'typebox'
114
-
115
- const API = Procedures<{ userId: string }, APIConfig>()
116
-
117
- API.Create('GetUser', {
47
+ // 3. REST procedure (CreateHttp) — GET /rpc/users/:id
48
+ procs.CreateHttp('GetUserRest', {
118
49
  path: '/users/:id',
119
50
  method: 'get',
51
+ scope: 'users',
120
52
  schema: {
121
- input: {
122
- pathParams: Type.Object({ id: Type.String() }),
123
- },
124
- returnType: Type.Object({ id: Type.String(), name: Type.String() }),
53
+ req: { pathParams: Type.Object({ id: Type.String() }) },
54
+ res: { body: Type.Object({ id: Type.String(), name: Type.String() }) },
125
55
  },
126
- }, async (ctx, { pathParams }) => {
127
- return await fetchUser(pathParams.id)
128
- })
56
+ }, async (ctx, { pathParams }) => fetchUser(pathParams.id))
129
57
 
130
- API.Create('CreateUser', {
131
- path: '/users',
132
- method: 'post',
58
+ // 4. REST stream (CreateHttpStream) — GET /rpc/streams/logs
59
+ procs.CreateHttpStream('TailLogs', {
60
+ path: '/streams/logs',
61
+ method: 'get',
62
+ scope: 'streams',
133
63
  schema: {
134
- input: {
135
- body: Type.Object({ name: Type.String(), email: Type.String() }),
136
- },
64
+ req: { query: Type.Object({ source: Type.String() }) },
65
+ yield: Type.Object({ line: Type.String() }),
137
66
  },
138
- }, async (ctx, { body }) => {
139
- return await createUser(body)
67
+ }, async function* (ctx, { query }) {
68
+ for await (const line of tail(query.source)) yield { line }
140
69
  })
141
70
 
142
- const app = new HonoAPIAppBuilder({ pathPrefix: '/api' })
143
- .register(API, (c) => ({ userId: c.req.header('x-user-id') || 'anonymous' }))
71
+ const app = new HonoAppBuilder({
72
+ pathPrefix: '/rpc',
73
+ rpc: { onSuccess: (proc, c) => log.info(`[rpc] ${proc.name}`) },
74
+ api: { onSuccess: (proc, c) => log.info(`[api] ${proc.name}`) },
75
+ stream: { defaultStreamMode: 'sse' },
76
+ })
77
+ .register(procs, (c) => ({ userId: c.req.header('x-user-id') || 'anonymous' }))
144
78
  .build()
145
-
146
- // Routes:
147
- // GET /api/users/:id -> 200
148
- // POST /api/users -> 201
149
79
  ```
150
80
 
151
- See the [Hono API Integration Guide](../src/implementations/http/hono-api/README.md) for the full surface: `schema.input` channels, query parsing, success-status defaults, and error handling.
81
+ `HonoAppBuilder`'s config is **stratified** kind-specific knobs (`onSuccess`, `queryParser`, `defaultStreamMode`, `onStreamStart`, `onStreamEnd`, `onMidStreamError`) live inside the matching `rpc:` / `api:` / `stream:` block. Cross-cutting hooks (`onRequestStart`, `onRequestEnd`, `onRequestError`, `errors`, `unknownError`, `onError`) stay at the top level.
82
+
83
+ For the full surface — config interfaces, path generation, context resolution, abort signal, lifecycle hooks, route doc shapes — see the [HTTP implementations overview](../src/implementations/http/README.md).
152
84
 
153
85
  ## Error Handling
154
86
 
@@ -165,7 +97,7 @@ Both modes also expose `onRequestError` — a cross-cutting observer for logging
165
97
 
166
98
  ```typescript
167
99
  import { defineErrorTaxonomy } from 'ts-procedures/http-errors'
168
- import { HonoAPIAppBuilder } from 'ts-procedures/hono-api'
100
+ import { HonoAppBuilder } from 'ts-procedures/hono'
169
101
 
170
102
  class UseCaseError extends Error {
171
103
  constructor(readonly externalMsg: string, readonly internalMsg: string) {
@@ -190,40 +122,34 @@ const appErrors = defineErrorTaxonomy({
190
122
  },
191
123
  })
192
124
 
193
- new HonoAPIAppBuilder({
125
+ new HonoAppBuilder({
194
126
  errors: appErrors,
195
127
  unknownError: {
196
128
  statusCode: 500,
197
129
  toResponse: () => ({ name: 'InternalServerError', message: 'Unexpected error' }),
198
130
  onCatch: (err, { procedure }) => logger.error({ procedure: procedure.name, err }),
199
131
  },
200
- }).register(API, /* ... */).build()
132
+ }).register(procs, /* ... */).build()
201
133
  ```
202
134
 
203
- The identical `errors` + `unknownError` shape plugs into `HonoRPCAppBuilder`, `ExpressRPCAppBuilder`, and `HonoStreamAppBuilder` (pre-stream only mid-stream uses `onMidStreamError`).
135
+ For streaming procedures the taxonomy covers the pre-stream path only; mid-stream errors are handled via `stream.onMidStreamError`.
204
136
 
205
137
  ### Imperative — the `onError` callback
206
138
 
207
139
  For apps that don't need typed client dispatch or declarative docs, configure `onError` directly and handle every error in one place:
208
140
 
209
141
  ```typescript
210
- new HonoAPIAppBuilder({
142
+ new HonoAppBuilder({
211
143
  onError: (procedure, c, error) => {
212
144
  logger.error(`[${procedure.name}]`, error)
213
145
  return c.json({ error: error.message ?? 'unknown error' }, 500)
214
146
  },
215
- }).register(API, /* ... */).build()
147
+ }).register(procs, /* ... */).build()
216
148
  ```
217
149
 
218
150
  (Need to route different error classes to different status codes? Use the taxonomy — that's exactly what it's designed for. Hand-writing `instanceof` ladders inside `onError` is [anti-pattern #20](../agent_config/claude-code/skills/ts-procedures/anti-patterns.md).)
219
151
 
220
- Signatures (differ by framework):
221
-
222
- | Builder | `onError` signature |
223
- |---|---|
224
- | `HonoAPIAppBuilder`, `HonoRPCAppBuilder` | `(procedure, c: Context, error) => Response \| Promise<Response>` |
225
- | `ExpressRPCAppBuilder` | `(procedure, req, res, error) => void` (write to `res`) |
226
- | `HonoStreamAppBuilder` | `(procedure, c: Context, error) => Response \| Promise<Response>` — pre-stream only |
152
+ `HonoAppBuilder`'s `onError` signature: `(procedure, c: Context, error) => Response | Promise<Response>` — for streaming procedures, pre-stream only.
227
153
 
228
154
  Picking between modes isn't irreversible: you can start with `onError`, migrate chunks to the taxonomy as your error model stabilizes, and leave the rest in `onError`. Both modes coexist in the dispatch order below.
229
155
 
@@ -232,27 +158,27 @@ Picking between modes isn't irreversible: you can start with `onError`, migrate
232
158
  `APIConfig` and `RPCConfig` are generic over a `TErrorKey extends string` parameter so you can declare which errors a specific route may emit:
233
159
 
234
160
  ```typescript
235
- import type { APIConfig } from 'ts-procedures/http'
161
+ const procs = Procedures<Ctx>()
162
+ type ErrorKey = keyof typeof appErrors & string
236
163
 
237
- type MyAPIConfig = APIConfig<keyof typeof appErrors & string>
238
- const API = Procedures<Ctx, MyAPIConfig>()
239
-
240
- API.Create('GetUser', {
164
+ procs.CreateHttp('GetUser', {
241
165
  path: '/users/:id',
242
166
  method: 'get',
243
- errors: ['UseCaseError'], // typo-checked against the taxonomy keys
167
+ errors: ['UseCaseError'] satisfies ErrorKey[], // typo-checked against the taxonomy keys
244
168
  schema: { /* ... */ },
245
169
  }, /* handler */)
246
170
  ```
247
171
 
248
172
  These per-route declarations flow into the DocEnvelope and drive typed `catch` blocks on generated clients — see [Client & Codegen → Typed Error Handling](./client-and-codegen.md#typed-error-handling).
249
173
 
174
+ **Tip:** if a factory exclusively contains HTTP procedures, prefer the factory-level generic form `Procedures<Ctx, APIConfig<keyof typeof appErrors & string>>()` — it bakes the typo-checked error keys into every route on that factory so individual `errors: [...] satisfies ErrorKey[]` annotations are no longer needed. The per-route `satisfies` form above is the right pick when a single factory mixes HTTP procedures with other config shapes.
175
+
250
176
  ### Cross-cutting observability — `onRequestError`
251
177
 
252
178
  `onRequestError` fires for every caught error, **before** dispatch. It's an observer — it can't mutate the response. Use it for APM, distributed tracing, custom logging, or metrics where you want one hook that sees every error regardless of which mode dispatched it.
253
179
 
254
180
  ```typescript
255
- new HonoAPIAppBuilder({
181
+ new HonoAppBuilder({
256
182
  errors: appErrors,
257
183
  onRequestError: async ({ err, procedure, raw }) => {
258
184
  sentry.captureException(err, { procedure: procedure.name })
@@ -271,41 +197,19 @@ The observer is awaited before the response is sent, and any error it throws is
271
197
 
272
198
  Configuring only the taxonomy, only `onError`, both, or neither are all valid. When neither is configured the builder goes straight from step 1 to step 4.
273
199
 
274
- ## One Hono Server, Multiple Builders
200
+ ## DocRegistry Composing Docs
275
201
 
276
- You don't need a separate Hono instance per builder. `HonoRPCAppBuilder`, `HonoAPIAppBuilder`, and `HonoStreamAppBuilder` each accept an optional `app?: Hono` in their config pass the same instance and they all mount their routes onto the same server:
202
+ For a single-builder app, the simplest path is `builder.toDocEnvelope({ basePath, errors })` it wraps `DocRegistry` for you and produces the same envelope shape:
277
203
 
278
204
  ```typescript
279
- import { Hono } from 'hono'
280
- import { HonoRPCAppBuilder } from 'ts-procedures/hono-rpc'
281
- import { HonoAPIAppBuilder } from 'ts-procedures/hono-api'
282
- import { HonoStreamAppBuilder } from 'ts-procedures/hono-stream'
283
- import { DocRegistry } from 'ts-procedures/http-docs'
284
-
285
- const app = new Hono()
286
-
287
- const rpcBuilder = new HonoRPCAppBuilder({ app, pathPrefix: '/rpc' })
288
- .register(RPC, ctxResolver)
289
- const apiBuilder = new HonoAPIAppBuilder({ app, pathPrefix: '/api' })
290
- .register(API, ctxResolver)
291
- const streamBuilder = new HonoStreamAppBuilder({ app })
292
- .register(Stream, ctxResolver)
205
+ const builder = new HonoAppBuilder({ pathPrefix: '/api', errors: appErrors })
206
+ .register(procs, ctxResolver)
207
+ const app = builder.build()
293
208
 
294
- rpcBuilder.build()
295
- apiBuilder.build()
296
- streamBuilder.build()
297
-
298
- const docs = new DocRegistry().from(rpcBuilder).from(apiBuilder).from(streamBuilder)
299
- app.get('/docs', (c) => c.json(docs.toJSON()))
209
+ app.get('/docs', (c) => c.json(builder.toDocEnvelope()))
300
210
  ```
301
211
 
302
- One server, one Hono instance, one `/docs` endpoint. The three builders are **registration scopes**, not separate servers each owns the routes it mounts (RPC vs API vs Stream) but all of them coexist on the same listener. Mix in custom middleware (`app.use(...)`), health checks, or static routes on the shared `app` before or after `.build()`.
303
-
304
- If you omit `app`, each builder constructs its own internal `Hono` instance — useful when you really do want isolated apps (multi-tenant routing, separate ports, etc.).
305
-
306
- ## DocRegistry — Composing Docs from Multiple Builders
307
-
308
- Use `DocRegistry` to compose route documentation from any combination of HTTP builders into a typed envelope:
212
+ For multi-app aggregatione.g., two `HonoAppBuilder` instances mounted under different prefixes use `DocRegistry` directly:
309
213
 
310
214
  ```typescript
311
215
  import { DocRegistry } from 'ts-procedures/http-docs'
@@ -315,9 +219,8 @@ const docs = new DocRegistry({
315
219
  headers: [{ name: 'Authorization', description: 'Bearer token', required: false }],
316
220
  errors: appErrors, // your ErrorTaxonomy — auto-converted to ErrorDocs, framework defaults merged
317
221
  })
318
- .from(rpcBuilder)
319
- .from(apiBuilder)
320
- .from(streamBuilder)
222
+ .from(publicBuilder)
223
+ .from(adminBuilder)
321
224
 
322
225
  app.get('/docs', (c) => c.json(docs.toJSON()))
323
226
  ```
@@ -328,7 +231,7 @@ For errors that aren't in your taxonomy (middleware-level, infrastructure, doc-o
328
231
 
329
232
  ```typescript
330
233
  const docs = new DocRegistry({ errors: appErrors, basePath: '/api' })
331
- .from(rpcBuilder)
234
+ .from(honoBuilder)
332
235
  .documentError({ name: 'RateLimitExceeded', statusCode: 429, description: 'too many requests' })
333
236
  ```
334
237
 
@@ -339,10 +242,20 @@ The `DocRegistry` output is the input for [Client Code Generation](./client-and-
339
242
  ## Type Exports
340
243
 
341
244
  ```typescript
342
- // HTTP types
343
- import type { RPCConfig, RPCHttpRouteDoc, StreamHttpRouteDoc, StreamMode, APIConfig, APIHttpRouteDoc, APIInput, HttpMethod } from 'ts-procedures/http'
344
-
345
- // Hono API (REST-style)
346
- import { HonoAPIAppBuilder } from 'ts-procedures/hono-api'
347
- import type { APIConfig, APIHttpRouteDoc, APIInput, HttpMethod, QueryParser } from 'ts-procedures/hono-api'
245
+ // Shared HTTP types
246
+ import type {
247
+ RPCConfig,
248
+ RPCHttpRouteDoc,
249
+ StreamHttpRouteDoc,
250
+ HttpStreamRouteDoc,
251
+ StreamMode,
252
+ APIConfig,
253
+ APIHttpRouteDoc,
254
+ APIInput,
255
+ HttpMethod,
256
+ } from 'ts-procedures/http'
257
+
258
+ // Hono builder + Hono-specific types
259
+ import { HonoAppBuilder } from 'ts-procedures/hono'
260
+ import type { HonoAppBuilderConfig, QueryParser, OnRequestErrorContext, ExtendProcedureDoc } from 'ts-procedures/hono'
348
261
  ```
package/docs/streaming.md CHANGED
@@ -105,72 +105,15 @@ for await (const item of CancellableStream({}, {})) {
105
105
  }
106
106
  ```
107
107
 
108
- ## SSE Integration Example
108
+ ## SSE Integration
109
109
 
110
- ```typescript
111
- import express from 'express'
112
- import { Procedures } from 'ts-procedures'
113
-
114
- const app = express()
115
-
116
- const { CreateStream, getProcedures } = Procedures<{ req: express.Request }>({
117
- onCreate: (proc) => {
118
- if (proc.isStream) {
119
- // Register streaming procedures as SSE endpoints
120
- app.get(`/stream/${proc.name}`, async (req, res) => {
121
- res.writeHead(200, {
122
- 'Content-Type': 'text/event-stream',
123
- 'Cache-Control': 'no-cache',
124
- 'Connection': 'keep-alive',
125
- })
126
-
127
- const generator = proc.handler({ req }, req.query)
128
-
129
- req.on('close', async () => {
130
- // Client disconnected - stop the generator
131
- await generator.return(undefined)
132
- })
133
-
134
- try {
135
- for await (const data of generator) {
136
- res.write(`data: ${JSON.stringify(data)}\n\n`)
137
- }
138
- } finally {
139
- res.end()
140
- }
141
- })
142
- }
143
- },
144
- })
145
-
146
- // Define a streaming procedure
147
- CreateStream(
148
- 'LiveFeed',
149
- {
150
- schema: {
151
- params: Type.Object({ channel: Type.String() }),
152
- yieldType: Type.Object({ event: Type.String(), data: Type.Any() }),
153
- },
154
- },
155
- async function* (ctx, params) {
156
- while (!ctx.signal.aborted) {
157
- const event = await pollForEvent(params.channel)
158
- yield event
159
- }
160
- },
161
- )
162
-
163
- app.listen(3000)
164
- // SSE endpoint: GET /stream/LiveFeed?channel=updates
165
- ```
166
-
167
- For the built-in Hono streaming integration, see the [Hono Stream README](../src/implementations/http/hono-stream/README.md).
110
+ For the built-in Hono streaming integration, see [HTTP Integrations](./http-integrations.md). `HonoAppBuilder` dispatches `CreateStream` and `CreateHttpStream` procedures as SSE or text streams from the same `register()` call as your RPC and REST routes.
168
111
 
169
112
  ## Stream Errors
170
113
 
171
114
  Streaming procedures support the same error handling as regular procedures (see [Error Handling](./core.md#error-handling)).
172
115
 
173
- For HTTP stream endpoints, pre-stream errors (validation, context resolution, anything thrown before the first yield) go through the same two peer error-handling modes as every other HTTP builder — either the declarative `errors` / `unknownError` taxonomy (from `defineErrorTaxonomy`) or the imperative `onError` callback on `HonoStreamAppBuilder`. Cross-cutting `onRequestError` observer fires for every pre-stream error. See [HTTP Integrations → Error Handling](./http-integrations.md#error-handling) for the full contract. Mid-stream errors (thrown after the first yield) still flow through `onMidStreamError` and are surfaced to the client as SSE error events — the HTTP status is already committed once streaming begins, so mid-stream is outside the peer error modes.
116
+ For HTTP stream endpoints, pre-stream errors (validation, context resolution, anything thrown before the first yield) go through the same two peer error-handling modes as every other HTTP builder — either the declarative `errors` / `unknownError` taxonomy (from `defineErrorTaxonomy`) or the imperative `onError` callback on `HonoAppBuilder`. Cross-cutting `onRequestError` observer fires for every pre-stream error. See [HTTP Integrations → Error Handling](./http-integrations.md#error-handling) for the full contract. Mid-stream errors (thrown after the first yield) still flow through `onMidStreamError` and are surfaced to the client as SSE error events — the HTTP status is already committed once streaming begins, so mid-stream is outside the peer error modes.
174
117
 
175
118
  ```typescript
176
119
  const { StreamWithErrors } = CreateStream(
@@ -60,7 +60,6 @@ Open `package.json` and confirm both:
60
60
  "optionalDependencies": {
61
61
  "ajsc": "7.2.0",
62
62
  "astro": "^5.0.0",
63
- "express": "^5.2.1",
64
63
  "hono": "^4.7.4"
65
64
  },
66
65
  "devDependencies": {
@@ -990,7 +989,6 @@ Dispatch rules:
990
989
 
991
990
  ## What's NOT included
992
991
 
993
- - Express RPC support (Express uses Node `req`/`res`, not Web Fetch).
994
992
  - DocRegistry coupling — wire `DocRegistry` against the same builders separately for client codegen.
995
993
  ````
996
994
 
@@ -1253,7 +1251,7 @@ Multi-app: pass an array; first non-404 response wins. All-404 falls back to the
1253
1251
 
1254
1252
  Constraints:
1255
1253
  - Astro 5+ in SSR (or `prerender = false`).
1256
- - Express builders are NOT supported by this adapter Hono builders only.
1254
+ - Hono builders only the adapter accepts `Request`/`Response` apps.
1257
1255
  ````
1258
1256
 
1259
1257
  - [ ] **Step 3: Update patterns.md**
@@ -1270,8 +1268,6 @@ When a downstream developer is building inside an Astro app, recommend the catch
1270
1268
  3. Mount the built app(s) in a single catch-all file: `src/pages/api/[...rest].ts`. Use `pathPrefix: '/api'` so your Hono routes don't need to repeat the prefix.
1271
1269
 
1272
1270
  Anti-pattern: don't create one Astro file per procedure — that loses the centralized factory wiring and forces the developer to repeat the context closure.
1273
-
1274
- Anti-pattern: don't try to use `express-rpc` with the Astro adapter. The adapter only accepts Web-Fetch apps (Hono).
1275
1271
  ````
1276
1272
 
1277
1273
  - [ ] **Step 4: Mirror the same content into Copilot and Cursor rules**
@@ -1283,7 +1279,7 @@ In each file, locate the existing builders section and append (verbatim — same
1283
1279
  ```markdown
1284
1280
  ## Astro adapter
1285
1281
 
1286
- Catch-all endpoint pattern. Build Hono apps once with HonoAPI/RPC/Stream builders, mount via `createAstroHandler` in `src/pages/api/[...rest].ts` with `pathPrefix: '/api'`. Read Astro context inside factory closures with `getAstroContext(c)`. Multi-app dispatch is first-non-404-wins. Express builders are not supported.
1282
+ Catch-all endpoint pattern. Build Hono apps once with HonoAPI/RPC/Stream builders, mount via `createAstroHandler` in `src/pages/api/[...rest].ts` with `pathPrefix: '/api'`. Read Astro context inside factory closures with `getAstroContext(c)`. Multi-app dispatch is first-non-404-wins.
1287
1283
  ```
1288
1284
 
1289
1285
  - [ ] **Step 5: Run the docs-consistency check**
@@ -1388,7 +1384,6 @@ If nothing changed, skip this step.
1388
1384
  - `stripPrefix(request, prefix)` — defined Task 2, called Task 4. Same signature.
1389
1385
 
1390
1386
  **Out-of-scope items confirmed not in plan:**
1391
- - Express adapter — explicitly excluded
1392
1387
  - Native Astro builders — explicitly excluded
1393
1388
  - DocRegistry coupling — wired separately in walkthrough (Task 10), not in adapter
1394
1389
  - `dispatch: 'merge'` knob — not introduced