ts-procedures 8.6.0 → 9.1.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 (630) hide show
  1. package/CHANGELOG.md +540 -0
  2. package/README.md +166 -101
  3. package/agent_config/claude-code/.claude-plugin/plugin.json +1 -1
  4. package/agent_config/claude-code/agents/ts-procedures-architect.md +11 -10
  5. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +25 -12
  6. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +10 -12
  7. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +141 -45
  8. package/agent_config/claude-code/skills/ts-procedures/checklist.md +7 -6
  9. package/agent_config/claude-code/skills/ts-procedures/patterns.md +45 -6
  10. package/agent_config/claude-code/skills/ts-procedures/templates/client.md +1 -1
  11. package/agent_config/claude-code/skills/ts-procedures/templates/hono.md +1 -1
  12. package/agent_config/copilot/copilot-instructions.md +50 -33
  13. package/agent_config/cursor/cursorrules +50 -33
  14. package/build/adapters/astro/astro-context.js.map +1 -0
  15. package/build/adapters/astro/create-handler.js.map +1 -0
  16. package/build/adapters/astro/index.js.map +1 -0
  17. package/build/{implementations/http → adapters}/astro/index.test.js +1 -1
  18. package/build/adapters/astro/index.test.js.map +1 -0
  19. package/build/adapters/astro/rewrite-request.js.map +1 -0
  20. package/build/adapters/hono/envelope-parity.test.js +98 -0
  21. package/build/adapters/hono/envelope-parity.test.js.map +1 -0
  22. package/build/{implementations/http → adapters}/hono/handlers/http-stream.d.ts +1 -1
  23. package/build/adapters/hono/handlers/http-stream.js +55 -0
  24. package/build/adapters/hono/handlers/http-stream.js.map +1 -0
  25. package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.js +1 -1
  26. package/build/adapters/hono/handlers/http-stream.test.js.map +1 -0
  27. package/build/{implementations/http → adapters}/hono/handlers/http.d.ts +1 -1
  28. package/build/adapters/hono/handlers/http.js +50 -0
  29. package/build/adapters/hono/handlers/http.js.map +1 -0
  30. package/build/{implementations/http → adapters}/hono/handlers/http.test.js +1 -1
  31. package/build/adapters/hono/handlers/http.test.js.map +1 -0
  32. package/build/{implementations/http → adapters}/hono/handlers/rpc.d.ts +2 -2
  33. package/build/adapters/hono/handlers/rpc.js +23 -0
  34. package/build/adapters/hono/handlers/rpc.js.map +1 -0
  35. package/build/{implementations/http → adapters}/hono/handlers/rpc.test.js +1 -1
  36. package/build/adapters/hono/handlers/rpc.test.js.map +1 -0
  37. package/build/adapters/hono/handlers/stream.d.ts +12 -0
  38. package/build/adapters/hono/handlers/stream.js +89 -0
  39. package/build/adapters/hono/handlers/stream.js.map +1 -0
  40. package/build/{implementations/http → adapters}/hono/handlers/stream.test.js +3 -2
  41. package/build/adapters/hono/handlers/stream.test.js.map +1 -0
  42. package/build/{implementations/http → adapters}/hono/index.d.ts +24 -12
  43. package/build/{implementations/http → adapters}/hono/index.js +19 -8
  44. package/build/adapters/hono/index.js.map +1 -0
  45. package/build/{implementations/http → adapters}/hono/index.test.js +2 -4
  46. package/build/adapters/hono/index.test.js.map +1 -0
  47. package/build/{implementations/http → adapters/hono}/on-request-error.test.js +2 -2
  48. package/build/adapters/hono/on-request-error.test.js.map +1 -0
  49. package/build/adapters/hono/request.d.ts +7 -0
  50. package/build/adapters/hono/request.js +22 -0
  51. package/build/adapters/hono/request.js.map +1 -0
  52. package/build/{implementations/http → adapters/hono}/route-errors.test.js +4 -4
  53. package/build/adapters/hono/route-errors.test.js.map +1 -0
  54. package/build/adapters/hono/types.d.ts +55 -0
  55. package/build/adapters/hono/types.js +19 -0
  56. package/build/adapters/hono/types.js.map +1 -0
  57. package/build/client/freeze.test.js +39 -0
  58. package/build/client/freeze.test.js.map +1 -0
  59. package/build/client/typed-error-dispatch.test.js +2 -2
  60. package/build/client/typed-error-dispatch.test.js.map +1 -1
  61. package/build/codegen/__fixtures__/make-envelope.d.ts +1 -1
  62. package/build/codegen/bin/cli.d.ts +5 -0
  63. package/build/codegen/bin/cli.js +139 -182
  64. package/build/codegen/bin/cli.js.map +1 -1
  65. package/build/codegen/bin/cli.test.js +12 -2
  66. package/build/codegen/bin/cli.test.js.map +1 -1
  67. package/build/codegen/bin/flag-specs.d.ts +9 -0
  68. package/build/codegen/bin/flag-specs.js +33 -31
  69. package/build/codegen/bin/flag-specs.js.map +1 -1
  70. package/build/codegen/bin/flag-specs.test.js +14 -1
  71. package/build/codegen/bin/flag-specs.test.js.map +1 -1
  72. package/build/codegen/collect-models.d.ts +1 -1
  73. package/build/codegen/emit/api-route.d.ts +8 -0
  74. package/build/codegen/emit/api-route.js +156 -0
  75. package/build/codegen/emit/api-route.js.map +1 -0
  76. package/build/codegen/emit/context.d.ts +30 -0
  77. package/build/codegen/emit/context.js +2 -0
  78. package/build/codegen/emit/context.js.map +1 -0
  79. package/build/codegen/emit/declarations.d.ts +24 -0
  80. package/build/codegen/emit/declarations.js +48 -0
  81. package/build/codegen/emit/declarations.js.map +1 -0
  82. package/build/codegen/emit/format-types.d.ts +61 -0
  83. package/build/codegen/emit/format-types.js +188 -0
  84. package/build/codegen/emit/format-types.js.map +1 -0
  85. package/build/codegen/emit/http-stream-route.d.ts +7 -0
  86. package/build/codegen/emit/http-stream-route.js +138 -0
  87. package/build/codegen/emit/http-stream-route.js.map +1 -0
  88. package/build/codegen/emit/route-shared.d.ts +37 -0
  89. package/build/codegen/emit/route-shared.js +88 -0
  90. package/build/codegen/emit/route-shared.js.map +1 -0
  91. package/build/codegen/emit/rpc-route.d.ts +7 -0
  92. package/build/codegen/emit/rpc-route.js +37 -0
  93. package/build/codegen/emit/rpc-route.js.map +1 -0
  94. package/build/codegen/emit/scope-file.d.ts +39 -0
  95. package/build/codegen/emit/scope-file.js +166 -0
  96. package/build/codegen/emit/scope-file.js.map +1 -0
  97. package/build/codegen/emit/stream-route.d.ts +7 -0
  98. package/build/codegen/emit/stream-route.js +62 -0
  99. package/build/codegen/emit/stream-route.js.map +1 -0
  100. package/build/codegen/emit-errors.d.ts +1 -1
  101. package/build/codegen/emit-errors.integration.test.js +1 -1
  102. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  103. package/build/codegen/emit-scope.d.ts +13 -30
  104. package/build/codegen/emit-scope.js +15 -844
  105. package/build/codegen/emit-scope.js.map +1 -1
  106. package/build/codegen/emit-scope.test.js +67 -0
  107. package/build/codegen/emit-scope.test.js.map +1 -1
  108. package/build/codegen/goldens.test.js +69 -0
  109. package/build/codegen/goldens.test.js.map +1 -0
  110. package/build/codegen/group-routes.d.ts +1 -1
  111. package/build/codegen/pipeline.d.ts +1 -1
  112. package/build/codegen/resolve-envelope.d.ts +1 -1
  113. package/build/codegen/targets/_shared/error-schemas.d.ts +1 -1
  114. package/build/codegen/targets/_shared/route-slots.d.ts +1 -1
  115. package/build/codegen/targets/_shared/target-run.d.ts +1 -1
  116. package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +1 -1
  117. package/build/codegen/targets/swift/emit-route-swift.d.ts +1 -1
  118. package/build/core/create-http-stream.d.ts +50 -0
  119. package/build/core/create-http-stream.js +108 -0
  120. package/build/core/create-http-stream.js.map +1 -0
  121. package/build/{create-http-stream.test.js → core/create-http-stream.test.js} +1 -1
  122. package/build/core/create-http-stream.test.js.map +1 -0
  123. package/build/core/create-http.d.ts +51 -0
  124. package/build/core/create-http.js +65 -0
  125. package/build/core/create-http.js.map +1 -0
  126. package/build/{create-http.test.js → core/create-http.test.js} +27 -4
  127. package/build/core/create-http.test.js.map +1 -0
  128. package/build/core/create-stream.d.ts +26 -0
  129. package/build/core/create-stream.js +80 -0
  130. package/build/core/create-stream.js.map +1 -0
  131. package/build/{create-stream.test.js → core/create-stream.test.js} +23 -28
  132. package/build/core/create-stream.test.js.map +1 -0
  133. package/build/core/create.d.ts +22 -0
  134. package/build/core/create.js +71 -0
  135. package/build/core/create.js.map +1 -0
  136. package/build/{create.test.js → core/create.test.js} +25 -46
  137. package/build/core/create.test.js.map +1 -0
  138. package/build/core/definition-site.d.ts +24 -0
  139. package/build/{stack-utils.js → core/definition-site.js} +20 -20
  140. package/build/core/definition-site.js.map +1 -0
  141. package/build/{stack-utils.test.js → core/definition-site.test.js} +12 -3
  142. package/build/core/definition-site.test.js.map +1 -0
  143. package/build/{errors.d.ts → core/errors.d.ts} +19 -8
  144. package/build/{errors.js → core/errors.js} +21 -26
  145. package/build/core/errors.js.map +1 -0
  146. package/build/core/errors.test.js.map +1 -0
  147. package/build/core/factory-options.test.js +82 -0
  148. package/build/core/factory-options.test.js.map +1 -0
  149. package/build/core/http-route.d.ts +13 -0
  150. package/build/core/http-route.js +54 -0
  151. package/build/core/http-route.js.map +1 -0
  152. package/build/core/internal.d.ts +72 -0
  153. package/build/core/internal.js +128 -0
  154. package/build/core/internal.js.map +1 -0
  155. package/build/{migration.test.js → core/migration.test.js} +17 -1
  156. package/build/core/migration.test.js.map +1 -0
  157. package/build/core/procedures.d.ts +143 -0
  158. package/build/core/procedures.js +64 -0
  159. package/build/core/procedures.js.map +1 -0
  160. package/build/{index.test.js → core/procedures.test.js} +14 -11
  161. package/build/core/procedures.test.js.map +1 -0
  162. package/build/core/types.d.ts +183 -0
  163. package/build/{schema → core}/types.js.map +1 -1
  164. package/build/exports.d.ts +31 -11
  165. package/build/exports.js +23 -8
  166. package/build/exports.js.map +1 -1
  167. package/build/schema/adapter.d.ts +35 -0
  168. package/build/schema/adapter.js +13 -0
  169. package/build/schema/adapter.js.map +1 -0
  170. package/build/schema/adapter.test.js +53 -0
  171. package/build/schema/adapter.test.js.map +1 -0
  172. package/build/schema/compile.d.ts +37 -0
  173. package/build/schema/compile.js +38 -0
  174. package/build/schema/compile.js.map +1 -0
  175. package/build/schema/compile.test.js +78 -0
  176. package/build/schema/compile.test.js.map +1 -0
  177. package/build/schema/compute-schema.d.ts +47 -37
  178. package/build/schema/compute-schema.js +86 -29
  179. package/build/schema/compute-schema.js.map +1 -1
  180. package/build/schema/compute-schema.test.js +158 -40
  181. package/build/schema/compute-schema.test.js.map +1 -1
  182. package/build/schema/json-schema.d.ts +17 -0
  183. package/build/schema/json-schema.js +2 -0
  184. package/build/schema/json-schema.js.map +1 -0
  185. package/build/schema/typebox.d.ts +11 -0
  186. package/build/schema/typebox.js +24 -0
  187. package/build/schema/typebox.js.map +1 -0
  188. package/build/schema/typebox.test.js +34 -0
  189. package/build/schema/typebox.test.js.map +1 -0
  190. package/build/server/context.d.ts +8 -0
  191. package/build/server/context.js +7 -0
  192. package/build/server/context.js.map +1 -0
  193. package/build/server/context.test.js +16 -0
  194. package/build/server/context.test.js.map +1 -0
  195. package/build/{doc-envelope.d.ts → server/doc-envelope.d.ts} +1 -1
  196. package/build/server/doc-envelope.js.map +1 -0
  197. package/build/server/doc-envelope.test.d.ts +1 -0
  198. package/build/server/doc-envelope.test.js.map +1 -0
  199. package/build/{implementations/http → server}/doc-registry.d.ts +7 -2
  200. package/build/{implementations/http → server}/doc-registry.js +9 -5
  201. package/build/server/doc-registry.js.map +1 -0
  202. package/build/server/doc-registry.test.d.ts +1 -0
  203. package/build/{implementations/http → server}/doc-registry.test.js +27 -24
  204. package/build/server/doc-registry.test.js.map +1 -0
  205. package/build/server/docs/docs.test.d.ts +1 -0
  206. package/build/server/docs/docs.test.js +237 -0
  207. package/build/server/docs/docs.test.js.map +1 -0
  208. package/build/{implementations/http/hono → server}/docs/http-doc.d.ts +2 -2
  209. package/build/{implementations/http/hono → server}/docs/http-doc.js +1 -1
  210. package/build/server/docs/http-doc.js.map +1 -0
  211. package/build/{implementations/http/hono → server}/docs/http-stream-doc.d.ts +2 -2
  212. package/build/{implementations/http/hono → server}/docs/http-stream-doc.js +1 -1
  213. package/build/server/docs/http-stream-doc.js.map +1 -0
  214. package/build/{implementations/http/hono → server}/docs/rpc-doc.d.ts +2 -2
  215. package/build/{implementations/http/hono → server}/docs/rpc-doc.js +1 -1
  216. package/build/server/docs/rpc-doc.js.map +1 -0
  217. package/build/{implementations/http/hono → server}/docs/stream-doc.d.ts +2 -2
  218. package/build/{implementations/http/hono → server}/docs/stream-doc.js +1 -1
  219. package/build/server/docs/stream-doc.js.map +1 -0
  220. package/build/server/errors/dispatch.d.ts +96 -0
  221. package/build/{implementations/http/error-dispatch.js → server/errors/dispatch.js} +20 -10
  222. package/build/server/errors/dispatch.js.map +1 -0
  223. package/build/server/errors/dispatch.test.d.ts +1 -0
  224. package/build/server/errors/dispatch.test.js +418 -0
  225. package/build/server/errors/dispatch.test.js.map +1 -0
  226. package/build/{implementations/http/error-taxonomy.d.ts → server/errors/taxonomy.d.ts} +8 -17
  227. package/build/{implementations/http/error-taxonomy.js → server/errors/taxonomy.js} +6 -15
  228. package/build/server/errors/taxonomy.js.map +1 -0
  229. package/build/server/errors/taxonomy.test.d.ts +1 -0
  230. package/build/{implementations/http/error-taxonomy.test.js → server/errors/taxonomy.test.js} +45 -39
  231. package/build/server/errors/taxonomy.test.js.map +1 -0
  232. package/build/server/index.d.ts +29 -0
  233. package/build/server/index.js +27 -0
  234. package/build/server/index.js.map +1 -0
  235. package/build/server/no-framework-imports.test.d.ts +1 -0
  236. package/build/server/no-framework-imports.test.js +40 -0
  237. package/build/server/no-framework-imports.test.js.map +1 -0
  238. package/build/{implementations/http/hono/path.d.ts → server/paths.d.ts} +2 -3
  239. package/build/{implementations/http/hono/path.js → server/paths.js} +1 -1
  240. package/build/server/paths.js.map +1 -0
  241. package/build/server/paths.test.d.ts +1 -0
  242. package/build/server/paths.test.js +111 -0
  243. package/build/server/paths.test.js.map +1 -0
  244. package/build/server/request/params.d.ts +29 -0
  245. package/build/server/request/params.js +43 -0
  246. package/build/server/request/params.js.map +1 -0
  247. package/build/server/request/params.test.d.ts +1 -0
  248. package/build/server/request/params.test.js +91 -0
  249. package/build/server/request/params.test.js.map +1 -0
  250. package/build/server/request/query.d.ts +9 -0
  251. package/build/server/request/query.js +22 -0
  252. package/build/server/request/query.js.map +1 -0
  253. package/build/server/request/query.test.d.ts +1 -0
  254. package/build/server/request/query.test.js +60 -0
  255. package/build/server/request/query.test.js.map +1 -0
  256. package/build/server/sse.d.ts +70 -0
  257. package/build/server/sse.js +94 -0
  258. package/build/server/sse.js.map +1 -0
  259. package/build/server/sse.test.d.ts +1 -0
  260. package/build/server/sse.test.js +98 -0
  261. package/build/server/sse.test.js.map +1 -0
  262. package/build/{implementations → server}/types.d.ts +17 -15
  263. package/build/{implementations → server}/types.js.map +1 -1
  264. package/docs/astro-adapter.md +8 -9
  265. package/docs/client-and-codegen.md +10 -4
  266. package/docs/client-error-handling.md +5 -5
  267. package/docs/codegen-kotlin.md +2 -3
  268. package/docs/codegen-swift.md +1 -2
  269. package/docs/core.md +135 -54
  270. package/docs/http-integrations.md +58 -6
  271. package/docs/migration-v8-to-v9.md +200 -0
  272. package/docs/plans/2026-06-09-v9-rewrite.md +130 -0
  273. package/docs/specs/2026-06-09-v9-rewrite-design.md +221 -0
  274. package/docs/streaming.md +12 -0
  275. package/package.json +25 -48
  276. package/src/{implementations/http → adapters}/astro/index.test.ts +2 -2
  277. package/src/adapters/hono/__fixtures__/parity-envelope.json +389 -0
  278. package/src/adapters/hono/envelope-parity.test.ts +126 -0
  279. package/src/{implementations/http → adapters}/hono/handlers/http-stream.test.ts +1 -1
  280. package/src/adapters/hono/handlers/http-stream.ts +73 -0
  281. package/src/{implementations/http → adapters}/hono/handlers/http.test.ts +1 -1
  282. package/src/adapters/hono/handlers/http.ts +70 -0
  283. package/src/{implementations/http → adapters}/hono/handlers/rpc.test.ts +2 -2
  284. package/src/adapters/hono/handlers/rpc.ts +39 -0
  285. package/src/{implementations/http → adapters}/hono/handlers/stream.test.ts +4 -3
  286. package/src/{implementations/http → adapters}/hono/handlers/stream.ts +19 -92
  287. package/src/{implementations/http → adapters}/hono/index.test.ts +14 -16
  288. package/src/{implementations/http → adapters}/hono/index.ts +35 -30
  289. package/src/{implementations/http → adapters/hono}/on-request-error.test.ts +3 -3
  290. package/src/adapters/hono/request.ts +28 -0
  291. package/src/{implementations/http → adapters/hono}/route-errors.test.ts +5 -5
  292. package/src/{implementations/http → adapters}/hono/types.ts +43 -20
  293. package/src/client/freeze.test.ts +41 -0
  294. package/src/client/typed-error-dispatch.test.ts +3 -3
  295. package/src/codegen/__fixtures__/make-envelope.ts +1 -1
  296. package/src/codegen/__fixtures__/models-envelope.json +310 -0
  297. package/src/codegen/__goldens__/MANIFEST.json +85 -0
  298. package/src/codegen/__goldens__/kotlin-default--models/Billing.kt +112 -0
  299. package/src/codegen/__goldens__/kotlin-default--models/BillingReports.kt +26 -0
  300. package/src/codegen/__goldens__/kotlin-default--models/Orders.kt +88 -0
  301. package/src/codegen/__goldens__/kotlin-default--users/Users.kt +189 -0
  302. package/src/codegen/__goldens__/swift-default--models/Billing.swift +97 -0
  303. package/src/codegen/__goldens__/swift-default--models/BillingReports.swift +20 -0
  304. package/src/codegen/__goldens__/swift-default--models/Orders.swift +81 -0
  305. package/src/codegen/__goldens__/swift-default--users/Users.swift +204 -0
  306. package/src/codegen/__goldens__/ts-default--models/_client.ts +1319 -0
  307. package/src/codegen/__goldens__/ts-default--models/_errors.ts +90 -0
  308. package/src/codegen/__goldens__/ts-default--models/_models.ts +10 -0
  309. package/src/codegen/__goldens__/ts-default--models/_types.ts +502 -0
  310. package/src/codegen/__goldens__/ts-default--models/billing-reports.ts +29 -0
  311. package/src/codegen/__goldens__/ts-default--models/billing.ts +67 -0
  312. package/src/codegen/__goldens__/ts-default--models/index.ts +48 -0
  313. package/src/codegen/__goldens__/ts-default--models/orders.ts +80 -0
  314. package/src/codegen/__goldens__/ts-default--users/_client.ts +1319 -0
  315. package/src/codegen/__goldens__/ts-default--users/_errors.ts +90 -0
  316. package/src/codegen/__goldens__/ts-default--users/_types.ts +502 -0
  317. package/src/codegen/__goldens__/ts-default--users/index.ts +38 -0
  318. package/src/codegen/__goldens__/ts-default--users/users.ts +169 -0
  319. package/src/codegen/__goldens__/ts-external-runtime--models/_errors.ts +90 -0
  320. package/src/codegen/__goldens__/ts-external-runtime--models/_models.ts +10 -0
  321. package/src/codegen/__goldens__/ts-external-runtime--models/billing-reports.ts +29 -0
  322. package/src/codegen/__goldens__/ts-external-runtime--models/billing.ts +67 -0
  323. package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +48 -0
  324. package/src/codegen/__goldens__/ts-external-runtime--models/orders.ts +80 -0
  325. package/src/codegen/__goldens__/ts-external-runtime--users/_errors.ts +90 -0
  326. package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +38 -0
  327. package/src/codegen/__goldens__/ts-external-runtime--users/users.ts +169 -0
  328. package/src/codegen/__goldens__/ts-flat--models/_client.ts +1319 -0
  329. package/src/codegen/__goldens__/ts-flat--models/_errors.ts +87 -0
  330. package/src/codegen/__goldens__/ts-flat--models/_models.ts +10 -0
  331. package/src/codegen/__goldens__/ts-flat--models/_types.ts +502 -0
  332. package/src/codegen/__goldens__/ts-flat--models/billing-reports.ts +28 -0
  333. package/src/codegen/__goldens__/ts-flat--models/billing.ts +51 -0
  334. package/src/codegen/__goldens__/ts-flat--models/index.ts +42 -0
  335. package/src/codegen/__goldens__/ts-flat--models/orders.ts +73 -0
  336. package/src/codegen/__goldens__/ts-flat--users/_client.ts +1319 -0
  337. package/src/codegen/__goldens__/ts-flat--users/_errors.ts +87 -0
  338. package/src/codegen/__goldens__/ts-flat--users/_types.ts +502 -0
  339. package/src/codegen/__goldens__/ts-flat--users/index.ts +34 -0
  340. package/src/codegen/__goldens__/ts-flat--users/users.ts +126 -0
  341. package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +1319 -0
  342. package/src/codegen/__goldens__/ts-no-share-models--models/_errors.ts +90 -0
  343. package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +502 -0
  344. package/src/codegen/__goldens__/ts-no-share-models--models/billing-reports.ts +29 -0
  345. package/src/codegen/__goldens__/ts-no-share-models--models/billing.ts +111 -0
  346. package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +48 -0
  347. package/src/codegen/__goldens__/ts-no-share-models--models/orders.ts +112 -0
  348. package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +1319 -0
  349. package/src/codegen/__goldens__/ts-no-share-models--users/_errors.ts +90 -0
  350. package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +502 -0
  351. package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +38 -0
  352. package/src/codegen/__goldens__/ts-no-share-models--users/users.ts +169 -0
  353. package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +1319 -0
  354. package/src/codegen/__goldens__/ts-shared-models-module--models/_errors.ts +90 -0
  355. package/src/codegen/__goldens__/ts-shared-models-module--models/_models.ts +7 -0
  356. package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +502 -0
  357. package/src/codegen/__goldens__/ts-shared-models-module--models/billing-reports.ts +29 -0
  358. package/src/codegen/__goldens__/ts-shared-models-module--models/billing.ts +67 -0
  359. package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +48 -0
  360. package/src/codegen/__goldens__/ts-shared-models-module--models/orders.ts +80 -0
  361. package/src/codegen/bin/cli.test.ts +13 -2
  362. package/src/codegen/bin/cli.ts +181 -144
  363. package/src/codegen/bin/flag-specs.test.ts +16 -1
  364. package/src/codegen/bin/flag-specs.ts +43 -31
  365. package/src/codegen/bundle-size.test.ts +1 -1
  366. package/src/codegen/collect-models.ts +1 -1
  367. package/src/codegen/e2e.test.ts +1 -1
  368. package/src/codegen/emit/api-route.ts +184 -0
  369. package/src/codegen/emit/context.ts +32 -0
  370. package/src/codegen/emit/declarations.ts +49 -0
  371. package/src/codegen/emit/format-types.ts +232 -0
  372. package/src/codegen/emit/http-stream-route.ts +162 -0
  373. package/src/codegen/emit/route-shared.ts +104 -0
  374. package/src/codegen/emit/rpc-route.ts +49 -0
  375. package/src/codegen/emit/scope-file.ts +226 -0
  376. package/src/codegen/emit/stream-route.ts +81 -0
  377. package/src/codegen/emit-errors.integration.test.ts +2 -2
  378. package/src/codegen/emit-errors.test.ts +1 -1
  379. package/src/codegen/emit-errors.ts +1 -1
  380. package/src/codegen/emit-scope.test.ts +75 -2
  381. package/src/codegen/emit-scope.ts +15 -1048
  382. package/src/codegen/goldens.test.ts +89 -0
  383. package/src/codegen/group-routes.test.ts +1 -1
  384. package/src/codegen/group-routes.ts +1 -1
  385. package/src/codegen/pipeline.test.ts +1 -1
  386. package/src/codegen/pipeline.ts +1 -1
  387. package/src/codegen/resolve-envelope.test.ts +1 -1
  388. package/src/codegen/resolve-envelope.ts +1 -1
  389. package/src/codegen/targets/_shared/error-schemas.test.ts +1 -1
  390. package/src/codegen/targets/_shared/error-schemas.ts +1 -1
  391. package/src/codegen/targets/_shared/route-slots.test.ts +1 -1
  392. package/src/codegen/targets/_shared/route-slots.ts +1 -1
  393. package/src/codegen/targets/_shared/target-run.ts +1 -1
  394. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +1 -1
  395. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +1 -1
  396. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +1 -1
  397. package/src/codegen/targets/swift/access-level.test.ts +1 -1
  398. package/src/codegen/targets/swift/emit-route-swift.test.ts +1 -1
  399. package/src/codegen/targets/swift/emit-route-swift.ts +1 -1
  400. package/src/codegen/targets/swift/emit-scope-swift.test.ts +1 -1
  401. package/src/codegen/targets/ts/shared-models.test.ts +1 -1
  402. package/src/{create-http-stream.test.ts → core/create-http-stream.test.ts} +1 -1
  403. package/src/core/create-http-stream.ts +207 -0
  404. package/src/{create-http.test.ts → core/create-http.test.ts} +31 -4
  405. package/src/core/create-http.ts +126 -0
  406. package/src/{create-stream.test.ts → core/create-stream.test.ts} +28 -31
  407. package/src/core/create-stream.ts +142 -0
  408. package/src/{create.test.ts → core/create.test.ts} +25 -57
  409. package/src/core/create.ts +121 -0
  410. package/src/{stack-utils.test.ts → core/definition-site.test.ts} +14 -3
  411. package/src/{stack-utils.ts → core/definition-site.ts} +20 -23
  412. package/src/{errors.test.ts → core/errors.test.ts} +1 -1
  413. package/src/{errors.ts → core/errors.ts} +30 -28
  414. package/src/core/factory-options.test.ts +112 -0
  415. package/src/core/http-route.ts +73 -0
  416. package/src/core/internal.ts +203 -0
  417. package/src/{migration.test.ts → core/migration.test.ts} +23 -1
  418. package/src/{index.test.ts → core/procedures.test.ts} +13 -11
  419. package/src/core/procedures.ts +75 -0
  420. package/src/core/types.ts +196 -0
  421. package/src/exports.ts +60 -11
  422. package/src/schema/adapter.test.ts +58 -0
  423. package/src/schema/adapter.ts +45 -0
  424. package/src/schema/compile.test.ts +95 -0
  425. package/src/schema/compile.ts +64 -0
  426. package/src/schema/compute-schema.test.ts +222 -41
  427. package/src/schema/compute-schema.ts +145 -71
  428. package/src/schema/json-schema.ts +21 -0
  429. package/src/schema/typebox.test.ts +40 -0
  430. package/src/schema/typebox.ts +27 -0
  431. package/src/server/context.test.ts +22 -0
  432. package/src/server/context.ts +18 -0
  433. package/src/{doc-envelope.test.ts → server/doc-envelope.test.ts} +2 -2
  434. package/src/{doc-envelope.ts → server/doc-envelope.ts} +1 -1
  435. package/src/{implementations/http → server}/doc-registry.test.ts +32 -26
  436. package/src/{implementations/http → server}/doc-registry.ts +11 -7
  437. package/src/server/docs/docs.test.ts +287 -0
  438. package/src/{implementations/http/hono → server}/docs/http-doc.ts +3 -3
  439. package/src/{implementations/http/hono → server}/docs/http-stream-doc.ts +3 -3
  440. package/src/{implementations/http/hono → server}/docs/rpc-doc.ts +3 -3
  441. package/src/{implementations/http/hono → server}/docs/stream-doc.ts +3 -3
  442. package/src/server/errors/dispatch.test.ts +450 -0
  443. package/src/server/errors/dispatch.ts +189 -0
  444. package/src/{implementations/http/error-taxonomy.test.ts → server/errors/taxonomy.test.ts} +45 -39
  445. package/src/{implementations/http/error-taxonomy.ts → server/errors/taxonomy.ts} +8 -17
  446. package/src/server/index.ts +29 -0
  447. package/src/server/no-framework-imports.test.ts +43 -0
  448. package/src/server/paths.test.ts +141 -0
  449. package/src/{implementations/http/hono/path.ts → server/paths.ts} +2 -13
  450. package/src/server/request/params.test.ts +143 -0
  451. package/src/server/request/params.ts +68 -0
  452. package/src/server/request/query.test.ts +70 -0
  453. package/src/server/request/query.ts +24 -0
  454. package/src/server/sse.test.ts +113 -0
  455. package/src/server/sse.ts +117 -0
  456. package/src/{implementations → server}/types.ts +17 -16
  457. package/build/create-http-stream.d.ts +0 -58
  458. package/build/create-http-stream.js +0 -122
  459. package/build/create-http-stream.js.map +0 -1
  460. package/build/create-http-stream.test.js.map +0 -1
  461. package/build/create-http.d.ts +0 -49
  462. package/build/create-http.js +0 -108
  463. package/build/create-http.js.map +0 -1
  464. package/build/create-http.test.js.map +0 -1
  465. package/build/create-stream.d.ts +0 -35
  466. package/build/create-stream.js +0 -123
  467. package/build/create-stream.js.map +0 -1
  468. package/build/create-stream.test.js.map +0 -1
  469. package/build/create.d.ts +0 -28
  470. package/build/create.js +0 -82
  471. package/build/create.js.map +0 -1
  472. package/build/create.test.js.map +0 -1
  473. package/build/doc-envelope.js.map +0 -1
  474. package/build/doc-envelope.test.js.map +0 -1
  475. package/build/errors.js.map +0 -1
  476. package/build/errors.test.js.map +0 -1
  477. package/build/implementations/http/astro/astro-context.js.map +0 -1
  478. package/build/implementations/http/astro/create-handler.js.map +0 -1
  479. package/build/implementations/http/astro/index.js.map +0 -1
  480. package/build/implementations/http/astro/index.test.js.map +0 -1
  481. package/build/implementations/http/astro/rewrite-request.js.map +0 -1
  482. package/build/implementations/http/doc-registry.js.map +0 -1
  483. package/build/implementations/http/doc-registry.test.js.map +0 -1
  484. package/build/implementations/http/error-dispatch.d.ts +0 -76
  485. package/build/implementations/http/error-dispatch.js.map +0 -1
  486. package/build/implementations/http/error-dispatch.test.js +0 -254
  487. package/build/implementations/http/error-dispatch.test.js.map +0 -1
  488. package/build/implementations/http/error-taxonomy.js.map +0 -1
  489. package/build/implementations/http/error-taxonomy.test.js.map +0 -1
  490. package/build/implementations/http/hono/docs/http-doc.js.map +0 -1
  491. package/build/implementations/http/hono/docs/http-stream-doc.js.map +0 -1
  492. package/build/implementations/http/hono/docs/rpc-doc.js.map +0 -1
  493. package/build/implementations/http/hono/docs/stream-doc.js.map +0 -1
  494. package/build/implementations/http/hono/handlers/http-stream.js +0 -123
  495. package/build/implementations/http/hono/handlers/http-stream.js.map +0 -1
  496. package/build/implementations/http/hono/handlers/http-stream.test.js.map +0 -1
  497. package/build/implementations/http/hono/handlers/http.js +0 -110
  498. package/build/implementations/http/hono/handlers/http.js.map +0 -1
  499. package/build/implementations/http/hono/handlers/http.test.js.map +0 -1
  500. package/build/implementations/http/hono/handlers/rpc.js +0 -32
  501. package/build/implementations/http/hono/handlers/rpc.js.map +0 -1
  502. package/build/implementations/http/hono/handlers/rpc.test.js.map +0 -1
  503. package/build/implementations/http/hono/handlers/stream.d.ts +0 -23
  504. package/build/implementations/http/hono/handlers/stream.js +0 -147
  505. package/build/implementations/http/hono/handlers/stream.js.map +0 -1
  506. package/build/implementations/http/hono/handlers/stream.test.js.map +0 -1
  507. package/build/implementations/http/hono/index.js.map +0 -1
  508. package/build/implementations/http/hono/index.test.js.map +0 -1
  509. package/build/implementations/http/hono/path.js.map +0 -1
  510. package/build/implementations/http/hono/path.test.js +0 -83
  511. package/build/implementations/http/hono/path.test.js.map +0 -1
  512. package/build/implementations/http/hono/types.d.ts +0 -51
  513. package/build/implementations/http/hono/types.js.map +0 -1
  514. package/build/implementations/http/on-request-error.test.js.map +0 -1
  515. package/build/implementations/http/route-errors.test.js.map +0 -1
  516. package/build/index.d.ts +0 -175
  517. package/build/index.js +0 -47
  518. package/build/index.js.map +0 -1
  519. package/build/index.test.js.map +0 -1
  520. package/build/migration.test.js.map +0 -1
  521. package/build/schema/extract-json-schema.d.ts +0 -2
  522. package/build/schema/extract-json-schema.js +0 -12
  523. package/build/schema/extract-json-schema.js.map +0 -1
  524. package/build/schema/extract-json-schema.test.js +0 -23
  525. package/build/schema/extract-json-schema.test.js.map +0 -1
  526. package/build/schema/parser.d.ts +0 -36
  527. package/build/schema/parser.js +0 -210
  528. package/build/schema/parser.js.map +0 -1
  529. package/build/schema/parser.test.js +0 -120
  530. package/build/schema/parser.test.js.map +0 -1
  531. package/build/schema/resolve-schema-lib.d.ts +0 -12
  532. package/build/schema/resolve-schema-lib.js +0 -11
  533. package/build/schema/resolve-schema-lib.js.map +0 -1
  534. package/build/schema/resolve-schema-lib.test.js +0 -17
  535. package/build/schema/resolve-schema-lib.test.js.map +0 -1
  536. package/build/schema/types.d.ts +0 -8
  537. package/build/schema/types.js +0 -2
  538. package/build/stack-utils.d.ts +0 -25
  539. package/build/stack-utils.js.map +0 -1
  540. package/build/stack-utils.test.js.map +0 -1
  541. package/build/types.d.ts +0 -142
  542. package/build/types.js +0 -2
  543. package/build/types.js.map +0 -1
  544. package/docs/decisions/2026-06-02-monorepo-split-evaluation.md +0 -80
  545. package/docs/handoffs/2026-06-08-dx-round2-declines.md +0 -45
  546. package/docs/handoffs/ajsc-named-type-collision.md +0 -134
  547. package/docs/handoffs/ajsc-named-type-support.md +0 -181
  548. package/docs/handoffs/shared-models-auto-resolve-response.md +0 -181
  549. package/docs/npm-workspaces-migration-plan.md +0 -611
  550. package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +0 -886
  551. package/docs/superpowers/plans/2026-04-24-kotlin-codegen-target.md +0 -1265
  552. package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +0 -1993
  553. package/docs/superpowers/plans/2026-04-29-safe-result-api.md +0 -2293
  554. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +0 -1391
  555. package/docs/superpowers/plans/2026-05-08-create-http.md +0 -3355
  556. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +0 -3365
  557. package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +0 -1292
  558. package/docs/superpowers/plans/2026-06-06-shared-models-convention-and-diagnostics.md +0 -659
  559. package/docs/superpowers/plans/2026-06-08-codegen-dx-surfacing.md +0 -428
  560. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +0 -401
  561. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +0 -314
  562. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +0 -264
  563. package/docs/superpowers/specs/2026-04-29-safe-result-api-design.md +0 -324
  564. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +0 -252
  565. package/docs/superpowers/specs/2026-05-08-create-http-design.md +0 -409
  566. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +0 -411
  567. package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +0 -285
  568. package/docs/superpowers/specs/2026-06-08-dx-feedback-round-2-design.md +0 -376
  569. package/src/create-http-stream.ts +0 -191
  570. package/src/create-http.ts +0 -210
  571. package/src/create-stream.ts +0 -228
  572. package/src/create.ts +0 -172
  573. package/src/implementations/http/README.md +0 -390
  574. package/src/implementations/http/error-dispatch.test.ts +0 -283
  575. package/src/implementations/http/error-dispatch.ts +0 -176
  576. package/src/implementations/http/hono/handlers/http-stream.ts +0 -152
  577. package/src/implementations/http/hono/handlers/http.ts +0 -145
  578. package/src/implementations/http/hono/handlers/rpc.ts +0 -54
  579. package/src/implementations/http/hono/path.test.ts +0 -96
  580. package/src/index.ts +0 -101
  581. package/src/schema/extract-json-schema.test.ts +0 -25
  582. package/src/schema/extract-json-schema.ts +0 -15
  583. package/src/schema/parser.test.ts +0 -182
  584. package/src/schema/parser.ts +0 -265
  585. package/src/schema/resolve-schema-lib.test.ts +0 -19
  586. package/src/schema/resolve-schema-lib.ts +0 -29
  587. package/src/schema/types.ts +0 -20
  588. package/src/types.ts +0 -133
  589. /package/build/{implementations/http → adapters}/astro/astro-context.d.ts +0 -0
  590. /package/build/{implementations/http → adapters}/astro/astro-context.js +0 -0
  591. /package/build/{implementations/http → adapters}/astro/create-handler.d.ts +0 -0
  592. /package/build/{implementations/http → adapters}/astro/create-handler.js +0 -0
  593. /package/build/{implementations/http → adapters}/astro/index.d.ts +0 -0
  594. /package/build/{implementations/http → adapters}/astro/index.js +0 -0
  595. /package/build/{implementations/http → adapters}/astro/index.test.d.ts +0 -0
  596. /package/build/{implementations/http → adapters}/astro/rewrite-request.d.ts +0 -0
  597. /package/build/{implementations/http → adapters}/astro/rewrite-request.js +0 -0
  598. /package/build/{create-http-stream.test.d.ts → adapters/hono/envelope-parity.test.d.ts} +0 -0
  599. /package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.d.ts +0 -0
  600. /package/build/{implementations/http → adapters}/hono/handlers/http.test.d.ts +0 -0
  601. /package/build/{implementations/http → adapters}/hono/handlers/rpc.test.d.ts +0 -0
  602. /package/build/{implementations/http → adapters}/hono/handlers/stream.test.d.ts +0 -0
  603. /package/build/{implementations/http → adapters}/hono/index.test.d.ts +0 -0
  604. /package/build/{implementations/http → adapters/hono}/on-request-error.test.d.ts +0 -0
  605. /package/build/{implementations/http → adapters/hono}/route-errors.test.d.ts +0 -0
  606. /package/build/{create-http.test.d.ts → client/freeze.test.d.ts} +0 -0
  607. /package/build/{create-stream.test.d.ts → codegen/goldens.test.d.ts} +0 -0
  608. /package/build/{create.test.d.ts → core/create-http-stream.test.d.ts} +0 -0
  609. /package/build/{doc-envelope.test.d.ts → core/create-http.test.d.ts} +0 -0
  610. /package/build/{errors.test.d.ts → core/create-stream.test.d.ts} +0 -0
  611. /package/build/{implementations/http/doc-registry.test.d.ts → core/create.test.d.ts} +0 -0
  612. /package/build/{implementations/http/error-dispatch.test.d.ts → core/definition-site.test.d.ts} +0 -0
  613. /package/build/{implementations/http/error-taxonomy.test.d.ts → core/errors.test.d.ts} +0 -0
  614. /package/build/{errors.test.js → core/errors.test.js} +0 -0
  615. /package/build/{implementations/http/hono/path.test.d.ts → core/factory-options.test.d.ts} +0 -0
  616. /package/build/{migration.test.d.ts → core/migration.test.d.ts} +0 -0
  617. /package/build/{index.test.d.ts → core/procedures.test.d.ts} +0 -0
  618. /package/build/{implementations/http/hono → core}/types.js +0 -0
  619. /package/build/schema/{extract-json-schema.test.d.ts → adapter.test.d.ts} +0 -0
  620. /package/build/schema/{parser.test.d.ts → compile.test.d.ts} +0 -0
  621. /package/build/schema/{resolve-schema-lib.test.d.ts → typebox.test.d.ts} +0 -0
  622. /package/build/{stack-utils.test.d.ts → server/context.test.d.ts} +0 -0
  623. /package/build/{doc-envelope.js → server/doc-envelope.js} +0 -0
  624. /package/build/{doc-envelope.test.js → server/doc-envelope.test.js} +0 -0
  625. /package/build/{implementations → server}/types.js +0 -0
  626. /package/src/{implementations/http → adapters}/astro/README.md +0 -0
  627. /package/src/{implementations/http → adapters}/astro/astro-context.ts +0 -0
  628. /package/src/{implementations/http → adapters}/astro/create-handler.ts +0 -0
  629. /package/src/{implementations/http → adapters}/astro/index.ts +0 -0
  630. /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
+ }