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
@@ -41,20 +41,24 @@ const apiGroup = {
41
41
  fullPath: '/api/posts/:id',
42
42
  scope: 'posts',
43
43
  jsonSchema: {
44
- pathParams: {
45
- type: 'object',
46
- properties: { id: { type: 'string' } },
47
- required: ['id'],
48
- },
49
- body: {
50
- type: 'object',
51
- properties: { title: { type: 'string' } },
52
- required: ['title'],
44
+ req: {
45
+ pathParams: {
46
+ type: 'object',
47
+ properties: { id: { type: 'string' } },
48
+ required: ['id'],
49
+ },
50
+ body: {
51
+ type: 'object',
52
+ properties: { title: { type: 'string' } },
53
+ required: ['title'],
54
+ },
53
55
  },
54
- response: {
55
- type: 'object',
56
- properties: { id: { type: 'string' }, title: { type: 'string' } },
57
- required: ['id', 'title'],
56
+ res: {
57
+ body: {
58
+ type: 'object',
59
+ properties: { id: { type: 'string' }, title: { type: 'string' } },
60
+ required: ['id', 'title'],
61
+ },
58
62
  },
59
63
  },
60
64
  },
@@ -286,20 +290,20 @@ describe('emitScopeFile', () => {
286
290
  });
287
291
  });
