ts-procedures 7.3.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/README.md +65 -3
  2. package/agent_config/claude-code/agents/ts-procedures-architect.md +6 -8
  3. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +30 -33
  4. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +104 -53
  5. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +205 -232
  6. package/agent_config/claude-code/skills/ts-procedures/patterns.md +80 -153
  7. package/agent_config/claude-code/skills/ts-procedures-review/SKILL.md +1 -1
  8. package/agent_config/claude-code/skills/ts-procedures-review/checklist.md +4 -5
  9. package/agent_config/claude-code/skills/ts-procedures-scaffold/SKILL.md +4 -7
  10. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono.md +223 -0
  11. package/agent_config/copilot/copilot-instructions.md +34 -48
  12. package/agent_config/cursor/cursorrules +34 -48
  13. package/build/client/call.js +4 -1
  14. package/build/client/call.js.map +1 -1
  15. package/build/client/call.test.js +23 -0
  16. package/build/client/call.test.js.map +1 -1
  17. package/build/client/fetch-adapter.js +3 -1
  18. package/build/client/fetch-adapter.js.map +1 -1
  19. package/build/client/fetch-adapter.test.js +11 -1
  20. package/build/client/fetch-adapter.test.js.map +1 -1
  21. package/build/client/index.test.js +7 -7
  22. package/build/client/index.test.js.map +1 -1
  23. package/build/client/request-builder.d.ts +1 -1
  24. package/build/client/request-builder.js +2 -2
  25. package/build/client/request-builder.js.map +1 -1
  26. package/build/client/stream.js +13 -2
  27. package/build/client/stream.js.map +1 -1
  28. package/build/client/stream.test.js +32 -7
  29. package/build/client/stream.test.js.map +1 -1
  30. package/build/client/typed-error-dispatch.test.js +8 -92
  31. package/build/client/typed-error-dispatch.test.js.map +1 -1
  32. package/build/client/types.d.ts +21 -3
  33. package/build/codegen/bin/cli.js +0 -0
  34. package/build/codegen/e2e.test.js +87 -23
  35. package/build/codegen/e2e.test.js.map +1 -1
  36. package/build/codegen/emit-errors.integration.test.js +1 -1
  37. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  38. package/build/codegen/emit-scope.js +308 -47
  39. package/build/codegen/emit-scope.js.map +1 -1
  40. package/build/codegen/emit-scope.test.js +363 -110
  41. package/build/codegen/emit-scope.test.js.map +1 -1
  42. package/build/codegen/pipeline.test.js +7 -7
  43. package/build/codegen/pipeline.test.js.map +1 -1
  44. package/build/codegen/resolve-envelope.js +1 -1
  45. package/build/codegen/resolve-envelope.js.map +1 -1
  46. package/build/codegen/resolve-envelope.test.js +5 -5
  47. package/build/codegen/resolve-envelope.test.js.map +1 -1
  48. package/build/codegen/targets/_shared/route-slots.d.ts +8 -3
  49. package/build/codegen/targets/_shared/route-slots.js +49 -8
  50. package/build/codegen/targets/_shared/route-slots.js.map +1 -1
  51. package/build/codegen/targets/_shared/route-slots.test.js +99 -26
  52. package/build/codegen/targets/_shared/route-slots.test.js.map +1 -1
  53. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js +88 -17
  54. package/build/codegen/targets/kotlin/emit-route-kotlin.test.js.map +1 -1
  55. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js +9 -6
  56. package/build/codegen/targets/kotlin/emit-scope-kotlin.test.js.map +1 -1
  57. package/build/codegen/targets/kotlin/integration.test.js +6 -0
  58. package/build/codegen/targets/kotlin/integration.test.js.map +1 -1
  59. package/build/codegen/targets/swift/access-level.test.js +8 -11
  60. package/build/codegen/targets/swift/access-level.test.js.map +1 -1
  61. package/build/codegen/targets/swift/emit-route-swift.test.js +91 -20
  62. package/build/codegen/targets/swift/emit-route-swift.test.js.map +1 -1
  63. package/build/codegen/targets/swift/emit-scope-swift.test.js +12 -9
  64. package/build/codegen/targets/swift/emit-scope-swift.test.js.map +1 -1
  65. package/build/codegen/targets/swift/integration.test.js +6 -0
  66. package/build/codegen/targets/swift/integration.test.js.map +1 -1
  67. package/build/create-http-stream.d.ts +58 -0
  68. package/build/create-http-stream.js +122 -0
  69. package/build/create-http-stream.js.map +1 -0
  70. package/build/create-http-stream.test.js +88 -0
  71. package/build/create-http-stream.test.js.map +1 -0
  72. package/build/create-http.d.ts +49 -0
  73. package/build/create-http.js +108 -0
  74. package/build/create-http.js.map +1 -0
  75. package/build/create-http.test.js +137 -0
  76. package/build/create-http.test.js.map +1 -0
  77. package/build/create-stream.d.ts +35 -0
  78. package/build/create-stream.js +123 -0
  79. package/build/create-stream.js.map +1 -0
  80. package/build/create-stream.test.js +428 -0
  81. package/build/create-stream.test.js.map +1 -0
  82. package/build/create.d.ts +28 -0
  83. package/build/create.js +82 -0
  84. package/build/create.js.map +1 -0
  85. package/build/create.test.js +483 -0
  86. package/build/create.test.js.map +1 -0
  87. package/build/exports.d.ts +2 -0
  88. package/build/implementations/http/astro/index.test.js +20 -12
  89. package/build/implementations/http/astro/index.test.js.map +1 -1
  90. package/build/implementations/http/doc-registry.js +1 -1
  91. package/build/implementations/http/doc-registry.js.map +1 -1
  92. package/build/implementations/http/doc-registry.test.js +36 -5
  93. package/build/implementations/http/doc-registry.test.js.map +1 -1
  94. package/build/implementations/http/error-dispatch.d.ts +76 -0
  95. package/build/implementations/http/error-dispatch.js +77 -0
  96. package/build/implementations/http/error-dispatch.js.map +1 -0
  97. package/build/implementations/http/error-dispatch.test.js +254 -0
  98. package/build/implementations/http/error-dispatch.test.js.map +1 -0
  99. package/build/implementations/http/error-taxonomy.d.ts +5 -5
  100. package/build/implementations/http/hono/docs/http-doc.d.ts +6 -0
  101. package/build/implementations/http/hono/docs/http-doc.js +42 -0
  102. package/build/implementations/http/hono/docs/http-doc.js.map +1 -0
  103. package/build/implementations/http/hono/docs/http-stream-doc.d.ts +6 -0
  104. package/build/implementations/http/hono/docs/http-stream-doc.js +40 -0
  105. package/build/implementations/http/hono/docs/http-stream-doc.js.map +1 -0
  106. package/build/implementations/http/hono/docs/rpc-doc.d.ts +6 -0
  107. package/build/implementations/http/hono/docs/rpc-doc.js +24 -0
  108. package/build/implementations/http/hono/docs/rpc-doc.js.map +1 -0
  109. package/build/implementations/http/hono/docs/stream-doc.d.ts +6 -0
  110. package/build/implementations/http/hono/docs/stream-doc.js +42 -0
  111. package/build/implementations/http/hono/docs/stream-doc.js.map +1 -0
  112. package/build/implementations/http/hono/handlers/http-stream.d.ts +10 -0
  113. package/build/implementations/http/hono/handlers/http-stream.js +123 -0
  114. package/build/implementations/http/hono/handlers/http-stream.js.map +1 -0
  115. package/build/implementations/http/hono/handlers/http-stream.test.js +128 -0
  116. package/build/implementations/http/hono/handlers/http-stream.test.js.map +1 -0
  117. package/build/implementations/http/hono/handlers/http.d.ts +10 -0
  118. package/build/implementations/http/hono/handlers/http.js +115 -0
  119. package/build/implementations/http/hono/handlers/http.js.map +1 -0
  120. package/build/implementations/http/hono/handlers/http.test.js +118 -0
  121. package/build/implementations/http/hono/handlers/http.test.js.map +1 -0
  122. package/build/implementations/http/hono/handlers/rpc.d.ts +11 -0
  123. package/build/implementations/http/hono/handlers/rpc.js +32 -0
  124. package/build/implementations/http/hono/handlers/rpc.js.map +1 -0
  125. package/build/implementations/http/hono/handlers/rpc.test.js +73 -0
  126. package/build/implementations/http/hono/handlers/rpc.test.js.map +1 -0
  127. package/build/implementations/http/hono/handlers/stream.d.ts +23 -0
  128. package/build/implementations/http/hono/handlers/stream.js +147 -0
  129. package/build/implementations/http/hono/handlers/stream.js.map +1 -0
  130. package/build/implementations/http/hono/handlers/stream.test.d.ts +1 -0
  131. package/build/implementations/http/hono/handlers/stream.test.js +177 -0
  132. package/build/implementations/http/hono/handlers/stream.test.js.map +1 -0
  133. package/build/implementations/http/hono/index.d.ts +57 -0
  134. package/build/implementations/http/hono/index.js +149 -0
  135. package/build/implementations/http/hono/index.js.map +1 -0
  136. package/build/implementations/http/hono/index.test.d.ts +1 -0
  137. package/build/implementations/http/hono/index.test.js +274 -0
  138. package/build/implementations/http/hono/index.test.js.map +1 -0
  139. package/build/implementations/http/hono/path.d.ts +17 -0
  140. package/build/implementations/http/hono/path.js +39 -0
  141. package/build/implementations/http/hono/path.js.map +1 -0
  142. package/build/implementations/http/hono/path.test.d.ts +1 -0
  143. package/build/implementations/http/hono/path.test.js +83 -0
  144. package/build/implementations/http/hono/path.test.js.map +1 -0
  145. package/build/implementations/http/hono/types.d.ts +51 -0
  146. package/build/implementations/http/hono/types.js.map +1 -0
  147. package/build/implementations/http/on-request-error.test.js +6 -96
  148. package/build/implementations/http/on-request-error.test.js.map +1 -1
  149. package/build/implementations/http/route-errors.test.js +11 -59
  150. package/build/implementations/http/route-errors.test.js.map +1 -1
  151. package/build/implementations/types.d.ts +43 -9
  152. package/build/index.d.ts +124 -124
  153. package/build/index.js +10 -221
  154. package/build/index.js.map +1 -1
  155. package/build/index.test.js +20 -919
  156. package/build/index.test.js.map +1 -1
  157. package/build/migration.test.d.ts +1 -0
  158. package/build/migration.test.js +34 -0
  159. package/build/migration.test.js.map +1 -0
  160. package/build/schema/compute-schema.d.ts +11 -3
  161. package/build/schema/compute-schema.js +13 -7
  162. package/build/schema/compute-schema.js.map +1 -1
  163. package/build/schema/parser.d.ts +11 -3
  164. package/build/schema/parser.js +49 -9
  165. package/build/schema/parser.js.map +1 -1
  166. package/build/stack-utils.js +8 -0
  167. package/build/stack-utils.js.map +1 -1
  168. package/build/types.d.ts +142 -0
  169. package/build/types.js.map +1 -0
  170. package/docs/astro-adapter.md +5 -5
  171. package/docs/core.md +15 -17
  172. package/docs/http-integrations.md +83 -170
  173. package/docs/streaming.md +3 -60
  174. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +2 -7
  175. package/docs/superpowers/plans/2026-05-08-create-http.md +3355 -0
  176. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +3365 -0
  177. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +1 -3
  178. package/docs/superpowers/specs/2026-05-08-create-http-design.md +409 -0
  179. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +411 -0
  180. package/package.json +4 -22
  181. package/src/client/call.test.ts +26 -0
  182. package/src/client/call.ts +4 -1
  183. package/src/client/fetch-adapter.test.ts +14 -1
  184. package/src/client/fetch-adapter.ts +3 -1
  185. package/src/client/index.test.ts +7 -7
  186. package/src/client/request-builder.ts +2 -2
  187. package/src/client/stream.test.ts +39 -7
  188. package/src/client/stream.ts +16 -2
  189. package/src/client/typed-error-dispatch.test.ts +7 -97
  190. package/src/client/types.ts +21 -3
  191. package/src/codegen/__fixtures__/users-envelope.json +119 -38
  192. package/src/codegen/e2e.test.ts +98 -24
  193. package/src/codegen/emit-errors.integration.test.ts +1 -1
  194. package/src/codegen/emit-scope.test.ts +395 -110
  195. package/src/codegen/emit-scope.ts +350 -55
  196. package/src/codegen/pipeline.test.ts +7 -7
  197. package/src/codegen/resolve-envelope.test.ts +5 -5
  198. package/src/codegen/resolve-envelope.ts +1 -1
  199. package/src/codegen/targets/_shared/route-slots.test.ts +109 -26
  200. package/src/codegen/targets/_shared/route-slots.ts +48 -11
  201. package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +73 -0
  202. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +100 -17
  203. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +9 -6
  204. package/src/codegen/targets/kotlin/integration.test.ts +19 -0
  205. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +79 -0
  206. package/src/codegen/targets/swift/access-level.test.ts +8 -11
  207. package/src/codegen/targets/swift/emit-route-swift.test.ts +103 -20
  208. package/src/codegen/targets/swift/emit-scope-swift.test.ts +12 -9
  209. package/src/codegen/targets/swift/integration.test.ts +17 -0
  210. package/src/create-http-stream.test.ts +97 -0
  211. package/src/create-http-stream.ts +191 -0
  212. package/src/create-http.test.ts +163 -0
  213. package/src/create-http.ts +211 -0
  214. package/src/create-stream.test.ts +565 -0
  215. package/src/create-stream.ts +228 -0
  216. package/src/create.test.ts +658 -0
  217. package/src/create.ts +172 -0
  218. package/src/exports.ts +2 -0
  219. package/src/implementations/http/README.md +135 -95
  220. package/src/implementations/http/astro/README.md +4 -5
  221. package/src/implementations/http/astro/index.test.ts +25 -18
  222. package/src/implementations/http/doc-registry.test.ts +42 -5
  223. package/src/implementations/http/doc-registry.ts +1 -1
  224. package/src/implementations/http/error-dispatch.test.ts +283 -0
  225. package/src/implementations/http/error-dispatch.ts +176 -0
  226. package/src/implementations/http/error-taxonomy.ts +5 -5
  227. package/src/implementations/http/hono/docs/http-doc.ts +43 -0
  228. package/src/implementations/http/hono/docs/http-stream-doc.ts +44 -0
  229. package/src/implementations/http/hono/docs/rpc-doc.ts +34 -0
  230. package/src/implementations/http/hono/docs/stream-doc.ts +53 -0
  231. package/src/implementations/http/hono/handlers/http-stream.test.ts +150 -0
  232. package/src/implementations/http/hono/handlers/http-stream.ts +152 -0
  233. package/src/implementations/http/hono/handlers/http.test.ts +130 -0
  234. package/src/implementations/http/hono/handlers/http.ts +147 -0
  235. package/src/implementations/http/hono/handlers/rpc.test.ts +81 -0
  236. package/src/implementations/http/hono/handlers/rpc.ts +54 -0
  237. package/src/implementations/http/hono/handlers/stream.test.ts +198 -0
  238. package/src/implementations/http/hono/handlers/stream.ts +208 -0
  239. package/src/implementations/http/hono/index.test.ts +329 -0
  240. package/src/implementations/http/hono/index.ts +204 -0
  241. package/src/implementations/http/hono/path.test.ts +96 -0
  242. package/src/implementations/http/hono/path.ts +59 -0
  243. package/src/implementations/http/hono/types.ts +93 -0
  244. package/src/implementations/http/on-request-error.test.ts +10 -116
  245. package/src/implementations/http/route-errors.test.ts +11 -77
  246. package/src/implementations/types.ts +44 -9
  247. package/src/index.test.ts +22 -1249
  248. package/src/index.ts +49 -485
  249. package/src/migration.test.ts +48 -0
  250. package/src/schema/compute-schema.ts +26 -12
  251. package/src/schema/parser.ts +62 -12
  252. package/src/stack-utils.ts +8 -0
  253. package/src/types.ts +133 -0
  254. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/express-rpc.md +0 -137
  255. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-api.md +0 -173
  256. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-rpc.md +0 -142
  257. package/agent_config/claude-code/skills/ts-procedures-scaffold/templates/hono-stream.md +0 -147
  258. package/build/implementations/http/express-rpc/error-taxonomy.test.js +0 -83
  259. package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +0 -1
  260. package/build/implementations/http/express-rpc/index.d.ts +0 -125
  261. package/build/implementations/http/express-rpc/index.js +0 -216
  262. package/build/implementations/http/express-rpc/index.js.map +0 -1
  263. package/build/implementations/http/express-rpc/index.test.js +0 -684
  264. package/build/implementations/http/express-rpc/index.test.js.map +0 -1
  265. package/build/implementations/http/express-rpc/types.d.ts +0 -11
  266. package/build/implementations/http/express-rpc/types.js.map +0 -1
  267. package/build/implementations/http/hono-api/error-taxonomy.test.js +0 -137
  268. package/build/implementations/http/hono-api/error-taxonomy.test.js.map +0 -1
  269. package/build/implementations/http/hono-api/index.d.ts +0 -151
  270. package/build/implementations/http/hono-api/index.js +0 -344
  271. package/build/implementations/http/hono-api/index.js.map +0 -1
  272. package/build/implementations/http/hono-api/index.test.js +0 -992
  273. package/build/implementations/http/hono-api/index.test.js.map +0 -1
  274. package/build/implementations/http/hono-api/types.d.ts +0 -13
  275. package/build/implementations/http/hono-api/types.js.map +0 -1
  276. package/build/implementations/http/hono-rpc/error-taxonomy.test.js +0 -64
  277. package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +0 -1
  278. package/build/implementations/http/hono-rpc/index.d.ts +0 -130
  279. package/build/implementations/http/hono-rpc/index.js +0 -209
  280. package/build/implementations/http/hono-rpc/index.js.map +0 -1
  281. package/build/implementations/http/hono-rpc/index.test.js +0 -828
  282. package/build/implementations/http/hono-rpc/index.test.js.map +0 -1
  283. package/build/implementations/http/hono-rpc/types.d.ts +0 -11
  284. package/build/implementations/http/hono-rpc/types.js +0 -2
  285. package/build/implementations/http/hono-rpc/types.js.map +0 -1
  286. package/build/implementations/http/hono-stream/error-taxonomy.test.js +0 -159
  287. package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +0 -1
  288. package/build/implementations/http/hono-stream/index.d.ts +0 -171
  289. package/build/implementations/http/hono-stream/index.js +0 -415
  290. package/build/implementations/http/hono-stream/index.js.map +0 -1
  291. package/build/implementations/http/hono-stream/index.test.js +0 -1383
  292. package/build/implementations/http/hono-stream/index.test.js.map +0 -1
  293. package/build/implementations/http/hono-stream/types.d.ts +0 -15
  294. package/build/implementations/http/hono-stream/types.js +0 -2
  295. package/build/implementations/http/hono-stream/types.js.map +0 -1
  296. package/src/implementations/http/express-rpc/README.md +0 -280
  297. package/src/implementations/http/express-rpc/error-taxonomy.test.ts +0 -103
  298. package/src/implementations/http/express-rpc/index.test.ts +0 -957
  299. package/src/implementations/http/express-rpc/index.ts +0 -327
  300. package/src/implementations/http/express-rpc/types.ts +0 -16
  301. package/src/implementations/http/hono-api/README.md +0 -284
  302. package/src/implementations/http/hono-api/error-taxonomy.test.ts +0 -179
  303. package/src/implementations/http/hono-api/index.test.ts +0 -1341
  304. package/src/implementations/http/hono-api/index.ts +0 -519
  305. package/src/implementations/http/hono-api/types.ts +0 -16
  306. package/src/implementations/http/hono-rpc/README.md +0 -357
  307. package/src/implementations/http/hono-rpc/error-taxonomy.test.ts +0 -82
  308. package/src/implementations/http/hono-rpc/index.test.ts +0 -1107
  309. package/src/implementations/http/hono-rpc/index.ts +0 -320
  310. package/src/implementations/http/hono-rpc/types.ts +0 -16
  311. package/src/implementations/http/hono-stream/README.md +0 -559
  312. package/src/implementations/http/hono-stream/error-taxonomy.test.ts +0 -178
  313. package/src/implementations/http/hono-stream/index.test.ts +0 -1804
  314. package/src/implementations/http/hono-stream/index.ts +0 -622
  315. package/src/implementations/http/hono-stream/types.ts +0 -20
  316. /package/build/{implementations/http/express-rpc/error-taxonomy.test.d.ts → create-http-stream.test.d.ts} +0 -0
  317. /package/build/{implementations/http/express-rpc/index.test.d.ts → create-http.test.d.ts} +0 -0
  318. /package/build/{implementations/http/hono-api/error-taxonomy.test.d.ts → create-stream.test.d.ts} +0 -0
  319. /package/build/{implementations/http/hono-api/index.test.d.ts → create.test.d.ts} +0 -0
  320. /package/build/implementations/http/{hono-rpc/error-taxonomy.test.d.ts → error-dispatch.test.d.ts} +0 -0
  321. /package/build/implementations/http/{hono-rpc/index.test.d.ts → hono/handlers/http-stream.test.d.ts} +0 -0
  322. /package/build/implementations/http/{hono-stream/error-taxonomy.test.d.ts → hono/handlers/http.test.d.ts} +0 -0
  323. /package/build/implementations/http/{hono-stream/index.test.d.ts → hono/handlers/rpc.test.d.ts} +0 -0
  324. /package/build/implementations/http/{express-rpc → hono}/types.js +0 -0
  325. /package/build/{implementations/http/hono-api/types.js → types.js} +0 -0
