ts-procedures 8.6.0 → 9.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 (627) hide show
  1. package/README.md +166 -101
  2. package/agent_config/claude-code/.claude-plugin/plugin.json +1 -1
  3. package/agent_config/claude-code/agents/ts-procedures-architect.md +11 -10
  4. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +25 -12
  5. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +10 -12
  6. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +141 -45
  7. package/agent_config/claude-code/skills/ts-procedures/checklist.md +7 -6
  8. package/agent_config/claude-code/skills/ts-procedures/patterns.md +45 -6
  9. package/agent_config/claude-code/skills/ts-procedures/templates/client.md +1 -1
  10. package/agent_config/claude-code/skills/ts-procedures/templates/hono.md +1 -1
  11. package/agent_config/copilot/copilot-instructions.md +50 -33
  12. package/agent_config/cursor/cursorrules +50 -33
  13. package/build/adapters/astro/astro-context.js.map +1 -0
  14. package/build/adapters/astro/create-handler.js.map +1 -0
  15. package/build/adapters/astro/index.js.map +1 -0
  16. package/build/{implementations/http → adapters}/astro/index.test.js +1 -1
  17. package/build/adapters/astro/index.test.js.map +1 -0
  18. package/build/adapters/astro/rewrite-request.js.map +1 -0
  19. package/build/adapters/hono/envelope-parity.test.js +98 -0
  20. package/build/adapters/hono/envelope-parity.test.js.map +1 -0
  21. package/build/{implementations/http → adapters}/hono/handlers/http-stream.d.ts +1 -1
  22. package/build/adapters/hono/handlers/http-stream.js +55 -0
  23. package/build/adapters/hono/handlers/http-stream.js.map +1 -0
  24. package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.js +1 -1
  25. package/build/adapters/hono/handlers/http-stream.test.js.map +1 -0
  26. package/build/{implementations/http → adapters}/hono/handlers/http.d.ts +1 -1
  27. package/build/adapters/hono/handlers/http.js +50 -0
  28. package/build/adapters/hono/handlers/http.js.map +1 -0
  29. package/build/{implementations/http → adapters}/hono/handlers/http.test.js +1 -1
  30. package/build/adapters/hono/handlers/http.test.js.map +1 -0
  31. package/build/{implementations/http → adapters}/hono/handlers/rpc.d.ts +2 -2
  32. package/build/adapters/hono/handlers/rpc.js +23 -0
  33. package/build/adapters/hono/handlers/rpc.js.map +1 -0
  34. package/build/{implementations/http → adapters}/hono/handlers/rpc.test.js +1 -1
  35. package/build/adapters/hono/handlers/rpc.test.js.map +1 -0
  36. package/build/adapters/hono/handlers/stream.d.ts +12 -0
  37. package/build/adapters/hono/handlers/stream.js +89 -0
  38. package/build/adapters/hono/handlers/stream.js.map +1 -0
  39. package/build/{implementations/http → adapters}/hono/handlers/stream.test.js +3 -2
  40. package/build/adapters/hono/handlers/stream.test.js.map +1 -0
  41. package/build/{implementations/http → adapters}/hono/index.d.ts +24 -12
  42. package/build/{implementations/http → adapters}/hono/index.js +19 -8
  43. package/build/adapters/hono/index.js.map +1 -0
  44. package/build/{implementations/http → adapters}/hono/index.test.js +2 -4
  45. package/build/adapters/hono/index.test.js.map +1 -0
  46. package/build/{implementations/http → adapters/hono}/on-request-error.test.js +2 -2
  47. package/build/adapters/hono/on-request-error.test.js.map +1 -0
  48. package/build/adapters/hono/request.d.ts +7 -0
  49. package/build/adapters/hono/request.js +22 -0
  50. package/build/adapters/hono/request.js.map +1 -0
  51. package/build/{implementations/http → adapters/hono}/route-errors.test.js +4 -4
  52. package/build/adapters/hono/route-errors.test.js.map +1 -0
  53. package/build/adapters/hono/types.d.ts +55 -0
  54. package/build/adapters/hono/types.js +19 -0
  55. package/build/adapters/hono/types.js.map +1 -0
  56. package/build/client/freeze.test.js +39 -0
  57. package/build/client/freeze.test.js.map +1 -0
  58. package/build/client/typed-error-dispatch.test.js +2 -2
  59. package/build/client/typed-error-dispatch.test.js.map +1 -1
  60. package/build/codegen/__fixtures__/make-envelope.d.ts +1 -1
  61. package/build/codegen/bin/cli.d.ts +5 -0
  62. package/build/codegen/bin/cli.js +139 -182
  63. package/build/codegen/bin/cli.js.map +1 -1
  64. package/build/codegen/bin/cli.test.js +12 -2
  65. package/build/codegen/bin/cli.test.js.map +1 -1
  66. package/build/codegen/bin/flag-specs.d.ts +9 -0
  67. package/build/codegen/bin/flag-specs.js +33 -31
  68. package/build/codegen/bin/flag-specs.js.map +1 -1
  69. package/build/codegen/bin/flag-specs.test.js +14 -1
  70. package/build/codegen/bin/flag-specs.test.js.map +1 -1
  71. package/build/codegen/collect-models.d.ts +1 -1
  72. package/build/codegen/emit/api-route.d.ts +8 -0
  73. package/build/codegen/emit/api-route.js +156 -0
  74. package/build/codegen/emit/api-route.js.map +1 -0
  75. package/build/codegen/emit/context.d.ts +30 -0
  76. package/build/codegen/emit/context.js +2 -0
  77. package/build/codegen/emit/context.js.map +1 -0
  78. package/build/codegen/emit/declarations.d.ts +24 -0
  79. package/build/codegen/emit/declarations.js +48 -0
  80. package/build/codegen/emit/declarations.js.map +1 -0
  81. package/build/codegen/emit/format-types.d.ts +61 -0
  82. package/build/codegen/emit/format-types.js +188 -0
  83. package/build/codegen/emit/format-types.js.map +1 -0
  84. package/build/codegen/emit/http-stream-route.d.ts +7 -0
  85. package/build/codegen/emit/http-stream-route.js +138 -0
  86. package/build/codegen/emit/http-stream-route.js.map +1 -0
  87. package/build/codegen/emit/route-shared.d.ts +35 -0
  88. package/build/codegen/emit/route-shared.js +88 -0
  89. package/build/codegen/emit/route-shared.js.map +1 -0
  90. package/build/codegen/emit/rpc-route.d.ts +7 -0
  91. package/build/codegen/emit/rpc-route.js +37 -0
  92. package/build/codegen/emit/rpc-route.js.map +1 -0
  93. package/build/codegen/emit/scope-file.d.ts +39 -0
  94. package/build/codegen/emit/scope-file.js +166 -0
  95. package/build/codegen/emit/scope-file.js.map +1 -0
  96. package/build/codegen/emit/stream-route.d.ts +7 -0
  97. package/build/codegen/emit/stream-route.js +62 -0
  98. package/build/codegen/emit/stream-route.js.map +1 -0
  99. package/build/codegen/emit-errors.d.ts +1 -1
  100. package/build/codegen/emit-errors.integration.test.js +1 -1
  101. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  102. package/build/codegen/emit-scope.d.ts +13 -30
  103. package/build/codegen/emit-scope.js +15 -844
  104. package/build/codegen/emit-scope.js.map +1 -1
  105. package/build/codegen/goldens.test.js +69 -0
  106. package/build/codegen/goldens.test.js.map +1 -0
  107. package/build/codegen/group-routes.d.ts +1 -1
  108. package/build/codegen/pipeline.d.ts +1 -1
  109. package/build/codegen/resolve-envelope.d.ts +1 -1
  110. package/build/codegen/targets/_shared/error-schemas.d.ts +1 -1
  111. package/build/codegen/targets/_shared/route-slots.d.ts +1 -1
  112. package/build/codegen/targets/_shared/target-run.d.ts +1 -1
  113. package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +1 -1
  114. package/build/codegen/targets/swift/emit-route-swift.d.ts +1 -1
  115. package/build/core/create-http-stream.d.ts +50 -0
  116. package/build/core/create-http-stream.js +108 -0
  117. package/build/core/create-http-stream.js.map +1 -0
  118. package/build/{create-http-stream.test.js → core/create-http-stream.test.js} +1 -1
  119. package/build/core/create-http-stream.test.js.map +1 -0
  120. package/build/core/create-http.d.ts +51 -0
  121. package/build/core/create-http.js +65 -0
  122. package/build/core/create-http.js.map +1 -0
  123. package/build/{create-http.test.js → core/create-http.test.js} +13 -4
  124. package/build/core/create-http.test.js.map +1 -0
  125. package/build/core/create-stream.d.ts +26 -0
  126. package/build/core/create-stream.js +80 -0
  127. package/build/core/create-stream.js.map +1 -0
  128. package/build/{create-stream.test.js → core/create-stream.test.js} +23 -28
  129. package/build/core/create-stream.test.js.map +1 -0
  130. package/build/core/create.d.ts +22 -0
  131. package/build/core/create.js +71 -0
  132. package/build/core/create.js.map +1 -0
  133. package/build/{create.test.js → core/create.test.js} +25 -46
  134. package/build/core/create.test.js.map +1 -0
  135. package/build/core/definition-site.d.ts +24 -0
  136. package/build/{stack-utils.js → core/definition-site.js} +20 -20
  137. package/build/core/definition-site.js.map +1 -0
  138. package/build/{stack-utils.test.js → core/definition-site.test.js} +12 -3
  139. package/build/core/definition-site.test.js.map +1 -0
  140. package/build/{errors.d.ts → core/errors.d.ts} +19 -8
  141. package/build/{errors.js → core/errors.js} +21 -26
  142. package/build/core/errors.js.map +1 -0
  143. package/build/core/errors.test.js.map +1 -0
  144. package/build/core/factory-options.test.js +82 -0
  145. package/build/core/factory-options.test.js.map +1 -0
  146. package/build/core/http-route.d.ts +13 -0
  147. package/build/core/http-route.js +54 -0
  148. package/build/core/http-route.js.map +1 -0
  149. package/build/core/internal.d.ts +72 -0
  150. package/build/core/internal.js +128 -0
  151. package/build/core/internal.js.map +1 -0
  152. package/build/{migration.test.js → core/migration.test.js} +17 -1
  153. package/build/core/migration.test.js.map +1 -0
  154. package/build/core/procedures.d.ts +143 -0
  155. package/build/core/procedures.js +64 -0
  156. package/build/core/procedures.js.map +1 -0
  157. package/build/{index.test.js → core/procedures.test.js} +14 -11
  158. package/build/core/procedures.test.js.map +1 -0
  159. package/build/core/types.d.ts +182 -0
  160. package/build/{schema → core}/types.js.map +1 -1
  161. package/build/exports.d.ts +31 -11
  162. package/build/exports.js +23 -8
  163. package/build/exports.js.map +1 -1
  164. package/build/schema/adapter.d.ts +35 -0
  165. package/build/schema/adapter.js +13 -0
  166. package/build/schema/adapter.js.map +1 -0
  167. package/build/schema/adapter.test.js +53 -0
  168. package/build/schema/adapter.test.js.map +1 -0
  169. package/build/schema/compile.d.ts +37 -0
  170. package/build/schema/compile.js +38 -0
  171. package/build/schema/compile.js.map +1 -0
  172. package/build/schema/compile.test.js +78 -0
  173. package/build/schema/compile.test.js.map +1 -0
  174. package/build/schema/compute-schema.d.ts +47 -37
  175. package/build/schema/compute-schema.js +86 -29
  176. package/build/schema/compute-schema.js.map +1 -1
  177. package/build/schema/compute-schema.test.js +158 -40
  178. package/build/schema/compute-schema.test.js.map +1 -1
  179. package/build/schema/json-schema.d.ts +17 -0
  180. package/build/schema/json-schema.js +2 -0
  181. package/build/schema/json-schema.js.map +1 -0
  182. package/build/schema/typebox.d.ts +11 -0
  183. package/build/schema/typebox.js +24 -0
  184. package/build/schema/typebox.js.map +1 -0
  185. package/build/schema/typebox.test.js +34 -0
  186. package/build/schema/typebox.test.js.map +1 -0
  187. package/build/server/context.d.ts +8 -0
  188. package/build/server/context.js +7 -0
  189. package/build/server/context.js.map +1 -0
  190. package/build/server/context.test.js +16 -0
  191. package/build/server/context.test.js.map +1 -0
  192. package/build/{doc-envelope.d.ts → server/doc-envelope.d.ts} +1 -1
  193. package/build/server/doc-envelope.js.map +1 -0
  194. package/build/server/doc-envelope.test.d.ts +1 -0
  195. package/build/server/doc-envelope.test.js.map +1 -0
  196. package/build/{implementations/http → server}/doc-registry.d.ts +7 -2
  197. package/build/{implementations/http → server}/doc-registry.js +9 -5
  198. package/build/server/doc-registry.js.map +1 -0
  199. package/build/server/doc-registry.test.d.ts +1 -0
  200. package/build/{implementations/http → server}/doc-registry.test.js +27 -24
  201. package/build/server/doc-registry.test.js.map +1 -0
  202. package/build/server/docs/docs.test.d.ts +1 -0
  203. package/build/server/docs/docs.test.js +237 -0
  204. package/build/server/docs/docs.test.js.map +1 -0
  205. package/build/{implementations/http/hono → server}/docs/http-doc.d.ts +2 -2
  206. package/build/{implementations/http/hono → server}/docs/http-doc.js +1 -1
  207. package/build/server/docs/http-doc.js.map +1 -0
  208. package/build/{implementations/http/hono → server}/docs/http-stream-doc.d.ts +2 -2
  209. package/build/{implementations/http/hono → server}/docs/http-stream-doc.js +1 -1
  210. package/build/server/docs/http-stream-doc.js.map +1 -0
  211. package/build/{implementations/http/hono → server}/docs/rpc-doc.d.ts +2 -2
  212. package/build/{implementations/http/hono → server}/docs/rpc-doc.js +1 -1
  213. package/build/server/docs/rpc-doc.js.map +1 -0
  214. package/build/{implementations/http/hono → server}/docs/stream-doc.d.ts +2 -2
  215. package/build/{implementations/http/hono → server}/docs/stream-doc.js +1 -1
  216. package/build/server/docs/stream-doc.js.map +1 -0
  217. package/build/server/errors/dispatch.d.ts +96 -0
  218. package/build/{implementations/http/error-dispatch.js → server/errors/dispatch.js} +20 -10
  219. package/build/server/errors/dispatch.js.map +1 -0
  220. package/build/server/errors/dispatch.test.d.ts +1 -0
  221. package/build/server/errors/dispatch.test.js +418 -0
  222. package/build/server/errors/dispatch.test.js.map +1 -0
  223. package/build/{implementations/http/error-taxonomy.d.ts → server/errors/taxonomy.d.ts} +8 -17
  224. package/build/{implementations/http/error-taxonomy.js → server/errors/taxonomy.js} +6 -15
  225. package/build/server/errors/taxonomy.js.map +1 -0
  226. package/build/server/errors/taxonomy.test.d.ts +1 -0
  227. package/build/{implementations/http/error-taxonomy.test.js → server/errors/taxonomy.test.js} +45 -39
  228. package/build/server/errors/taxonomy.test.js.map +1 -0
  229. package/build/server/index.d.ts +29 -0
  230. package/build/server/index.js +27 -0
  231. package/build/server/index.js.map +1 -0
  232. package/build/server/no-framework-imports.test.d.ts +1 -0
  233. package/build/server/no-framework-imports.test.js +40 -0
  234. package/build/server/no-framework-imports.test.js.map +1 -0
  235. package/build/{implementations/http/hono/path.d.ts → server/paths.d.ts} +2 -3
  236. package/build/{implementations/http/hono/path.js → server/paths.js} +1 -1
  237. package/build/server/paths.js.map +1 -0
  238. package/build/server/paths.test.d.ts +1 -0
  239. package/build/server/paths.test.js +111 -0
  240. package/build/server/paths.test.js.map +1 -0
  241. package/build/server/request/params.d.ts +29 -0
  242. package/build/server/request/params.js +43 -0
  243. package/build/server/request/params.js.map +1 -0
  244. package/build/server/request/params.test.d.ts +1 -0
  245. package/build/server/request/params.test.js +91 -0
  246. package/build/server/request/params.test.js.map +1 -0
  247. package/build/server/request/query.d.ts +9 -0
  248. package/build/server/request/query.js +22 -0
  249. package/build/server/request/query.js.map +1 -0
  250. package/build/server/request/query.test.d.ts +1 -0
  251. package/build/server/request/query.test.js +60 -0
  252. package/build/server/request/query.test.js.map +1 -0
  253. package/build/server/sse.d.ts +70 -0
  254. package/build/server/sse.js +94 -0
  255. package/build/server/sse.js.map +1 -0
  256. package/build/server/sse.test.d.ts +1 -0
  257. package/build/server/sse.test.js +98 -0
  258. package/build/server/sse.test.js.map +1 -0
  259. package/build/{implementations → server}/types.d.ts +17 -15
  260. package/build/{implementations → server}/types.js.map +1 -1
  261. package/docs/astro-adapter.md +8 -9
  262. package/docs/client-and-codegen.md +4 -4
  263. package/docs/client-error-handling.md +5 -5
  264. package/docs/codegen-kotlin.md +2 -3
  265. package/docs/codegen-swift.md +1 -2
  266. package/docs/core.md +135 -54
  267. package/docs/http-integrations.md +58 -6
  268. package/docs/migration-v8-to-v9.md +192 -0
  269. package/docs/plans/2026-06-09-v9-rewrite.md +130 -0
  270. package/docs/specs/2026-06-09-v9-rewrite-design.md +221 -0
  271. package/docs/streaming.md +12 -0
  272. package/package.json +23 -47
  273. package/src/{implementations/http → adapters}/astro/index.test.ts +2 -2
  274. package/src/adapters/hono/__fixtures__/parity-envelope.json +389 -0
  275. package/src/adapters/hono/envelope-parity.test.ts +126 -0
  276. package/src/{implementations/http → adapters}/hono/handlers/http-stream.test.ts +1 -1
  277. package/src/adapters/hono/handlers/http-stream.ts +73 -0
  278. package/src/{implementations/http → adapters}/hono/handlers/http.test.ts +1 -1
  279. package/src/adapters/hono/handlers/http.ts +70 -0
  280. package/src/{implementations/http → adapters}/hono/handlers/rpc.test.ts +2 -2
  281. package/src/adapters/hono/handlers/rpc.ts +39 -0
  282. package/src/{implementations/http → adapters}/hono/handlers/stream.test.ts +4 -3
  283. package/src/{implementations/http → adapters}/hono/handlers/stream.ts +19 -92
  284. package/src/{implementations/http → adapters}/hono/index.test.ts +14 -16
  285. package/src/{implementations/http → adapters}/hono/index.ts +35 -30
  286. package/src/{implementations/http → adapters/hono}/on-request-error.test.ts +3 -3
  287. package/src/adapters/hono/request.ts +28 -0
  288. package/src/{implementations/http → adapters/hono}/route-errors.test.ts +5 -5
  289. package/src/{implementations/http → adapters}/hono/types.ts +43 -20
  290. package/src/client/freeze.test.ts +41 -0
  291. package/src/client/typed-error-dispatch.test.ts +3 -3
  292. package/src/codegen/__fixtures__/make-envelope.ts +1 -1
  293. package/src/codegen/__fixtures__/models-envelope.json +310 -0
  294. package/src/codegen/__goldens__/MANIFEST.json +85 -0
  295. package/src/codegen/__goldens__/kotlin-default--models/Billing.kt +112 -0
  296. package/src/codegen/__goldens__/kotlin-default--models/BillingReports.kt +26 -0
  297. package/src/codegen/__goldens__/kotlin-default--models/Orders.kt +88 -0
  298. package/src/codegen/__goldens__/kotlin-default--users/Users.kt +189 -0
  299. package/src/codegen/__goldens__/swift-default--models/Billing.swift +97 -0
  300. package/src/codegen/__goldens__/swift-default--models/BillingReports.swift +20 -0
  301. package/src/codegen/__goldens__/swift-default--models/Orders.swift +81 -0
  302. package/src/codegen/__goldens__/swift-default--users/Users.swift +204 -0
  303. package/src/codegen/__goldens__/ts-default--models/_client.ts +1319 -0
  304. package/src/codegen/__goldens__/ts-default--models/_errors.ts +90 -0
  305. package/src/codegen/__goldens__/ts-default--models/_models.ts +10 -0
  306. package/src/codegen/__goldens__/ts-default--models/_types.ts +502 -0
  307. package/src/codegen/__goldens__/ts-default--models/billing-reports.ts +29 -0
  308. package/src/codegen/__goldens__/ts-default--models/billing.ts +67 -0
  309. package/src/codegen/__goldens__/ts-default--models/index.ts +48 -0
  310. package/src/codegen/__goldens__/ts-default--models/orders.ts +80 -0
  311. package/src/codegen/__goldens__/ts-default--users/_client.ts +1319 -0
  312. package/src/codegen/__goldens__/ts-default--users/_errors.ts +90 -0
  313. package/src/codegen/__goldens__/ts-default--users/_types.ts +502 -0
  314. package/src/codegen/__goldens__/ts-default--users/index.ts +38 -0
  315. package/src/codegen/__goldens__/ts-default--users/users.ts +169 -0
  316. package/src/codegen/__goldens__/ts-external-runtime--models/_errors.ts +90 -0
  317. package/src/codegen/__goldens__/ts-external-runtime--models/_models.ts +10 -0
  318. package/src/codegen/__goldens__/ts-external-runtime--models/billing-reports.ts +29 -0
  319. package/src/codegen/__goldens__/ts-external-runtime--models/billing.ts +67 -0
  320. package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +48 -0
  321. package/src/codegen/__goldens__/ts-external-runtime--models/orders.ts +80 -0
  322. package/src/codegen/__goldens__/ts-external-runtime--users/_errors.ts +90 -0
  323. package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +38 -0
  324. package/src/codegen/__goldens__/ts-external-runtime--users/users.ts +169 -0
  325. package/src/codegen/__goldens__/ts-flat--models/_client.ts +1319 -0
  326. package/src/codegen/__goldens__/ts-flat--models/_errors.ts +87 -0
  327. package/src/codegen/__goldens__/ts-flat--models/_models.ts +10 -0
  328. package/src/codegen/__goldens__/ts-flat--models/_types.ts +502 -0
  329. package/src/codegen/__goldens__/ts-flat--models/billing-reports.ts +28 -0
  330. package/src/codegen/__goldens__/ts-flat--models/billing.ts +51 -0
  331. package/src/codegen/__goldens__/ts-flat--models/index.ts +42 -0
  332. package/src/codegen/__goldens__/ts-flat--models/orders.ts +73 -0
  333. package/src/codegen/__goldens__/ts-flat--users/_client.ts +1319 -0
  334. package/src/codegen/__goldens__/ts-flat--users/_errors.ts +87 -0
  335. package/src/codegen/__goldens__/ts-flat--users/_types.ts +502 -0
  336. package/src/codegen/__goldens__/ts-flat--users/index.ts +34 -0
  337. package/src/codegen/__goldens__/ts-flat--users/users.ts +126 -0
  338. package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +1319 -0
  339. package/src/codegen/__goldens__/ts-no-share-models--models/_errors.ts +90 -0
  340. package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +502 -0
  341. package/src/codegen/__goldens__/ts-no-share-models--models/billing-reports.ts +29 -0
  342. package/src/codegen/__goldens__/ts-no-share-models--models/billing.ts +111 -0
  343. package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +48 -0
  344. package/src/codegen/__goldens__/ts-no-share-models--models/orders.ts +112 -0
  345. package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +1319 -0
  346. package/src/codegen/__goldens__/ts-no-share-models--users/_errors.ts +90 -0
  347. package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +502 -0
  348. package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +38 -0
  349. package/src/codegen/__goldens__/ts-no-share-models--users/users.ts +169 -0
  350. package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +1319 -0
  351. package/src/codegen/__goldens__/ts-shared-models-module--models/_errors.ts +90 -0
  352. package/src/codegen/__goldens__/ts-shared-models-module--models/_models.ts +7 -0
  353. package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +502 -0
  354. package/src/codegen/__goldens__/ts-shared-models-module--models/billing-reports.ts +29 -0
  355. package/src/codegen/__goldens__/ts-shared-models-module--models/billing.ts +67 -0
  356. package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +48 -0
  357. package/src/codegen/__goldens__/ts-shared-models-module--models/orders.ts +80 -0
  358. package/src/codegen/bin/cli.test.ts +13 -2
  359. package/src/codegen/bin/cli.ts +181 -144
  360. package/src/codegen/bin/flag-specs.test.ts +16 -1
  361. package/src/codegen/bin/flag-specs.ts +43 -31
  362. package/src/codegen/bundle-size.test.ts +1 -1
  363. package/src/codegen/collect-models.ts +1 -1
  364. package/src/codegen/e2e.test.ts +1 -1
  365. package/src/codegen/emit/api-route.ts +184 -0
  366. package/src/codegen/emit/context.ts +32 -0
  367. package/src/codegen/emit/declarations.ts +49 -0
  368. package/src/codegen/emit/format-types.ts +232 -0
  369. package/src/codegen/emit/http-stream-route.ts +162 -0
  370. package/src/codegen/emit/route-shared.ts +102 -0
  371. package/src/codegen/emit/rpc-route.ts +49 -0
  372. package/src/codegen/emit/scope-file.ts +226 -0
  373. package/src/codegen/emit/stream-route.ts +81 -0
  374. package/src/codegen/emit-errors.integration.test.ts +2 -2
  375. package/src/codegen/emit-errors.test.ts +1 -1
  376. package/src/codegen/emit-errors.ts +1 -1
  377. package/src/codegen/emit-scope.test.ts +2 -2
  378. package/src/codegen/emit-scope.ts +15 -1048
  379. package/src/codegen/goldens.test.ts +89 -0
  380. package/src/codegen/group-routes.test.ts +1 -1
  381. package/src/codegen/group-routes.ts +1 -1
  382. package/src/codegen/pipeline.test.ts +1 -1
  383. package/src/codegen/pipeline.ts +1 -1
  384. package/src/codegen/resolve-envelope.test.ts +1 -1
  385. package/src/codegen/resolve-envelope.ts +1 -1
  386. package/src/codegen/targets/_shared/error-schemas.test.ts +1 -1
  387. package/src/codegen/targets/_shared/error-schemas.ts +1 -1
  388. package/src/codegen/targets/_shared/route-slots.test.ts +1 -1
  389. package/src/codegen/targets/_shared/route-slots.ts +1 -1
  390. package/src/codegen/targets/_shared/target-run.ts +1 -1
  391. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +1 -1
  392. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +1 -1
  393. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +1 -1
  394. package/src/codegen/targets/swift/access-level.test.ts +1 -1
  395. package/src/codegen/targets/swift/emit-route-swift.test.ts +1 -1
  396. package/src/codegen/targets/swift/emit-route-swift.ts +1 -1
  397. package/src/codegen/targets/swift/emit-scope-swift.test.ts +1 -1
  398. package/src/codegen/targets/ts/shared-models.test.ts +1 -1
  399. package/src/{create-http-stream.test.ts → core/create-http-stream.test.ts} +1 -1
  400. package/src/core/create-http-stream.ts +207 -0
  401. package/src/{create-http.test.ts → core/create-http.test.ts} +15 -4
  402. package/src/core/create-http.ts +126 -0
  403. package/src/{create-stream.test.ts → core/create-stream.test.ts} +28 -31
  404. package/src/core/create-stream.ts +142 -0
  405. package/src/{create.test.ts → core/create.test.ts} +25 -57
  406. package/src/core/create.ts +121 -0
  407. package/src/{stack-utils.test.ts → core/definition-site.test.ts} +14 -3
  408. package/src/{stack-utils.ts → core/definition-site.ts} +20 -23
  409. package/src/{errors.test.ts → core/errors.test.ts} +1 -1
  410. package/src/{errors.ts → core/errors.ts} +30 -28
  411. package/src/core/factory-options.test.ts +112 -0
  412. package/src/core/http-route.ts +73 -0
  413. package/src/core/internal.ts +203 -0
  414. package/src/{migration.test.ts → core/migration.test.ts} +23 -1
  415. package/src/{index.test.ts → core/procedures.test.ts} +13 -11
  416. package/src/core/procedures.ts +75 -0
  417. package/src/core/types.ts +195 -0
  418. package/src/exports.ts +60 -11
  419. package/src/schema/adapter.test.ts +58 -0
  420. package/src/schema/adapter.ts +45 -0
  421. package/src/schema/compile.test.ts +95 -0
  422. package/src/schema/compile.ts +64 -0
  423. package/src/schema/compute-schema.test.ts +222 -41
  424. package/src/schema/compute-schema.ts +145 -71
  425. package/src/schema/json-schema.ts +21 -0
  426. package/src/schema/typebox.test.ts +40 -0
  427. package/src/schema/typebox.ts +27 -0
  428. package/src/server/context.test.ts +22 -0
  429. package/src/server/context.ts +18 -0
  430. package/src/{doc-envelope.test.ts → server/doc-envelope.test.ts} +2 -2
  431. package/src/{doc-envelope.ts → server/doc-envelope.ts} +1 -1
  432. package/src/{implementations/http → server}/doc-registry.test.ts +32 -26
  433. package/src/{implementations/http → server}/doc-registry.ts +11 -7
  434. package/src/server/docs/docs.test.ts +287 -0
  435. package/src/{implementations/http/hono → server}/docs/http-doc.ts +3 -3
  436. package/src/{implementations/http/hono → server}/docs/http-stream-doc.ts +3 -3
  437. package/src/{implementations/http/hono → server}/docs/rpc-doc.ts +3 -3
  438. package/src/{implementations/http/hono → server}/docs/stream-doc.ts +3 -3
  439. package/src/server/errors/dispatch.test.ts +450 -0
  440. package/src/server/errors/dispatch.ts +189 -0
  441. package/src/{implementations/http/error-taxonomy.test.ts → server/errors/taxonomy.test.ts} +45 -39
  442. package/src/{implementations/http/error-taxonomy.ts → server/errors/taxonomy.ts} +8 -17
  443. package/src/server/index.ts +29 -0
  444. package/src/server/no-framework-imports.test.ts +43 -0
  445. package/src/server/paths.test.ts +141 -0
  446. package/src/{implementations/http/hono/path.ts → server/paths.ts} +2 -13
  447. package/src/server/request/params.test.ts +143 -0
  448. package/src/server/request/params.ts +68 -0
  449. package/src/server/request/query.test.ts +70 -0
  450. package/src/server/request/query.ts +24 -0
  451. package/src/server/sse.test.ts +113 -0
  452. package/src/server/sse.ts +117 -0
  453. package/src/{implementations → server}/types.ts +17 -16
  454. package/build/create-http-stream.d.ts +0 -58
  455. package/build/create-http-stream.js +0 -122
  456. package/build/create-http-stream.js.map +0 -1
  457. package/build/create-http-stream.test.js.map +0 -1
  458. package/build/create-http.d.ts +0 -49
  459. package/build/create-http.js +0 -108
  460. package/build/create-http.js.map +0 -1
  461. package/build/create-http.test.js.map +0 -1
  462. package/build/create-stream.d.ts +0 -35
  463. package/build/create-stream.js +0 -123
  464. package/build/create-stream.js.map +0 -1
  465. package/build/create-stream.test.js.map +0 -1
  466. package/build/create.d.ts +0 -28
  467. package/build/create.js +0 -82
  468. package/build/create.js.map +0 -1
  469. package/build/create.test.js.map +0 -1
  470. package/build/doc-envelope.js.map +0 -1
  471. package/build/doc-envelope.test.js.map +0 -1
  472. package/build/errors.js.map +0 -1
  473. package/build/errors.test.js.map +0 -1
  474. package/build/implementations/http/astro/astro-context.js.map +0 -1
  475. package/build/implementations/http/astro/create-handler.js.map +0 -1
  476. package/build/implementations/http/astro/index.js.map +0 -1
  477. package/build/implementations/http/astro/index.test.js.map +0 -1
  478. package/build/implementations/http/astro/rewrite-request.js.map +0 -1
  479. package/build/implementations/http/doc-registry.js.map +0 -1
  480. package/build/implementations/http/doc-registry.test.js.map +0 -1
  481. package/build/implementations/http/error-dispatch.d.ts +0 -76
  482. package/build/implementations/http/error-dispatch.js.map +0 -1
  483. package/build/implementations/http/error-dispatch.test.js +0 -254
  484. package/build/implementations/http/error-dispatch.test.js.map +0 -1
  485. package/build/implementations/http/error-taxonomy.js.map +0 -1
  486. package/build/implementations/http/error-taxonomy.test.js.map +0 -1
  487. package/build/implementations/http/hono/docs/http-doc.js.map +0 -1
  488. package/build/implementations/http/hono/docs/http-stream-doc.js.map +0 -1
  489. package/build/implementations/http/hono/docs/rpc-doc.js.map +0 -1
  490. package/build/implementations/http/hono/docs/stream-doc.js.map +0 -1
  491. package/build/implementations/http/hono/handlers/http-stream.js +0 -123
  492. package/build/implementations/http/hono/handlers/http-stream.js.map +0 -1
  493. package/build/implementations/http/hono/handlers/http-stream.test.js.map +0 -1
  494. package/build/implementations/http/hono/handlers/http.js +0 -110
  495. package/build/implementations/http/hono/handlers/http.js.map +0 -1
  496. package/build/implementations/http/hono/handlers/http.test.js.map +0 -1
  497. package/build/implementations/http/hono/handlers/rpc.js +0 -32
  498. package/build/implementations/http/hono/handlers/rpc.js.map +0 -1
  499. package/build/implementations/http/hono/handlers/rpc.test.js.map +0 -1
  500. package/build/implementations/http/hono/handlers/stream.d.ts +0 -23
  501. package/build/implementations/http/hono/handlers/stream.js +0 -147
  502. package/build/implementations/http/hono/handlers/stream.js.map +0 -1
  503. package/build/implementations/http/hono/handlers/stream.test.js.map +0 -1
  504. package/build/implementations/http/hono/index.js.map +0 -1
  505. package/build/implementations/http/hono/index.test.js.map +0 -1
  506. package/build/implementations/http/hono/path.js.map +0 -1
  507. package/build/implementations/http/hono/path.test.js +0 -83
  508. package/build/implementations/http/hono/path.test.js.map +0 -1
  509. package/build/implementations/http/hono/types.d.ts +0 -51
  510. package/build/implementations/http/hono/types.js.map +0 -1
  511. package/build/implementations/http/on-request-error.test.js.map +0 -1
  512. package/build/implementations/http/route-errors.test.js.map +0 -1
  513. package/build/index.d.ts +0 -175
  514. package/build/index.js +0 -47
  515. package/build/index.js.map +0 -1
  516. package/build/index.test.js.map +0 -1
  517. package/build/migration.test.js.map +0 -1
  518. package/build/schema/extract-json-schema.d.ts +0 -2
  519. package/build/schema/extract-json-schema.js +0 -12
  520. package/build/schema/extract-json-schema.js.map +0 -1
  521. package/build/schema/extract-json-schema.test.js +0 -23
  522. package/build/schema/extract-json-schema.test.js.map +0 -1
  523. package/build/schema/parser.d.ts +0 -36
  524. package/build/schema/parser.js +0 -210
  525. package/build/schema/parser.js.map +0 -1
  526. package/build/schema/parser.test.js +0 -120
  527. package/build/schema/parser.test.js.map +0 -1
  528. package/build/schema/resolve-schema-lib.d.ts +0 -12
  529. package/build/schema/resolve-schema-lib.js +0 -11
  530. package/build/schema/resolve-schema-lib.js.map +0 -1
  531. package/build/schema/resolve-schema-lib.test.js +0 -17
  532. package/build/schema/resolve-schema-lib.test.js.map +0 -1
  533. package/build/schema/types.d.ts +0 -8
  534. package/build/schema/types.js +0 -2
  535. package/build/stack-utils.d.ts +0 -25
  536. package/build/stack-utils.js.map +0 -1
  537. package/build/stack-utils.test.js.map +0 -1
  538. package/build/types.d.ts +0 -142
  539. package/build/types.js +0 -2
  540. package/build/types.js.map +0 -1
  541. package/docs/decisions/2026-06-02-monorepo-split-evaluation.md +0 -80
  542. package/docs/handoffs/2026-06-08-dx-round2-declines.md +0 -45
  543. package/docs/handoffs/ajsc-named-type-collision.md +0 -134
  544. package/docs/handoffs/ajsc-named-type-support.md +0 -181
  545. package/docs/handoffs/shared-models-auto-resolve-response.md +0 -181
  546. package/docs/npm-workspaces-migration-plan.md +0 -611
  547. package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +0 -886
  548. package/docs/superpowers/plans/2026-04-24-kotlin-codegen-target.md +0 -1265
  549. package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +0 -1993
  550. package/docs/superpowers/plans/2026-04-29-safe-result-api.md +0 -2293
  551. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +0 -1391
  552. package/docs/superpowers/plans/2026-05-08-create-http.md +0 -3355
  553. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +0 -3365
  554. package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +0 -1292
  555. package/docs/superpowers/plans/2026-06-06-shared-models-convention-and-diagnostics.md +0 -659
  556. package/docs/superpowers/plans/2026-06-08-codegen-dx-surfacing.md +0 -428
  557. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +0 -401
  558. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +0 -314
  559. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +0 -264
  560. package/docs/superpowers/specs/2026-04-29-safe-result-api-design.md +0 -324
  561. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +0 -252
  562. package/docs/superpowers/specs/2026-05-08-create-http-design.md +0 -409
  563. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +0 -411
  564. package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +0 -285
  565. package/docs/superpowers/specs/2026-06-08-dx-feedback-round-2-design.md +0 -376
  566. package/src/create-http-stream.ts +0 -191
  567. package/src/create-http.ts +0 -210
  568. package/src/create-stream.ts +0 -228
  569. package/src/create.ts +0 -172
  570. package/src/implementations/http/README.md +0 -390
  571. package/src/implementations/http/error-dispatch.test.ts +0 -283
  572. package/src/implementations/http/error-dispatch.ts +0 -176
  573. package/src/implementations/http/hono/handlers/http-stream.ts +0 -152
  574. package/src/implementations/http/hono/handlers/http.ts +0 -145
  575. package/src/implementations/http/hono/handlers/rpc.ts +0 -54
  576. package/src/implementations/http/hono/path.test.ts +0 -96
  577. package/src/index.ts +0 -101
  578. package/src/schema/extract-json-schema.test.ts +0 -25
  579. package/src/schema/extract-json-schema.ts +0 -15
  580. package/src/schema/parser.test.ts +0 -182
  581. package/src/schema/parser.ts +0 -265
  582. package/src/schema/resolve-schema-lib.test.ts +0 -19
  583. package/src/schema/resolve-schema-lib.ts +0 -29
  584. package/src/schema/types.ts +0 -20
  585. package/src/types.ts +0 -133
  586. /package/build/{implementations/http → adapters}/astro/astro-context.d.ts +0 -0
  587. /package/build/{implementations/http → adapters}/astro/astro-context.js +0 -0
  588. /package/build/{implementations/http → adapters}/astro/create-handler.d.ts +0 -0
  589. /package/build/{implementations/http → adapters}/astro/create-handler.js +0 -0
  590. /package/build/{implementations/http → adapters}/astro/index.d.ts +0 -0
  591. /package/build/{implementations/http → adapters}/astro/index.js +0 -0
  592. /package/build/{implementations/http → adapters}/astro/index.test.d.ts +0 -0
  593. /package/build/{implementations/http → adapters}/astro/rewrite-request.d.ts +0 -0
  594. /package/build/{implementations/http → adapters}/astro/rewrite-request.js +0 -0
  595. /package/build/{create-http-stream.test.d.ts → adapters/hono/envelope-parity.test.d.ts} +0 -0
  596. /package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.d.ts +0 -0
  597. /package/build/{implementations/http → adapters}/hono/handlers/http.test.d.ts +0 -0
  598. /package/build/{implementations/http → adapters}/hono/handlers/rpc.test.d.ts +0 -0
  599. /package/build/{implementations/http → adapters}/hono/handlers/stream.test.d.ts +0 -0
  600. /package/build/{implementations/http → adapters}/hono/index.test.d.ts +0 -0
  601. /package/build/{implementations/http → adapters/hono}/on-request-error.test.d.ts +0 -0
  602. /package/build/{implementations/http → adapters/hono}/route-errors.test.d.ts +0 -0
  603. /package/build/{create-http.test.d.ts → client/freeze.test.d.ts} +0 -0
  604. /package/build/{create-stream.test.d.ts → codegen/goldens.test.d.ts} +0 -0
  605. /package/build/{create.test.d.ts → core/create-http-stream.test.d.ts} +0 -0
  606. /package/build/{doc-envelope.test.d.ts → core/create-http.test.d.ts} +0 -0
  607. /package/build/{errors.test.d.ts → core/create-stream.test.d.ts} +0 -0
  608. /package/build/{implementations/http/doc-registry.test.d.ts → core/create.test.d.ts} +0 -0
  609. /package/build/{implementations/http/error-dispatch.test.d.ts → core/definition-site.test.d.ts} +0 -0
  610. /package/build/{implementations/http/error-taxonomy.test.d.ts → core/errors.test.d.ts} +0 -0
  611. /package/build/{errors.test.js → core/errors.test.js} +0 -0
  612. /package/build/{implementations/http/hono/path.test.d.ts → core/factory-options.test.d.ts} +0 -0
  613. /package/build/{migration.test.d.ts → core/migration.test.d.ts} +0 -0
  614. /package/build/{index.test.d.ts → core/procedures.test.d.ts} +0 -0
  615. /package/build/{implementations/http/hono → core}/types.js +0 -0
  616. /package/build/schema/{extract-json-schema.test.d.ts → adapter.test.d.ts} +0 -0
  617. /package/build/schema/{parser.test.d.ts → compile.test.d.ts} +0 -0
  618. /package/build/schema/{resolve-schema-lib.test.d.ts → typebox.test.d.ts} +0 -0
  619. /package/build/{stack-utils.test.d.ts → server/context.test.d.ts} +0 -0
  620. /package/build/{doc-envelope.js → server/doc-envelope.js} +0 -0
  621. /package/build/{doc-envelope.test.js → server/doc-envelope.test.js} +0 -0
  622. /package/build/{implementations → server}/types.js +0 -0
  623. /package/src/{implementations/http → adapters}/astro/README.md +0 -0
  624. /package/src/{implementations/http → adapters}/astro/astro-context.ts +0 -0
  625. /package/src/{implementations/http → adapters}/astro/create-handler.ts +0 -0
  626. /package/src/{implementations/http → adapters}/astro/index.ts +0 -0
  627. /package/src/{implementations/http → adapters}/astro/rewrite-request.ts +0 -0
