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,7 +1,6 @@
1
-
2
1
  import { describe, expect, it, test } from 'vitest'
3
- import { Procedures } from './index.js'
4
- import { v } from 'suretype'
2
+ import { Procedures } from './procedures.js'
3
+ import { ProcedureRegistrationError } from './errors.js'
5
4
  import { Type } from 'typebox'
6
5
 
7
6
  describe('Procedures', () => {
@@ -26,8 +25,8 @@ describe('Procedures', () => {
26
25
  'test-docs',
27
26
  {
28
27
  schema: {
29
- params: v.object({ name: v.string().required() }),
30
- returnType: v.string(),
28
+ params: Type.Object({ name: Type.String() }),
29
+ returnType: Type.String(),
31
30
  },
32
31
  },
33
32
  async () => {
@@ -62,6 +61,9 @@ describe('Procedures', () => {
62
61
  expect(() => {
63
62
  Create('DuplicateTest', {}, async () => 'second')
64
63
  }).toThrow('Procedure with name DuplicateTest is already registered')
64
+ expect(() => {
65
+ Create('DuplicateTest', {}, async () => 'second')
66
+ }).toThrow(ProcedureRegistrationError)
65
67
  })
66
68
 
67
69
  test('Procedures - getProcedure returns specific procedure', () => {
@@ -122,11 +124,11 @@ describe('Procedures', () => {
122
124
  })
123
125
  })
124
126
 
125
- describe('builder.config.noRuntimeValidation', () => {
126
- test('noRuntimeValidation does not interfere with onCreate callback', async () => {
127
+ describe('Procedures({ validation: false })', () => {
128
+ test('validation: false does not interfere with onCreate callback', async () => {
127
129
  const seen: string[] = []
128
130
  const { Create } = Procedures({
129
- config: { noRuntimeValidation: true },
131
+ validation: false,
130
132
  onCreate: (proc) => {
131
133
  seen.push(proc.name)
132
134
  },
@@ -141,9 +143,9 @@ describe('builder.config.noRuntimeValidation', () => {
141
143
  expect(seen).toEqual(['Registered'])
142
144
  })
143
145
 
144
- test('noRuntimeValidation: false is rejected by the type system', () => {
145
- // @ts-expect-error - only `true` (or omitted) is allowed for noRuntimeValidation
146
- void Procedures({ config: { noRuntimeValidation: false } })
146
+ test('validation: true is rejected by the type system', () => {
147
+ // @ts-expect-error - only `false` or `{ ajv }` (or omitted) is allowed for validation
148
+ void Procedures({ validation: true })
147
149
  })
148
150
  })
149
151
 
@@ -0,0 +1,75 @@
1
+ import { makeCreate } from './create.js'
2
+ import { makeCreateStream } from './create-stream.js'
3
+ import { makeCreateHttp } from './create-http.js'
4
+ import { makeCreateHttpStream } from './create-http-stream.js'
5
+ import { createValidatorCompiler } from '../schema/compile.js'
6
+ import { typeboxAdapter } from '../schema/typebox.js'
7
+ import type { FactoryRuntime } from './internal.js'
8
+ import type { AnyProcedureRegistration, ProceduresOptions, TNoContextProvided } from './types.js'
9
+
10
+ /**
11
+ * Creates a procedure factory.
12
+ *
13
+ * ```ts
14
+ * type Ctx = { db: Db }
15
+ * const { Create, CreateStream, CreateHttp, CreateHttpStream, getProcedures } =
16
+ * Procedures<Ctx>({
17
+ * validation: { ajv: { coerceTypes: false } }, // or `false` to skip per-call validation
18
+ * schema: { adapters: [myZodAdapter] }, // TypeBox is built in
19
+ * http: { pathPrefix: '/v1', scope: 'billing' }, // CreateHttp* defaults
20
+ * onCreate: (procedure) => log(procedure.kind, procedure.name),
21
+ * })
22
+ * ```
23
+ *
24
+ * - `TContext` — the context every handler receives (plus injected `error()`
25
+ * and `signal`).
26
+ * - `TExtendedConfig` — extra per-procedure config fields (e.g. `scope`,
27
+ * `version`, auth flags) carried through to registrations, `info`, and
28
+ * `onCreate`.
29
+ */
30
+ export function Procedures<TContext = TNoContextProvided, TExtendedConfig = unknown>(
31
+ options?: ProceduresOptions<TContext, TExtendedConfig>,
32
+ ) {
33
+ const registry = new Map<string, AnyProcedureRegistration<TContext, TExtendedConfig>>()
34
+
35
+ const runtime: FactoryRuntime<TContext, TExtendedConfig> = {
36
+ registry,
37
+ onCreate: options?.onCreate,
38
+ skipValidation: options?.validation === false,
39
+ adapters: [...(options?.schema?.adapters ?? []), typeboxAdapter],
40
+ compile: createValidatorCompiler(options?.validation === false ? undefined : options?.validation),
41
+ httpDefaults: options?.http,
42
+ }
43
+
44
+ const Create = makeCreate<TContext, TExtendedConfig>(runtime)
45
+ const CreateStream = makeCreateStream<TContext, TExtendedConfig>(runtime)
46
+ const CreateHttp = makeCreateHttp<TContext>(runtime)
47
+ const CreateHttpStream = makeCreateHttpStream<TContext>(runtime)
48
+
49
+ return {
50
+ /** All registered procedures, in registration order. */
51
+ getProcedures: () => {
52
+ return Array.from(registry.values())
53
+ },
54
+
55
+ /** A specific procedure by name. */
56
+ getProcedure: (name: string) => {
57
+ return registry.get(name)
58
+ },
59
+
60
+ /** Removes a procedure by name. Returns whether it existed. */
61
+ removeProcedure: (name: string) => {
62
+ return registry.delete(name)
63
+ },
64
+
65
+ /** Clears all registered procedures. */
66
+ clear: () => {
67
+ registry.clear()
68
+ },
69
+
70
+ Create,
71
+ CreateStream,
72
+ CreateHttp,
73
+ CreateHttpStream,
74
+ }
75
+ }
@@ -0,0 +1,196 @@
1
+ import type * as AJV from 'ajv'
2
+ import type { ProcedureError } from './errors.js'
3
+ import type { SchemaAdapter } from '../schema/adapter.js'
4
+ import type { TJSONSchema } from '../schema/json-schema.js'
5
+ import type { Validate } from '../schema/compile.js'
6
+
7
+ export type TNoContextProvided = unknown
8
+
9
+ /**
10
+ * Context the framework injects into every handler on top of the
11
+ * factory-level `TContext`.
12
+ */
13
+ export type TLocalContext = {
14
+ /** Creates a `ProcedureError` carrying this procedure's name + definition site. */
15
+ error: (message: string, meta?: object) => ProcedureError
16
+ /** Present when the server implementation provides one (HonoAppBuilder does). */
17
+ signal?: AbortSignal
18
+ }
19
+
20
+ /** Stream handlers always get a signal (aborts on client disconnect or completion). */
21
+ export type TStreamContext = TLocalContext & {
22
+ signal: AbortSignal
23
+ }
24
+
25
+ /**
26
+ * Discriminant on every procedure registration that drives builder routing.
27
+ *
28
+ * - `'rpc'` — Create() registration
29
+ * - `'rpc-stream'` — CreateStream() registration
30
+ * - `'http'` — CreateHttp() registration
31
+ * - `'http-stream'` — CreateHttpStream() registration
32
+ */
33
+ export type ProcedureKind = 'rpc' | 'rpc-stream' | 'http' | 'http-stream'
34
+
35
+ export type TProcedureRegistration<TContext = unknown, TExtendedConfig = unknown> = {
36
+ name: string
37
+ kind: 'rpc'
38
+ config: {
39
+ description?: string
40
+ schema?: {
41
+ params?: TJSONSchema
42
+ returnType?: TJSONSchema
43
+ }
44
+ validation?: {
45
+ params?: Validate
46
+ }
47
+ } & TExtendedConfig
48
+ handler: (ctx: TContext, params?: any) => Promise<any>
49
+ }
50
+
51
+ export type TStreamProcedureRegistration<TContext = unknown, TExtendedConfig = unknown> = {
52
+ name: string
53
+ kind: 'rpc-stream'
54
+ config: {
55
+ description?: string
56
+ schema?: {
57
+ params?: TJSONSchema
58
+ yieldType?: TJSONSchema
59
+ returnType?: TJSONSchema
60
+ }
61
+ validation?: {
62
+ params?: Validate
63
+ yield?: Validate
64
+ }
65
+ validateYields?: boolean
66
+ } & TExtendedConfig
67
+ handler: (ctx: TContext, params?: any) => AsyncGenerator<any, any, unknown>
68
+ }
69
+
70
+ export type HttpMethod = 'get' | 'post' | 'put' | 'delete' | 'patch' | 'head'
71
+
72
+ export type TCreateHttpConfig<TReq, TRes, TErrorKey extends string = string> = {
73
+ path: string
74
+ method: HttpMethod
75
+ successStatus?: number
76
+ scope?: string
77
+ errors?: TErrorKey[]
78
+ description?: string
79
+ /** Optional — a no-input, no-output route (e.g. a 204 logout) may omit it. */
80
+ schema?: {
81
+ req?: TReq
82
+ res?: TRes
83
+ }
84
+ }
85
+
86
+ export type THttpProcedureRegistration<TContext = unknown> = {
87
+ name: string
88
+ kind: 'http'
89
+ config: {
90
+ path: string
91
+ method: HttpMethod
92
+ successStatus?: number
93
+ scope?: string
94
+ errors?: string[]
95
+ description?: string
96
+ schema?: {
97
+ req?: Record<string, TJSONSchema>
98
+ res?: { body?: TJSONSchema; headers?: TJSONSchema }
99
+ }
100
+ validation?: {
101
+ req?: Record<string, Validate>
102
+ }
103
+ }
104
+ handler: (ctx: TContext, req?: any) => Promise<any>
105
+ }
106
+
107
+ export type THttpStreamProcedureRegistration<TContext = unknown> = {
108
+ name: string
109
+ kind: 'http-stream'
110
+ config: {
111
+ path: string
112
+ method: HttpMethod
113
+ scope?: string
114
+ errors?: string[]
115
+ description?: string
116
+ schema?: {
117
+ req?: Record<string, TJSONSchema>
118
+ res?: { headers?: TJSONSchema }
119
+ yield?: TJSONSchema
120
+ returnType?: TJSONSchema
121
+ }
122
+ validation?: {
123
+ req?: Record<string, Validate>
124
+ yield?: Validate
125
+ }
126
+ validateYields?: boolean
127
+ }
128
+ handler: (
129
+ ctx: TContext,
130
+ req?: any,
131
+ ) => Promise<{ stream: AsyncGenerator<any, any, unknown>; initialHeaders?: Record<string, string> }>
132
+ }
133
+
134
+ /**
135
+ * The shape every creator returns: the handler under its own name (so
136
+ * `const { GetUser } = Create('GetUser', ...)` works), the same handler as
137
+ * `procedure`, and the introspectable `info`.
138
+ */
139
+ export type ProcedureResult<TName extends string, THandler, TInfo> = {
140
+ [K in TName]: THandler
141
+ } & {
142
+ procedure: THandler
143
+ info: TInfo
144
+ }
145
+
146
+ /** Union of all four registration shapes a factory can hold. */
147
+ export type AnyProcedureRegistration<TContext = unknown, TExtendedConfig = unknown> =
148
+ | TProcedureRegistration<TContext, TExtendedConfig>
149
+ | TStreamProcedureRegistration<TContext, TExtendedConfig>
150
+ | THttpProcedureRegistration<TContext>
151
+ | THttpStreamProcedureRegistration<TContext>
152
+
153
+ /**
154
+ * Options for `Procedures()`.
155
+ */
156
+ export type ProceduresOptions<TContext = unknown, TExtendedConfig = unknown> = {
157
+ /**
158
+ * Called once per registered procedure with the full registration object.
159
+ * Use the `kind` discriminant to narrow to the specific shape. This is the
160
+ * seam for custom framework integration (Fastify, Koa, raw http, ...).
161
+ */
162
+ onCreate?: (procedure: AnyProcedureRegistration<TContext, TExtendedConfig>) => void
163
+
164
+ /**
165
+ * Runtime validation behavior:
166
+ * - omitted — validate every call with the default AJV configuration
167
+ * (`allErrors`, `coerceTypes`, `removeAdditional`)
168
+ * - `false` — skip per-call validation for the whole factory. JSON Schema
169
+ * and validators are still computed at registration time (bad schemas
170
+ * still fail fast); only the per-call runs are skipped. For trusted
171
+ * internal factories whose callers are type-checked at build time.
172
+ * - `{ ajv }` — AJV options merged over the defaults, or a configured
173
+ * `Ajv` instance used as-is.
174
+ */
175
+ validation?: false | { ajv?: AJV.Ajv | AJV.Options }
176
+
177
+ /**
178
+ * Schema-library integration. TypeBox is built in; prepend adapters here to
179
+ * register procedures with other schema libraries (see `SchemaAdapter`).
180
+ */
181
+ schema?: {
182
+ adapters?: SchemaAdapter[]
183
+ }
184
+
185
+ /**
186
+ * Factory-level defaults for `CreateHttp` / `CreateHttpStream` routes:
187
+ * - `pathPrefix` — prepended to every route's `path` at registration time
188
+ * (this is part of the route's identity, unlike a server adapter's mount
189
+ * prefix)
190
+ * - `scope` — default codegen scope for routes that don't set one
191
+ */
192
+ http?: {
193
+ pathPrefix?: string
194
+ scope?: string
195
+ }
196
+ }
package/src/exports.ts CHANGED
@@ -1,11 +1,60 @@
1
- export * from './index.js'
2
- export * from './errors.js'
3
- export * from './stack-utils.js'
4
- export * from './schema/extract-json-schema.js'
5
- export * from './schema/parser.js'
6
- export * from './schema/resolve-schema-lib.js'
7
- export * from './schema/types.js'
8
- export type { HttpReturn } from './create-http.js'
9
- export type { TCreateHttpConfig } from './types.js'
10
- export { writeDocEnvelope, type DocEnvelopeSource } from './doc-envelope.js'
11
- export type { DocEnvelope } from './implementations/types.js'
1
+ /**
2
+ * ts-procedures — root entry point.
3
+ *
4
+ * Subpath exports:
5
+ * - `ts-procedures/hono` — HonoAppBuilder server adapter
6
+ * - `ts-procedures/astro` — Astro catch-all adapter (delegates to Hono apps)
7
+ * - `ts-procedures/server` — transport-agnostic server layer (build your own adapter)
8
+ * - `ts-procedures/http` HTTP doc/config types (types only)
9
+ * - `ts-procedures/http-docs` DocRegistry (multi-app envelope aggregation)
10
+ * - `ts-procedures/http-errors` error taxonomy helpers
11
+ * - `ts-procedures/client` runtime client for generated code
12
+ * - `ts-procedures/codegen` — client code generation (also: npx ts-procedures-codegen)
13
+ */
14
+
15
+ // Core — the Procedures factory and everything handlers touch
16
+ export { Procedures } from './core/procedures.js'
17
+ export type {
18
+ ProceduresOptions,
19
+ ProcedureKind,
20
+ AnyProcedureRegistration,
21
+ TProcedureRegistration,
22
+ TStreamProcedureRegistration,
23
+ THttpProcedureRegistration,
24
+ THttpStreamProcedureRegistration,
25
+ TCreateHttpConfig,
26
+ TLocalContext,
27
+ TStreamContext,
28
+ TNoContextProvided,
29
+ HttpMethod,
30
+ } from './core/types.js'
31
+ export type { HttpReturn } from './core/create-http.js'
32
+ export {
33
+ ProcedureError,
34
+ ProcedureValidationError,
35
+ ProcedureRegistrationError,
36
+ ProcedureYieldValidationError,
37
+ } from './core/errors.js'
38
+ export type { ProcedureErrorKind } from './core/errors.js'
39
+ export { captureDefinitionInfo, formatDefinitionInfo } from './core/definition-site.js'
40
+ export type { DefinitionInfo, DefinitionLocation } from './core/definition-site.js'
41
+
42
+ // Schema — adapters, inference, validation
43
+ export type { SchemaAdapter } from './schema/adapter.js'
44
+ export { extractJsonSchema } from './schema/adapter.js'
45
+ export { typeboxAdapter, isTypeboxSchema } from './schema/typebox.js'
46
+ export { computeSchema } from './schema/compute-schema.js'
47
+ export type { ComputedSchema } from './schema/compute-schema.js'
48
+ export { createValidatorCompiler, DEFAULT_AJV_OPTIONS } from './schema/compile.js'
49
+ export type {
50
+ Validate,
51
+ ValidatorCompiler,
52
+ ValidationOptions,
53
+ TSchemaValidationError,
54
+ } from './schema/compile.js'
55
+ export type { Infer, TSchemaLib, TJSONSchema, Prettify } from './schema/json-schema.js'
56
+
57
+ // Doc envelope — offline codegen input
58
+ export { writeDocEnvelope } from './server/doc-envelope.js'
59
+ export type { DocEnvelopeSource } from './server/doc-envelope.js'
60
+ export type { DocEnvelope } from './server/types.js'
@@ -0,0 +1,58 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { Type } from 'typebox'
3
+ import { extractJsonSchema } from './adapter.js'
4
+ import type { SchemaAdapter } from './adapter.js'
5
+ import { typeboxAdapter } from './typebox.js'
6
+
7
+ describe('extractJsonSchema()', () => {
8
+ const typebox = Type.Object({ name: Type.String() })
9
+
10
+ test('it extracts TypeBox json-schema', () => {
11
+ expect(extractJsonSchema(typebox, [typeboxAdapter])).toMatchObject({
12
+ type: 'object',
13
+ properties: { name: { type: 'string' } },
14
+ required: ['name'],
15
+ })
16
+ })
17
+
18
+ test('it returns undefined when no adapter recognizes the value', () => {
19
+ expect(extractJsonSchema({ type: 'object' }, [typeboxAdapter])).toBeUndefined()
20
+ expect(extractJsonSchema('string value', [typeboxAdapter])).toBeUndefined()
21
+ expect(extractJsonSchema(null, [typeboxAdapter])).toBeUndefined()
22
+ expect(extractJsonSchema(undefined, [typeboxAdapter])).toBeUndefined()
23
+ })
24
+
25
+ test('it returns undefined when the adapter list is empty', () => {
26
+ expect(extractJsonSchema(typebox, [])).toBeUndefined()
27
+ })
28
+
29
+ test('it runs the adapter chain in order — first match wins', () => {
30
+ const everything: SchemaAdapter = {
31
+ name: 'everything',
32
+ detect: () => true,
33
+ toJsonSchema: () => ({ type: 'string' }),
34
+ }
35
+
36
+ // typeboxAdapter first: TypeBox schema goes through identity conversion
37
+ expect(extractJsonSchema(typebox, [typeboxAdapter, everything])).toBe(typebox)
38
+ // everything first: it claims the value before typeboxAdapter sees it
39
+ expect(extractJsonSchema(typebox, [everything, typeboxAdapter])).toEqual({ type: 'string' })
40
+ })
41
+
42
+ test('it supports custom adapters for non-TypeBox schema objects', () => {
43
+ class FakeZodType {
44
+ constructor(readonly jsonSchema: Record<string, any>) {}
45
+ }
46
+ const fakeZodAdapter: SchemaAdapter = {
47
+ name: 'fake-zod',
48
+ detect: (s) => s instanceof FakeZodType,
49
+ toJsonSchema: (s) => (s as FakeZodType).jsonSchema,
50
+ }
51
+
52
+ const schema = new FakeZodType({ type: 'object', properties: { id: { type: 'number' } } })
53
+ expect(extractJsonSchema(schema, [typeboxAdapter, fakeZodAdapter])).toEqual({
54
+ type: 'object',
55
+ properties: { id: { type: 'number' } },
56
+ })
57
+ })
58
+ })
@@ -0,0 +1,45 @@
1
+ import type { TJSONSchema } from './json-schema.js'
2
+
3
+ /**
4
+ * Bridges a schema library to the framework.
5
+ *
6
+ * The framework only ever needs one thing from a schema object: its JSON
7
+ * Schema. Everything downstream (AJV validation, route docs, codegen) works on
8
+ * JSON Schema. Implement this interface to plug in any schema library:
9
+ *
10
+ * ```ts
11
+ * const zodAdapter: SchemaAdapter = {
12
+ * name: 'zod',
13
+ * detect: (s) => s instanceof z.ZodType,
14
+ * toJsonSchema: (s) => z.toJSONSchema(s as z.ZodType),
15
+ * }
16
+ * const { Create } = Procedures({ schema: { adapters: [zodAdapter] } })
17
+ * ```
18
+ *
19
+ * Note: compile-time type inference (`Infer<T>`) is only built in for TypeBox;
20
+ * custom adapters get runtime validation and docs, with params inferred as
21
+ * `unknown` unless you annotate handler types yourself.
22
+ */
23
+ export interface SchemaAdapter {
24
+ /** Short identifier used in registration error messages. */
25
+ name: string
26
+ /** Whether this adapter recognizes the given schema object. */
27
+ detect(schema: unknown): boolean
28
+ /** Converts a recognized schema object to JSON Schema. */
29
+ toJsonSchema(schema: unknown): TJSONSchema
30
+ }
31
+
32
+ /**
33
+ * Runs the adapter chain against a schema value. Returns the JSON Schema from
34
+ * the first adapter whose `detect` matches, or `undefined` when no adapter
35
+ * recognizes the value (the caller reports the registration error).
36
+ */
37
+ export function extractJsonSchema(
38
+ schema: unknown,
39
+ adapters: readonly SchemaAdapter[],
40
+ ): TJSONSchema | undefined {
41
+ for (const adapter of adapters) {
42
+ if (adapter.detect(schema)) return adapter.toJsonSchema(schema)
43
+ }
44
+ return undefined
45
+ }
@@ -0,0 +1,95 @@
1
+ import { describe, expect, test } from 'vitest'
2
+ import { Type } from 'typebox'
3
+ import * as AJV from 'ajv'
4
+ import { createValidatorCompiler, DEFAULT_AJV_OPTIONS } from './compile.js'
5
+
6
+ describe('createValidatorCompiler', () => {
7
+ describe('default configuration', () => {
8
+ const compile = createValidatorCompiler()
9
+
10
+ test('validator returns {} on success', () => {
11
+ const validate = compile(Type.Object({ name: Type.String(), age: Type.Number() }))
12
+ const result = validate({ name: 'John', age: 30 })
13
+ expect(result).toEqual({})
14
+ expect(result.errors).toBeUndefined()
15
+ })
16
+
17
+ test('validator returns { errors } on failure', () => {
18
+ const validate = compile(Type.Object({ name: Type.String() }))
19
+ const result = validate({})
20
+ expect(result.errors).toBeDefined()
21
+ expect(result.errors?.[0]?.message).toMatch(/must have required property 'name'/)
22
+ })
23
+
24
+ test('allErrors: reports every failure, not just the first', () => {
25
+ const validate = compile(
26
+ Type.Object({ name: Type.String(), age: Type.Number() }),
27
+ )
28
+ const result = validate({ name: { nested: '' }, age: 'not-a-number' })
29
+ expect(result.errors?.length).toEqual(2)
30
+ })
31
+
32
+ test('coerceTypes: coerces primitive types in place', () => {
33
+ const validate = compile(Type.Object({ age: Type.Number() }))
34
+ const value: Record<string, unknown> = { age: '30' }
35
+ expect(validate(value).errors).toBeUndefined()
36
+ expect(value.age).toBe(30)
37
+ })
38
+
39
+ test('removeAdditional: strips unknown properties in place', () => {
40
+ const validate = compile(
41
+ Type.Object({ name: Type.String() }, { additionalProperties: false }),
42
+ )
43
+ const value: Record<string, unknown> = { name: 'John', extra: 'gone' }
44
+ expect(validate(value).errors).toBeUndefined()
45
+ expect(value).toEqual({ name: 'John' })
46
+ })
47
+
48
+ test('ajv-formats is wired in (format keywords validate)', () => {
49
+ const validate = compile(Type.Object({ email: Type.String({ format: 'email' }) }))
50
+ expect(validate({ email: 'john@example.com' }).errors).toBeUndefined()
51
+ expect(validate({ email: 'not-an-email' }).errors).toBeDefined()
52
+ })
53
+
54
+ test('compile throws on an invalid JSON schema', () => {
55
+ expect(() => compile({ type: 'invalid-schema-type' })).toThrow()
56
+ })
57
+
58
+ test('DEFAULT_AJV_OPTIONS matches the documented v8 behavior', () => {
59
+ expect(DEFAULT_AJV_OPTIONS).toEqual({
60
+ allErrors: true,
61
+ coerceTypes: true,
62
+ removeAdditional: true,
63
+ })
64
+ })
65
+ })
66
+
67
+ describe('custom AJV options merge over the defaults', () => {
68
+ test('coerceTypes: false disables coercion while keeping other defaults', () => {
69
+ const compile = createValidatorCompiler({ ajv: { coerceTypes: false } })
70
+ const validate = compile(Type.Object({ age: Type.Number(), name: Type.String() }))
71
+
72
+ // No coercion: a string is no longer accepted for a number
73
+ expect(validate({ age: '30', name: 'John' }).errors).toBeDefined()
74
+ expect(validate({ age: 30, name: 'John' }).errors).toBeUndefined()
75
+
76
+ // allErrors default still applies (both bad fields reported)
77
+ expect(validate({ age: 'x', name: 42 }).errors?.length).toEqual(2)
78
+ })
79
+ })
80
+
81
+ describe('preconfigured Ajv instance', () => {
82
+ test('uses the instance as-is (no default options applied)', () => {
83
+ const ajv = new AJV.Ajv() // no coerceTypes, no allErrors, no formats
84
+ const compile = createValidatorCompiler({ ajv })
85
+ const validate = compile(Type.Object({ age: Type.Number(), name: Type.String() }))
86
+
87
+ // No coercion from the default config
88
+ expect(validate({ age: '30', name: 'John' }).errors).toBeDefined()
89
+ // No allErrors: only the first failure is reported
90
+ expect(validate({ age: 'x', name: 42 }).errors?.length).toEqual(1)
91
+ // Valid input still passes
92
+ expect(validate({ age: 30, name: 'John' }).errors).toBeUndefined()
93
+ })
94
+ })
95
+ })
@@ -0,0 +1,64 @@
1
+ import { default as addFormats } from 'ajv-formats'
2
+ import * as AJV from 'ajv'
3
+ import type { TJSONSchema } from './json-schema.js'
4
+
5
+ export type TSchemaValidationError = AJV.ErrorObject
6
+
7
+ /**
8
+ * A compiled validator. Returns `{}` on success, `{ errors }` on failure —
9
+ * the same shape AJV-based validators have carried since v1, and the shape
10
+ * every registration's `config.validation.*` function exposes.
11
+ */
12
+ export type Validate = (value?: any) => { errors?: TSchemaValidationError[] }
13
+
14
+ /** Compiles a JSON Schema into a {@link Validate} function. */
15
+ export type ValidatorCompiler = (jsonSchema: TJSONSchema) => Validate
16
+
17
+ /**
18
+ * `Procedures({ validation })` shape:
19
+ * - omitted — validate with the default AJV configuration
20
+ * - `false` — skip per-call validation entirely (schemas/validators are still
21
+ * computed at registration time so bad schemas fail fast)
22
+ * - `{ ajv }` — custom AJV options merged over the defaults, or a fully
23
+ * configured `Ajv` instance to use as-is
24
+ */
25
+ export type ValidationOptions = false | { ajv?: AJV.Ajv | AJV.Options }
26
+
27
+ /**
28
+ * Default AJV configuration — unchanged from every prior major version:
29
+ * report all errors, coerce primitive types, strip unknown properties.
30
+ */
31
+ export const DEFAULT_AJV_OPTIONS: AJV.Options = {
32
+ allErrors: true,
33
+ coerceTypes: true,
34
+ removeAdditional: true,
35
+ }
36
+
37
+ function isAjvInstance(value: AJV.Ajv | AJV.Options | undefined): value is AJV.Ajv {
38
+ return typeof (value as { compile?: unknown } | undefined)?.compile === 'function'
39
+ }
40
+
41
+ /**
42
+ * Creates a {@link ValidatorCompiler} backed by AJV. Each `Procedures()`
43
+ * factory owns one compiler, so AJV configuration is per-factory instead of
44
+ * a module-level singleton.
45
+ */
46
+ export function createValidatorCompiler(options?: { ajv?: AJV.Ajv | AJV.Options }): ValidatorCompiler {
47
+ const ajv = isAjvInstance(options?.ajv)
48
+ ? options.ajv
49
+ : // eslint-disable-next-line @typescript-eslint/ban-ts-comment
50
+ // @ts-expect-error ajv-formats' types lag behind ajv's
51
+ (addFormats(new AJV.Ajv({ ...DEFAULT_AJV_OPTIONS, ...options?.ajv })) as AJV.Ajv)
52
+
53
+ return function compile(jsonSchema: TJSONSchema): Validate {
54
+ const validator = ajv.compile(jsonSchema)
55
+ return (value?: any) => {
56
+ const valid = validator(value)
57
+ if (!valid) {
58
+ const errors = validator.errors
59
+ return { errors: errors?.length ? [...errors] : undefined }
60
+ }
61
+ return {}
62
+ }
63
+ }
64
+ }