@@ -12,7 +12,6 @@ The goal is a "drop in the entry point" adapter: a single catch-all Astro file d
12
12
 
13
13
  ## Non-goals
14
14
 
15
- - Express RPC support. Express uses Node `req`/`res`, not Web `Request`/`Response`. A bridge is non-trivial (body streams, hijacked sockets, `res.flushHeaders`); defer until requested.
16
15
  - Native Astro builders. Mirroring `HonoAPIAppBuilder` as `AstroAPIAppBuilder` would duplicate path-matching, schema validation, error taxonomy, and DocRegistry plumbing. The catch-all pattern covers the request without that cost.
17
16
  - Per-procedure file scaffolding (one Astro file per procedure). Out of scope for v1.
18
17
  - DocRegistry / codegen integration. Users keep wiring `DocRegistry` against the same builders they pass to the adapter; the adapter returns no `.docs`.
@@ -229,7 +228,6 @@ Integration-style, real builders, simulated `Request`:
229
228
  },
230
229
  "optionalDependencies": {
231
230
  "ajsc": "...",
232
- "express": "...",
233
231
  "hono": "...",
234
232
  "astro": "^5.0.0"
235
233
  },
@@ -239,7 +237,7 @@ Integration-style, real builders, simulated `Request`:
239
237
  }