@@ -1,16 +1,28 @@
1
- import { describe, it, expect } from 'vitest'
1
+ import { describe, expect, it } from 'vitest'
2
2
  import { Type } from 'typebox'
3
- import { v } from 'suretype'
4
3
  import { computeSchema } from './compute-schema.js'
5
- import { ProcedureRegistrationError } from '../errors.js'
4
+ import { createValidatorCompiler } from './compile.js'
5
+ import { typeboxAdapter } from './typebox.js'
6
+ import { ProcedureRegistrationError } from '../core/errors.js'
7
+
8
+ const options = {
9
+ adapters: [typeboxAdapter],
10
+ compile: createValidatorCompiler(),
11
+ }
6
12
 
7
13
  describe('computeSchema', () => {
8
14
  it('should return empty schema and validations when no schema provided', () => {
9
- const result = computeSchema('test-procedure')
15
+ const result = computeSchema('test-procedure', undefined, options)
10
16
 
11
17
  expect(result).toEqual({
12
- jsonSchema: { params: undefined, returnType: undefined },
13
- validations: {}
18
+ jsonSchema: {
19
+ params: undefined,
20
+ returnType: undefined,
21
+ yieldType: undefined,
22
+ req: undefined,
23
+ res: undefined,
24
+ },
25
+ validations: {},
14
26
  })
15
27
  })
16
28
 
@@ -19,11 +31,11 @@ describe('computeSchema', () => {
19
31
  const schema = {
20
32
  params: Type.Object({
21
33
  name: Type.String(),
22
- age: Type.Number()
23
- })
34
+ age: Type.Number(),
35
+ }),
24
36
  }
25
37
 
26
- const result = computeSchema('test-procedure', schema)
38
+ const result = computeSchema('test-procedure', schema, options)
27
39
 
28
40
  expect(result.jsonSchema.params).toBeDefined()
29
41
  expect(result.validations.params).toBeDefined()
@@ -33,45 +45,154 @@ describe('computeSchema', () => {
33
45
  expect(result.validations.params?.(validInput).errors).toBeUndefined()
34
46
 
35
47
  // Test invalid input
36
- const invalidInput = { name: 123, age: 'invalid' }
48
+ const invalidInput = { name: { nested: true }, age: 'invalid' }
37
49
  expect(result.validations.params?.(invalidInput).errors).toBeDefined()
50
+ // allErrors: both failing fields reported
51
+ expect(result.validations.params?.(invalidInput).errors?.length).toEqual(2)
52
+ })
53
+
54
+ it('extracts params json-schema equal to the TypeBox schema (identity)', () => {
55
+ const params = Type.Object({ name: Type.String(), age: Type.Number() })
56
+ const result = computeSchema('test-procedure', { params }, options)
57
+
58
+ expect(result.jsonSchema.params).toEqual(params)
38
59
  })
39
60
 
40
- it('should correctly process returnType schema', () => {
61
+ it('should correctly process returnType schema (documentation only, never validated)', () => {
41
62
  const schema = {
42
63
  returnType: Type.Object({
43
- result: Type.Boolean()
44
- })
64
+ result: Type.Boolean(),
65
+ }),
45
66
  }
46
67
 
47
- const result = computeSchema('test-procedure', schema)
68
+ const result = computeSchema('test-procedure', schema, options)
48
69
 
49
70
  expect(result.jsonSchema.returnType).toBeDefined()
50
71
  expect(result.validations.params).toBeUndefined()
72
+ expect(result.validations).toEqual({})
73
+ })
74
+
75
+ it('should compile a validator for yieldType', () => {
76
+ const schema = {
77
+ yieldType: Type.Object({ chunk: Type.String() }),
78
+ }
79
+
80
+ const result = computeSchema('test-procedure', schema, options)
81
+
82
+ expect(result.jsonSchema.yieldType).toBeDefined()
83
+ expect(result.validations.yield).toBeDefined()
84
+ expect(result.validations.yield?.({ chunk: 'hello' }).errors).toBeUndefined()
85
+ expect(result.validations.yield?.({}).errors).toBeDefined()
51
86
  })
52
87
  })