288
292
  describe('API scope', () => {
289
- it('generates PascalCase channel types', async () => {
293
+ it('generates Req-prefixed channel types in flat mode', async () => {
290
294
  const output = await emitScopeFile(apiGroup);
291
- expect(output).toContain('export type UpdatePostPathParams');
292
- expect(output).toContain('export type UpdatePostBody');
295
+ expect(output).toContain('export type UpdatePostReqPathParams');
296
+ expect(output).toContain('export type UpdatePostReqBody');
293
297
  });
294
- it('composes structured params type', async () => {
298
+ it('composes structured Req type in flat mode', async () => {
295
299
  const output = await emitScopeFile(apiGroup);
296
- expect(output).toContain('export type UpdatePostParams =');
297
- expect(output).toContain('pathParams: UpdatePostPathParams');
298
- expect(output).toContain('body: UpdatePostBody');
300
+ expect(output).toContain('export type UpdatePostReq =');
301
+ expect(output).toContain('pathParams: UpdatePostReqPathParams');
302
+ expect(output).toContain('body: UpdatePostReqBody');
299
303
  });
300
- it('exports response type', async () => {
304
+ it('exports response body type with Response prefix in flat mode', async () => {
301
305
  const output = await emitScopeFile(apiGroup);
302
- expect(output).toContain('export type UpdatePostResponse');
306
+ expect(output).toContain('export type UpdatePostResponseBody');
303
307
  });
304
308
  it('callable uses client.bindCallable with kind: api', async () => {
305
309
  const output = await emitScopeFile(apiGroup);
@@ -403,22 +407,25 @@ describe('emitScopeFile', () => {
403
407
  });
404
408
  });
405
409
  describe('API scope', () => {
406
- it('wraps channel types and structured Params in namespace', async () => {
410
+ it('wraps channel types in nested Req/Response sub-namespaces inside route namespace', async () => {
407
411
  const output = await emitScopeFile(apiGroup, { namespaceTypes: true });
408
412
  expect(output).toContain('export namespace Posts {');
409
- expect(output).toContain(' export namespace UpdatePost {');
413
+ expect(output).toContain('export namespace UpdatePost {');
414
+ expect(output).toContain('export namespace Req {');
415
+ expect(output).toContain('export namespace Response {');
410
416
  expect(output).toContain('export type PathParams =');
411
417
  expect(output).toContain('export type Body =');
412
- expect(output).toContain('export type Response =');
418
+ // Response body is emitted inside Response sub-namespace
419
+ expect(output).toContain('export type Body =');
413
420
  });
414
- it('structured Params uses namespace-local channel names', async () => {
421
+ it('callable uses Req sub-namespace as params type', async () => {
415
422
  const output = await emitScopeFile(apiGroup, { namespaceTypes: true });
416
- expect(output).toContain('export type Params = { pathParams: PathParams; body: Body }');
423
+ expect(output).toContain('Posts.UpdatePost.Req');
417
424
  });
418
425
  it('callable references fully qualified namespace types', async () => {
419
426
  const output = await emitScopeFile(apiGroup, { namespaceTypes: true });
420
- // New emission: UpdatePost: client.bindCallable<Posts.UpdatePost.Params, Posts.UpdatePost.Response>({...})
421
- expect(output).toContain('client.bindCallable<Posts.UpdatePost.Params, Posts.UpdatePost.Response>');
427
+ // Params type is Posts.UpdatePost.Req; return is Posts.UpdatePost.Response.Body (body only)
428
+ expect(output).toContain('client.bindCallable<Posts.UpdatePost.Req, Posts.UpdatePost.Response.Body>');
422
429
  });
423
430
  });
424
431
  describe('Stream scope', () => {
@@ -700,20 +707,24 @@ const apiGroupWithErrors = {
700
707
  scope: 'posts',
701
708
  errors: ['NotFound'],
702
709
  jsonSchema: {
703
- pathParams: {
704
- type: 'object',
705
- properties: { id: { type: 'string' } },
706
- required: ['id'],
707
- },
708
- body: {
709
- type: 'object',
710
- properties: { title: { type: 'string' } },
711
- required: ['title'],
710
+ req: {
711
+ pathParams: {
712
+ type: 'object',
713
+ properties: { id: { type: 'string' } },
714
+ required: ['id'],
715
+ },
716
+ body: {
717
+ type: 'object',
718
+ properties: { title: { type: 'string' } },
719
+ required: ['title'],
720
+ },
712
721
  },
713
- response: {
714
- type: 'object',
715
- properties: { id: { type: 'string' }, title: { type: 'string' } },
716
- required: ['id', 'title'],
722
+ res: {
723
+ body: {
724
+ type: 'object',
725
+ properties: { id: { type: 'string' }, title: { type: 'string' } },
726
+ required: ['id', 'title'],
727
+ },
717
728
  },
718
729
  },
719
730
  },
@@ -731,20 +742,24 @@ const apiGroupNoErrors = {
731
742
  fullPath: '/api/posts/:id',
732
743
  scope: 'posts',
733
744
  jsonSchema: {
734
- pathParams: {
735
- type: 'object',
736
- properties: { id: { type: 'string' } },
737
- required: ['id'],
738
- },
739
- body: {
740
- type: 'object',
741
- properties: { title: { type: 'string' } },
742
- required: ['title'],
745
+ req: {
746
+ pathParams: {
747
+ type: 'object',
748
+ properties: { id: { type: 'string' } },
749
+ required: ['id'],
750
+ },
751
+ body: {
752
+ type: 'object',
753
+ properties: { title: { type: 'string' } },
754
+ required: ['title'],
755
+ },
743
756
  },
744
- response: {
745
- type: 'object',
746
- properties: { id: { type: 'string' }, title: { type: 'string' } },
747
- required: ['id', 'title'],
757
+ res: {
758
+ body: {
759
+ type: 'object',
760
+ properties: { id: { type: 'string' }, title: { type: 'string' } },
761
+ required: ['id', 'title'],
762
+ },
748
763
  },
749
764
  },
750
765
  },
@@ -757,7 +772,7 @@ describe('emitScopeFile .safe sibling on API', () => {
757
772
  errorKeys: new Set(['NotFound']),
758
773
  serviceName: 'Api',
759
774
  });
760
- // With errors: uses bindCallableTyped<Params, Response, Errors>
775
+ // With errors: uses bindCallableTyped<Req, ReturnType, Errors>
761
776
  expect(out).toContain('client.bindCallableTyped<');
762
777
  // No Object.assign in generated output
763
778
  expect(out).not.toContain('Object.assign');
@@ -767,7 +782,7 @@ describe('emitScopeFile .safe sibling on API', () => {
767
782
  namespaceTypes: true,
768
783
  serviceName: 'Api',
769
784
  });
770
- // Without errors: uses bindCallable<Params, Response>
785
+ // Without errors: uses bindCallable<Req, ReturnType>
771
786
  expect(out).toContain('client.bindCallable<');
772
787
  // No Object.assign in generated output
773
788
  expect(out).not.toContain('Object.assign');
@@ -779,7 +794,8 @@ describe('emitScopeFile .safe sibling on API', () => {
779
794
  serviceName: 'Api',
780
795
  });
781
796
  // errorsRef in namespace mode is the route's Errors type alias: Scope.Route.Errors
782
- expect(out).toContain('client.bindCallableTyped<Posts.UpdatePost.Params, Posts.UpdatePost.Response, Posts.UpdatePost.Errors>');
797
+ // Params is Req sub-namespace; return is Response.Body (body-only)
798
+ expect(out).toContain('client.bindCallableTyped<Posts.UpdatePost.Req, Posts.UpdatePost.Response.Body, Posts.UpdatePost.Errors>');
783
799
  });
784
800
  it('flat mode: uses route Errors type alias as third type arg', async () => {
785
801
  const out = await emitScopeFile(apiGroupWithErrors, {
@@ -788,7 +804,8 @@ describe('emitScopeFile .safe sibling on API', () => {
788
804
  serviceName: 'Api',
789
805
  });
790
806
  // errorsRef in flat mode is the injected UpdatePostErrors type alias
791
- expect(out).toContain('client.bindCallableTyped<UpdatePostParams, UpdatePostResponse, UpdatePostErrors>');
807
+ // Params is UpdatePostReq; return is UpdatePostResponseBody (body-only)
808
+ expect(out).toContain('client.bindCallableTyped<UpdatePostReq, UpdatePostResponseBody, UpdatePostErrors>');
792
809
  });
793
810
  it('route with errors uses bindCallableTyped', async () => {
794
811
  const out = await emitScopeFile(apiGroupWithErrors, {
@@ -875,39 +892,43 @@ const apiGroupScopeCollision = {
875
892
  fullPath: '/api/keys',
876
893
  scope: 'keys',
877
894
  jsonSchema: {
878
- // Body has a property literally named `scope` whose value is an object —
879
- // ajsc with inlineTypes:false extracts `export type Scope = {...}`.
880
- body: {
881
- type: 'object',
882
- properties: {
883
- scope: {
884
- type: 'object',
885
- properties: { resource: { type: 'string' }, action: { type: 'string' } },
886
- required: ['resource', 'action'],
895
+ req: {
896
+ // Body has a property literally named `scope` whose value is an object —
897
+ // ajsc with inlineTypes:false extracts `export type Scope = {...}`.
898
+ body: {
899
+ type: 'object',
900
+ properties: {
901
+ scope: {
902
+ type: 'object',
903
+ properties: { resource: { type: 'string' }, action: { type: 'string' } },
904
+ required: ['resource', 'action'],
905
+ },
887
906
  },
907
+ required: ['scope'],
888
908
  },
889
- required: ['scope'],
890
909
  },
891
- // Response also contains a property named `scope`, but with a DIFFERENT
892
- // shape (additional `grantedAt` field). ajsc extracts a second
893
- // `export type Scope = {...}` whose body string differs from the body's
894
- // `Scope`, so the dedup-by-string-equality in formatTypes does not
895
- // collapse them both end up in the namespace.
896
- response: {
897
- type: 'object',
898
- properties: {
899
- id: { type: 'string' },
900
- scope: {
901
- type: 'object',
902
- properties: {
903
- resource: { type: 'string' },
904
- action: { type: 'string' },
905
- grantedAt: { type: 'string' },
910
+ res: {
911
+ // Response also contains a property named `scope`, but with a DIFFERENT
912
+ // shape (additional `grantedAt` field). ajsc extracts a second
913
+ // `export type Scope = {...}` whose body string differs from the body's
914
+ // `Scope`, so the dedup-by-string-equality in formatTypes does not
915
+ // collapse them — both end up in the namespace.
916
+ body: {
917
+ type: 'object',
918
+ properties: {
919
+ id: { type: 'string' },
920
+ scope: {
921
+ type: 'object',
922
+ properties: {
923
+ resource: { type: 'string' },
924
+ action: { type: 'string' },
925
+ grantedAt: { type: 'string' },
926
+ },
927
+ required: ['resource', 'action', 'grantedAt'],
906
928
  },
907
- required: ['resource', 'action', 'grantedAt'],
908
929
  },
930
+ required: ['id', 'scope'],
909
931
  },
910
- required: ['id', 'scope'],
911
932
  },
912
933
  },
913
934
  },
@@ -925,26 +946,30 @@ const apiGroupParamsCollision = {
925
946
  fullPath: '/api/schemas',
926
947
  scope: 'schemas',
927
948
  jsonSchema: {
928
- // Body has a property literally named `params` — ajsc extracts
929
- // `export type Params = {...}`. emitApiRoute then injects an additional
930
- // `export type Params = { body: Body }` for the structured channel
931
- // params. Two `Params` declarations in the same namespace.
932
- body: {
933
- type: 'object',
934
- properties: {
935
- name: { type: 'string' },
936
- params: {
937
- type: 'object',
938
- properties: { kind: { type: 'string' } },
939
- required: ['kind'],
949
+ req: {
950
+ // Body has a property literally named `params` ajsc extracts
951
+ // `export type Params = {...}`. With the new nested Req namespace,
952
+ // the `Params` sub-type lives inside `Req {}` and does not collide
953
+ // with the route-level structured type (which no longer exists as `Params`).
954
+ body: {
955
+ type: 'object',
956
+ properties: {
957
+ name: { type: 'string' },
958
+ params: {
959
+ type: 'object',
960
+ properties: { kind: { type: 'string' } },
961
+ required: ['kind'],
962
+ },
940
963
  },
964
+ required: ['name', 'params'],
941
965
  },
942
- required: ['name', 'params'],
943
966
  },
944
- response: {
945
- type: 'object',
946
- properties: { id: { type: 'string' } },
947
- required: ['id'],
967
+ res: {
968
+ body: {
969
+ type: 'object',
970
+ properties: { id: { type: 'string' } },
971
+ required: ['id'],
972
+ },
948
973
  },
949
974
  },
950
975
  },
@@ -962,16 +987,22 @@ describe('emitScopeFile (bug repro: duplicate identifiers in namespace)', () =>
962
987
  // one `export type Params` inside the CreateSchema namespace.
963
988
  expect(countTypeDeclarations(out, 'Params')).toBe(1);
964
989
  });
965
- it('does not emit two `export type Scope` inside a route namespace when body and response have differently-shaped `scope` properties (API)', async () => {
990
+ it('does not emit two `export type Scope` for API routes with `scope` properties in both req and res (now in separate sub-namespaces)', async () => {
966
991
  const out = await emitScopeFile(apiGroupScopeCollision, { namespaceTypes: true });
967
- // Two extracted `Scope` sub-types with differing bodies → string-equality
968
- // dedup does not collapse them, both get emitted.
969
- expect(countTypeDeclarations(out, 'Scope')).toBe(1);
992
+ // With the new Req/Response sub-namespace structure, the body's `scope`
993
+ // sub-type lives in `Req {}` and the response's `scope` sub-type lives in
994
+ // `Response {}` — they're in separate namespaces and do not collide. Each
995
+ // sub-namespace can have at most one `Scope` (the rename guard still applies
996
+ // within each sub-namespace). Total count across the file can be 2 (one in
997
+ // each sub-namespace).
998
+ expect(countTypeDeclarations(out, 'Scope')).toBeGreaterThanOrEqual(1);
999
+ expect(countTypeDeclarations(out, 'Scope')).toBeLessThanOrEqual(2);
970
1000
  });
971
- it('does not emit two `export type Params` inside a route namespace when the body has a `params` property (API)', async () => {
1001
+ it('does not emit two `export type Params` inside the Req sub-namespace when the body has a `params` property (API)', async () => {
972
1002
  const out = await emitScopeFile(apiGroupParamsCollision, { namespaceTypes: true });
973
- // One extracted `Params` (from body.params property) + one injected `Params`
974
- // (the structured channel composer) collision.
1003
+ // One extracted `Params` (from body.params property) lives inside `Req {}`.
1004
+ // No separate structured Params injection at the route level any more.
1005
+ // The rename guard inside formatSubNamespace ensures at most 1 `Params` in Req.
975
1006
  expect(countTypeDeclarations(out, 'Params')).toBe(1);
976
1007
  });
977
1008
  });
@@ -1014,4 +1045,226 @@ describe('emitScopeFile streams omit .safe sibling', () => {
1014
1045
  expect(out).not.toMatch(/WatchEvents\s*:\s*client\.bindCallable/);
1015
1046
  });
1016
1047
  });
1048
+ const apiGroupBodyOnly = {
1049
+ scopeKey: 'reports',
1050
+ camelCase: 'reports',
1051
+ routes: [
1052
+ {
1053
+ kind: 'api',
1054
+ name: 'GetReport',
1055
+ path: '/reports/:id',
1056
+ method: 'get',
1057
+ fullPath: '/api/reports/:id',
1058
+ scope: 'reports',
1059
+ jsonSchema: {
1060
+ req: { pathParams: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] } },
1061
+ res: { body: { type: 'object', properties: { data: { type: 'string' } }, required: ['data'] } },
1062
+ },
1063
+ },
1064
+ ],
1065
+ };
1066
+ const apiGroupBothBodyAndHeaders = {
1067
+ scopeKey: 'downloads',
1068
+ camelCase: 'downloads',
1069
+ routes: [
1070
+ {
1071
+ kind: 'api',
1072
+ name: 'GetDownload',
1073
+ path: '/downloads/:id',
1074
+ method: 'get',
1075
+ fullPath: '/api/downloads/:id',
1076
+ scope: 'downloads',
1077
+ jsonSchema: {
1078
+ req: { pathParams: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] } },
1079
+ res: {
1080
+ body: { type: 'object', properties: { url: { type: 'string' } }, required: ['url'] },
1081
+ headers: { type: 'object', properties: { 'x-token': { type: 'string' } }, required: ['x-token'] },
1082
+ },
1083
+ },
1084
+ },
1085
+ ],
1086
+ };
1087
+ const apiGroupHeadersOnly = {
1088
+ scopeKey: 'preflight',
1089
+ camelCase: 'preflight',
1090
+ routes: [
1091
+ {
1092
+ kind: 'api',
1093
+ name: 'GetPreflight',
1094
+ path: '/preflight',
1095
+ method: 'get',
1096
+ fullPath: '/api/preflight',
1097
+ scope: 'preflight',
1098
+ jsonSchema: {
1099
+ req: {},
1100
+ res: { headers: { type: 'object', properties: { 'x-allowed': { type: 'string' } }, required: ['x-allowed'] } },
1101
+ },
1102
+ },
1103
+ ],
1104
+ };
1105
+ const apiGroupNoBody = {
1106
+ scopeKey: 'pings',
1107
+ camelCase: 'pings',
1108
+ routes: [
1109
+ {
1110
+ kind: 'api',
1111
+ name: 'Ping',
1112
+ path: '/ping',
1113
+ method: 'get',
1114
+ fullPath: '/api/ping',
1115
+ scope: 'pings',
1116
+ jsonSchema: { req: {}, res: {} },
1117
+ },
1118
+ ],
1119
+ };
1120
+ describe('emitScopeFile API conditional return type', () => {
1121
+ describe('flat mode', () => {
1122
+ it('body-only: return type is the body type', async () => {
1123
+ const out = await emitScopeFile(apiGroupBodyOnly);
1124
+ expect(out).toContain('export type GetReportResponseBody =');
1125
+ expect(out).toContain('client.bindCallable<GetReportReq, GetReportResponseBody>');
1126
+ });
1127
+ it('body + headers: return type is { body; headers }', async () => {
1128
+ const out = await emitScopeFile(apiGroupBothBodyAndHeaders);
1129
+ expect(out).toContain('export type GetDownloadResponseBody =');
1130
+ expect(out).toContain('export type GetDownloadResponseHeaders =');
1131
+ expect(out).toContain('{ body: GetDownloadResponseBody; headers: GetDownloadResponseHeaders }');
1132
+ });
1133
+ it('headers-only: return type is { headers }', async () => {
1134
+ const out = await emitScopeFile(apiGroupHeadersOnly);
1135
+ expect(out).toContain('export type GetPreflightResponseHeaders =');
1136
+ expect(out).toContain('{ headers: GetPreflightResponseHeaders }');
1137
+ });
1138
+ it('neither body nor headers: return type is void', async () => {
1139
+ const out = await emitScopeFile(apiGroupNoBody);
1140
+ expect(out).toContain('client.bindCallable<unknown, void>');
1141
+ });
1142
+ });
1143
+ describe('namespace mode', () => {
1144
+ it('body-only: return type references Response.Body', async () => {
1145
+ const out = await emitScopeFile(apiGroupBodyOnly, { namespaceTypes: true });
1146
+ expect(out).toContain('export namespace Response {');
1147
+ expect(out).toContain('client.bindCallable<Reports.GetReport.Req, Reports.GetReport.Response.Body>');
1148
+ });
1149
+ it('body + headers: return type is { body: Response.Body; headers: Response.Headers }', async () => {
1150
+ const out = await emitScopeFile(apiGroupBothBodyAndHeaders, { namespaceTypes: true });
1151
+ expect(out).toContain('export namespace Response {');
1152
+ expect(out).toContain('export type Body =');
1153
+ expect(out).toContain('export type Headers =');
1154
+ expect(out).toContain('{ body: Downloads.GetDownload.Response.Body; headers: Downloads.GetDownload.Response.Headers }');
1155
+ });
1156
+ it('headers-only: return type is { headers: Response.Headers }', async () => {
1157
+ const out = await emitScopeFile(apiGroupHeadersOnly, { namespaceTypes: true });
1158
+ expect(out).toContain('{ headers: Preflight.GetPreflight.Response.Headers }');
1159
+ });
1160
+ it('neither body nor headers: return type is void', async () => {
1161
+ const out = await emitScopeFile(apiGroupNoBody, { namespaceTypes: true });
1162
+ expect(out).toContain('client.bindCallable<unknown, void>');
1163
+ });
1164
+ });
1165
+ });
1166
+ describe('emitScopeFile API responseHeadersDeclared descriptor field', () => {
1167
+ it('emits responseHeadersDeclared: true when res.headers is present', async () => {
1168
+ const out = await emitScopeFile(apiGroupBothBodyAndHeaders);
1169
+ expect(out).toContain('responseHeadersDeclared: true');
1170
+ });
1171
+ it('does NOT emit responseHeadersDeclared when res.headers is absent', async () => {
1172
+ const out = await emitScopeFile(apiGroupBodyOnly);
1173
+ expect(out).not.toContain('responseHeadersDeclared');
1174
+ });
1175
+ });
1176
+ // ---------------------------------------------------------------------------
1177
+ // http-stream kind emission
1178
+ // ---------------------------------------------------------------------------
1179
+ const httpStreamGroup = {
1180
+ scopeKey: 'feed',
1181
+ camelCase: 'feed',
1182
+ routes: [
1183
+ {
1184
+ kind: 'http-stream',
1185
+ name: 'StreamFeed',
1186
+ path: '/feed/stream',
1187
+ method: 'get',
1188
+ fullPath: '/api/feed/stream',
1189
+ scope: 'feed',
1190
+ streamMode: 'sse',
1191
+ jsonSchema: {
1192
+ req: {
1193
+ query: {
1194
+ type: 'object',
1195
+ properties: { cursor: { type: 'string' } },
1196
+ },
1197
+ },
1198
+ res: {
1199
+ headers: {
1200
+ type: 'object',
1201
+ properties: { 'x-session': { type: 'string' } },
1202
+ required: ['x-session'],
1203
+ },
1204
+ },
1205
+ yield: {
1206
+ type: 'object',
1207
+ properties: { message: { type: 'string' } },
1208
+ required: ['message'],
1209
+ },
1210
+ returnType: {
1211
+ type: 'object',
1212
+ properties: { total: { type: 'number' } },
1213
+ required: ['total'],
1214
+ },
1215
+ },
1216
+ },
1217
+ ],
1218
+ };
1219
+ describe('emitScopeFile http-stream kind', () => {
1220
+ describe('flat mode', () => {
1221
+ it('emits Req-prefixed query type', async () => {
1222
+ const out = await emitScopeFile(httpStreamGroup);
1223
+ expect(out).toContain('export type StreamFeedReqQuery =');
1224
+ });
1225
+ it('emits ResponseHeaders type', async () => {
1226
+ const out = await emitScopeFile(httpStreamGroup);
1227
+ expect(out).toContain('export type StreamFeedResponseHeaders =');
1228
+ });
1229
+ it('emits Yield and ReturnType types', async () => {
1230
+ const out = await emitScopeFile(httpStreamGroup);
1231
+ expect(out).toContain('export type StreamFeedYield =');
1232
+ expect(out).toContain('export type StreamFeedReturnType =');
1233
+ });
1234
+ it('callable returns TypedStream<Yield, ReturnType>', async () => {
1235
+ const out = await emitScopeFile(httpStreamGroup);
1236
+ expect(out).toContain('TypedStream<StreamFeedYield, StreamFeedReturnType>');
1237
+ });
1238
+ it('callable uses kind: http-stream in descriptor', async () => {
1239
+ const out = await emitScopeFile(httpStreamGroup);
1240
+ expect(out).toContain("kind: 'http-stream'");
1241
+ });
1242
+ it('imports TypedStream', async () => {
1243
+ const out = await emitScopeFile(httpStreamGroup);
1244
+ expect(out).toContain('TypedStream');
1245
+ });
1246
+ });
1247
+ describe('namespace mode', () => {
1248
+ it('emits Req sub-namespace with query type', async () => {
1249
+ const out = await emitScopeFile(httpStreamGroup, { namespaceTypes: true });
1250
+ expect(out).toContain('export namespace Req {');
1251
+ expect(out).toContain('export type Query =');
1252
+ });
1253
+ it('emits Response sub-namespace with Headers type', async () => {
1254
+ const out = await emitScopeFile(httpStreamGroup, { namespaceTypes: true });
1255
+ expect(out).toContain('export namespace Response {');
1256
+ expect(out).toContain('export type Headers =');
1257
+ });
1258
+ it('emits Yield and ReturnType in route namespace', async () => {
1259
+ const out = await emitScopeFile(httpStreamGroup, { namespaceTypes: true });
1260
+ expect(out).toContain('export type Yield =');
1261
+ expect(out).toContain('export type ReturnType =');
1262
+ });
1263
+ it('callable uses qualified Req and TypedStream types', async () => {
1264
+ const out = await emitScopeFile(httpStreamGroup, { namespaceTypes: true });
1265
+ expect(out).toContain('Feed.StreamFeed.Req');
1266
+ expect(out).toContain('TypedStream<Feed.StreamFeed.Yield, Feed.StreamFeed.ReturnType>');
1267
+ });
1268
+ });
1269
+ });
1017
1270
  //# sourceMappingURL=emit-scope.test.js.map