240
238
  ```
241
239
 
242
- Matching the existing pattern for `hono` and `express`: listed as `optionalDependencies` so it isn't pulled into non-Astro deployments, and as `devDependencies` so types resolve at build time. Astro is imported via `import type` only — zero runtime dependency on the published package.
240
+ Matching the existing pattern for `hono`: listed as `optionalDependencies` so it isn't pulled into non-Astro deployments, and as `devDependencies` so types resolve at build time. Astro is imported via `import type` only — zero runtime dependency on the published package.
243
241
 
244
242
  ## Agent config / docs
245
243
 
@@ -0,0 +1,409 @@
1
+ # CreateHttp & CreateHttpStream — Design
2
+
3
+ Date: 2026-05-08
4
+ Branch: TBD (next major — v8)
5
+ Status: design
6
+
7
+ ## Goal
8
+
9
+ Eliminate the long-standing `schema.params` vs `schema.input` ambiguity on the core `Create` / `CreateStream` primitives by splitting the surface into four purpose-shaped creators. RPC stays as the lean primitive; HTTP becomes its own first-class shape with structured request channels and response (body + headers) typing.
10
+
11
+ | Creator | Purpose | Schema shape |
12
+ |---|---|---|
13
+ | `Create` | RPC unary (today's primitive, simplified) | `{ params, returnType }` |
14
+ | `CreateStream` | RPC streaming (today's primitive, simplified) | `{ params, yieldType, returnType }` |
15
+ | `CreateHttp` | HTTP unary (new) | `{ req: { pathParams?, query?, body?, headers? }, res?: { body?, headers? } }` |
16
+ | `CreateHttpStream` | HTTP streaming (new) | `{ req: {...}, yield, returnType?, res?: { headers? } }` |
17
+
18
+ The `Create` / `CreateStream` shape stops accepting `schema.input` entirely. HTTP-specific config (`path`, `method`, `successStatus`, `scope`, `errors`) becomes first-class on the HTTP creators rather than living on a `TExtendedConfig` generic. Response headers — previously not modelable — become a typed first-class concept.
19
+
20
+ ## Non-goals
21
+
22
+ - **Runtime validation of `res.body` / `res.headers`.** Today `schema.returnType` is doc-only at runtime; the same rule applies to `res`. Adding a `validateResponse: true` opt-in is a clean follow-up but kept out to bound the breaking-changes scope to the input ambiguity cleanup.
23
+ - **`ctx.res.setHeader(...)` style imperative API.** Headers flow through the handler return value only. Pure return-driven, type-checkable end-to-end.
24
+ - **Per-builder migration adapters.** This is a major version. Clean break with informative `ProcedureRegistrationError` migration messages — no v7-compat shim layer.
25
+ - **Renaming `Create` or `CreateStream`.** Their shapes simplify (lose `schema.input`), but the names and the RPC posture stay.
26
+
27
+ ## Decisions locked during brainstorming
28
+
29
+ 1. **Four creators, one factory.** `Procedures<TContext>()` returns `{ Create, CreateStream, CreateHttp, CreateHttpStream }`. Mirrors the existing `Create` / `CreateStream` split.
30
+ 2. **Conditional return shape on HTTP creators.** Handler return widens type-driven from declared `res`:
31
+ - no `res` → `void`
32
+ - `res: { body }` → bare body (matches today's `schema.returnType` ergonomics)
33
+ - `res: { headers }` → `{ headers }`
34
+ - `res: { body, headers }` → `{ body, headers }`
35
+ 3. **HTTP fields baked into CreateHttp config.** `path`, `method`, `successStatus`, `scope`, `errors` live directly on the `CreateHttp` / `CreateHttpStream` config — no `Procedures<Ctx, APIConfig>()` plumbing for HTTP routes. `Create` / `CreateStream` keep `TExtendedConfig` for non-HTTP extensions (`RPCConfig`, etc.).
36
+ 4. **`CreateHttpStream` initial response headers** via async-preamble shape: when `res.headers` is declared, the handler is an `async` function returning `{ headers, stream: AsyncGenerator }`. When not, the handler is a plain `async function*`.
37
+ 5. **`schema.input` and `APIInput` removed.** Not deprecated — removed. `ProcedureRegistrationError` thrown at registration time with a v8 migration message.
38
+
39
+ ## API surface
40
+
41
+ ### The four creators
42
+
43
+ ```ts
44
+ const procs = Procedures<MyContext>()
45
+
46
+ // 1. RPC unary — schema.input removed; schema.params is the only input shape
47
+ procs.Create('GetUser', {
48
+ schema: {
49
+ params: Type.Object({ id: Type.String() }),
50
+ returnType: Type.Object({ id: Type.String(), name: Type.String() }),
51
+ },
52
+ }, async (ctx, { id }) => ({ id, name: 'John' }))
53
+
54
+ // 2. RPC streaming — schema.input removed
55
+ procs.CreateStream('Tail', {
56
+ schema: {
57
+ params: Type.Object({ source: Type.String() }),
58
+ yieldType: Type.Object({ line: Type.String() }),
59
+ returnType: Type.Object({ totalLines: Type.Number() }),
60
+ },
61
+ }, async function* (ctx, { source }) { /* ... */ })
62
+
63
+ // 3. HTTP unary
64
+ procs.CreateHttp('GetUser', {
65
+ path: '/users/:id',
66
+ method: 'get',
67
+ successStatus: 200, // optional, defaulted by method
68
+ scope: 'users', // optional, codegen grouping
69
+ errors: ['UserNotFound'], // optional, taxonomy keys (TErrorKey-narrowable)
70
+ schema: {
71
+ req: {
72
+ pathParams: Type.Object({ id: Type.String() }),
73
+ query: Type.Object({ include: Type.Optional(Type.String()) }),
74
+ },
75
+ res: {
76
+ body: Type.Object({ id: Type.String(), name: Type.String() }),
77
+ headers: Type.Object({ 'x-rate-limit-remaining': Type.String() }),
78
+ },
79
+ },
80
+ }, async (ctx, { pathParams, query }) => ({
81
+ body: { id: pathParams.id, name: 'John' },
82
+ headers: { 'x-rate-limit-remaining': '99' },
83
+ }))
84
+
85
+ // 4. HTTP streaming — async preamble + generator when res.headers declared
86
+ procs.CreateHttpStream('TailLogs', {
87
+ path: '/streams/logs',
88
+ method: 'get',
89
+ scope: 'streams',
90
+ schema: {
91
+ req: { query: Type.Object({ source: Type.String() }) },
92
+ yield: Type.Object({ line: Type.String() }),
93
+ returnType: Type.Object({ totalLines: Type.Number() }),
94
+ res: { headers: Type.Object({ 'x-stream-id': Type.String() }) },
95
+ },
96
+ }, async (ctx, { query }) => {
97
+ const streamId = await openStream(query.source)
98
+ return {
99
+ headers: { 'x-stream-id': streamId },
100
+ stream: (async function* () {
101
+ yield { line: 'a' }
102
+ return { totalLines: 1 }
103
+ })(),
104
+ }
105
+ })
106
+
107
+ // 4b. Without res.headers — plain async generator (today's CreateStream shape)
108
+ procs.CreateHttpStream('TailLogs', {
109
+ path: '/streams/logs', method: 'get',
110
+ schema: {
111
+ req: { query: Type.Object({ source: Type.String() }) },
112
+ yield: Type.Object({ line: Type.String() }),
113
+ returnType: Type.Object({ totalLines: Type.Number() }),
114
+ },
115
+ }, async function* (ctx, { query }) {
116
+ yield { line: 'a' }
117
+ return { totalLines: 1 }
118
+ })
119
+ ```
120
+
121
+ ### Handler signature inference
122
+
123
+ ```ts
124
+ type CreateHttpHandler<TReq, TRes, TContext> = (
125
+ ctx: TContext & TLocalContext,
126
+ req: PrettifyChannels<TReq>,
127
+ ) => Promise<HttpReturn<TRes>>
128
+
129
+ type HttpReturn<TRes> =
130
+ TRes extends { body: infer B; headers: infer H } ? { body: Infer<B>; headers: Infer<H> }
131
+ : TRes extends { headers: infer H } ? { headers: Infer<H> }
132
+ : TRes extends { body: infer B } ? Infer<B>
133
+ : void
134
+ ```
135
+
136
+ `PrettifyChannels<TReq>` maps each declared channel through `TSchemaLib<TReq[K]>` — same machinery as today's `schema.input` inference at `src/index.ts:127-130`.
137
+
138
+ `ctx` shape is unchanged from today: `TContext & { error, signal? }` for `CreateHttp`, `TContext & { error, signal: AbortSignal }` for `CreateHttpStream`. Hono builders inject `c.req.raw.signal` automatically.
139
+
140
+ ### Generic over `TErrorKey`
141
+
142
+ Same compile-time typo protection as today's `APIConfig<TErrorKey>`, lifted onto the creator. `TErrorKey` defaults to `string` (unconstrained) and gets narrowed in one of two ways:
143
+
144
+ **Per-call narrowing via `satisfies`** (zero ceremony):
145
+
146
+ ```ts
147
+ const appErrors = defineErrorTaxonomy({
148
+ UserNotFound: { class: UserNotFoundError, statusCode: 404 },
149
+ })
150
+ type AppErrorKey = keyof typeof appErrors & string
151
+
152
+ procs.CreateHttp('GetUser', {
153
+ path: '/users/:id', method: 'get',
154
+ errors: ['UserNotFound', 'NotARealKey'] satisfies AppErrorKey[], // ^^ TS error
155
+ schema: { req: {...}, res: {...} },
156
+ }, handler)
157
+ ```
158
+
159
+ **App-wide narrowing via aliased creator** (DRYer for large apps): expose a typed alias once at module-init time and use it everywhere:
160
+
161
+ ```ts
162
+ const procs = Procedures<MyContext>()
163
+ const HttpRoute = procs.CreateHttp as
164
+ <TName extends string, TReq, TRes>(
165
+ name: TName,
166
+ config: CreateHttpConfig<TReq, TRes, AppErrorKey>,
167
+ handler: CreateHttpHandler<TReq, TRes, MyContext>,
168
+ ) => ReturnType<typeof procs.CreateHttp<TName, TReq, TRes, AppErrorKey>>
169
+
170
+ HttpRoute('GetUser', { ..., errors: ['UserNotFound'] }, handler)
171
+ ```
172
+
173
+ The framework ships `CreateHttpConfig` and `CreateHttpHandler` as exported helper types so the alias pattern is a one-liner per app.
174
+
175
+ ### `kind` discriminant on every registration
176
+
177
+ Replaces today's `isStream?: boolean`. Builders filter by kind; non-matching procedures recorded in `skippedProcedures` and warned at `DocRegistry.toJSON()` time.
178
+
179
+ ```ts
180
+ type ProcedureKind = 'rpc' | 'rpc-stream' | 'http' | 'http-stream'
181
+ ```
182
+
183
+ | Creator | `kind` | Served by |
184
+ |---|---|---|
185
+ | `Create` | `'rpc'` | hono-rpc |
186
+ | `CreateStream` | `'rpc-stream'` | hono-stream |
187
+ | `CreateHttp` | `'http'` | hono-api |
188
+ | `CreateHttpStream` | `'http-stream'` | hono-api |
189
+
190
+ ## Builder integration
191
+
192
+ ### `HonoAPIAppBuilder` — unified HTTP builder
193
+
194
+ Serves both `'http'` and `'http-stream'` registrations. Single mount, single error config, single doc source. Internal branch on kind:
195
+
196
+ - **`'http'` branch:** today's flow with three differences:
197
+ 1. Reads `path` / `method` / `successStatus` / `scope` / `errors` directly off the registration (no `Procedures<Ctx, APIConfig>()` generic plumbing).
198
+ 2. Drops the `schema.params` body/query fallback. `req` channels are the only source.
199
+ 3. When the handler returns `{ body, headers }`, iterate headers via `c.header(k, v)` before `c.json(body, status)` / `c.body(null, status)`. Error responses don't carry handler-declared headers.
200
+ - **`'http-stream'` branch:** pre-stream phase (validation + async preamble if `res.headers` declared) → if it throws, error taxonomy serializes a normal HTTP error (no SSE opened); if it succeeds, response headers are written, then the SSE/text stream opens. Mid-stream errors continue through `onMidStreamError`. The `isPrevalidated` flag pattern (today used by HonoStreamAppBuilder) extends to this branch.
201
+
202
+ `HonoAPIFactoryItem<TFactory>` simplifies — no `APIConfig` extension generic. `extendProcedureDoc` callback signature is unchanged, but the `base` doc handed to it has the new `req`/`res` grouping (callbacks reading `base.jsonSchema.body` directly need to read `base.jsonSchema.req.body` after upgrade).
203
+
204
+ The path-param consistency check (`extractPathParamNames` + schema key matching) **moves from the Hono builder into core `CreateHttp` registration** — fires at registration time regardless of which HTTP builder is attached. `ProcedureRegistrationError` with the existing well-formed message.
205
+
206
+ ### Other builders — minimal change
207
+
208
+ - **`HonoStreamAppBuilder`:** unchanged externally. Internally filters by `kind === 'rpc-stream'`. Symmetric pair to `HonoRPCAppBuilder` for serving `Create` / `CreateStream`.
209
+ - **`HonoRPCAppBuilder`:** unchanged externally. Internally filters by `kind === 'rpc'`. CreateHttp registrations on the same factory get recorded in `skippedProcedures`.
210
+ - **Astro adapter** (`src/implementations/http/astro/`): same kind-aware updates as hono-api. Mirrors the hono-api pattern. Implementation phase.
211
+
212
+ ### Mixed-kind factories
213
+
214
+ Because all four creators share one `Procedures()` factory, you *can* mix `Create` and `CreateHttp` in the same factory. Builders pick out what they serve. The user-facing rule: register a builder for each kind you want to serve.
215
+
216
+ ## Doc envelope & codegen impact
217
+
218
+ ### `APIHttpRouteDoc` regroups under `req` / `res`
219
+
220
+ Symmetric with the registration shape — removes the awkward "request `headers` vs response `headers`" overload at the JSON schema level (today both would just be top-level `headers`):
221
+
222
+ ```ts
223
+ // before
224
+ jsonSchema: { pathParams?, query?, body?, headers?, response? }
225
+
226
+ // after
227
+ jsonSchema: {
228
+ req: { pathParams?, query?, body?, headers? }
229
+ res?: { body?, headers? }
230
+ }
231
+ ```
232
+
233
+ ### New `'http-stream'` kind in the envelope
234
+
235
+ Existing `StreamHttpRouteDoc` (kind `'stream'`) keeps serving `CreateStream` unchanged. New variant for `CreateHttpStream`:
236
+
237
+ ```ts
238
+ interface HttpStreamRouteDoc {
239
+ kind: 'http-stream'
240
+ name: string
241
+ scope?: string
242
+ path: string
243
+ method: HttpMethod
244
+ fullPath: string
245
+ streamMode: StreamMode
246
+ jsonSchema: {
247
+ req: { pathParams?, query?, body?, headers? }
248
+ res?: { headers? } // body absent — yield/returnType replace it
249
+ yield?: Record<string, unknown>
250
+ returnType?: Record<string, unknown>
251
+ }
252
+ errors?: string[] // pre-stream only
253
+ }
254
+ ```
255
+
256
+ `AnyHttpRouteDoc = RPCHttpRouteDoc | APIHttpRouteDoc | StreamHttpRouteDoc | HttpStreamRouteDoc`.
257
+
258
+ ### Generated callable shape (TS target)
259
+
260
+ Conditional return widens symmetric to the server side:
261
+
262
+ ```ts
263
+ // res: { body } only — bare body (no break for routes without res.headers)
264
+ function getUser(req, opts?): Promise<GetUser.Response.Body>
265
+
266
+ // res: { body, headers }
267
+ function getUser(req, opts?): Promise<{ body: GetUser.Response.Body; headers: GetUser.Response.Headers }>
268
+
269
+ // res: { headers } only
270
+ function getUser(req, opts?): Promise<{ headers: GetUser.Response.Headers }>
271
+ ```
272
+
273
+ Generated namespace (namespace mode):
274
+ ```
275
+ Users.GetUser.Req.PathParams
276
+ Users.GetUser.Req.Query
277
+ Users.GetUser.Req.Body
278
+ Users.GetUser.Req.Headers
279
+ Users.GetUser.Response.Body
280
+ Users.GetUser.Response.Headers
281
+ Users.GetUser.Errors
282
+ ```
283
+
284
+ Flat-mode aliases: `GetUserReqPathParams`, `GetUserReqBody`, `GetUserResponseBody`, `GetUserResponseHeaders`. Naming lives in `src/codegen/emit-scope.ts` and per-target run modules; `targets/_shared/route-slots.ts` gets a response-headers slot.
285
+
286
+ `.safe()` widens identically: `Result<{ body, headers }, ETyped>` when headers declared. The `'typed'` arm omission rule (when no `route.errors`) is unchanged.
287
+
288
+ ### `CreateHttpStream` generated callable
289
+
290
+ Returns `TypedStream<TYield, TReturn>` as today; `TypedStream` gains an optional `.headers` field surfaced by the adapter when `res.headers` is declared on the route:
291
+
292
+ ```ts
293
+ interface TypedStream<TYield, TReturn> {
294
+ [Symbol.asyncIterator](): AsyncIterator<TYield>
295
+ result: Promise<TReturn>
296
+ headers?: Headers // populated at stream-open time
297
+ }
298
+ ```
299
+
300
+ At runtime `.headers` is always populated (the adapter has the response Headers object). The TypeScript surface marks it optional and emits it on the route's `TypedStream` type only when `res.headers` is declared, so callers without declared response headers don't see it in their type — no behavior difference, just type-level discipline. `AdapterStreamResponse` extends with a `headers: Headers` field; `executeStream` wires it onto the constructed `TypedStream`.
301
+
302
+ ### Kotlin / Swift targets
303
+
304
+ Mobile devs own the HTTP layer entirely (existing posture). Emit a `Response.Headers` data class / struct only when `res.headers` is declared. Consumer's HTTP wrapper maps response headers into it. No runtime adapter changes for these targets.
305
+
306
+ ### Self-contained codegen
307
+
308
+ `_client.ts` extends to read response headers from the unary response and surface initial headers on the stream response. Everything else (error registry, runtime classes, dispatch, `_errors.ts`, `_types.ts`) is unchanged. Source-hash invalidation forces regeneration on upgrade — no migration tooling needed.
309
+
310
+ ## Error handling
311
+
312
+ The existing taxonomy system (`defineErrorTaxonomy`, `resolveErrorResponse`, `defaultErrorTaxonomy`) carries forward unchanged. Per-route `errors` keys, dispatch order (`onRequestError` observer → taxonomy → `onError` → hard default), and the client error registry / dispatch all keep their shape.
313
+
314
+ ### `CreateHttpStream` error lifecycle
315
+
316
+ - **Pre-stream** (validation, async preamble): unary error dispatch — taxonomy / `onError` / hard default. SSE response never opened. Identical to today's HonoStreamAppBuilder pre-stream behavior, extended to the async preamble step.
317
+ - **Mid-stream** (errors thrown after first yield): `onMidStreamError`, unchanged. Taxonomy doesn't apply — response already committed.
318
+
319
+ ### `isPrevalidated` and `noRuntimeValidation`
320
+
321
+ Both unchanged. `isPrevalidated` flag pattern extends to the new `'http-stream'` builder branch. `noRuntimeValidation` opts the entire factory out of per-call AJV for all four creators (JSON Schema still computed at registration time).
322
+
323
+ ### New registration-time errors (all `ProcedureRegistrationError`)
324
+
325
+ | Trigger | Migration message |
326
+ |---|---|
327
+ | `schema.input` on `Create` / `CreateStream` | "`schema.input` was removed in v8. Use `CreateHttp` / `CreateHttpStream` for per-channel HTTP validation." |
328
+ | `path` / `method` / `req` / `res` on `Create` / `CreateStream` | "HTTP fields require `CreateHttp` / `CreateHttpStream`." |
329
+ | `schema.params` on `CreateHttp` / `CreateHttpStream` | "Use `schema.req.body` (or `query`) instead of `schema.params`." |
330
+ | Path template params don't match `req.pathParams` schema keys | (existing message, moved into core) |
331
+
332
+ Phrased as "X was removed in v8, use Y" so anyone running v7 code against the v8 core gets pointed straight at the fix.
333
+
334
+ ## Source organization
335
+
336
+ `src/index.ts` is 537 lines today. Adding two more creators inline doubles the surface. Split:
337
+
338
+ ```
339
+ src/
340
+ index.ts # Procedures factory, glue (~80 lines)
341
+ create.ts # Create
342
+ create-stream.ts # CreateStream
343
+ create-http.ts # CreateHttp + path-param consistency check
344
+ create-http-stream.ts # CreateHttpStream
345
+ types.ts # TLocalContext, TStreamContext, registration types, ProcedureKind
346
+ schema/ # unchanged
347
+ implementations/ # builders updated per "Builder integration" section
348
+ codegen/ # updated per "Doc envelope & codegen impact" section
349
+ client/ # _client.ts response.headers + TypedStream.headers
350
+ ```
351
+
352
+ Each creator is independent and self-contained — passes the "what does it do, how do you use it, what does it depend on" test.
353
+
354
+ ## Migration
355
+
356
+ Major version (v8). No deprecation period. Registration errors are the migration safety net.
357
+
358
+ | v7 | v8 |
359
+ |---|---|
360
+ | `Procedures<Ctx, APIConfig>()` | `Procedures<Ctx>()` |
361
+ | `.Create('GetUser', { path, method, schema: { input: {...} } }, h)` | `.CreateHttp('GetUser', { path, method, schema: { req: {...}, res: { body: ... } } }, h)` |
362
+ | `.CreateStream('Tail', { path, method, schema: { input: {...} } }, g)` | `.CreateHttpStream('Tail', { path, method, schema: { req: {...}, yield: ... } }, g)` |
363
+ | `schema.input.pathParams` | `schema.req.pathParams` |
364
+ | `schema.params` on an HTTP route | `schema.req.body` or `schema.req.query` (explicit channel) |
365
+ | `APIInput<{...}>` satisfies type | removed — channels typed by `req` directly |
366
+ | `Procedures<Ctx, RPCConfig>().Create(...)` | unchanged — RPC factories keep `TExtendedConfig` |
367
+ | Handler `(ctx, { pathParams, query, body }) => result` | unchanged — request side identical |
368
+ | Handler `return result` | unchanged unless `res.headers` declared → `return { body, headers }` |
369
+
370
+ ### What's NOT changing
371
+
372
+ - `HonoRPCAppBuilder`, `HonoStreamAppBuilder` external APIs.
373
+ - `DocRegistry`, error taxonomy public API.
374
+ - Client error dispatch, generated error registry, per-route `Errors` union.
375
+ - Per-call `ProcedureCallOptions`, hooks pipeline, `RequestMeta` augmentation.
376
+ - `TypedStream` external API (only addition: optional `.headers`).
377
+ - AJV config (`allErrors`, `coerceTypes`, `removeAdditional`).
378
+ - Codegen flag set, CLI surface, `--target ts/kotlin/swift`.
379
+
380
+ ### Codegen consumer migration
381
+
382
+ 1. `npm install` v8 server packages.
383
+ 2. Restart the dev server / rebuild.
384
+ 3. Re-run `npx ts-procedures-codegen` (or `--watch`). Source hash invalidates; fresh files written.
385
+ 4. TS callers update flat-mode aliases (`GetUserResponse` → `GetUserResponseBody`); namespace-mode users get `Users.GetUser.Response.Body` automatically.
386
+ 5. Routes adopting `res.headers` update await sites: `const { body, headers } = await api.users.getUser(req)`.
387
+
388
+ ## Testing
389
+
390
+ | Test file | Coverage |
391
+ |---|---|
392
+ | `src/create.test.ts` | Extracted from `index.test.ts`. Create-only path. Schema-input rejection. |
393
+ | `src/create-stream.test.ts` | CreateStream-only. Schema-input rejection. Yield validation, abort, generator return value. |
394
+ | `src/create-http.test.ts` | All four req-channel combos. Response shape: body-only, body+headers, headers-only, void. Registration errors (HTTP fields rejected on Create, path-param mismatch, `schema.params` rejected). `TErrorKey` compile-time narrowing via `expectTypeOf`. |
395
+ | `src/create-http-stream.test.ts` | Both handler shapes (async generator vs. async-returning-`{headers, stream}`). Pre-stream errors as HTTP errors. Mid-stream errors → `onMidStreamError`. Initial headers applied before first yield. |
396
+ | `src/implementations/http/hono-api/index.test.ts` | Both `'http'` and `'http-stream'` kinds. Response headers application. `skippedProcedures` for non-http kinds. |
397
+ | `src/implementations/http/{hono-rpc,hono-stream}/index.test.ts` | Filter by `kind`. `skippedProcedures` populated when CreateHttp procedures are registered to RPC factories. |
398
+ | `src/codegen/__fixtures__/users-envelope.json` | Regenerated to v8 envelope (`req`/`res` grouping, new `'http-stream'` kind). |
399
+ | `src/codegen/targets/{ts,kotlin,swift}/run.test.ts` | Snapshot updates. New tests for `Response.Headers` emission. |
400
+ | `src/client/call.test.ts`, `stream.test.ts` | Response-headers parsing on unary; `TypedStream.headers` populated for streams declaring `res.headers`. |
401
+
402
+ ## Out-of-scope follow-ups
403
+
404
+ These are flagged for the implementation phase but not part of this design:
405
+
406
+ - **`agent_config/` updates** — `claude-code/skills/ts-procedures-scaffold/templates/`, `claude-code/skills/ts-procedures/patterns.md`, `anti-patterns.md`, `cursor/cursorrules`, `copilot/copilot-instructions.md` updated to use `CreateHttp` for HTTP examples.
407
+ - **`CHANGELOG.md` and `README.md`** — major-version entry with migration table and v7→v8 expectations.
408
+ - **`validateResponse: true` opt-in** — runtime validation of `res.body` / `res.headers`. Clean follow-up; non-breaking.
409
+ - **Astro adapter detail design** — mirrors hono-api; called out as "same kind-aware updates" but not specced separately.