ts-procedures 8.5.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (635) hide show
  1. package/README.md +166 -101
  2. package/agent_config/claude-code/.claude-plugin/plugin.json +1 -1
  3. package/agent_config/claude-code/agents/ts-procedures-architect.md +11 -10
  4. package/agent_config/claude-code/skills/ts-procedures/SKILL.md +25 -12
  5. package/agent_config/claude-code/skills/ts-procedures/anti-patterns.md +10 -12
  6. package/agent_config/claude-code/skills/ts-procedures/api-reference.md +141 -45
  7. package/agent_config/claude-code/skills/ts-procedures/checklist.md +7 -6
  8. package/agent_config/claude-code/skills/ts-procedures/patterns.md +45 -6
  9. package/agent_config/claude-code/skills/ts-procedures/templates/client.md +1 -1
  10. package/agent_config/claude-code/skills/ts-procedures/templates/hono.md +1 -1
  11. package/agent_config/copilot/copilot-instructions.md +50 -33
  12. package/agent_config/cursor/cursorrules +50 -33
  13. package/build/adapters/astro/astro-context.js.map +1 -0
  14. package/build/adapters/astro/create-handler.js.map +1 -0
  15. package/build/adapters/astro/index.js.map +1 -0
  16. package/build/{implementations/http → adapters}/astro/index.test.js +1 -1
  17. package/build/adapters/astro/index.test.js.map +1 -0
  18. package/build/adapters/astro/rewrite-request.js.map +1 -0
  19. package/build/adapters/hono/envelope-parity.test.js +98 -0
  20. package/build/adapters/hono/envelope-parity.test.js.map +1 -0
  21. package/build/{implementations/http → adapters}/hono/handlers/http-stream.d.ts +1 -1
  22. package/build/adapters/hono/handlers/http-stream.js +55 -0
  23. package/build/adapters/hono/handlers/http-stream.js.map +1 -0
  24. package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.js +1 -1
  25. package/build/adapters/hono/handlers/http-stream.test.js.map +1 -0
  26. package/build/{implementations/http → adapters}/hono/handlers/http.d.ts +1 -1
  27. package/build/adapters/hono/handlers/http.js +50 -0
  28. package/build/adapters/hono/handlers/http.js.map +1 -0
  29. package/build/{implementations/http → adapters}/hono/handlers/http.test.js +1 -1
  30. package/build/adapters/hono/handlers/http.test.js.map +1 -0
  31. package/build/{implementations/http → adapters}/hono/handlers/rpc.d.ts +2 -2
  32. package/build/adapters/hono/handlers/rpc.js +23 -0
  33. package/build/adapters/hono/handlers/rpc.js.map +1 -0
  34. package/build/{implementations/http → adapters}/hono/handlers/rpc.test.js +1 -1
  35. package/build/adapters/hono/handlers/rpc.test.js.map +1 -0
  36. package/build/adapters/hono/handlers/stream.d.ts +12 -0
  37. package/build/adapters/hono/handlers/stream.js +89 -0
  38. package/build/adapters/hono/handlers/stream.js.map +1 -0
  39. package/build/{implementations/http → adapters}/hono/handlers/stream.test.js +3 -2
  40. package/build/adapters/hono/handlers/stream.test.js.map +1 -0
  41. package/build/{implementations/http → adapters}/hono/index.d.ts +24 -12
  42. package/build/{implementations/http → adapters}/hono/index.js +19 -8
  43. package/build/adapters/hono/index.js.map +1 -0
  44. package/build/{implementations/http → adapters}/hono/index.test.js +2 -4
  45. package/build/adapters/hono/index.test.js.map +1 -0
  46. package/build/{implementations/http → adapters/hono}/on-request-error.test.js +2 -2
  47. package/build/adapters/hono/on-request-error.test.js.map +1 -0
  48. package/build/adapters/hono/request.d.ts +7 -0
  49. package/build/adapters/hono/request.js +22 -0
  50. package/build/adapters/hono/request.js.map +1 -0
  51. package/build/{implementations/http → adapters/hono}/route-errors.test.js +4 -4
  52. package/build/adapters/hono/route-errors.test.js.map +1 -0
  53. package/build/adapters/hono/types.d.ts +55 -0
  54. package/build/adapters/hono/types.js +19 -0
  55. package/build/adapters/hono/types.js.map +1 -0
  56. package/build/client/freeze.test.js +39 -0
  57. package/build/client/freeze.test.js.map +1 -0
  58. package/build/client/typed-error-dispatch.test.js +2 -2
  59. package/build/client/typed-error-dispatch.test.js.map +1 -1
  60. package/build/codegen/__fixtures__/make-envelope.d.ts +1 -1
  61. package/build/codegen/bin/cli.d.ts +5 -0
  62. package/build/codegen/bin/cli.js +139 -182
  63. package/build/codegen/bin/cli.js.map +1 -1
  64. package/build/codegen/bin/cli.test.js +12 -2
  65. package/build/codegen/bin/cli.test.js.map +1 -1
  66. package/build/codegen/bin/flag-specs.d.ts +9 -0
  67. package/build/codegen/bin/flag-specs.js +33 -31
  68. package/build/codegen/bin/flag-specs.js.map +1 -1
  69. package/build/codegen/bin/flag-specs.test.js +14 -1
  70. package/build/codegen/bin/flag-specs.test.js.map +1 -1
  71. package/build/codegen/collect-models.d.ts +1 -1
  72. package/build/codegen/emit/api-route.d.ts +8 -0
  73. package/build/codegen/emit/api-route.js +156 -0
  74. package/build/codegen/emit/api-route.js.map +1 -0
  75. package/build/codegen/emit/context.d.ts +30 -0
  76. package/build/codegen/emit/context.js +2 -0
  77. package/build/codegen/emit/context.js.map +1 -0
  78. package/build/codegen/emit/declarations.d.ts +24 -0
  79. package/build/codegen/emit/declarations.js +48 -0
  80. package/build/codegen/emit/declarations.js.map +1 -0
  81. package/build/codegen/emit/format-types.d.ts +61 -0
  82. package/build/codegen/emit/format-types.js +188 -0
  83. package/build/codegen/emit/format-types.js.map +1 -0
  84. package/build/codegen/emit/http-stream-route.d.ts +7 -0
  85. package/build/codegen/emit/http-stream-route.js +138 -0
  86. package/build/codegen/emit/http-stream-route.js.map +1 -0
  87. package/build/codegen/emit/route-shared.d.ts +35 -0
  88. package/build/codegen/emit/route-shared.js +88 -0
  89. package/build/codegen/emit/route-shared.js.map +1 -0
  90. package/build/codegen/emit/rpc-route.d.ts +7 -0
  91. package/build/codegen/emit/rpc-route.js +37 -0
  92. package/build/codegen/emit/rpc-route.js.map +1 -0
  93. package/build/codegen/emit/scope-file.d.ts +39 -0
  94. package/build/codegen/emit/scope-file.js +166 -0
  95. package/build/codegen/emit/scope-file.js.map +1 -0
  96. package/build/codegen/emit/stream-route.d.ts +7 -0
  97. package/build/codegen/emit/stream-route.js +62 -0
  98. package/build/codegen/emit/stream-route.js.map +1 -0
  99. package/build/codegen/emit-errors.d.ts +1 -1
  100. package/build/codegen/emit-errors.integration.test.js +1 -1
  101. package/build/codegen/emit-errors.integration.test.js.map +1 -1
  102. package/build/codegen/emit-index.js +13 -0
  103. package/build/codegen/emit-index.js.map +1 -1
  104. package/build/codegen/emit-index.test.js +25 -0
  105. package/build/codegen/emit-index.test.js.map +1 -1
  106. package/build/codegen/emit-scope.d.ts +13 -30
  107. package/build/codegen/emit-scope.js +15 -807
  108. package/build/codegen/emit-scope.js.map +1 -1
  109. package/build/codegen/emit-scope.test.js +86 -4
  110. package/build/codegen/emit-scope.test.js.map +1 -1
  111. package/build/codegen/goldens.test.js +69 -0
  112. package/build/codegen/goldens.test.js.map +1 -0
  113. package/build/codegen/group-routes.d.ts +1 -1
  114. package/build/codegen/pipeline.d.ts +1 -1
  115. package/build/codegen/resolve-envelope.d.ts +1 -1
  116. package/build/codegen/targets/_shared/error-schemas.d.ts +1 -1
  117. package/build/codegen/targets/_shared/route-slots.d.ts +1 -1
  118. package/build/codegen/targets/_shared/target-run.d.ts +1 -1
  119. package/build/codegen/targets/kotlin/emit-route-kotlin.d.ts +1 -1
  120. package/build/codegen/targets/swift/emit-route-swift.d.ts +1 -1
  121. package/build/core/create-http-stream.d.ts +50 -0
  122. package/build/core/create-http-stream.js +108 -0
  123. package/build/core/create-http-stream.js.map +1 -0
  124. package/build/{create-http-stream.test.js → core/create-http-stream.test.js} +1 -1
  125. package/build/core/create-http-stream.test.js.map +1 -0
  126. package/build/core/create-http.d.ts +51 -0
  127. package/build/core/create-http.js +65 -0
  128. package/build/core/create-http.js.map +1 -0
  129. package/build/{create-http.test.js → core/create-http.test.js} +13 -4
  130. package/build/core/create-http.test.js.map +1 -0
  131. package/build/core/create-stream.d.ts +26 -0
  132. package/build/core/create-stream.js +80 -0
  133. package/build/core/create-stream.js.map +1 -0
  134. package/build/{create-stream.test.js → core/create-stream.test.js} +23 -28
  135. package/build/core/create-stream.test.js.map +1 -0
  136. package/build/core/create.d.ts +22 -0
  137. package/build/core/create.js +71 -0
  138. package/build/core/create.js.map +1 -0
  139. package/build/{create.test.js → core/create.test.js} +25 -46
  140. package/build/core/create.test.js.map +1 -0
  141. package/build/core/definition-site.d.ts +24 -0
  142. package/build/{stack-utils.js → core/definition-site.js} +20 -20
  143. package/build/core/definition-site.js.map +1 -0
  144. package/build/{stack-utils.test.js → core/definition-site.test.js} +12 -3
  145. package/build/core/definition-site.test.js.map +1 -0
  146. package/build/{errors.d.ts → core/errors.d.ts} +19 -8
  147. package/build/{errors.js → core/errors.js} +21 -26
  148. package/build/core/errors.js.map +1 -0
  149. package/build/core/errors.test.js.map +1 -0
  150. package/build/core/factory-options.test.js +82 -0
  151. package/build/core/factory-options.test.js.map +1 -0
  152. package/build/core/http-route.d.ts +13 -0
  153. package/build/core/http-route.js +54 -0
  154. package/build/core/http-route.js.map +1 -0
  155. package/build/core/internal.d.ts +72 -0
  156. package/build/core/internal.js +128 -0
  157. package/build/core/internal.js.map +1 -0
  158. package/build/{migration.test.js → core/migration.test.js} +17 -1
  159. package/build/core/migration.test.js.map +1 -0
  160. package/build/core/procedures.d.ts +143 -0
  161. package/build/core/procedures.js +64 -0
  162. package/build/core/procedures.js.map +1 -0
  163. package/build/{index.test.js → core/procedures.test.js} +14 -11
  164. package/build/core/procedures.test.js.map +1 -0
  165. package/build/core/types.d.ts +182 -0
  166. package/build/{schema → core}/types.js.map +1 -1
  167. package/build/exports.d.ts +31 -11
  168. package/build/exports.js +23 -8
  169. package/build/exports.js.map +1 -1
  170. package/build/schema/adapter.d.ts +35 -0
  171. package/build/schema/adapter.js +13 -0
  172. package/build/schema/adapter.js.map +1 -0
  173. package/build/schema/adapter.test.js +53 -0
  174. package/build/schema/adapter.test.js.map +1 -0
  175. package/build/schema/compile.d.ts +37 -0
  176. package/build/schema/compile.js +38 -0
  177. package/build/schema/compile.js.map +1 -0
  178. package/build/schema/compile.test.js +78 -0
  179. package/build/schema/compile.test.js.map +1 -0
  180. package/build/schema/compute-schema.d.ts +47 -37
  181. package/build/schema/compute-schema.js +86 -29
  182. package/build/schema/compute-schema.js.map +1 -1
  183. package/build/schema/compute-schema.test.js +158 -40
  184. package/build/schema/compute-schema.test.js.map +1 -1
  185. package/build/schema/json-schema.d.ts +17 -0
  186. package/build/schema/json-schema.js +2 -0
  187. package/build/schema/json-schema.js.map +1 -0
  188. package/build/schema/typebox.d.ts +11 -0
  189. package/build/schema/typebox.js +24 -0
  190. package/build/schema/typebox.js.map +1 -0
  191. package/build/schema/typebox.test.js +34 -0
  192. package/build/schema/typebox.test.js.map +1 -0
  193. package/build/server/context.d.ts +8 -0
  194. package/build/server/context.js +7 -0
  195. package/build/server/context.js.map +1 -0
  196. package/build/server/context.test.js +16 -0
  197. package/build/server/context.test.js.map +1 -0
  198. package/build/{doc-envelope.d.ts → server/doc-envelope.d.ts} +1 -1
  199. package/build/server/doc-envelope.js.map +1 -0
  200. package/build/server/doc-envelope.test.d.ts +1 -0
  201. package/build/server/doc-envelope.test.js.map +1 -0
  202. package/build/{implementations/http → server}/doc-registry.d.ts +7 -2
  203. package/build/{implementations/http → server}/doc-registry.js +9 -5
  204. package/build/server/doc-registry.js.map +1 -0
  205. package/build/server/doc-registry.test.d.ts +1 -0
  206. package/build/{implementations/http → server}/doc-registry.test.js +27 -24
  207. package/build/server/doc-registry.test.js.map +1 -0
  208. package/build/server/docs/docs.test.d.ts +1 -0
  209. package/build/server/docs/docs.test.js +237 -0
  210. package/build/server/docs/docs.test.js.map +1 -0
  211. package/build/{implementations/http/hono → server}/docs/http-doc.d.ts +2 -2
  212. package/build/{implementations/http/hono → server}/docs/http-doc.js +1 -1
  213. package/build/server/docs/http-doc.js.map +1 -0
  214. package/build/{implementations/http/hono → server}/docs/http-stream-doc.d.ts +2 -2
  215. package/build/{implementations/http/hono → server}/docs/http-stream-doc.js +1 -1
  216. package/build/server/docs/http-stream-doc.js.map +1 -0
  217. package/build/{implementations/http/hono → server}/docs/rpc-doc.d.ts +2 -2
  218. package/build/{implementations/http/hono → server}/docs/rpc-doc.js +1 -1
  219. package/build/server/docs/rpc-doc.js.map +1 -0
  220. package/build/{implementations/http/hono → server}/docs/stream-doc.d.ts +2 -2
  221. package/build/{implementations/http/hono → server}/docs/stream-doc.js +1 -1
  222. package/build/server/docs/stream-doc.js.map +1 -0
  223. package/build/server/errors/dispatch.d.ts +96 -0
  224. package/build/{implementations/http/error-dispatch.js → server/errors/dispatch.js} +20 -10
  225. package/build/server/errors/dispatch.js.map +1 -0
  226. package/build/server/errors/dispatch.test.d.ts +1 -0
  227. package/build/server/errors/dispatch.test.js +418 -0
  228. package/build/server/errors/dispatch.test.js.map +1 -0
  229. package/build/{implementations/http/error-taxonomy.d.ts → server/errors/taxonomy.d.ts} +8 -17
  230. package/build/{implementations/http/error-taxonomy.js → server/errors/taxonomy.js} +6 -15
  231. package/build/server/errors/taxonomy.js.map +1 -0
  232. package/build/server/errors/taxonomy.test.d.ts +1 -0
  233. package/build/{implementations/http/error-taxonomy.test.js → server/errors/taxonomy.test.js} +45 -39
  234. package/build/server/errors/taxonomy.test.js.map +1 -0
  235. package/build/server/index.d.ts +29 -0
  236. package/build/server/index.js +27 -0
  237. package/build/server/index.js.map +1 -0
  238. package/build/server/no-framework-imports.test.d.ts +1 -0
  239. package/build/server/no-framework-imports.test.js +40 -0
  240. package/build/server/no-framework-imports.test.js.map +1 -0
  241. package/build/{implementations/http/hono/path.d.ts → server/paths.d.ts} +2 -3
  242. package/build/{implementations/http/hono/path.js → server/paths.js} +1 -1
  243. package/build/server/paths.js.map +1 -0
  244. package/build/server/paths.test.d.ts +1 -0
  245. package/build/server/paths.test.js +111 -0
  246. package/build/server/paths.test.js.map +1 -0
  247. package/build/server/request/params.d.ts +29 -0
  248. package/build/server/request/params.js +43 -0
  249. package/build/server/request/params.js.map +1 -0
  250. package/build/server/request/params.test.d.ts +1 -0
  251. package/build/server/request/params.test.js +91 -0
  252. package/build/server/request/params.test.js.map +1 -0
  253. package/build/server/request/query.d.ts +9 -0
  254. package/build/server/request/query.js +22 -0
  255. package/build/server/request/query.js.map +1 -0
  256. package/build/server/request/query.test.d.ts +1 -0
  257. package/build/server/request/query.test.js +60 -0
  258. package/build/server/request/query.test.js.map +1 -0
  259. package/build/server/sse.d.ts +70 -0
  260. package/build/server/sse.js +94 -0
  261. package/build/server/sse.js.map +1 -0
  262. package/build/server/sse.test.d.ts +1 -0
  263. package/build/server/sse.test.js +98 -0
  264. package/build/server/sse.test.js.map +1 -0
  265. package/build/{implementations → server}/types.d.ts +17 -15
  266. package/build/{implementations → server}/types.js.map +1 -1
  267. package/docs/astro-adapter.md +8 -9
  268. package/docs/client-and-codegen.md +4 -4
  269. package/docs/client-error-handling.md +92 -5
  270. package/docs/codegen-kotlin.md +2 -3
  271. package/docs/codegen-swift.md +1 -2
  272. package/docs/core.md +135 -54
  273. package/docs/http-integrations.md +83 -6
  274. package/docs/migration-v8-to-v9.md +192 -0
  275. package/docs/plans/2026-06-09-v9-rewrite.md +130 -0
  276. package/docs/specs/2026-06-09-v9-rewrite-design.md +221 -0
  277. package/docs/streaming.md +12 -0
  278. package/package.json +23 -47
  279. package/src/{implementations/http → adapters}/astro/index.test.ts +2 -2
  280. package/src/adapters/hono/__fixtures__/parity-envelope.json +389 -0
  281. package/src/adapters/hono/envelope-parity.test.ts +126 -0
  282. package/src/{implementations/http → adapters}/hono/handlers/http-stream.test.ts +1 -1
  283. package/src/adapters/hono/handlers/http-stream.ts +73 -0
  284. package/src/{implementations/http → adapters}/hono/handlers/http.test.ts +1 -1
  285. package/src/adapters/hono/handlers/http.ts +70 -0
  286. package/src/{implementations/http → adapters}/hono/handlers/rpc.test.ts +2 -2
  287. package/src/adapters/hono/handlers/rpc.ts +39 -0
  288. package/src/{implementations/http → adapters}/hono/handlers/stream.test.ts +4 -3
  289. package/src/{implementations/http → adapters}/hono/handlers/stream.ts +19 -92
  290. package/src/{implementations/http → adapters}/hono/index.test.ts +14 -16
  291. package/src/{implementations/http → adapters}/hono/index.ts +35 -30
  292. package/src/{implementations/http → adapters/hono}/on-request-error.test.ts +3 -3
  293. package/src/adapters/hono/request.ts +28 -0
  294. package/src/{implementations/http → adapters/hono}/route-errors.test.ts +5 -5
  295. package/src/{implementations/http → adapters}/hono/types.ts +43 -20
  296. package/src/client/freeze.test.ts +41 -0
  297. package/src/client/typed-error-dispatch.test.ts +3 -3
  298. package/src/codegen/__fixtures__/make-envelope.ts +1 -1
  299. package/src/codegen/__fixtures__/models-envelope.json +310 -0
  300. package/src/codegen/__fixtures__/users-envelope.json +9 -0
  301. package/src/codegen/__goldens__/MANIFEST.json +85 -0
  302. package/src/codegen/__goldens__/kotlin-default--models/Billing.kt +112 -0
  303. package/src/codegen/__goldens__/kotlin-default--models/BillingReports.kt +26 -0
  304. package/src/codegen/__goldens__/kotlin-default--models/Orders.kt +88 -0
  305. package/src/codegen/__goldens__/kotlin-default--users/Users.kt +189 -0
  306. package/src/codegen/__goldens__/swift-default--models/Billing.swift +97 -0
  307. package/src/codegen/__goldens__/swift-default--models/BillingReports.swift +20 -0
  308. package/src/codegen/__goldens__/swift-default--models/Orders.swift +81 -0
  309. package/src/codegen/__goldens__/swift-default--users/Users.swift +204 -0
  310. package/src/codegen/__goldens__/ts-default--models/_client.ts +1319 -0
  311. package/src/codegen/__goldens__/ts-default--models/_errors.ts +90 -0
  312. package/src/codegen/__goldens__/ts-default--models/_models.ts +10 -0
  313. package/src/codegen/__goldens__/ts-default--models/_types.ts +502 -0
  314. package/src/codegen/__goldens__/ts-default--models/billing-reports.ts +29 -0
  315. package/src/codegen/__goldens__/ts-default--models/billing.ts +67 -0
  316. package/src/codegen/__goldens__/ts-default--models/index.ts +48 -0
  317. package/src/codegen/__goldens__/ts-default--models/orders.ts +80 -0
  318. package/src/codegen/__goldens__/ts-default--users/_client.ts +1319 -0
  319. package/src/codegen/__goldens__/ts-default--users/_errors.ts +90 -0
  320. package/src/codegen/__goldens__/ts-default--users/_types.ts +502 -0
  321. package/src/codegen/__goldens__/ts-default--users/index.ts +38 -0
  322. package/src/codegen/__goldens__/ts-default--users/users.ts +169 -0
  323. package/src/codegen/__goldens__/ts-external-runtime--models/_errors.ts +90 -0
  324. package/src/codegen/__goldens__/ts-external-runtime--models/_models.ts +10 -0
  325. package/src/codegen/__goldens__/ts-external-runtime--models/billing-reports.ts +29 -0
  326. package/src/codegen/__goldens__/ts-external-runtime--models/billing.ts +67 -0
  327. package/src/codegen/__goldens__/ts-external-runtime--models/index.ts +48 -0
  328. package/src/codegen/__goldens__/ts-external-runtime--models/orders.ts +80 -0
  329. package/src/codegen/__goldens__/ts-external-runtime--users/_errors.ts +90 -0
  330. package/src/codegen/__goldens__/ts-external-runtime--users/index.ts +38 -0
  331. package/src/codegen/__goldens__/ts-external-runtime--users/users.ts +169 -0
  332. package/src/codegen/__goldens__/ts-flat--models/_client.ts +1319 -0
  333. package/src/codegen/__goldens__/ts-flat--models/_errors.ts +87 -0
  334. package/src/codegen/__goldens__/ts-flat--models/_models.ts +10 -0
  335. package/src/codegen/__goldens__/ts-flat--models/_types.ts +502 -0
  336. package/src/codegen/__goldens__/ts-flat--models/billing-reports.ts +28 -0
  337. package/src/codegen/__goldens__/ts-flat--models/billing.ts +51 -0
  338. package/src/codegen/__goldens__/ts-flat--models/index.ts +42 -0
  339. package/src/codegen/__goldens__/ts-flat--models/orders.ts +73 -0
  340. package/src/codegen/__goldens__/ts-flat--users/_client.ts +1319 -0
  341. package/src/codegen/__goldens__/ts-flat--users/_errors.ts +87 -0
  342. package/src/codegen/__goldens__/ts-flat--users/_types.ts +502 -0
  343. package/src/codegen/__goldens__/ts-flat--users/index.ts +34 -0
  344. package/src/codegen/__goldens__/ts-flat--users/users.ts +126 -0
  345. package/src/codegen/__goldens__/ts-no-share-models--models/_client.ts +1319 -0
  346. package/src/codegen/__goldens__/ts-no-share-models--models/_errors.ts +90 -0
  347. package/src/codegen/__goldens__/ts-no-share-models--models/_types.ts +502 -0
  348. package/src/codegen/__goldens__/ts-no-share-models--models/billing-reports.ts +29 -0
  349. package/src/codegen/__goldens__/ts-no-share-models--models/billing.ts +111 -0
  350. package/src/codegen/__goldens__/ts-no-share-models--models/index.ts +48 -0
  351. package/src/codegen/__goldens__/ts-no-share-models--models/orders.ts +112 -0
  352. package/src/codegen/__goldens__/ts-no-share-models--users/_client.ts +1319 -0
  353. package/src/codegen/__goldens__/ts-no-share-models--users/_errors.ts +90 -0
  354. package/src/codegen/__goldens__/ts-no-share-models--users/_types.ts +502 -0
  355. package/src/codegen/__goldens__/ts-no-share-models--users/index.ts +38 -0
  356. package/src/codegen/__goldens__/ts-no-share-models--users/users.ts +169 -0
  357. package/src/codegen/__goldens__/ts-shared-models-module--models/_client.ts +1319 -0
  358. package/src/codegen/__goldens__/ts-shared-models-module--models/_errors.ts +90 -0
  359. package/src/codegen/__goldens__/ts-shared-models-module--models/_models.ts +7 -0
  360. package/src/codegen/__goldens__/ts-shared-models-module--models/_types.ts +502 -0
  361. package/src/codegen/__goldens__/ts-shared-models-module--models/billing-reports.ts +29 -0
  362. package/src/codegen/__goldens__/ts-shared-models-module--models/billing.ts +67 -0
  363. package/src/codegen/__goldens__/ts-shared-models-module--models/index.ts +48 -0
  364. package/src/codegen/__goldens__/ts-shared-models-module--models/orders.ts +80 -0
  365. package/src/codegen/bin/cli.test.ts +13 -2
  366. package/src/codegen/bin/cli.ts +181 -144
  367. package/src/codegen/bin/flag-specs.test.ts +16 -1
  368. package/src/codegen/bin/flag-specs.ts +43 -31
  369. package/src/codegen/bundle-size.test.ts +1 -1
  370. package/src/codegen/collect-models.ts +1 -1
  371. package/src/codegen/e2e.test.ts +1 -1
  372. package/src/codegen/emit/api-route.ts +184 -0
  373. package/src/codegen/emit/context.ts +32 -0
  374. package/src/codegen/emit/declarations.ts +49 -0
  375. package/src/codegen/emit/format-types.ts +232 -0
  376. package/src/codegen/emit/http-stream-route.ts +162 -0
  377. package/src/codegen/emit/route-shared.ts +102 -0
  378. package/src/codegen/emit/rpc-route.ts +49 -0
  379. package/src/codegen/emit/scope-file.ts +226 -0
  380. package/src/codegen/emit/stream-route.ts +81 -0
  381. package/src/codegen/emit-errors.integration.test.ts +2 -2
  382. package/src/codegen/emit-errors.test.ts +1 -1
  383. package/src/codegen/emit-errors.ts +1 -1
  384. package/src/codegen/emit-index.test.ts +34 -0
  385. package/src/codegen/emit-index.ts +19 -0
  386. package/src/codegen/emit-scope.test.ts +96 -6
  387. package/src/codegen/emit-scope.ts +15 -1003
  388. package/src/codegen/goldens.test.ts +89 -0
  389. package/src/codegen/group-routes.test.ts +1 -1
  390. package/src/codegen/group-routes.ts +1 -1
  391. package/src/codegen/pipeline.test.ts +1 -1
  392. package/src/codegen/pipeline.ts +1 -1
  393. package/src/codegen/resolve-envelope.test.ts +1 -1
  394. package/src/codegen/resolve-envelope.ts +1 -1
  395. package/src/codegen/targets/_shared/error-schemas.test.ts +1 -1
  396. package/src/codegen/targets/_shared/error-schemas.ts +1 -1
  397. package/src/codegen/targets/_shared/route-slots.test.ts +1 -1
  398. package/src/codegen/targets/_shared/route-slots.ts +1 -1
  399. package/src/codegen/targets/_shared/target-run.ts +1 -1
  400. package/src/codegen/targets/kotlin/__fixtures__/users-golden.kt +6 -0
  401. package/src/codegen/targets/kotlin/emit-route-kotlin.test.ts +1 -1
  402. package/src/codegen/targets/kotlin/emit-route-kotlin.ts +1 -1
  403. package/src/codegen/targets/kotlin/emit-scope-kotlin.test.ts +1 -1
  404. package/src/codegen/targets/swift/__fixtures__/users-golden.swift +6 -0
  405. package/src/codegen/targets/swift/access-level.test.ts +1 -1
  406. package/src/codegen/targets/swift/emit-route-swift.test.ts +1 -1
  407. package/src/codegen/targets/swift/emit-route-swift.ts +1 -1
  408. package/src/codegen/targets/swift/emit-scope-swift.test.ts +1 -1
  409. package/src/codegen/targets/ts/shared-models.test.ts +1 -1
  410. package/src/{create-http-stream.test.ts → core/create-http-stream.test.ts} +1 -1
  411. package/src/core/create-http-stream.ts +207 -0
  412. package/src/{create-http.test.ts → core/create-http.test.ts} +15 -4
  413. package/src/core/create-http.ts +126 -0
  414. package/src/{create-stream.test.ts → core/create-stream.test.ts} +28 -31
  415. package/src/core/create-stream.ts +142 -0
  416. package/src/{create.test.ts → core/create.test.ts} +25 -57
  417. package/src/core/create.ts +121 -0
  418. package/src/{stack-utils.test.ts → core/definition-site.test.ts} +14 -3
  419. package/src/{stack-utils.ts → core/definition-site.ts} +20 -23
  420. package/src/{errors.test.ts → core/errors.test.ts} +1 -1
  421. package/src/{errors.ts → core/errors.ts} +30 -28
  422. package/src/core/factory-options.test.ts +112 -0
  423. package/src/core/http-route.ts +73 -0
  424. package/src/core/internal.ts +203 -0
  425. package/src/{migration.test.ts → core/migration.test.ts} +23 -1
  426. package/src/{index.test.ts → core/procedures.test.ts} +13 -11
  427. package/src/core/procedures.ts +75 -0
  428. package/src/core/types.ts +195 -0
  429. package/src/exports.ts +60 -11
  430. package/src/schema/adapter.test.ts +58 -0
  431. package/src/schema/adapter.ts +45 -0
  432. package/src/schema/compile.test.ts +95 -0
  433. package/src/schema/compile.ts +64 -0
  434. package/src/schema/compute-schema.test.ts +222 -41
  435. package/src/schema/compute-schema.ts +145 -71
  436. package/src/schema/json-schema.ts +21 -0
  437. package/src/schema/typebox.test.ts +40 -0
  438. package/src/schema/typebox.ts +27 -0
  439. package/src/server/context.test.ts +22 -0
  440. package/src/server/context.ts +18 -0
  441. package/src/{doc-envelope.test.ts → server/doc-envelope.test.ts} +2 -2
  442. package/src/{doc-envelope.ts → server/doc-envelope.ts} +1 -1
  443. package/src/{implementations/http → server}/doc-registry.test.ts +32 -26
  444. package/src/{implementations/http → server}/doc-registry.ts +11 -7
  445. package/src/server/docs/docs.test.ts +287 -0
  446. package/src/{implementations/http/hono → server}/docs/http-doc.ts +3 -3
  447. package/src/{implementations/http/hono → server}/docs/http-stream-doc.ts +3 -3
  448. package/src/{implementations/http/hono → server}/docs/rpc-doc.ts +3 -3
  449. package/src/{implementations/http/hono → server}/docs/stream-doc.ts +3 -3
  450. package/src/server/errors/dispatch.test.ts +450 -0
  451. package/src/server/errors/dispatch.ts +189 -0
  452. package/src/{implementations/http/error-taxonomy.test.ts → server/errors/taxonomy.test.ts} +45 -39
  453. package/src/{implementations/http/error-taxonomy.ts → server/errors/taxonomy.ts} +8 -17
  454. package/src/server/index.ts +29 -0
  455. package/src/server/no-framework-imports.test.ts +43 -0
  456. package/src/server/paths.test.ts +141 -0
  457. package/src/{implementations/http/hono/path.ts → server/paths.ts} +2 -13
  458. package/src/server/request/params.test.ts +143 -0
  459. package/src/server/request/params.ts +68 -0
  460. package/src/server/request/query.test.ts +70 -0
  461. package/src/server/request/query.ts +24 -0
  462. package/src/server/sse.test.ts +113 -0
  463. package/src/server/sse.ts +117 -0
  464. package/src/{implementations → server}/types.ts +17 -16
  465. package/build/create-http-stream.d.ts +0 -58
  466. package/build/create-http-stream.js +0 -122
  467. package/build/create-http-stream.js.map +0 -1
  468. package/build/create-http-stream.test.js.map +0 -1
  469. package/build/create-http.d.ts +0 -49
  470. package/build/create-http.js +0 -108
  471. package/build/create-http.js.map +0 -1
  472. package/build/create-http.test.js.map +0 -1
  473. package/build/create-stream.d.ts +0 -35
  474. package/build/create-stream.js +0 -123
  475. package/build/create-stream.js.map +0 -1
  476. package/build/create-stream.test.js.map +0 -1
  477. package/build/create.d.ts +0 -28
  478. package/build/create.js +0 -82
  479. package/build/create.js.map +0 -1
  480. package/build/create.test.js.map +0 -1
  481. package/build/doc-envelope.js.map +0 -1
  482. package/build/doc-envelope.test.js.map +0 -1
  483. package/build/errors.js.map +0 -1
  484. package/build/errors.test.js.map +0 -1
  485. package/build/implementations/http/astro/astro-context.js.map +0 -1
  486. package/build/implementations/http/astro/create-handler.js.map +0 -1
  487. package/build/implementations/http/astro/index.js.map +0 -1
  488. package/build/implementations/http/astro/index.test.js.map +0 -1
  489. package/build/implementations/http/astro/rewrite-request.js.map +0 -1
  490. package/build/implementations/http/doc-registry.js.map +0 -1
  491. package/build/implementations/http/doc-registry.test.js.map +0 -1
  492. package/build/implementations/http/error-dispatch.d.ts +0 -76
  493. package/build/implementations/http/error-dispatch.js.map +0 -1
  494. package/build/implementations/http/error-dispatch.test.js +0 -254
  495. package/build/implementations/http/error-dispatch.test.js.map +0 -1
  496. package/build/implementations/http/error-taxonomy.js.map +0 -1
  497. package/build/implementations/http/error-taxonomy.test.js.map +0 -1
  498. package/build/implementations/http/hono/docs/http-doc.js.map +0 -1
  499. package/build/implementations/http/hono/docs/http-stream-doc.js.map +0 -1
  500. package/build/implementations/http/hono/docs/rpc-doc.js.map +0 -1
  501. package/build/implementations/http/hono/docs/stream-doc.js.map +0 -1
  502. package/build/implementations/http/hono/handlers/http-stream.js +0 -123
  503. package/build/implementations/http/hono/handlers/http-stream.js.map +0 -1
  504. package/build/implementations/http/hono/handlers/http-stream.test.js.map +0 -1
  505. package/build/implementations/http/hono/handlers/http.js +0 -110
  506. package/build/implementations/http/hono/handlers/http.js.map +0 -1
  507. package/build/implementations/http/hono/handlers/http.test.js.map +0 -1
  508. package/build/implementations/http/hono/handlers/rpc.js +0 -32
  509. package/build/implementations/http/hono/handlers/rpc.js.map +0 -1
  510. package/build/implementations/http/hono/handlers/rpc.test.js.map +0 -1
  511. package/build/implementations/http/hono/handlers/stream.d.ts +0 -23
  512. package/build/implementations/http/hono/handlers/stream.js +0 -147
  513. package/build/implementations/http/hono/handlers/stream.js.map +0 -1
  514. package/build/implementations/http/hono/handlers/stream.test.js.map +0 -1
  515. package/build/implementations/http/hono/index.js.map +0 -1
  516. package/build/implementations/http/hono/index.test.js.map +0 -1
  517. package/build/implementations/http/hono/path.js.map +0 -1
  518. package/build/implementations/http/hono/path.test.js +0 -83
  519. package/build/implementations/http/hono/path.test.js.map +0 -1
  520. package/build/implementations/http/hono/types.d.ts +0 -51
  521. package/build/implementations/http/hono/types.js.map +0 -1
  522. package/build/implementations/http/on-request-error.test.js.map +0 -1
  523. package/build/implementations/http/route-errors.test.js.map +0 -1
  524. package/build/index.d.ts +0 -175
  525. package/build/index.js +0 -47
  526. package/build/index.js.map +0 -1
  527. package/build/index.test.js.map +0 -1
  528. package/build/migration.test.js.map +0 -1
  529. package/build/schema/extract-json-schema.d.ts +0 -2
  530. package/build/schema/extract-json-schema.js +0 -12
  531. package/build/schema/extract-json-schema.js.map +0 -1
  532. package/build/schema/extract-json-schema.test.js +0 -23
  533. package/build/schema/extract-json-schema.test.js.map +0 -1
  534. package/build/schema/parser.d.ts +0 -36
  535. package/build/schema/parser.js +0 -210
  536. package/build/schema/parser.js.map +0 -1
  537. package/build/schema/parser.test.js +0 -120
  538. package/build/schema/parser.test.js.map +0 -1
  539. package/build/schema/resolve-schema-lib.d.ts +0 -12
  540. package/build/schema/resolve-schema-lib.js +0 -11
  541. package/build/schema/resolve-schema-lib.js.map +0 -1
  542. package/build/schema/resolve-schema-lib.test.js +0 -17
  543. package/build/schema/resolve-schema-lib.test.js.map +0 -1
  544. package/build/schema/types.d.ts +0 -8
  545. package/build/schema/types.js +0 -2
  546. package/build/stack-utils.d.ts +0 -25
  547. package/build/stack-utils.js.map +0 -1
  548. package/build/stack-utils.test.js.map +0 -1
  549. package/build/types.d.ts +0 -142
  550. package/build/types.js +0 -2
  551. package/build/types.js.map +0 -1
  552. package/docs/decisions/2026-06-02-monorepo-split-evaluation.md +0 -80
  553. package/docs/handoffs/ajsc-named-type-collision.md +0 -134
  554. package/docs/handoffs/ajsc-named-type-support.md +0 -181
  555. package/docs/handoffs/shared-models-auto-resolve-response.md +0 -181
  556. package/docs/npm-workspaces-migration-plan.md +0 -611
  557. package/docs/superpowers/plans/2026-04-24-doc-registry-simplification.md +0 -886
  558. package/docs/superpowers/plans/2026-04-24-kotlin-codegen-target.md +0 -1265
  559. package/docs/superpowers/plans/2026-04-25-ajsc-v7-kotlin-polish.md +0 -1993
  560. package/docs/superpowers/plans/2026-04-29-safe-result-api.md +0 -2293
  561. package/docs/superpowers/plans/2026-05-07-astro-adapter.md +0 -1391
  562. package/docs/superpowers/plans/2026-05-08-create-http.md +0 -3355
  563. package/docs/superpowers/plans/2026-05-08-hono-app-builder-convergence.md +0 -3365
  564. package/docs/superpowers/plans/2026-06-05-dx-feedback-round.md +0 -1292
  565. package/docs/superpowers/plans/2026-06-06-shared-models-convention-and-diagnostics.md +0 -659
  566. package/docs/superpowers/specs/2026-04-24-kotlin-swift-codegen-design.md +0 -401
  567. package/docs/superpowers/specs/2026-04-25-ajsc-v7-kotlin-polish-design.md +0 -314
  568. package/docs/superpowers/specs/2026-04-25-swift-codegen-design.md +0 -264
  569. package/docs/superpowers/specs/2026-04-29-safe-result-api-design.md +0 -324
  570. package/docs/superpowers/specs/2026-05-07-astro-adapter-design.md +0 -252
  571. package/docs/superpowers/specs/2026-05-08-create-http-design.md +0 -409
  572. package/docs/superpowers/specs/2026-05-08-hono-app-builder-convergence-design.md +0 -411
  573. package/docs/superpowers/specs/2026-06-05-dx-feedback-round-design.md +0 -285
  574. package/src/create-http-stream.ts +0 -191
  575. package/src/create-http.ts +0 -210
  576. package/src/create-stream.ts +0 -228
  577. package/src/create.ts +0 -172
  578. package/src/implementations/http/README.md +0 -390
  579. package/src/implementations/http/error-dispatch.test.ts +0 -283
  580. package/src/implementations/http/error-dispatch.ts +0 -176
  581. package/src/implementations/http/hono/handlers/http-stream.ts +0 -152
  582. package/src/implementations/http/hono/handlers/http.ts +0 -145
  583. package/src/implementations/http/hono/handlers/rpc.ts +0 -54
  584. package/src/implementations/http/hono/path.test.ts +0 -96
  585. package/src/index.ts +0 -101
  586. package/src/schema/extract-json-schema.test.ts +0 -25
  587. package/src/schema/extract-json-schema.ts +0 -15
  588. package/src/schema/parser.test.ts +0 -182
  589. package/src/schema/parser.ts +0 -265
  590. package/src/schema/resolve-schema-lib.test.ts +0 -19
  591. package/src/schema/resolve-schema-lib.ts +0 -29
  592. package/src/schema/types.ts +0 -20
  593. package/src/types.ts +0 -133
  594. /package/build/{implementations/http → adapters}/astro/astro-context.d.ts +0 -0
  595. /package/build/{implementations/http → adapters}/astro/astro-context.js +0 -0
  596. /package/build/{implementations/http → adapters}/astro/create-handler.d.ts +0 -0
  597. /package/build/{implementations/http → adapters}/astro/create-handler.js +0 -0
  598. /package/build/{implementations/http → adapters}/astro/index.d.ts +0 -0
  599. /package/build/{implementations/http → adapters}/astro/index.js +0 -0
  600. /package/build/{implementations/http → adapters}/astro/index.test.d.ts +0 -0
  601. /package/build/{implementations/http → adapters}/astro/rewrite-request.d.ts +0 -0
  602. /package/build/{implementations/http → adapters}/astro/rewrite-request.js +0 -0
  603. /package/build/{create-http-stream.test.d.ts → adapters/hono/envelope-parity.test.d.ts} +0 -0
  604. /package/build/{implementations/http → adapters}/hono/handlers/http-stream.test.d.ts +0 -0
  605. /package/build/{implementations/http → adapters}/hono/handlers/http.test.d.ts +0 -0
  606. /package/build/{implementations/http → adapters}/hono/handlers/rpc.test.d.ts +0 -0
  607. /package/build/{implementations/http → adapters}/hono/handlers/stream.test.d.ts +0 -0
  608. /package/build/{implementations/http → adapters}/hono/index.test.d.ts +0 -0
  609. /package/build/{implementations/http → adapters/hono}/on-request-error.test.d.ts +0 -0
  610. /package/build/{implementations/http → adapters/hono}/route-errors.test.d.ts +0 -0
  611. /package/build/{create-http.test.d.ts → client/freeze.test.d.ts} +0 -0
  612. /package/build/{create-stream.test.d.ts → codegen/goldens.test.d.ts} +0 -0
  613. /package/build/{create.test.d.ts → core/create-http-stream.test.d.ts} +0 -0
  614. /package/build/{doc-envelope.test.d.ts → core/create-http.test.d.ts} +0 -0
  615. /package/build/{errors.test.d.ts → core/create-stream.test.d.ts} +0 -0
  616. /package/build/{implementations/http/doc-registry.test.d.ts → core/create.test.d.ts} +0 -0
  617. /package/build/{implementations/http/error-dispatch.test.d.ts → core/definition-site.test.d.ts} +0 -0
  618. /package/build/{implementations/http/error-taxonomy.test.d.ts → core/errors.test.d.ts} +0 -0
  619. /package/build/{errors.test.js → core/errors.test.js} +0 -0
  620. /package/build/{implementations/http/hono/path.test.d.ts → core/factory-options.test.d.ts} +0 -0
  621. /package/build/{migration.test.d.ts → core/migration.test.d.ts} +0 -0
  622. /package/build/{index.test.d.ts → core/procedures.test.d.ts} +0 -0
  623. /package/build/{implementations/http/hono → core}/types.js +0 -0
  624. /package/build/schema/{extract-json-schema.test.d.ts → adapter.test.d.ts} +0 -0
  625. /package/build/schema/{parser.test.d.ts → compile.test.d.ts} +0 -0
  626. /package/build/schema/{resolve-schema-lib.test.d.ts → typebox.test.d.ts} +0 -0
  627. /package/build/{stack-utils.test.d.ts → server/context.test.d.ts} +0 -0
  628. /package/build/{doc-envelope.js → server/doc-envelope.js} +0 -0
  629. /package/build/{doc-envelope.test.js → server/doc-envelope.test.js} +0 -0
  630. /package/build/{implementations → server}/types.js +0 -0
  631. /package/src/{implementations/http → adapters}/astro/README.md +0 -0
  632. /package/src/{implementations/http → adapters}/astro/astro-context.ts +0 -0
  633. /package/src/{implementations/http → adapters}/astro/create-handler.ts +0 -0
  634. /package/src/{implementations/http → adapters}/astro/index.ts +0 -0
  635. /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,195 @@
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
+ schema: {
80
+ req?: TReq
81
+ res?: TRes
82
+ }
83
+ }
84
+
85
+ export type THttpProcedureRegistration<TContext = unknown> = {
86
+ name: string
87
+ kind: 'http'
88
+ config: {
89
+ path: string
90
+ method: HttpMethod
91
+ successStatus?: number
92
+ scope?: string
93
+ errors?: string[]
94
+ description?: string
95
+ schema?: {
96
+ req?: Record<string, TJSONSchema>
97
+ res?: { body?: TJSONSchema; headers?: TJSONSchema }
98
+ }
99
+ validation?: {
100
+ req?: Record<string, Validate>
101
+ }
102
+ }
103
+ handler: (ctx: TContext, req?: any) => Promise<any>
104
+ }
105
+
106
+ export type THttpStreamProcedureRegistration<TContext = unknown> = {
107
+ name: string
108
+ kind: 'http-stream'
109
+ config: {
110
+ path: string
111
+ method: HttpMethod
112
+ scope?: string
113
+ errors?: string[]
114
+ description?: string
115
+ schema?: {
116
+ req?: Record<string, TJSONSchema>
117
+ res?: { headers?: TJSONSchema }
118
+ yield?: TJSONSchema
119
+ returnType?: TJSONSchema
120
+ }
121
+ validation?: {
122
+ req?: Record<string, Validate>
123
+ yield?: Validate
124
+ }
125
+ validateYields?: boolean
126
+ }
127
+ handler: (
128
+ ctx: TContext,
129
+ req?: any,
130
+ ) => Promise<{ stream: AsyncGenerator<any, any, unknown>; initialHeaders?: Record<string, string> }>
131
+ }
132
+
133
+ /**
134
+ * The shape every creator returns: the handler under its own name (so
135
+ * `const { GetUser } = Create('GetUser', ...)` works), the same handler as
136
+ * `procedure`, and the introspectable `info`.
137
+ */
138
+ export type ProcedureResult<TName extends string, THandler, TInfo> = {
139
+ [K in TName]: THandler
140
+ } & {
141
+ procedure: THandler
142
+ info: TInfo
143
+ }
144
+
145
+ /** Union of all four registration shapes a factory can hold. */
146
+ export type AnyProcedureRegistration<TContext = unknown, TExtendedConfig = unknown> =
147
+ | TProcedureRegistration<TContext, TExtendedConfig>
148
+ | TStreamProcedureRegistration<TContext, TExtendedConfig>
149
+ | THttpProcedureRegistration<TContext>
150
+ | THttpStreamProcedureRegistration<TContext>
151
+
152
+ /**
153
+ * Options for `Procedures()`.
154
+ */
155
+ export type ProceduresOptions<TContext = unknown, TExtendedConfig = unknown> = {
156
+ /**
157
+ * Called once per registered procedure with the full registration object.
158
+ * Use the `kind` discriminant to narrow to the specific shape. This is the
159
+ * seam for custom framework integration (Fastify, Koa, raw http, ...).
160
+ */
161
+ onCreate?: (procedure: AnyProcedureRegistration<TContext, TExtendedConfig>) => void
162
+
163
+ /**
164
+ * Runtime validation behavior:
165
+ * - omitted — validate every call with the default AJV configuration
166
+ * (`allErrors`, `coerceTypes`, `removeAdditional`)
167
+ * - `false` — skip per-call validation for the whole factory. JSON Schema
168
+ * and validators are still computed at registration time (bad schemas
169
+ * still fail fast); only the per-call runs are skipped. For trusted
170
+ * internal factories whose callers are type-checked at build time.
171
+ * - `{ ajv }` — AJV options merged over the defaults, or a configured
172
+ * `Ajv` instance used as-is.
173
+ */
174
+ validation?: false | { ajv?: AJV.Ajv | AJV.Options }
175
+
176
+ /**
177
+ * Schema-library integration. TypeBox is built in; prepend adapters here to
178
+ * register procedures with other schema libraries (see `SchemaAdapter`).
179
+ */
180
+ schema?: {
181
+ adapters?: SchemaAdapter[]
182
+ }
183
+
184
+ /**
185
+ * Factory-level defaults for `CreateHttp` / `CreateHttpStream` routes:
186
+ * - `pathPrefix` — prepended to every route's `path` at registration time
187
+ * (this is part of the route's identity, unlike a server adapter's mount
188
+ * prefix)
189
+ * - `scope` — default codegen scope for routes that don't set one
190
+ */
191
+ http?: {
192
+ pathPrefix?: string
193
+ scope?: string
194
+ }
195
+ }
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
+ }