53
88
 
54
- describe('with Suretype schema', () => {
55
- it('should correctly process params schema', () => {
89
+ describe('req channels (HTTP input)', () => {
90
+ it('extracts and validates each req channel independently', () => {
56
91
  const schema = {
57
- params: v.object({
58
- name: v.string(),
59
- age: v.number()
60
- })
92
+ req: {
93
+ pathParams: Type.Object({ id: Type.String() }),
94
+ query: Type.Object({ limit: Type.Number() }),
95
+ body: Type.Object({ name: Type.String() }),
96
+ headers: Type.Object({ 'x-api-key': Type.String() }),
97
+ },
61
98
  }
62
99
 
63
- const result = computeSchema('test-procedure', schema)
100
+ const result = computeSchema('test-procedure', schema, options)
64
101
 
65
- expect(result.jsonSchema.params).toBeDefined()
66
- expect(result.validations.params).toBeDefined()
102
+ for (const channel of ['pathParams', 'query', 'body', 'headers']) {
103
+ expect(result.jsonSchema.req?.[channel]).toBeDefined()
104
+ expect(result.validations.req?.[channel]).toBeDefined()
105
+ }
67
106
 
68
- // Test validation function
69
- const validInput = { name: 'John', age: 30 }
70
- expect(result.validations.params?.(validInput).errors).toBeUndefined()
107
+ expect(result.validations.req!.pathParams!({ id: 'abc' }).errors).toBeUndefined()
108
+ expect(result.validations.req!.pathParams!({}).errors).toBeDefined()
71
109
 
72
- // Test invalid input
73
- const invalidInput = { name: 123, age: 'invalid' }
74
- expect(result.validations.params?.(invalidInput).errors).toBeDefined()
110
+ // coerceTypes applies per channel (query strings become numbers)
111
+ expect(result.validations.req!.query!({ limit: '10' }).errors).toBeUndefined()
112
+ expect(result.validations.req!.body!({ name: 42 }).errors).toBeUndefined() // coerced to '42'
113
+ expect(result.validations.req!.body!({}).errors).toBeDefined()
114
+ })
115
+
116
+ it('skips undefined req channel values', () => {
117
+ const schema = {
118
+ req: {
119
+ body: Type.Object({ name: Type.String() }),
120
+ query: undefined,
121
+ },
122
+ }
123
+
124
+ const result = computeSchema('test-procedure', schema, options)
125
+
126
+ expect(result.jsonSchema.req?.body).toBeDefined()
127
+ expect(result.jsonSchema.req && 'query' in result.jsonSchema.req).toBe(false)
128
+ expect(result.validations.req?.query).toBeUndefined()
129
+ })
130
+ })
131
+
132
+ describe('res channels (HTTP output, documentation only)', () => {
133
+ it('extracts res.body and res.headers without compiling validators', () => {
134
+ const schema = {
135
+ res: {
136
+ body: Type.Object({ id: Type.String() }),
137
+ headers: Type.Object({ 'x-rate-limit': Type.String() }),
138
+ },
139
+ }
140
+
141
+ const result = computeSchema('test-procedure', schema, options)
142
+
143
+ expect(result.jsonSchema.res?.body).toBeDefined()
144
+ expect(result.jsonSchema.res?.headers).toBeDefined()
145
+ expect(result.validations).toEqual({})
146
+ })
147
+
148
+ it('extracts only the res channels provided', () => {
149
+ const result = computeSchema(
150
+ 'test-procedure',
151
+ { res: { body: Type.Object({ ok: Type.Boolean() }) } },
152
+ options,
153
+ )
154
+
155
+ expect(result.jsonSchema.res?.body).toBeDefined()
156
+ expect(result.jsonSchema.res?.headers).toBeUndefined()
157
+ })
158
+ })
159
+
160
+ describe('guards', () => {
161
+ it('throws ProcedureRegistrationError when schema.params and schema.req are both defined', () => {
162
+ const schema = {
163
+ params: Type.Object({ a: Type.String() }),
164
+ req: { body: Type.Object({ b: Type.String() }) },
165
+ }
166
+
167
+ expect(() => computeSchema('test-procedure', schema, options)).toThrow(
168
+ ProcedureRegistrationError,
169
+ )
170
+ expect(() => computeSchema('test-procedure', schema, options)).toThrow(
171
+ /schema\.params and schema\.req are mutually exclusive for procedure "test-procedure"/,
172
+ )
173
+ })
174
+
175
+ it('throws a migration error when the removed schema.input is used', () => {
176
+ const schema = {
177
+ input: { body: Type.Object({ b: Type.String() }) },
178
+ } as Parameters<typeof computeSchema>[1]
179
+
180
+ expect(() => computeSchema('test-procedure', schema, options)).toThrow(
181
+ ProcedureRegistrationError,
182
+ )
183
+ expect(() => computeSchema('test-procedure', schema, options)).toThrow(
184
+ /schema\.input was removed in v8\. Use CreateHttp \/ CreateHttpStream/,
185
+ )
186
+ })
187
+
188
+ it('does not trip the schema.input guard when input is explicitly undefined', () => {
189
+ const schema = {
190
+ input: undefined,
191
+ params: Type.Object({ a: Type.String() }),
192
+ }
193
+
194
+ const result = computeSchema('test-procedure', schema, options)
195
+ expect(result.jsonSchema.params).toBeDefined()
75
196
  })
76
197
  })
77
198
 
@@ -79,42 +200,73 @@ describe('computeSchema', () => {
79
200
  it('should throw ProcedureRegistrationError for invalid schema', () => {
80
201
  const invalidSchema = {
81
202
  params: {
82
- type: 'invalid-schema-type'
83
- }
203
+ type: 'invalid-schema-type',
204
+ },
84
205
  }
85
206
 
86
- expect(() => computeSchema('test-procedure', invalidSchema))
87
- .toThrow(ProcedureRegistrationError)
207
+ expect(() => computeSchema('test-procedure', invalidSchema, options)).toThrow(
208
+ ProcedureRegistrationError,
209
+ )
88
210
  })
89
211
 
90
- it('should include procedure name in error message', () => {
212
+ it('should include procedure name and channel in the error message', () => {
91
213
  const invalidSchema = {
92
214
  params: {
93
- type: 'invalid-schema-type'
94
- }
215
+ type: 'invalid-schema-type',
216
+ },
95
217
  }
96
218
 
97
219
  try {
98
- computeSchema('test-procedure', invalidSchema)
220
+ computeSchema('test-procedure', invalidSchema, options)
221
+ expect.unreachable('computeSchema should have thrown')
99
222
  } catch (error: any) {
100
223
  expect(error instanceof ProcedureRegistrationError).toBe(true)
101
224
  expect(error.message).toContain('test-procedure')
225
+ expect(error.message).toMatch(/Error parsing schema for test-procedure - schema\.params/)
226
+ expect(error.message).toMatch(/Error extracting json schema schema\.params/)
227
+ // The error names the registered adapters so the dev knows what was tried
228
+ expect(error.message).toContain('typebox')
102
229
  }
103
230
  })
231
+
232
+ it('throws a meaningful error for an unrecognized returnType', () => {
233
+ expect(() =>
234
+ computeSchema('test-procedure', { returnType: 'string value' as any }, options),
235
+ ).toThrow(/Error extracting json schema schema\.returnType/)
236
+ })
237
+
238
+ it('throws a meaningful error naming the failing req channel', () => {
239
+ expect(() =>
240
+ computeSchema(
241
+ 'test-procedure',
242
+ { req: { query: { not: 'a schema' } } },
243
+ options,
244
+ ),
245
+ ).toThrow(/Error extracting json schema schema\.req\.query/)
246
+ })
247
+
248
+ it('throws a compile error when the schema is recognized but invalid JSON Schema', () => {
249
+ // Looks like a TypeBox schema (has ~kind) but AJV rejects it at compile time
250
+ const recognizedButInvalid = { '~kind': 'Object', type: 'not-a-real-type' }
251
+
252
+ expect(() =>
253
+ computeSchema('test-procedure', { params: recognizedButInvalid }, options),
254
+ ).toThrow(/Error compiling schema\.params for validator/)
255
+ })
104
256
  })
105
257
 
106
258
  describe('combined schemas', () => {
107
259
  it('should handle both params and returnType schemas', () => {
108
260
  const schema = {
109
261
  params: Type.Object({
110
- input: Type.String()
262
+ input: Type.String(),
111
263
  }),
112
264
  returnType: Type.Object({
113
- output: Type.Boolean()
114
- })
265
+ output: Type.Boolean(),
266
+ }),
115
267
  }
116
268
 
117
- const result = computeSchema('test-procedure', schema)
269
+ const result = computeSchema('test-procedure', schema, options)
118
270
 
119
271
  expect(result.jsonSchema.params).toBeDefined()
120
272
  expect(result.jsonSchema.returnType).toBeDefined()
@@ -124,5 +276,34 @@ describe('computeSchema', () => {
124
276
  const validInput = { input: 'test' }
125
277
  expect(result.validations.params?.(validInput).errors).toBeUndefined()
126
278
  })
279
+
280
+ it('compiles independent validators for separate computeSchema calls', () => {
281
+ const first = computeSchema(
282
+ 'first',
283
+ {
284
+ params: Type.Object({ a: Type.String() }),
285
+ returnType: Type.Object({ b: Type.Null() }),
286
+ },
287
+ options,
288
+ )
289
+
290
+ const second = computeSchema(
291
+ 'second',
292
+ {
293
+ params: Type.Object({ c: Type.String() }),
294
+ returnType: Type.Object({ d: Type.Number() }),
295
+ },
296
+ options,
297
+ )
298
+
299
+ expect(first.validations.params?.({}).errors?.[0]?.message).toMatch(
300
+ /must have required property 'a'/,
301
+ )
302
+ expect(second.validations.params?.({ c: 'test' })).toMatchObject({})
303
+ // first's validator is unaffected by second's compilation
304
+ expect(first.validations.params?.({}).errors?.[0]?.message).toMatch(
305
+ /must have required property 'a'/,
306
+ )
307
+ })
127
308
  })
128
309
  })
@@ -1,103 +1,177 @@
1
- import type { TSchemaValidationError } from './parser.js';
2
- import { schemaParser } from './parser.js'
3
- import { ProcedureRegistrationError } from '../errors.js'
4
- import type { TJSONSchema } from './types.js'
5
- import type { DefinitionInfo } from '../stack-utils.js'
1
+ import { ProcedureRegistrationError } from '../core/errors.js'
2
+ import type { DefinitionInfo } from '../core/definition-site.js'
3
+ import { extractJsonSchema } from './adapter.js'
4
+ import type { SchemaAdapter } from './adapter.js'
5
+ import type { TJSONSchema } from './json-schema.js'
6
+ import type { TSchemaValidationError, Validate, ValidatorCompiler } from './compile.js'
7
+
8
+ export type ComputedJsonSchema = {
9
+ params?: TJSONSchema
10
+ returnType?: TJSONSchema
11
+ yieldType?: TJSONSchema
12
+ req?: Record<string, TJSONSchema>
13
+ res?: { body?: TJSONSchema; headers?: TJSONSchema }
14
+ }
15
+
16
+ export type ComputedValidations = {
17
+ params?: Validate
18
+ yield?: Validate
19
+ req?: Record<string, Validate>
20
+ }
21
+
22
+ export type ComputedSchema = {
23
+ jsonSchema: ComputedJsonSchema
24
+ validations: ComputedValidations
25
+ }
26
+
27
+ export type ComputeSchemaInput = {
28
+ params?: unknown
29
+ returnType?: unknown
30
+ yieldType?: unknown
31
+ req?: Record<string, unknown>
32
+ res?: { body?: unknown; headers?: unknown }
33
+ }
34
+
35
+ type ComputeContext = {
36
+ name: string
37
+ adapters: readonly SchemaAdapter[]
38
+ compile: ValidatorCompiler
39
+ definitionInfo?: DefinitionInfo
40
+ }
41
+
42
+ function fail(ctx: ComputeContext, channel: string, detail: string): never {
43
+ throw new ProcedureRegistrationError(
44
+ ctx.name,
45
+ `Error parsing schema for ${ctx.name} - ${channel}: ${detail}`,
46
+ ctx.definitionInfo,
47
+ )
48
+ }
6
49
 
7
50
  /**
8
- * This function is used to compute the JSON schema and validation functions
9
- * for a given schema.
51
+ * Extracts JSON Schema for one channel via the adapter chain. Throws a
52
+ * `ProcedureRegistrationError` naming the channel when no adapter recognizes
53
+ * the value or the adapter itself throws.
54
+ */
55
+ function extractChannel(ctx: ComputeContext, channel: string, raw: unknown): TJSONSchema {
56
+ let extracted: TJSONSchema | undefined
57
+ try {
58
+ extracted = extractJsonSchema(raw, ctx.adapters)
59
+ } catch (e: any) {
60
+ fail(ctx, channel, `Error extracting json schema ${channel} - ${e.message}`)
61
+ }
62
+ if (!extracted) {
63
+ const known = ctx.adapters.map((a) => a.name).join(', ')
64
+ fail(
65
+ ctx,
66
+ channel,
67
+ `Error extracting json schema ${channel} - it might be empty or not recognized by any schema adapter (registered: ${known})`,
68
+ )
69
+ }
70
+ return extracted
71
+ }
72
+
73
+ /** Extracts and compiles one validated channel. */
74
+ function compileChannel(ctx: ComputeContext, channel: string, raw: unknown): { jsonSchema: TJSONSchema; validate: Validate } {
75
+ const jsonSchema = extractChannel(ctx, channel, raw)
76
+ try {
77
+ return { jsonSchema, validate: ctx.compile(jsonSchema) }
78
+ } catch (e: any) {
79
+ fail(ctx, channel, `Error compiling ${channel} for validator - ${e.message}`)
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Computes JSON Schema and validators for a procedure's schema config.
85
+ *
86
+ * Channels:
87
+ * - `params` (RPC input) — validated
88
+ * - `yieldType` (stream output) — validated only when `validateYields: true`
89
+ * - `returnType` — documentation/codegen only, never validated
90
+ * - `req.{pathParams,query,body,headers}` (HTTP input) — each independently validated
91
+ * - `res.{body,headers}` (HTTP output) — documentation/codegen only
10
92
  *
11
- * @param name The name of the procedure
12
- * @param schema Procedure schema
13
- * @param definitionInfo Optional definition info for error reporting
93
+ * Guards:
94
+ * - `schema.params` and `schema.req` are mutually exclusive (RPC vs HTTP)
95
+ * - `schema.input` (removed in v8) gets a migration error
14
96
  */
15
- export function computeSchema<TParamsSchemaType, TReturnTypeSchemaType, TYieldTypeSchemaType = unknown>(
97
+ export function computeSchema(
16
98
  name: string,
17
- schema?: {
18
- params?: TParamsSchemaType
19
- returnType?: TReturnTypeSchemaType
20
- yieldType?: TYieldTypeSchemaType
21
- req?: Record<string, unknown>
22
- res?: { body?: unknown; headers?: unknown }
99
+ schema: ComputeSchemaInput | undefined,
100
+ options: {
101
+ adapters: readonly SchemaAdapter[]
102
+ compile: ValidatorCompiler
103
+ definitionInfo?: DefinitionInfo
23
104
  },
24
- // Used for error stack trace details
25
- definitionInfo?: DefinitionInfo
26
- ): {
27
- jsonSchema: {
28
- params?: TJSONSchema
29
- returnType?: TJSONSchema
30
- yieldType?: TJSONSchema
31
- req?: Record<string, TJSONSchema>
32
- res?: { body?: TJSONSchema; headers?: TJSONSchema }
33
- }
34
- validations: {
35
- params?: (params?: any) => { errors?: TSchemaValidationError[] }
36
- yield?: (value?: any) => { errors?: TSchemaValidationError[] }
37
- req?: Record<string, (value?: any) => { errors?: TSchemaValidationError[] }>
38
- }
39
- } {
40
- const jsonSchema: {
41
- params?: TJSONSchema
42
- returnType?: TJSONSchema
43
- yieldType?: TJSONSchema
44
- req?: Record<string, TJSONSchema>
45
- res?: { body?: TJSONSchema; headers?: TJSONSchema }
46
- } = {
105
+ ): ComputedSchema {
106
+ const jsonSchema: ComputedJsonSchema = {
47
107
  params: undefined,
48
108
  returnType: undefined,
49
109
  yieldType: undefined,
50
110
  req: undefined,
51
111
  res: undefined,
52
112
  }
113
+ const validations: ComputedValidations = {}
114
+
115
+ if (!schema) return { jsonSchema, validations }
53
116
 
54
- const validations: {
55
- params?: (params?: any) => { errors?: TSchemaValidationError[] }
56
- yield?: (value?: any) => { errors?: TSchemaValidationError[] }
57
- req?: Record<string, (value?: any) => { errors?: TSchemaValidationError[] }>
58
- } = {}
117
+ const ctx: ComputeContext = { name, ...options }
59
118
 
60
119
  // Migration guard: schema.input was removed in v8
61
- if (schema && 'input' in schema && (schema as any).input !== undefined) {
120
+ if ('input' in schema && (schema as { input?: unknown }).input !== undefined) {
62
121
  throw new ProcedureRegistrationError(
63
122
  name,
64
123
  `schema.input was removed in v8. Use CreateHttp / CreateHttpStream for per-channel HTTP validation. Procedure: "${name}".`,
65
- definitionInfo,
124
+ options.definitionInfo,
66
125
  )
67
126
  }
68
127
 
69
128
  // Mutual exclusivity: params and req cannot both be defined
70
- if (schema?.params && schema?.req) {
129
+ if (schema.params && schema.req) {
71
130
  throw new ProcedureRegistrationError(
72
131
  name,
73
132
  `schema.params and schema.req are mutually exclusive for procedure "${name}". Use schema.params for RPC procedures or schema.req for HTTP procedures.`,
74
- definitionInfo
133
+ options.definitionInfo,
75
134
  )
76
135
  }
77
136
 
78
- if (schema) {
79
- const {
80
- jsonSchema: { params, returnType, yieldType, req, res },
81
- validation,
82
- } = schemaParser(schema, (errors) => {
83
- throw new ProcedureRegistrationError(
84
- name,
85
- `Error parsing schema for ${name} - ${Object.entries(errors)
86
- .map(([key, error]) => `${key}: ${error}`)
87
- .join(', ')}`,
88
- definitionInfo
89
- )
90
- })
91
-
92
- jsonSchema.params = params
93
- jsonSchema.returnType = returnType
94
- jsonSchema.yieldType = yieldType
95
- jsonSchema.req = req
96
- jsonSchema.res = res
97
- validations.params = validation.params
98
- validations.yield = validation.yield
99
- validations.req = validation.req
137
+ if (schema.params) {
138
+ const { jsonSchema: extracted, validate } = compileChannel(ctx, 'schema.params', schema.params)
139
+ jsonSchema.params = extracted
140
+ validations.params = validate
141
+ }
142
+
143
+ if (schema.returnType) {
144
+ jsonSchema.returnType = extractChannel(ctx, 'schema.returnType', schema.returnType)
145
+ }
146
+
147
+ if (schema.yieldType) {
148
+ const { jsonSchema: extracted, validate } = compileChannel(ctx, 'schema.yieldType', schema.yieldType)
149
+ jsonSchema.yieldType = extracted
150
+ validations.yield = validate
151
+ }
152
+
153
+ if (schema.req) {
154
+ jsonSchema.req = {}
155
+ validations.req = {}
156
+ for (const [channelName, channelSchema] of Object.entries(schema.req)) {
157
+ if (!channelSchema) continue
158
+ const { jsonSchema: extracted, validate } = compileChannel(ctx, `schema.req.${channelName}`, channelSchema)
159
+ jsonSchema.req[channelName] = extracted
160
+ validations.req[channelName] = validate
161
+ }
162
+ }
163
+
164
+ if (schema.res) {
165
+ jsonSchema.res = {}
166
+ if (schema.res.body) {
167
+ jsonSchema.res.body = extractChannel(ctx, 'schema.res.body', schema.res.body)
168
+ }
169
+ if (schema.res.headers) {
170
+ jsonSchema.res.headers = extractChannel(ctx, 'schema.res.headers', schema.res.headers)
171
+ }
100
172
  }
101
173
 
102
174
  return { jsonSchema, validations }
103
175
  }
176
+
177
+ export type { TSchemaValidationError }
@@ -0,0 +1,21 @@
1
+ import type { Static, TSchema } from 'typebox'
2
+
3
+ /** A plain JSON Schema object (the lingua franca of the whole library). */
4
+ export type TJSONSchema = Record<string, any>
5
+
6
+ /** Flattens an intersection type for readable IDE hovers. */
7
+ export type Prettify<TObject> = {
8
+ [Key in keyof TObject]: TObject[Key]
9
+ } & {}
10
+
11
+ /**
12
+ * Infers the static TypeScript type from a schema-library value.
13
+ *
14
+ * TypeBox is the built-in schema library; a custom {@link SchemaAdapter} can
15
+ * make other libraries work at runtime, but compile-time inference is only
16
+ * provided for TypeBox (other schemas infer as `unknown`).
17
+ */
18
+ export type Infer<SchemaType> = SchemaType extends TSchema ? Static<SchemaType> : unknown
19
+
20
+ /** v8-compatible alias for {@link Infer}. */
21
+ export type TSchemaLib<SchemaType> = Infer<SchemaType>
@@ -0,0 +1,40 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { Type } from 'typebox'
3
+ import { isTypeboxSchema, typeboxAdapter } from './typebox.js'
4
+
5
+ describe('typebox schema detection', () => {
6
+ const typebox = Type.Object({ name: Type.String() })
7
+
8
+ test('it recognizes TypeBox schema', () => {
9
+ expect(isTypeboxSchema(typebox)).toBe(true)
10
+ })
11
+
12
+ test('it rejects non-TypeBox values', () => {
13
+ expect(isTypeboxSchema({ type: 'object' })).toBe(false)
14
+ expect(isTypeboxSchema('string value')).toBe(false)
15
+ expect(isTypeboxSchema(123)).toBe(false)
16
+ expect(isTypeboxSchema(null)).toBe(false)
17
+ expect(isTypeboxSchema(undefined)).toBe(false)
18
+ })
19
+
20
+ test('it recognizes legacy @sinclair/typebox schemas (Symbol.for kind)', () => {
21
+ const legacy = { [Symbol.for('TypeBox.Kind')]: 'Object', type: 'object' }
22
+ expect(isTypeboxSchema(legacy)).toBe(true)
23
+ })
24
+
25
+ describe('typeboxAdapter', () => {
26
+ test('it exposes the adapter name used in registration errors', () => {
27
+ expect(typeboxAdapter.name).toBe('typebox')
28
+ })
29
+
30
+ test('detect matches isTypeboxSchema', () => {
31
+ expect(typeboxAdapter.detect(typebox)).toBe(true)
32
+ expect(typeboxAdapter.detect({ type: 'object' })).toBe(false)
33
+ expect(typeboxAdapter.detect(null)).toBe(false)
34
+ })
35
+
36
+ test('toJsonSchema is the identity (TypeBox schemas ARE JSON Schema)', () => {
37
+ expect(typeboxAdapter.toJsonSchema(typebox)).toBe(typebox)
38
+ })
39
+ })
40
+ })
@@ -0,0 +1,27 @@
1
+ import type { SchemaAdapter } from './adapter.js'
2
+ import type { TJSONSchema } from './json-schema.js'
3
+
4
+ const TYPEBOX_KIND = Symbol.for('TypeBox.Kind')
5
+
6
+ /**
7
+ * Built-in adapter for TypeBox (`import { Type } from 'typebox'`).
8
+ *
9
+ * Detection covers both typebox v1 (`~kind` property) and legacy
10
+ * `@sinclair/typebox` 0.3x (`Symbol.for('TypeBox.Kind')`). TypeBox schemas
11
+ * already ARE JSON Schema, so conversion is the identity.
12
+ */
13
+ export const typeboxAdapter: SchemaAdapter = {
14
+ name: 'typebox',
15
+ detect(schema: unknown): boolean {
16
+ if (typeof schema !== 'object' || schema === null) return false
17
+ return '~kind' in schema || TYPEBOX_KIND in schema
18
+ },
19
+ toJsonSchema(schema: unknown): TJSONSchema {
20
+ return schema as TJSONSchema
21
+ },
22
+ }
23
+
24
+ /** v8-compatible helper: is this value a TypeBox schema? */
25
+ export function isTypeboxSchema(schema: unknown): boolean {
26
+ return typeboxAdapter.detect(schema)
27
+ }