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
@@ -105,11 +105,11 @@ const { TransferFunds } = Create(
105
105
 
106
106
  ## Error Taxonomy (declarative error-to-response mapping)
107
107
 
108
- `defineErrorTaxonomy` replaces `instanceof` ladders inside `onError`. Register error classes once with their status code and serializer, pass to any HTTP builder. Works across `hono-api`, `hono-rpc`, `express-rpc`, and `hono-stream` pre-stream (mid-stream still uses `onMidStreamError`).
108
+ `defineErrorTaxonomy` replaces `instanceof` ladders inside `onError`. Register error classes once with their status code and serializer, pass to `HonoAppBuilder` for `rpc`, `http`, and pre-stream paths. Mid-stream errors (generator throws after the first yield) still go through `stream.onMidStreamError`.
109
109
 
110
110
  ```typescript
111
111
  import { defineErrorTaxonomy } from 'ts-procedures/http-errors'
112
- import { HonoAPIAppBuilder } from 'ts-procedures/hono-api'
112
+ import { HonoAppBuilder } from 'ts-procedures/hono'
113
113
 
114
114
  class UseCaseError extends Error {
115
115
  constructor(readonly externalMsg: string, readonly internalMsg: string) {
@@ -135,7 +135,7 @@ const appErrors = defineErrorTaxonomy({
135
135
  },
136
136
  })
137
137
 
138
- new HonoAPIAppBuilder({
138
+ new HonoAppBuilder({
139
139
  errors: appErrors,
140
140
  unknownError: {
141
141
  toResponse: () => ({ name: 'InternalServerError', message: 'Unexpected error' }),
@@ -159,25 +159,23 @@ Key rules:
159
159
  - `defineErrorTaxonomy` topologically sorts `class:` entries so a subclass always resolves before its base — declaration order inside the helper no longer matters for inheritance chains. `match:` entries keep declared order.
160
160
  - The core wraps any non-`ProcedureError` thrown from a handler into a `ProcedureError` with `.cause` set. The resolver unwraps this automatically so your taxonomy sees the real class.
161
161
  - Two peer modes: declarative (`errors` + `unknownError`) or imperative (`onError`). Both are first-class. When neither is configured, the builder falls through to a hard default (`{ error: message }`, 500).
162
- - `onCatch`'s `raw` is the framework request object (Hono `Context` / `{ req, res }` for Express) typed as `unknown` — cast at the use site.
162
+ - `onCatch`'s `raw` is the framework request object (Hono `Context`) typed as `unknown` — cast at the use site.
163
163
 
164
164
  ### Per-route error declaration (typed)
165
165
 
166
- Narrow `APIConfig` / `RPCConfig` to your taxonomy's keys for compile-time typo protection, and declare which errors each procedure may emit. These populate the DocEnvelope per-route so generated clients can type `catch` blocks precisely.
166
+ Declare which errors each procedure may emit via the `errors` field on `CreateHttp` / `Create` config. These populate the DocEnvelope per-route so generated clients can type `catch` blocks precisely. For compile-time typo protection, pass the taxonomy key type as the `TErrorKey` generic on `CreateHttp`.
167
167
 
168
168
  ```typescript
169
- import { APIConfig } from 'ts-procedures/http'
170
169
  import { appErrors } from './errors/taxonomy'
171
170
 
172
- type MyAPIConfig = APIConfig<keyof typeof appErrors & string>
171
+ const API = Procedures<Ctx>()
173
172
 
174
- const API = Procedures<Ctx, MyAPIConfig>()
175
-
176
- API.Create('GetUser', {
173
+ // CreateHttp accepts TErrorKey as a generic for compile-time protection
174
+ API.CreateHttp<keyof typeof appErrors & string>('GetUser', {
177
175
  path: '/users/:id',
178
176
  method: 'get',
179
177
  errors: ['UseCaseError', 'AuthError'], // typed against taxonomy keys; typos are TS errors
180
- schema: { /* ... */ },
178
+ schema: { req: { /* ... */ } },
181
179
  }, async (ctx, params) => { /* ... */ })
182
180
  ```
183
181
 
@@ -476,60 +474,11 @@ for (const proc of getProcedures()) {
476
474
 
477
475
  ---
478
476
 
479
- ## Express RPC Integration
480
-
481
- ```typescript
482
- import { Procedures } from 'ts-procedures'
483
- import { ExpressRPCAppBuilder } from 'ts-procedures/express-rpc'
484
- import { Type } from 'typebox'
485
- import type { RPCConfig } from 'ts-procedures/http'
486
-
487
- // 1. Define context and procedures
488
- type AppContext = { userId: string; requestId: string }
489
- const { Create } = Procedures<AppContext, RPCConfig>()
490
-
491
- const { GetUser } = Create(
492
- 'GetUser',
493
- { scope: 'users', version: 1, schema: { params: Type.Object({ id: Type.String() }) } },
494
- async (ctx, params) => fetchUser(params.id)
495
- )
496
-
497
- const { UpdateUser } = Create(
498
- 'UpdateUser',
499
- { scope: 'users', version: 1 },
500
- async (ctx, params) => updateUser(params)
501
- )
502
-
503
- // 2. Build Express app — the taxonomy handles framework errors (ProcedureValidationError
504
- // maps to 400 by default) and anything the app throws; unknownError is the last resort.
505
- const app = new ExpressRPCAppBuilder({
506
- pathPrefix: '/api',
507
- errors: appErrors, // from defineErrorTaxonomy({ ... })
508
- unknownError: {
509
- toResponse: (err) => ({ error: (err as Error).message }),
510
- },
511
- })
512
- .register(
513
- { getProcedures: () => [GetUser.info, UpdateUser.info] }, // Or use the factory directly
514
- async (req) => ({
515
- userId: await getUserIdFromToken(req.headers.authorization),
516
- requestId: req.headers['x-request-id'] || crypto.randomUUID(),
517
- })
518
- )
519
- .build()
520
-
521
- // Routes created:
522
- // POST /api/users/get-user/1
523
- // POST /api/users/update-user/1
524
- ```
525
-
526
- ---
527
-
528
477
  ## Hono RPC Integration
529
478
 
530
479
  ```typescript
531
480
  import { Procedures } from 'ts-procedures'
532
- import { HonoRPCAppBuilder } from 'ts-procedures/hono-rpc'
481
+ import { HonoAppBuilder } from 'ts-procedures/hono'
533
482
  import type { RPCConfig } from 'ts-procedures/http'
534
483
 
535
484
  type AppContext = { userId: string }
@@ -539,7 +488,7 @@ RPC.Create('GetUser', { scope: 'users', version: 1 }, async (ctx, params) => {
539
488
  return fetchUser(params.id)
540
489
  })
541
490
 
542
- const app = new HonoRPCAppBuilder({ pathPrefix: '/api' })
491
+ const app = new HonoAppBuilder({ pathPrefix: '/api' })
543
492
  .register(RPC, (c) => ({
544
493
  userId: c.req.header('x-user-id') || 'anonymous',
545
494
  }))
@@ -552,7 +501,7 @@ const app = new HonoRPCAppBuilder({ pathPrefix: '/api' })
552
501
 
553
502
  ```typescript
554
503
  import { Procedures } from 'ts-procedures'
555
- import { HonoStreamAppBuilder, sse } from 'ts-procedures/hono-stream'
504
+ import { HonoAppBuilder, sse } from 'ts-procedures/hono'
556
505
  import { Type } from 'typebox'
557
506
  import type { RPCConfig } from 'ts-procedures/http'
558
507
 
@@ -578,13 +527,15 @@ const { StreamEvents } = StreamRPC.CreateStream(
578
527
  }
579
528
  )
580
529
 
581
- const app = new HonoStreamAppBuilder({
530
+ const app = new HonoAppBuilder({
582
531
  pathPrefix: '/api',
583
- defaultStreamMode: 'sse',
584
- onMidStreamError: (procedure, c, error) => ({
585
- data: { error: error.message },
586
- closeStream: true,
587
- }),
532
+ stream: {
533
+ defaultStreamMode: 'sse',
534
+ onMidStreamError: (procedure, c, error) => ({
535
+ data: { error: error.message },
536
+ closeStream: true,
537
+ }),
538
+ },
588
539
  })
589
540
  .register(StreamRPC, (c) => ({
590
541
  userId: c.req.header('x-user-id') || 'anonymous',
@@ -599,8 +550,10 @@ const app = new HonoStreamAppBuilder({
599
550
  ## Text Streaming Mode
600
551
 
601
552
  ```typescript
602
- const app = new HonoStreamAppBuilder({
603
- defaultStreamMode: 'text', // Newline-delimited JSON
553
+ const app = new HonoAppBuilder({
554
+ stream: {
555
+ defaultStreamMode: 'text', // Newline-delimited JSON
556
+ },
604
557
  })
605
558
  .register(StreamRPC, contextFactory)
606
559
  .build()
@@ -610,35 +563,38 @@ const app = new HonoStreamAppBuilder({
610
563
 
611
564
  ---
612
565
 
613
- ## Hono API Integration (REST-style)
566
+ ## Hono API Integration (REST-style) — v8 `CreateHttp`
567
+
568
+ In v8, HTTP routes use `CreateHttp` (and `CreateHttpStream` for streaming). The factory no longer needs an `APIConfig` type parameter; HTTP fields (`path`, `method`, `scope`, `errors`) live on the `CreateHttp` config directly.
614
569
 
615
570
  ```typescript
616
571
  import { Procedures } from 'ts-procedures'
617
- import { HonoAPIAppBuilder } from 'ts-procedures/hono-api'
618
- import type { APIConfig } from 'ts-procedures/http'
572
+ import { HonoAppBuilder } from 'ts-procedures/hono'
619
573
  import { Type } from 'typebox'
620
574
 
621
575
  type AppContext = { userId: string }
622
- const API = Procedures<AppContext, APIConfig>()
576
+ const API = Procedures<AppContext>()
623
577
 
624
- API.Create('GetUser', {
578
+ API.CreateHttp('GetUser', {
625
579
  path: '/users/:id',
626
580
  method: 'get',
627
581
  schema: {
628
- input: {
582
+ req: {
629
583
  pathParams: Type.Object({ id: Type.String() }),
630
584
  },
631
- returnType: Type.Object({ id: Type.String(), name: Type.String() }),
585
+ res: {
586
+ body: Type.Object({ id: Type.String(), name: Type.String() }),
587
+ },
632
588
  },
633
589
  }, async (ctx, { pathParams }) => {
634
590
  return await fetchUser(pathParams.id)
635
591
  })
636
592
 
637
- API.Create('CreateUser', {
593
+ API.CreateHttp('CreateUser', {
638
594
  path: '/users',
639
595
  method: 'post',
640
596
  schema: {
641
- input: {
597
+ req: {
642
598
  body: Type.Object({ name: Type.String(), email: Type.String() }),
643
599
  },
644
600
  },
@@ -646,11 +602,11 @@ API.Create('CreateUser', {
646
602
  return await createUser(body)
647
603
  })
648
604
 
649
- API.Create('DeleteUser', {
605
+ API.CreateHttp('DeleteUser', {
650
606
  path: '/users/:id',
651
607
  method: 'delete',
652
608
  schema: {
653
- input: {
609
+ req: {
654
610
  pathParams: Type.Object({ id: Type.String() }),
655
611
  },
656
612
  },
@@ -658,7 +614,7 @@ API.Create('DeleteUser', {
658
614
  await deleteUser(pathParams.id)
659
615
  })
660
616
 
661
- const app = new HonoAPIAppBuilder({
617
+ const app = new HonoAppBuilder({
662
618
  pathPrefix: '/api',
663
619
  errors: appErrors, // taxonomy maps error classes to statuses/bodies; ProcedureValidationError → 400 by default
664
620
  unknownError: {
@@ -678,59 +634,29 @@ const app = new HonoAPIAppBuilder({
678
634
 
679
635
  ---
680
636
 
681
- ## Extended Config with APIConfig
682
-
683
- ```typescript
684
- import { Procedures } from 'ts-procedures'
685
- import type { APIConfig } from 'ts-procedures/http'
686
-
687
- type AppContext = { userId: string }
688
-
689
- const { Create } = Procedures<AppContext, APIConfig>()
690
-
691
- // Every procedure now MUST include path and method
692
- const { GetUser } = Create(
693
- 'GetUser',
694
- {
695
- path: '/users/:id',
696
- method: 'get',
697
- schema: {
698
- input: {
699
- pathParams: Type.Object({ id: Type.String() }),
700
- query: Type.Object({ include: Type.Optional(Type.String()) }),
701
- },
702
- },
703
- },
704
- async (ctx, { pathParams, query }) => {
705
- return await fetchUser(pathParams.id, { include: query.include })
706
- }
707
- )
708
- ```
709
-
710
- ---
711
-
712
- ## schema.input — Multi-Channel Structured Input
637
+ ## schema.req Multi-Channel Structured Input (v8)
713
638
 
714
- Use `schema.input` instead of `schema.params` for structured per-channel validation:
639
+ Use `schema.req` for structured per-channel validation. Channels: `pathParams`, `query`, `body`, `headers`.
715
640
 
716
641
  ```typescript
717
- const { Create } = Procedures<AppContext, APIConfig>()
642
+ const API = Procedures<AppContext>()
718
643
 
719
- Create('UpdateUserField', {
644
+ API.CreateHttp('UpdateUserField', {
720
645
  path: '/users/:id',
721
646
  method: 'put',
722
647
  schema: {
723
- input: {
648
+ req: {
724
649
  pathParams: Type.Object({ id: Type.String() }),
725
650
  query: Type.Object({ notify: Type.Optional(Type.Boolean()) }),
726
651
  body: Type.Object({ field: Type.String(), value: Type.String() }),
727
652
  headers: Type.Object({ 'x-idempotency-key': Type.String() }),
728
653
  },
729
- returnType: Type.Object({ ok: Type.Boolean() }),
654
+ res: {
655
+ body: Type.Object({ ok: Type.Boolean() }),
656
+ },
730
657
  },
731
658
  }, async (ctx, { pathParams, query, body, headers }) => {
732
659
  // Each channel independently typed and validated
733
- // Validation errors include channel name: "Validation error for UpdateUserField in input.body"
734
660
  await updateField(pathParams.id, body.field, body.value, {
735
661
  idempotencyKey: headers['x-idempotency-key'],
736
662
  })
@@ -741,23 +667,27 @@ Create('UpdateUserField', {
741
667
 
742
668
  ---
743
669
 
744
- ## APIInput Channel Constraint
670
+ ## Response Headers (v8 `CreateHttp`)
745
671
 
746
- Use `satisfies APIInput` to catch channel name typos at compile time:
672
+ When `schema.res.headers` is declared, the handler must return `{ body, headers }` instead of the body bare. The client surfaces initial response headers on `TypedStream.headers` for streaming routes.
747
673
 
748
674
  ```typescript
749
- import type { APIInput } from 'ts-procedures/hono-api'
750
-
751
- Create('Search', {
752
- path: '/search',
675
+ API.CreateHttp('DownloadReport', {
676
+ path: '/reports/:id/download',
753
677
  method: 'get',
754
678
  schema: {
755
- input: {
756
- query: Type.Object({ q: Type.String() }),
757
- } satisfies APIInput,
679
+ req: { pathParams: Type.Object({ id: Type.String() }) },
680
+ res: {
681
+ body: Type.Object({ url: Type.String() }),
682
+ headers: Type.Object({ 'x-report-format': Type.String() }),
683
+ },
758
684
  },
759
- }, async (ctx, { query }) => {
760
- return await search(query.q)
685
+ }, async (ctx, { pathParams }) => {
686
+ const report = await generateReport(pathParams.id)
687
+ return {
688
+ body: { url: report.url },
689
+ headers: { 'x-report-format': report.format },
690
+ }
761
691
  })
762
692
  ```
763
693
 
@@ -816,11 +746,11 @@ PublicRPC.Create('HealthCheck', { scope: 'health', version: 1 }, async () => ({
816
746
  AuthRPC.Create('GetProfile', { scope: 'users', version: 1 }, async (ctx) => fetchProfile(ctx.userId))
817
747
 
818
748
  // Register with different context resolvers
819
- const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
820
- .register(PublicRPC, (req) => ({ requestId: req.headers['x-request-id'] }))
821
- .register(AuthRPC, async (req) => ({
822
- userId: await authenticate(req),
823
- requestId: req.headers['x-request-id'],
749
+ const app = new HonoAppBuilder({ pathPrefix: '/api' })
750
+ .register(PublicRPC, (c) => ({ requestId: c.req.header('x-request-id') }))
751
+ .register(AuthRPC, async (c) => ({
752
+ userId: await authenticate(c),
753
+ requestId: c.req.header('x-request-id'),
824
754
  }))
825
755
  .build()
826
756
  ```
@@ -830,7 +760,7 @@ const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
830
760
  ## Documentation Generation with extendProcedureDoc
831
761
 
832
762
  ```typescript
833
- const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
763
+ const app = new HonoAppBuilder({ pathPrefix: '/api' })
834
764
  .register(RPC, contextFactory, ({ base, procedure }) => ({
835
765
  summary: procedure.config.description,
836
766
  tags: [base.scope],
@@ -944,20 +874,19 @@ describe('StreamNotifications', () => {
944
874
  ## Testing HTTP Builders
945
875
 
946
876
  ```typescript
947
- import supertest from 'supertest'
948
-
949
- describe('Express RPC', () => {
950
- const app = new ExpressRPCAppBuilder({ pathPrefix: '/api' })
951
- .register(RPC, { userId: 'test-user', requestId: 'test' })
877
+ describe('Hono RPC', () => {
878
+ const app = new HonoAppBuilder({ pathPrefix: '/api' })
879
+ .register(RPC, () => ({ userId: 'test-user', requestId: 'test' }))
952
880
  .build()
953
881
 
954
882
  test('POST /api/users/get-user/1', async () => {
955
- const res = await supertest(app)
956
- .post('/api/users/get-user/1')
957
- .send({ id: 'user-123' })
958
- .expect(200)
883
+ const res = await app.request('/api/users/get-user/1', {
884
+ method: 'POST',
885
+ body: JSON.stringify({ id: 'user-123' }),
886
+ })
959
887
 
960
- expect(res.body).toEqual({ id: 'user-123', name: 'John' })
888
+ expect(res.status).toBe(200)
889
+ expect(await res.json()).toEqual({ id: 'user-123', name: 'John' })
961
890
  })
962
891
  })
963
892
  ```
@@ -966,13 +895,13 @@ describe('Express RPC', () => {
966
895
 
967
896
  ## Lifecycle Hook Execution Order
968
897
 
969
- ### Standard RPC (Express/Hono)
898
+ ### Standard RPC (HonoAppBuilder)
970
899
  ```
971
900
  onRequestStart → factoryContext() → handler() → onSuccess → onRequestEnd
972
901
  → onError → onRequestEnd
973
902
  ```
974
903
 
975
- ### Streaming (HonoStreamAppBuilder)
904
+ ### Streaming (HonoAppBuilder)
976
905
  ```
977
906
  onRequestStart → factoryContext() → params validation
978
907
  → onError (if invalid) → onRequestEnd
@@ -1202,10 +1131,8 @@ const axiosAdapter: ClientAdapter = {
1202
1131
 
1203
1132
  When a downstream developer is building inside an Astro app, recommend the catch-all pattern:
1204
1133
 
1205
- 1. Build the Hono app ONCE in `src/server/api.ts` using `HonoAPIAppBuilder` / `HonoRPCAppBuilder` / `HonoStreamAppBuilder` exactly as you would for any other deployment.
1134
+ 1. Build the Hono app ONCE in `src/server/api.ts` using `HonoAppBuilder` exactly as you would for any other deployment.
1206
1135
  2. Inside the factory-context closure, call `getAstroContext(c)` to read `locals`, `cookies`, `params`, etc.
1207
1136
  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.
1208
1137
 
1209
1138
  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.
1210
-
1211
- Anti-pattern: don't try to use `express-rpc` with the Astro adapter. The adapter only accepts Web-Fetch apps (Hono).
@@ -14,7 +14,7 @@ Parse `$ARGUMENTS` as a file or directory path. If a directory, review all `.ts`
14
14
  ## Instructions
15
15
 
16
16
  1. Read the target file(s).
17
- 2. Identify ts-procedures imports (`ts-procedures`, `ts-procedures/express-rpc`, `ts-procedures/hono-rpc`, `ts-procedures/hono-stream`, `ts-procedures/hono-api`, `ts-procedures/http`, `ts-procedures/http-docs`, `ts-procedures/http-errors`, `ts-procedures/client`, `ts-procedures/codegen`) to determine file types.
17
+ 2. Identify ts-procedures imports (`ts-procedures`, `ts-procedures/hono`, `ts-procedures/http`, `ts-procedures/http-docs`, `ts-procedures/http-errors`, `ts-procedures/client`, `ts-procedures/codegen`) to determine file types.
18
18
  3. Check each file against the categorized checklist in [checklist.md](checklist.md).
19
19
  4. For detailed code examples of each violation pattern, reference [anti-patterns.md](../ts-procedures/anti-patterns.md) — it shows 20 common mistakes with before/after code fixes and severity ratings.
20
20
  5. Output findings grouped by severity.
@@ -57,11 +57,10 @@
57
57
 
58
58
  ---
59
59
 
60
- ## HTTP Builder Checks (Express/Hono)
60
+ ## HTTP Builder Checks (HonoAppBuilder)
61
61
 
62
62
  ### CRITICAL
63
- - [ ] Standard `Create` procedures registered with `ExpressRPCAppBuilder` or `HonoRPCAppBuilder`, NOT `HonoStreamAppBuilder`
64
- - [ ] Stream `CreateStream` procedures registered with `HonoStreamAppBuilder`, NOT the RPC builders
63
+ - [ ] `Create` (RPC), `CreateHttp` (REST), `CreateStream` (RPC stream), and `CreateHttpStream` (REST stream) all registered on the same `HonoAppBuilder` — kind dispatch is automatic
65
64
  - [ ] Custom error classes are registered via `defineErrorTaxonomy` + builder's `errors` config — NOT hand-written `onError` instanceof ladders (anti-pattern #20)
66
65
  - [ ] If a handler throws a non-`ProcedureError`, its class is either in the taxonomy or intentionally caught by `unknownError`
67
66
 
@@ -80,7 +79,7 @@
80
79
 
81
80
  ---
82
81
 
83
- ## Streaming Checks (HonoStreamAppBuilder)
82
+ ## Streaming Checks (HonoAppBuilder)
84
83
 
85
84
  ### CRITICAL
86
85
  - [ ] Pre-stream errors handled via either peer mode — `errors` + `unknownError` taxonomy OR `onError` callback (the hono-stream `onPreStreamError` was renamed to `onError` in v6)
@@ -98,7 +97,7 @@
98
97
 
99
98
  ---
100
99
 
101
- ## API Builder Checks (HonoAPIAppBuilder)
100
+ ## API Builder Checks (HonoAppBuilder)
102
101
 
103
102
  ### CRITICAL
104
103
  - [ ] `build()` is called synchronously — it returns `Hono`, NOT `Promise<Hono>`. Do not `await` it.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ts-procedures-scaffold
3
- description: "Generate ts-procedures implementations with correct patterns — procedures, streams, Express RPC, Hono RPC, Hono streaming, REST APIs, and client setup."
3
+ description: "Generate ts-procedures implementations with correct patterns — procedures, streams, Hono apps (RPC, streams, REST in one builder), and client setup."
4
4
  argument-hint: "<type> <Name>"
5
5
  allowed-tools: Read Write
6
6
  ---
@@ -18,9 +18,9 @@ If either argument is missing, ask the user for `<type>` and `<Name>`.
18
18
  3. Derive placeholder variants from the provided PascalCase Name:
19
19
  - `{{Name}}` — PascalCase as given (e.g., `UserProfile`)
20
20
  - `{{name}}` — camelCase (e.g., `userProfile`)
21
- - For URL scopes and file paths, use kebab-case (e.g., `user-profile`)
21
+ - `{{kebab}}` kebab-case (e.g., `user-profile`)
22
22
  4. Read the template file from `templates/$0.md` (relative to this skill directory).
23
- 5. Replace all `{{Name}}` and `{{name}}` placeholders with the appropriate variants.
23
+ 5. Replace all `{{Name}}`, `{{name}}`, and `{{kebab}}` placeholders with the appropriate variants.
24
24
  6. Generate the implementation file(s) following the template exactly.
25
25
  7. Also generate a colocated test file following ts-procedures test conventions.
26
26
 
@@ -30,10 +30,7 @@ If either argument is missing, ask the user for `<type>` and `<Name>`.
30
30
  |------|----------|----------------|
31
31
  | `procedure` | `templates/procedure.md` | `{{Name}}.procedure.ts`, `{{Name}}.procedure.test.ts` |
32
32
  | `stream-procedure` | `templates/stream-procedure.md` | `{{Name}}.stream.ts`, `{{Name}}.stream.test.ts` |
33
- | `express-rpc` | `templates/express-rpc.md` | `{{Name}}.rpc.ts`, `{{Name}}.rpc.test.ts` |
34
- | `hono-rpc` | `templates/hono-rpc.md` | `{{Name}}.rpc.ts`, `{{Name}}.rpc.test.ts` |
35
- | `hono-stream` | `templates/hono-stream.md` | `{{Name}}.stream-rpc.ts`, `{{Name}}.stream-rpc.test.ts` |
36
- | `hono-api` | `templates/hono-api.md` | `{{Name}}.api.ts`, `{{Name}}.api.test.ts` |
33
+ | `hono` | `templates/hono.md` | `{{Name}}.hono.ts`, `{{Name}}.hono.test.ts` |
37
34
  | `client` | `templates/client.md` | `{{Name}}.client.ts`, `{{Name}}.client.test.ts` |
38
35
  | `astro-catchall` | `templates/astro-catchall.md` | `src/pages/api/[...rest].ts` |
39
36