ts-procedures 8.6.0 → 9.0.0

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