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,320 +0,0 @@
1
- import { Hono, Context } from 'hono'
2
- import { kebabCase } from 'es-toolkit/string'
3
- import { TProcedureRegistration } from '../../../index.js'
4
- import {
5
- ExtractConfig,
6
- ExtractContext,
7
- ProceduresFactory,
8
- RPCConfig,
9
- RPCHttpRouteDoc,
10
- } from '../../types.js'
11
- import {
12
- ErrorTaxonomy,
13
- ErrorTaxonomyEntry,
14
- UnknownErrorConfig,
15
- defineErrorTaxonomy,
16
- resolveErrorResponse,
17
- } from '../error-taxonomy.js'
18
- import { castArray } from 'es-toolkit/compat'
19
- import { HonoFactoryItem } from './types.js'
20
-
21
- export type { RPCConfig, RPCHttpRouteDoc }
22
- export { defineErrorTaxonomy }
23
- export type { ErrorTaxonomy, ErrorTaxonomyEntry, UnknownErrorConfig }
24
-
25
- export type HonoRPCAppBuilderConfig = {
26
- /**
27
- * An existing Hono application instance to use.
28
- * If not provided, a new instance will be created.
29
- */
30
- app?: Hono
31
- /** Optional path prefix for all RPC routes. */
32
- pathPrefix?: string
33
- onRequestStart?: (c: Context) => void
34
- onRequestEnd?: (c: Context) => void
35
- onSuccess?: (procedure: TProcedureRegistration, c: Context) => void
36
- /**
37
- * Declarative error-to-response mapping (one of the two peer error modes).
38
- * See hono-api for the full taxonomy contract. User entries take precedence
39
- * over the framework default taxonomy.
40
- */
41
- errors?: ErrorTaxonomy
42
- /** Fallback serializer for errors not matched by the taxonomy. */
43
- unknownError?: UnknownErrorConfig
44
- /**
45
- * Imperative error callback — the other peer error mode. Receives every
46
- * error directly and returns the HTTP response. Use this when you want full
47
- * control over the response shape, or alongside `errors` for the tail of
48
- * errors the taxonomy doesn't cover.
49
- */
50
- onError?: (
51
- procedure: TProcedureRegistration,
52
- c: Context,
53
- error: Error
54
- ) => Response | Promise<Response>
55
- /**
56
- * Cross-cutting observer — fires for every caught error, BEFORE dispatch.
57
- * Awaited. Cannot mutate the response. Intended for logging, tracing, and
58
- * metrics. Thrown errors inside the observer are swallowed and logged.
59
- */
60
- onRequestError?: (ctx: OnRequestErrorContext) => void | Promise<void>
61
- }
62
-
63
- /**
64
- * Context passed to the `onRequestError` observer.
65
- */
66
- export type OnRequestErrorContext = {
67
- err: unknown
68
- procedure: TProcedureRegistration
69
- raw: Context
70
- }
71
-
72
- /**
73
- * Builder class for creating a Hono application with RPC routes.
74
- *
75
- * Usage:
76
- * const PublicRPC = Procedures<PublicRPCContext, RPCConfig>()
77
- * const ProtectedRPC = Procedures<ProtectedRPCContext, RPCConfig>()
78
- *
79
- * const rpcApp = new HonoRPCAppBuilder()
80
- * .register(PublicRPC, (c): Promise<PublicRPCContext> => { /* context resolution logic * / })
81
- * .register(ProtectedRPC, (c): Promise<ProtectedRPCContext> => { /* context resolution logic * / })
82
- * .build();
83
- *
84
- * const app = rpcApp.app; // Hono application
85
- * const docs = rpcApp.docs; // RPC route documentation
86
- */
87
- export class HonoRPCAppBuilder {
88
- /**
89
- * Constructor for HonoRPCAppBuilder.
90
- *
91
- * @param config
92
- */
93
- constructor(readonly config?: HonoRPCAppBuilderConfig) {
94
- if (config?.app) {
95
- this._app = config.app
96
- }
97
-
98
- if (config?.onRequestStart) {
99
- this._app.use('*', async (c, next) => {
100
- config.onRequestStart!(c)
101
- await next()
102
- })
103
- }
104
-
105
- if (config?.onRequestEnd) {
106
- this._app.use('*', async (c, next) => {
107
- await next()
108
- config.onRequestEnd!(c)
109
- })
110
- }
111
- }
112
-
113
- /**
114
- * Generates the RPC route path based on the RPC configuration.
115
- * `RPCConfig.scope` can be a string or an array of strings to form nested paths.
116
- *
117
- * Example
118
- * name: 'GetUser'
119
- * scope: ['users', 'profile']
120
- * version: 1
121
- * path: /users/profile/get-user/1
122
- * @param config
123
- */
124
- static makeRPCHttpRoutePath({
125
- name,
126
- config,
127
- prefix,
128
- }: {
129
- name: string
130
- prefix?: string
131
- config: RPCConfig
132
- }) {
133
- const normalizedPrefix = prefix ? (prefix.startsWith('/') ? prefix : `/${prefix}`) : ''
134
-
135
- return `${normalizedPrefix}/${castArray(config.scope).map(kebabCase).join('/')}/${kebabCase(name)}/${String(config.version).trim()}`
136
- }
137
-
138
- /**
139
- * Instance method wrapper for makeRPCHttpRoutePath that uses the builder's pathPrefix.
140
- * @param config - The RPC configuration
141
- */
142
- makeRPCHttpRoutePath(name: string, config: RPCConfig): string {
143
- return HonoRPCAppBuilder.makeRPCHttpRoutePath({
144
- name,
145
- config,
146
- prefix: this.config?.pathPrefix,
147
- })
148
- }
149
-
150
- private factories: HonoFactoryItem<any>[] = []
151
-
152
- private _app: Hono = new Hono()
153
- private _docs: (RPCHttpRouteDoc & object)[] = []
154
- private _skipped: { name: string; reason: string }[] = []
155
-
156
- get app(): Hono {
157
- return this._app
158
- }
159
-
160
- get docs(): RPCHttpRouteDoc[] {
161
- return this._docs
162
- }
163
-
164
- /**
165
- * Procedures that were skipped at `build()` time because they don't fit
166
- * this builder (e.g. streaming procedures registered against an RPC
167
- * builder). Surfaced via `DocSource.skippedProcedures` so DocRegistry can
168
- * warn about coverage gaps.
169
- */
170
- get skippedProcedures(): { name: string; reason: string }[] {
171
- return this._skipped
172
- }
173
-
174
- /**
175
- * Registers a procedure factory with its context.
176
- * @param factory - The procedure factory created by Procedures<Context, RPCConfig>()
177
- * @param factoryContext - The context for procedure handlers. Can be a direct value,
178
- * a sync function (c) => Context, or an async function (c) => Promise<Context>
179
- * @param extendProcedureDoc - A custom function to extend the generated RPC route documentation for each procedure.
180
- */
181
- register<TFactory extends ProceduresFactory>(
182
- factory: TFactory,
183
- factoryContext:
184
- | ExtractContext<TFactory>
185
- | ((c: Context) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>),
186
- extendProcedureDoc?: (params: {
187
- /* RPC App builder base http route doc */
188
- base: RPCHttpRouteDoc
189
- /* Procedure registration */
190
- procedure: TProcedureRegistration<any, ExtractConfig<TFactory>>
191
- }) => Record<string, any>
192
- ): this {
193
- this.factories.push({ factory, factoryContext, extendProcedureDoc } as HonoFactoryItem<any>)
194
- return this
195
- }
196
-
197
- /**
198
- * Builds and returns the Hono application with registered RPC routes.
199
- * @return Hono
200
- */
201
- build(): Hono {
202
- this.factories.forEach(({ factory, factoryContext, extendProcedureDoc }) => {
203
- factory.getProcedures().forEach((procedure: TProcedureRegistration<any, RPCConfig>) => {
204
- // Skip streaming procedures — RPC builder cannot serve them. Without
205
- // this guard, the procedure would silently get a POST route that
206
- // returns its async generator object as a JSON response, which is not
207
- // a useful failure mode. Procedures meant to stream should be
208
- // registered with HonoStreamAppBuilder.
209
- if ((procedure as { isStream?: boolean }).isStream === true) {
210
- const reason =
211
- 'Streaming procedure registered with HonoRPCAppBuilder — register it with HonoStreamAppBuilder instead.'
212
- this._skipped.push({ name: procedure.name, reason })
213
- console.warn(
214
- `[ts-procedures hono-rpc] Skipping procedure "${procedure.name}": ${reason}`
215
- )
216
- return
217
- }
218
-
219
- const route = this.buildRpcHttpRouteDoc(procedure, extendProcedureDoc)
220
-
221
- this._docs.push(route)
222
-
223
- this._app.post(route.path, async (c) => {
224
- try {
225
- const context =
226
- typeof factoryContext === 'function'
227
- ? await factoryContext(c)
228
- : (factoryContext as ExtractContext<typeof factory>)
229
-
230
- // Hono uses c.req.json() for body parsing
231
- const body = await c.req.json().catch(() => ({}))
232
- const result = await procedure.handler({ ...context, signal: c.req.raw.signal }, body)
233
-
234
- if (this.config?.onSuccess) {
235
- this.config.onSuccess(procedure, c)
236
- }
237
-
238
- // Hono returns Response objects via c.json()
239
- return c.json(result)
240
- } catch (error) {
241
- if (this.config?.onRequestError) {
242
- try {
243
- await this.config.onRequestError({ err: error, procedure, raw: c })
244
- } catch (observerErr) {
245
- console.error('[ts-procedures hono-rpc] onRequestError threw — swallowed:', observerErr)
246
- }
247
- }
248
- if (this.config?.errors || this.config?.unknownError) {
249
- const resolved = resolveErrorResponse({
250
- err: error,
251
- userTaxonomy: this.config.errors,
252
- unknownError: this.config.unknownError,
253
- procedure,
254
- raw: c,
255
- })
256
- if (resolved) {
257
- await resolved.runOnCatch()
258
- return c.json(resolved.body, resolved.statusCode as never)
259
- }
260
- }
261
- if (this.config?.onError) {
262
- return this.config.onError(procedure, c, error as Error)
263
- }
264
- return c.json({ error: (error as Error).message }, 500)
265
- }
266
- })
267
- })
268
- })
269
-
270
- return this._app
271
- }
272
-
273
- /**
274
- * Generates the RPC HTTP route for the given procedure.
275
- * @param procedure
276
- */
277
- private buildRpcHttpRouteDoc(
278
- procedure: TProcedureRegistration<any, RPCConfig>,
279
- extendProcedureDoc: HonoFactoryItem['extendProcedureDoc']
280
- ): RPCHttpRouteDoc {
281
- const { config } = procedure
282
- const path = HonoRPCAppBuilder.makeRPCHttpRoutePath({
283
- name: procedure.name,
284
- config,
285
- prefix: this.config?.pathPrefix,
286
- })
287
- const method = 'post' as const // RPCs use POST method
288
- const jsonSchema: { body?: Record<string, unknown>; response?: Record<string, unknown> } = {}
289
-
290
- if (config.schema?.params) {
291
- jsonSchema.body = config.schema.params
292
- }
293
- if (config.schema?.returnType) {
294
- jsonSchema.response = config.schema.returnType
295
- }
296
-
297
- const base: RPCHttpRouteDoc = {
298
- kind: 'rpc' as const,
299
- name: procedure.name,
300
- version: config.version,
301
- scope: config.scope,
302
- path,
303
- method,
304
- jsonSchema,
305
- }
306
- if (config.errors && config.errors.length > 0) {
307
- base.errors = [...config.errors]
308
- }
309
- let extendedDoc: object = {}
310
-
311
- if (extendProcedureDoc) {
312
- extendedDoc = extendProcedureDoc({ base, procedure })
313
- }
314
-
315
- return {
316
- ...extendedDoc,
317
- ...base,
318
- }
319
- }
320
- }
@@ -1,16 +0,0 @@
1
- import { ExtractConfig, ExtractContext, RPCConfig, RPCHttpRouteDoc } from '../../types.js'
2
- import { Procedures, TProcedureRegistration } from '../../../index.js'
3
- import { Context } from 'hono'
4
-
5
- export type HonoFactoryItem<TFactory = ReturnType<typeof Procedures<any, RPCConfig>>> = {
6
- factory: TFactory
7
- factoryContext:
8
- | ExtractContext<TFactory>
9
- | ((c: Context) => ExtractContext<TFactory> | Promise<ExtractContext<TFactory>>)
10
- extendProcedureDoc?: (params: {
11
- /* RPC App builder base http route doc */
12
- base: RPCHttpRouteDoc
13
- /* Procedure registration */
14
- procedure: TProcedureRegistration<any, ExtractConfig<TFactory>>
15
- }) => Record<string, any>
16
- }