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
@@ -1,142 +0,0 @@
1
- # Hono RPC Template: {{Name}}
2
-
3
- ## Implementation — `{{Name}}.rpc.ts`
4
-
5
- ```typescript
6
- import { Procedures } from 'ts-procedures'
7
- import { HonoRPCAppBuilder, defineErrorTaxonomy } from 'ts-procedures/hono-rpc'
8
- import type { RPCConfig } from 'ts-procedures/http'
9
- import { Type } from 'typebox'
10
-
11
- // ─── Context ──────────────────────────────────────────────
12
-
13
- type {{Name}}Context = {
14
- userId: string
15
- requestId: string
16
- }
17
-
18
- // ─── Procedures ───────────────────────────────────────────
19
-
20
- const RPC = Procedures<{{Name}}Context, RPCConfig>()
21
-
22
- export const { GetItem } = RPC.Create(
23
- 'GetItem',
24
- {
25
- scope: '{{name}}', // TODO: set URL scope
26
- version: 1,
27
- description: 'Fetch item by ID',
28
- schema: {
29
- params: Type.Object({
30
- id: Type.String(),
31
- }),
32
- returnType: Type.Object({
33
- id: Type.String(),
34
- name: Type.String(),
35
- }),
36
- },
37
- },
38
- async (ctx, params) => {
39
- // TODO: implement
40
- return { id: params.id, name: 'Example' }
41
- }
42
- )
43
-
44
- export const { ListItems } = RPC.Create(
45
- 'ListItems',
46
- {
47
- scope: '{{name}}',
48
- version: 1,
49
- description: 'List all items',
50
- schema: {
51
- params: Type.Object({
52
- page: Type.Optional(Type.Number()),
53
- limit: Type.Optional(Type.Number()),
54
- }),
55
- },
56
- },
57
- async (ctx, params) => {
58
- // TODO: implement
59
- return { items: [], total: 0 }
60
- }
61
- )
62
-
63
- // ─── Error Taxonomy ───────────────────────────────────────
64
- // Declare the error classes this service throws. Framework errors
65
- // (ProcedureValidationError → 400, ctx.error() → 500) are caught by the
66
- // default taxonomy automatically. Add your own classes here — handlers just
67
- // `throw` them and the builder serializes via this map. See
68
- // docs/http-integrations.md#error-handling for the full contract.
69
-
70
- const {{name}}Errors = defineErrorTaxonomy({
71
- // Example — replace with your app's error classes:
72
- // NotFoundError: { class: NotFoundError, statusCode: 404 },
73
- // AuthError: { class: AuthError, statusCode: 401 },
74
- })
75
-
76
- // ─── Hono App Builder ─────────────────────────────────────
77
-
78
- export const {{name}}App = new HonoRPCAppBuilder({
79
- pathPrefix: '/api',
80
- errors: {{name}}Errors,
81
- unknownError: {
82
- statusCode: 500,
83
- toResponse: () => ({ name: 'InternalServerError', message: 'Unexpected error' }),
84
- onCatch: (err, { procedure }) => console.error(`[${procedure.name}]`, err),
85
- },
86
- })
87
- .register(RPC, (c) => ({
88
- userId: c.req.header('x-user-id') || 'anonymous',
89
- requestId: c.req.header('x-request-id') || crypto.randomUUID(),
90
- }))
91
- .build()
92
-
93
- // Route map:
94
- // POST /api/{{name}}/get-item/1
95
- // POST /api/{{name}}/list-items/1
96
-
97
- // Documentation: {{name}}App.docs
98
- ```
99
-
100
- ## Test — `{{Name}}.rpc.test.ts`
101
-
102
- ```typescript
103
- import { describe, test, expect } from 'vitest'
104
- import { {{name}}App } from './{{Name}}.rpc'
105
-
106
- describe('{{Name}} RPC', () => {
107
- test('GET item returns expected result', async () => {
108
- const res = await {{name}}App.request('/api/{{name}}/get-item/1', {
109
- method: 'POST',
110
- headers: { 'Content-Type': 'application/json' },
111
- body: JSON.stringify({ id: 'item-1' }),
112
- })
113
-
114
- expect(res.status).toBe(200)
115
- const body = await res.json()
116
- expect(body).toEqual({ id: 'item-1', name: 'Example' })
117
- })
118
-
119
- test('returns 400 for invalid params', async () => {
120
- const res = await {{name}}App.request('/api/{{name}}/get-item/1', {
121
- method: 'POST',
122
- headers: { 'Content-Type': 'application/json' },
123
- body: JSON.stringify({}),
124
- })
125
-
126
- expect(res.status).toBe(400)
127
- })
128
-
129
- test('LIST items returns array', async () => {
130
- const res = await {{name}}App.request('/api/{{name}}/list-items/1', {
131
- method: 'POST',
132
- headers: { 'Content-Type': 'application/json' },
133
- body: JSON.stringify({ page: 1, limit: 10 }),
134
- })
135
-
136
- expect(res.status).toBe(200)
137
- const body = await res.json()
138
- expect(body).toHaveProperty('items')
139
- expect(body).toHaveProperty('total')
140
- })
141
- })
142
- ```
@@ -1,147 +0,0 @@
1
- # Hono Stream Template: {{Name}}
2
-
3
- ## Implementation — `{{Name}}.stream-rpc.ts`
4
-
5
- ```typescript
6
- import { Procedures } from 'ts-procedures'
7
- import { HonoStreamAppBuilder, sse, defineErrorTaxonomy } from 'ts-procedures/hono-stream'
8
- import type { RPCConfig } from 'ts-procedures/http'
9
- import { Type } from 'typebox'
10
-
11
- // ─── Context ──────────────────────────────────────────────
12
-
13
- type {{Name}}Context = {
14
- userId: string
15
- }
16
-
17
- // ─── Stream Procedures ────────────────────────────────────
18
-
19
- const StreamRPC = Procedures<{{Name}}Context, RPCConfig>()
20
-
21
- export const { {{Name}}Stream } = StreamRPC.CreateStream(
22
- '{{Name}}Stream',
23
- {
24
- scope: '{{name}}', // TODO: set URL scope
25
- version: 1,
26
- description: 'TODO: describe what this streams',
27
- schema: {
28
- params: Type.Object({
29
- // TODO: define input parameters
30
- channel: Type.String(),
31
- }),
32
- yieldType: Type.Object({
33
- // TODO: define shape of each yielded value
34
- type: Type.String(),
35
- payload: Type.Any(),
36
- timestamp: Type.Number(),
37
- }),
38
- },
39
- },
40
- async function* (ctx, params) {
41
- // ctx.signal is ALWAYS present in stream handlers
42
-
43
- // TODO: implement streaming logic
44
- let counter = 0
45
- while (!ctx.signal.aborted) {
46
- const event = await pollForEvents(params.channel, { signal: ctx.signal })
47
-
48
- // Use sse() to attach SSE metadata (event type, id, retry)
49
- yield sse(
50
- { type: event.type, payload: event.data, timestamp: Date.now() },
51
- { event: event.type, id: String(counter++) }
52
- )
53
- }
54
- }
55
- )
56
-
57
- // Placeholder — replace with real event source
58
- async function pollForEvents(channel: string, opts?: { signal?: AbortSignal }) {
59
- await new Promise(r => setTimeout(r, 1000))
60
- return { type: 'update', data: { value: Math.random() } }
61
- }
62
-
63
- // ─── Error Taxonomy (pre-stream) ──────────────────────────
64
- // Pre-stream errors (validation, context resolution) flow through the
65
- // taxonomy — framework errors are caught by the default taxonomy automatically.
66
- // Mid-stream errors (thrown after the first yield) still go through
67
- // onMidStreamError since the HTTP status is already committed.
68
-
69
- const {{name}}Errors = defineErrorTaxonomy({
70
- // Example — replace with your app's error classes:
71
- // AuthError: { class: AuthError, statusCode: 401 },
72
- })
73
-
74
- // ─── Hono Stream App Builder ──────────────────────────────
75
-
76
- export const {{name}}StreamApp = new HonoStreamAppBuilder({
77
- pathPrefix: '/api',
78
- defaultStreamMode: 'sse', // or 'text' for newline-delimited JSON
79
- errors: {{name}}Errors,
80
- unknownError: {
81
- statusCode: 500,
82
- toResponse: () => ({ name: 'InternalServerError', message: 'Unexpected error' }),
83
- },
84
- onMidStreamError: (procedure, c, error) => ({
85
- data: { type: 'error', payload: { message: error.message }, timestamp: Date.now() },
86
- closeStream: true,
87
- }),
88
- })
89
- .register(StreamRPC, (c) => ({
90
- userId: c.req.header('x-user-id') || 'anonymous',
91
- }))
92
- .build()
93
-
94
- // Routes:
95
- // GET /api/{{name}}/{{name}}-stream/1?channel=test
96
- // POST /api/{{name}}/{{name}}-stream/1 (body: { channel: "test" })
97
-
98
- // SSE output per yield:
99
- // event: {{Name}}Stream
100
- // id: 0
101
- // data: {"type":"update","payload":{...},"timestamp":1234567890}
102
- ```
103
-
104
- ## Test — `{{Name}}.stream-rpc.test.ts`
105
-
106
- ```typescript
107
- import { describe, test, expect } from 'vitest'
108
- import { {{name}}StreamApp } from './{{Name}}.stream-rpc'
109
-
110
- describe('{{Name}} Stream RPC', () => {
111
- test('GET returns SSE stream', async () => {
112
- const res = await {{name}}StreamApp.request(
113
- '/api/{{name}}/{{name}}-stream/1?channel=test'
114
- )
115
-
116
- expect(res.status).toBe(200)
117
- expect(res.headers.get('content-type')).toContain('text/event-stream')
118
- })
119
-
120
- test('POST returns SSE stream', async () => {
121
- const res = await {{name}}StreamApp.request(
122
- '/api/{{name}}/{{name}}-stream/1',
123
- {
124
- method: 'POST',
125
- headers: { 'Content-Type': 'application/json' },
126
- body: JSON.stringify({ channel: 'test' }),
127
- }
128
- )
129
-
130
- expect(res.status).toBe(200)
131
- expect(res.headers.get('content-type')).toContain('text/event-stream')
132
- })
133
-
134
- test('returns 400 for invalid params', async () => {
135
- const res = await {{name}}StreamApp.request(
136
- '/api/{{name}}/{{name}}-stream/1',
137
- {
138
- method: 'POST',
139
- headers: { 'Content-Type': 'application/json' },
140
- body: JSON.stringify({}),
141
- }
142
- )
143
-
144
- expect(res.status).toBe(400)
145
- })
146
- })
147
- ```
@@ -1,83 +0,0 @@
1
- import { describe, expect, test, vi } from 'vitest';
2
- import request from 'supertest';
3
- import { Type } from 'typebox';
4
- import { Procedures } from '../../../index.js';
5
- import { ExpressRPCAppBuilder, defineErrorTaxonomy } from './index.js';
6
- class UseCaseError extends Error {
7
- externalMsg;
8
- internalMsg;
9
- constructor(externalMsg, internalMsg) {
10
- super(externalMsg);
11
- this.externalMsg = externalMsg;
12
- this.internalMsg = internalMsg;
13
- this.name = 'UseCaseError';
14
- Object.setPrototypeOf(this, UseCaseError.prototype);
15
- }
16
- }
17
- describe('ExpressRPCAppBuilder — error taxonomy', () => {
18
- test('taxonomy catches user error thrown from RPC handler', async () => {
19
- const errors = defineErrorTaxonomy({
20
- UseCaseError: {
21
- class: UseCaseError,
22
- statusCode: 422,
23
- toResponse: (err) => ({ name: 'UseCaseError', message: err.externalMsg }),
24
- },
25
- });
26
- const RPC = Procedures();
27
- RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
28
- throw new UseCaseError('ext', 'int');
29
- });
30
- const app = new ExpressRPCAppBuilder({ errors }).register(RPC, () => ({})).build();
31
- const res = await request(app).post('/test/boom/1').send({});
32
- expect(res.status).toBe(422);
33
- expect(res.body).toEqual({ name: 'UseCaseError', message: 'ext' });
34
- });
35
- test('unknownError catches unmapped errors', async () => {
36
- const RPC = Procedures();
37
- RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
38
- throw new TypeError('db down');
39
- });
40
- const app = new ExpressRPCAppBuilder({
41
- unknownError: { statusCode: 503, toResponse: () => ({ name: 'ServiceUnavailable' }) },
42
- })
43
- .register(RPC, () => ({}))
44
- .build();
45
- const res = await request(app).post('/test/boom/1').send({});
46
- expect(res.status).toBe(503);
47
- expect(res.body).toEqual({ name: 'ServiceUnavailable' });
48
- });
49
- test('onCatch receives { req, res } as raw context', async () => {
50
- let rawSeen;
51
- const errors = defineErrorTaxonomy({
52
- UseCaseError: {
53
- class: UseCaseError,
54
- statusCode: 422,
55
- onCatch: (_err, ctx) => {
56
- rawSeen = ctx.raw;
57
- },
58
- },
59
- });
60
- const RPC = Procedures();
61
- RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
62
- throw new UseCaseError('ext', 'int');
63
- });
64
- const app = new ExpressRPCAppBuilder({ errors }).register(RPC, () => ({})).build();
65
- await request(app).post('/test/boom/1').send({});
66
- expect(rawSeen.req).toBeDefined();
67
- expect(rawSeen.res).toBeDefined();
68
- });
69
- test('onError callback handles errors not matched by the taxonomy', async () => {
70
- const onError = vi.fn((_p, _req, res) => {
71
- res.status(418).json({ legacy: true });
72
- });
73
- const RPC = Procedures();
74
- RPC.Create('Boom', { scope: 'test', version: 1, schema: { params: Type.Object({}) } }, async () => {
75
- throw new TypeError('legacy');
76
- });
77
- const app = new ExpressRPCAppBuilder({ onError }).register(RPC, () => ({})).build();
78
- const res = await request(app).post('/test/boom/1').send({});
79
- expect(res.status).toBe(418);
80
- expect(onError).toHaveBeenCalledOnce();
81
- });
82
- });
83
- //# sourceMappingURL=error-taxonomy.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"error-taxonomy.test.js","sourceRoot":"","sources":["../../../../src/implementations/http/express-rpc/error-taxonomy.test.ts"],"names":[],"mappings":"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"}
@@ -1,125 +0,0 @@
1
- import express from 'express';
2
- import { TProcedureRegistration } from '../../../index.js';
3
- import { ExtractConfig, ExtractContext, ProceduresFactory, RPCConfig, RPCHttpRouteDoc } from '../../types.js';
4
- import { ErrorTaxonomy, ErrorTaxonomyEntry, UnknownErrorConfig, defineErrorTaxonomy } from '../error-taxonomy.js';
5
- export type { RPCConfig, RPCHttpRouteDoc };
6
- export { defineErrorTaxonomy };
7
- export type { ErrorTaxonomy, ErrorTaxonomyEntry, UnknownErrorConfig };
8
- export type ExpressRPCAppBuilderConfig = {
9
- /**
10
- * An existing Express application instance to use.
11
- * When provided, ensure to set up necessary middleware (e.g., json/body parser) beforehand.
12
- * If not provided, a new instance will be created.
13
- */
14
- app?: express.Express;
15
- /** Optional path prefix for all RPC routes. */
16
- pathPrefix?: string;
17
- onRequestStart?: (req: express.Request) => void;
18
- onRequestEnd?: (req: express.Request, res: express.Response) => void;
19
- onSuccess?: (procedure: TProcedureRegistration, req: express.Request, res: express.Response) => void;
20
- /**
21
- * Declarative error-to-response mapping (one of the two peer error modes).
22
- * See hono-api for the full taxonomy contract. The `raw` field passed to
23
- * taxonomy callbacks is `{ req, res }`.
24
- */
25
- errors?: ErrorTaxonomy;
26
- /** Fallback serializer for errors not matched by the taxonomy. */
27
- unknownError?: UnknownErrorConfig;
28
- /**
29
- * Imperative error callback — the other peer error mode. Receives every
30
- * error directly and writes the response via `res`. Use this when you want
31
- * full control, or alongside `errors` for the tail of errors the taxonomy
32
- * doesn't cover.
33
- */
34
- onError?: (procedure: TProcedureRegistration, req: express.Request, res: express.Response, error: Error) => void;
35
- /**
36
- * Cross-cutting observer — fires for every caught error, BEFORE dispatch.
37
- * Awaited. Cannot write to `res` (observer only — check `res.headersSent`
38
- * if you must touch it). Thrown errors inside the observer are swallowed
39
- * and logged.
40
- */
41
- onRequestError?: (ctx: OnRequestErrorContext) => void | Promise<void>;
42
- };
43
- /**
44
- * Context passed to the `onRequestError` observer. `raw` is `{ req, res }`
45
- * for the in-flight request.
46
- */
47
- export type OnRequestErrorContext = {
48
- err: unknown;
49
- procedure: TProcedureRegistration;
50
- raw: {
51
- req: express.Request;
52
- res: express.Response;
53
- };
54
- };
55
- /**
56
- * Builder class for creating an Express application with RPC routes.
57
- *
58
- * Usage:
59
- * const PublicRPC = Procedures<PublicRPCContext, RPCConfig>()
60
- * const ProtectedRPC = Procedures<ProtectedRPCContext, RPCConfig>()
61
- *
62
- * const rpcApp = new ExpressRPCAppBuilder()
63
- * .register(PublicRPC, (req): Promise<PublicRPCContext> => { /* context resolution logic * / })
64
- * .register(ProtectedRPC, (req): Promise<ProtectedRPCContext> => { /* context resolution logic * / })
65
- * .build();
66
- *
67
- * const app = rpcApp.app; // Express application
68
- * const docs = rpcApp.docs; // RPC route documentation
69
- */
70
- export declare class ExpressRPCAppBuilder {
71
- readonly config?: ExpressRPCAppBuilderConfig | undefined;
72
- /**
73
- * Constructor for ExpressRPCAppBuilder.
74
- *
75
- * @param config
76
- */
77
- constructor(config?: ExpressRPCAppBuilderConfig | undefined);
78
- /**
79
- * Generates the RPC route path based on the RPC configuration.
80
- * `RPCConfig.scope` can be a string or an array of strings to form nested paths.
81
- *
82
- * Example
83
- * name: 'GetUser'
84
- * scope: ['users', 'profile']
85
- * version: 1
86
- * path: /users/profile/get-user/1
87
- * @param config
88
- */
89
- static makeRPCHttpRoutePath({ name, config, prefix, }: {
90
- name: string;
91
- prefix?: string;
92
- config: RPCConfig;
93
- }): string;
94
- /**
95
- * Instance method wrapper for makeRPCHttpRoutePath that uses the builder's pathPrefix.
96
- * @param config - The RPC configuration
97
- */
98
- makeRPCHttpRoutePath(name: string, config: RPCConfig): string;
99
- private factories;
100
- private _app;
101
- private _docs;
102
- get app(): express.Express;
103
- get docs(): RPCHttpRouteDoc[];
104
- /**
105
- * Registers a procedure factory with its context.
106
- * @param factory - The procedure factory created by Procedures<Context, RPCConfig>()
107
- * @param factoryContext - The context for procedure handlers. Can be a direct value,
108
- * a sync function (req) => Context, or an async function (req) => Promise<Context>
109
- * @param extendProcedureDoc - A custom function to extend the generated RPC route documentation for each procedure.
110
- */
111
- register<TFactory extends ProceduresFactory>(factory: TFactory, factoryContext: ExtractContext<TFactory> | ((req: express.Request) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>), extendProcedureDoc?: (params: {
112
- base: RPCHttpRouteDoc;
113
- procedure: TProcedureRegistration<any, ExtractConfig<TFactory>>;
114
- }) => Record<string, any>): this;
115
- /**
116
- * Builds and returns the Express application with registered RPC routes.
117
- * @return express.Application
118
- */
119
- build(): express.Application;
120
- /**
121
- * Generates the RPC HTTP route for the given procedure.
122
- * @param procedure
123
- */
124
- private buildRpcHttpRouteDoc;
125
- }