@warlock.js/core 5.30.0 → 5.31.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 (797) hide show
  1. package/CHANGELOG.md +142 -36
  2. package/README.md +28 -23
  3. package/bin/source-load-hook.mjs +63 -0
  4. package/bin/warlock.js +102 -42
  5. package/esm/cli/commands/add.command.mjs +4 -2
  6. package/esm/cli/commands/add.command.mjs.map +1 -1
  7. package/esm/cli/commands/agents-md/agents-md-command.action.mjs +69 -0
  8. package/esm/cli/commands/agents-md/agents-md-command.action.mjs.map +1 -0
  9. package/esm/cli/commands/agents-md.command.mjs +38 -0
  10. package/esm/cli/commands/agents-md.command.mjs.map +1 -0
  11. package/esm/cli/commands/board/board-command.action.mjs +279 -0
  12. package/esm/cli/commands/board/board-command.action.mjs.map +1 -0
  13. package/esm/cli/commands/board.command.mjs +78 -0
  14. package/esm/cli/commands/board.command.mjs.map +1 -0
  15. package/esm/cli/commands/build.command.mjs +6 -1
  16. package/esm/cli/commands/build.command.mjs.map +1 -1
  17. package/esm/cli/commands/check/check-command.action.mjs +57 -0
  18. package/esm/cli/commands/check/check-command.action.mjs.map +1 -0
  19. package/esm/cli/commands/check/child-typecheck.mjs +66 -0
  20. package/esm/cli/commands/check/child-typecheck.mjs.map +1 -0
  21. package/esm/cli/commands/check/format-problems.mjs +43 -0
  22. package/esm/cli/commands/check/format-problems.mjs.map +1 -0
  23. package/esm/cli/commands/check/typecheck-command.action.mjs +61 -0
  24. package/esm/cli/commands/check/typecheck-command.action.mjs.map +1 -0
  25. package/esm/cli/commands/check.command.mjs +50 -0
  26. package/esm/cli/commands/check.command.mjs.map +1 -0
  27. package/esm/cli/commands/dev-server.command.mjs +9 -1
  28. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  29. package/esm/cli/commands/doctor/boot-for-diagnostics.mjs +8 -3
  30. package/esm/cli/commands/doctor/boot-for-diagnostics.mjs.map +1 -1
  31. package/esm/cli/commands/doctor/check.types.d.mts +76 -0
  32. package/esm/cli/commands/doctor/check.types.d.mts.map +1 -0
  33. package/esm/cli/commands/doctor/checks/config.check.mjs +1 -0
  34. package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -1
  35. package/esm/cli/commands/doctor/checks/connectors.check.mjs +2 -0
  36. package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -1
  37. package/esm/cli/commands/doctor/checks/handler-signature.check.mjs +1 -0
  38. package/esm/cli/commands/doctor/checks/handler-signature.check.mjs.map +1 -1
  39. package/esm/cli/commands/doctor/checks/health.check.mjs +3 -0
  40. package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -1
  41. package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs +1 -0
  42. package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs.map +1 -1
  43. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +1 -0
  44. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
  45. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +1 -0
  46. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
  47. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +4 -0
  48. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
  49. package/esm/cli/commands/doctor/checks/routes.check.mjs +3 -0
  50. package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -1
  51. package/esm/cli/commands/doctor/doctor-command.action.mjs +14 -6
  52. package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
  53. package/esm/cli/commands/doctor/format-report.mjs +30 -2
  54. package/esm/cli/commands/doctor/format-report.mjs.map +1 -1
  55. package/esm/cli/commands/doctor.command.mjs +4 -0
  56. package/esm/cli/commands/doctor.command.mjs.map +1 -1
  57. package/esm/cli/commands/explain/explain-command.action.mjs +64 -0
  58. package/esm/cli/commands/explain/explain-command.action.mjs.map +1 -0
  59. package/esm/cli/commands/explain.command.mjs +23 -0
  60. package/esm/cli/commands/explain.command.mjs.map +1 -0
  61. package/esm/cli/commands/generate/generate.command.mjs +124 -124
  62. package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
  63. package/esm/cli/commands/generate/generators/endpoint.generator.mjs +311 -0
  64. package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -0
  65. package/esm/cli/commands/generate/generators/migration.generator.mjs +1 -1
  66. package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
  67. package/esm/cli/commands/generate/generators/model.generator.mjs +1 -1
  68. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs +341 -0
  69. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs.map +1 -0
  70. package/esm/cli/commands/generate/templates/stubs.mjs +19 -6
  71. package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
  72. package/esm/cli/commands/generate/utils/endpoint-schema.mjs +137 -0
  73. package/esm/cli/commands/generate/utils/endpoint-schema.mjs.map +1 -0
  74. package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
  75. package/esm/cli/commands/generate/utils/name-parser.mjs.map +1 -1
  76. package/esm/cli/commands/generate/utils/prompt.mjs.map +1 -1
  77. package/esm/cli/commands/generate/utils/writer.mjs +38 -13
  78. package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
  79. package/esm/cli/commands/inspect/inspect-command.action.mjs +72 -0
  80. package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -0
  81. package/esm/cli/commands/inspect.command.mjs +39 -0
  82. package/esm/cli/commands/inspect.command.mjs.map +1 -0
  83. package/esm/cli/commands/mcp/mcp-command.action.mjs +103 -0
  84. package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -0
  85. package/esm/cli/commands/mcp.command.mjs +76 -0
  86. package/esm/cli/commands/mcp.command.mjs.map +1 -0
  87. package/esm/cli/commands/openapi-generator.action.mjs.map +1 -1
  88. package/esm/cli/commands/openapi-generator.command.mjs.map +1 -1
  89. package/esm/cli/commands/postman-generator.action.mjs.map +1 -1
  90. package/esm/cli/commands/postman-generator.command.mjs.map +1 -1
  91. package/esm/cli/commands/routes/routes-diff.action.mjs +1 -1
  92. package/esm/cli/commands/test.command.mjs +131 -0
  93. package/esm/cli/commands/test.command.mjs.map +1 -0
  94. package/esm/cli/commands/trace/trace-command.action.mjs +145 -0
  95. package/esm/cli/commands/trace/trace-command.action.mjs.map +1 -0
  96. package/esm/cli/commands/trace.command.mjs +60 -0
  97. package/esm/cli/commands/trace.command.mjs.map +1 -0
  98. package/esm/cli/commands/typecheck.command.mjs +40 -0
  99. package/esm/cli/commands/typecheck.command.mjs.map +1 -0
  100. package/esm/cli/commands/upgrade.command.mjs +46 -0
  101. package/esm/cli/commands/upgrade.command.mjs.map +1 -0
  102. package/esm/cli/flush-and-exit.mjs +34 -0
  103. package/esm/cli/flush-and-exit.mjs.map +1 -0
  104. package/esm/cli/framework-cli-commands.mjs +23 -1
  105. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  106. package/esm/cli/parse-cli-args.mjs +1 -0
  107. package/esm/cli/parse-cli-args.mjs.map +1 -1
  108. package/esm/config/config-loader.d.mts.map +1 -1
  109. package/esm/config/config-loader.mjs +34 -13
  110. package/esm/config/config-loader.mjs.map +1 -1
  111. package/esm/config/config-schema.d.mts +67 -0
  112. package/esm/config/config-schema.d.mts.map +1 -0
  113. package/esm/config/config-schema.mjs +77 -0
  114. package/esm/config/config-schema.mjs.map +1 -0
  115. package/esm/config/index.d.mts +6 -0
  116. package/esm/config/index.mjs +1 -0
  117. package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
  118. package/esm/connectors/assert-no-reserved-connector-names.mjs +2 -1
  119. package/esm/connectors/assert-no-reserved-connector-names.mjs.map +1 -1
  120. package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
  121. package/esm/connectors/assert-unique-connector-names.mjs +26 -2
  122. package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
  123. package/esm/connectors/http-connector.d.mts.map +1 -1
  124. package/esm/connectors/http-connector.mjs +3 -2
  125. package/esm/connectors/http-connector.mjs.map +1 -1
  126. package/esm/connectors/single-server-warnings.mjs.map +1 -1
  127. package/esm/connectors/socket-connector.d.mts.map +1 -1
  128. package/esm/connectors/socket-connector.mjs.map +1 -1
  129. package/esm/container/index.d.mts.map +1 -1
  130. package/esm/container/index.mjs.map +1 -1
  131. package/esm/database/migrate-action.mjs.map +1 -1
  132. package/esm/database/models/database-log/database-log.d.mts +0 -28
  133. package/esm/database/models/database-log/database-log.d.mts.map +1 -1
  134. package/esm/database/seeds/seeder.errors.d.mts +4 -0
  135. package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
  136. package/esm/database/seeds/seeder.errors.mjs +2 -0
  137. package/esm/database/seeds/seeder.errors.mjs.map +1 -1
  138. package/esm/dev-server/boot-precondition-error.mjs +1 -0
  139. package/esm/dev-server/boot-precondition-error.mjs.map +1 -1
  140. package/esm/dev-server/create-worker.mjs +15 -9
  141. package/esm/dev-server/create-worker.mjs.map +1 -1
  142. package/esm/dev-server/dev-agent-tooling.mjs +135 -0
  143. package/esm/dev-server/dev-agent-tooling.mjs.map +1 -0
  144. package/esm/dev-server/dev-logger.mjs.map +1 -1
  145. package/esm/dev-server/development-server.mjs +8 -0
  146. package/esm/dev-server/development-server.mjs.map +1 -1
  147. package/esm/dev-server/files-orchestrator.mjs +4 -5
  148. package/esm/dev-server/files-orchestrator.mjs.map +1 -1
  149. package/esm/dev-server/files-watcher.mjs +1 -1
  150. package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +2 -3
  151. package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +1 -1
  152. package/esm/dev-server/health-checker/checkers/oxlint-health-checker.mjs +33 -0
  153. package/esm/dev-server/health-checker/checkers/oxlint-health-checker.mjs.map +1 -0
  154. package/esm/dev-server/health-checker/default-health-checkers.mjs +31 -0
  155. package/esm/dev-server/health-checker/default-health-checkers.mjs.map +1 -0
  156. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +9 -3
  157. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
  158. package/esm/dev-server/health-checker/files-healthcare.manager.mjs +15 -4
  159. package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
  160. package/esm/dev-server/health-checker/oxlint-runner.mjs +302 -0
  161. package/esm/dev-server/health-checker/oxlint-runner.mjs.map +1 -0
  162. package/esm/dev-server/health-checker/workers/oxlint-health.worker.d.mts +1 -0
  163. package/esm/dev-server/health-checker/workers/oxlint-health.worker.mjs +42 -0
  164. package/esm/dev-server/health-checker/workers/oxlint-health.worker.mjs.map +1 -0
  165. package/esm/dev-server/loader/loader-port-acks.mjs +1 -1
  166. package/esm/dev-server/loader/loader-port-acks.mjs.map +1 -1
  167. package/esm/dev-server/loader/register-loader.mjs +1 -1
  168. package/esm/dev-server/loader/register-loader.mjs.map +1 -1
  169. package/esm/dev-server/loader/resolve-hook.mjs +1 -1
  170. package/esm/dev-server/loader/transpile-cache.mjs +1 -1
  171. package/esm/dev-server/model-resource-typings.mjs.map +1 -1
  172. package/esm/dev-server/module-loader.mjs +1 -0
  173. package/esm/dev-server/module-loader.mjs.map +1 -1
  174. package/esm/dev-server/parse-imports.mjs +1 -1
  175. package/esm/dev-server/parse-imports.mjs.map +1 -1
  176. package/esm/dev-server/route-types-publisher.mjs +1 -1
  177. package/esm/dev-server/start-development-server.mjs.map +1 -1
  178. package/esm/dev-server/translation-keys-sources.mjs +1 -1
  179. package/esm/dev-server/translation-keys-sources.mjs.map +1 -1
  180. package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
  181. package/esm/dev-server/type-generator.mjs +3 -3
  182. package/esm/dev-server/type-generator.mjs.map +1 -1
  183. package/esm/dev-server/types.d.mts.map +1 -1
  184. package/esm/errors/container-key-missing-error.mjs +1 -0
  185. package/esm/errors/container-key-missing-error.mjs.map +1 -1
  186. package/esm/errors/error-codes.d.mts +653 -0
  187. package/esm/errors/error-codes.d.mts.map +1 -0
  188. package/esm/errors/error-codes.mjs +634 -0
  189. package/esm/errors/error-codes.mjs.map +1 -0
  190. package/esm/errors/esbuild-binary-missing-error.mjs +1 -0
  191. package/esm/errors/esbuild-binary-missing-error.mjs.map +1 -1
  192. package/esm/errors/index.d.mts +3 -1
  193. package/esm/errors/index.mjs +3 -1
  194. package/esm/errors/unknown-locale-error.mjs +1 -0
  195. package/esm/errors/unknown-locale-error.mjs.map +1 -1
  196. package/esm/errors/warlock-error.d.mts +23 -0
  197. package/esm/errors/warlock-error.d.mts.map +1 -0
  198. package/esm/errors/warlock-error.mjs +22 -0
  199. package/esm/errors/warlock-error.mjs.map +1 -0
  200. package/esm/generations/add-command.action.mjs +19 -3
  201. package/esm/generations/add-command.action.mjs.map +1 -1
  202. package/esm/generations/features/access.feature.mjs +1 -1
  203. package/esm/generations/features/access.feature.mjs.map +1 -1
  204. package/esm/generations/features/bull-board.feature.mjs +1 -1
  205. package/esm/generations/features/bull-board.feature.mjs.map +1 -1
  206. package/esm/generations/features/mysql.feature.mjs.map +1 -1
  207. package/esm/generations/features/notifications.feature.mjs +5 -2
  208. package/esm/generations/features/notifications.feature.mjs.map +1 -1
  209. package/esm/generations/features/queue.feature.mjs +1 -1
  210. package/esm/generations/features/queue.feature.mjs.map +1 -1
  211. package/esm/generations/features/react-email.feature.mjs +1 -1
  212. package/esm/generations/features/react-email.feature.mjs.map +1 -1
  213. package/esm/generations/features/shadcn.feature.mjs +1 -1
  214. package/esm/generations/features/shadcn.feature.mjs.map +1 -1
  215. package/esm/generations/features/shared/link-ai-package-import.mjs +1 -1
  216. package/esm/generations/features/shared/link-ai-package-import.mjs.map +1 -1
  217. package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
  218. package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
  219. package/esm/generations/features/shared/patch-tsconfig-include.mjs.map +1 -1
  220. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
  221. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs.map +1 -1
  222. package/esm/generations/features/sitemap.feature.mjs +1 -1
  223. package/esm/generations/features/sitemap.feature.mjs.map +1 -1
  224. package/esm/generations/features/tailwind.feature.mjs +1 -1
  225. package/esm/generations/features/tailwind.feature.mjs.map +1 -1
  226. package/esm/generations/features/test.feature.mjs +11 -6
  227. package/esm/generations/features/test.feature.mjs.map +1 -1
  228. package/esm/generations/features/web.feature.mjs +1 -1
  229. package/esm/generations/features/web.feature.mjs.map +1 -1
  230. package/esm/generations/generation-fs.mjs +73 -0
  231. package/esm/generations/generation-fs.mjs.map +1 -0
  232. package/esm/generations/generation-run.mjs +185 -0
  233. package/esm/generations/generation-run.mjs.map +1 -0
  234. package/esm/generations/stubs.mjs +155 -13
  235. package/esm/generations/stubs.mjs.map +1 -1
  236. package/esm/http/bounded-stream-queue.d.mts +10 -0
  237. package/esm/http/bounded-stream-queue.d.mts.map +1 -0
  238. package/esm/http/bounded-stream-queue.mjs +97 -0
  239. package/esm/http/bounded-stream-queue.mjs.map +1 -0
  240. package/esm/http/build-rate-limit-options.d.mts +13 -0
  241. package/esm/http/build-rate-limit-options.d.mts.map +1 -1
  242. package/esm/http/build-rate-limit-options.mjs.map +1 -1
  243. package/esm/http/conditional-request.d.mts +86 -0
  244. package/esm/http/conditional-request.d.mts.map +1 -0
  245. package/esm/http/conditional-request.mjs +121 -0
  246. package/esm/http/conditional-request.mjs.map +1 -0
  247. package/esm/http/csp.d.mts +2 -0
  248. package/esm/http/csp.d.mts.map +1 -1
  249. package/esm/http/csp.mjs +1 -0
  250. package/esm/http/csp.mjs.map +1 -1
  251. package/esm/http/csrf-origin-policy.mjs.map +1 -1
  252. package/esm/http/database/RequestLog.d.mts +24 -84
  253. package/esm/http/database/RequestLog.d.mts.map +1 -1
  254. package/esm/http/errors/errors.d.mts +2 -0
  255. package/esm/http/errors/errors.d.mts.map +1 -1
  256. package/esm/http/errors/errors.mjs +1 -0
  257. package/esm/http/errors/errors.mjs.map +1 -1
  258. package/esm/http/escape-header-value.d.mts +18 -0
  259. package/esm/http/escape-header-value.d.mts.map +1 -0
  260. package/esm/http/escape-header-value.mjs +27 -0
  261. package/esm/http/escape-header-value.mjs.map +1 -0
  262. package/esm/http/flush-pending-cookies.mjs.map +1 -1
  263. package/esm/http/index.d.mts +5 -2
  264. package/esm/http/index.mjs +4 -1
  265. package/esm/http/lazy-static.mjs +194 -0
  266. package/esm/http/lazy-static.mjs.map +1 -0
  267. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  268. package/esm/http/plugins.d.mts.map +1 -1
  269. package/esm/http/plugins.mjs +7 -4
  270. package/esm/http/plugins.mjs.map +1 -1
  271. package/esm/http/rate-limit-cache-store.mjs +2 -1
  272. package/esm/http/rate-limit-cache-store.mjs.map +1 -1
  273. package/esm/http/request-log-snapshot.d.mts +12 -5
  274. package/esm/http/request-log-snapshot.d.mts.map +1 -1
  275. package/esm/http/request-log-snapshot.mjs +83 -4
  276. package/esm/http/request-log-snapshot.mjs.map +1 -1
  277. package/esm/http/request.d.mts +2 -2
  278. package/esm/http/request.d.mts.map +1 -1
  279. package/esm/http/request.mjs +5 -4
  280. package/esm/http/request.mjs.map +1 -1
  281. package/esm/http/response.d.mts +11 -1
  282. package/esm/http/response.d.mts.map +1 -1
  283. package/esm/http/response.mjs +164 -76
  284. package/esm/http/response.mjs.map +1 -1
  285. package/esm/http/safe-redirect.d.mts +51 -0
  286. package/esm/http/safe-redirect.d.mts.map +1 -0
  287. package/esm/http/safe-redirect.mjs +80 -0
  288. package/esm/http/safe-redirect.mjs.map +1 -0
  289. package/esm/http/serialized.d.mts.map +1 -1
  290. package/esm/http/server.d.mts +3 -1
  291. package/esm/http/server.d.mts.map +1 -1
  292. package/esm/http/server.mjs +14 -4
  293. package/esm/http/server.mjs.map +1 -1
  294. package/esm/http/stream-transport.mjs +4 -2
  295. package/esm/http/stream-transport.mjs.map +1 -1
  296. package/esm/http/types.d.mts +44 -11
  297. package/esm/http/types.d.mts.map +1 -1
  298. package/esm/http/uploads/generate-image-variant.mjs +1 -1
  299. package/esm/http/uploads/generate-image-variants.d.mts +10 -7
  300. package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
  301. package/esm/http/uploads/generate-image-variants.mjs +61 -24
  302. package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
  303. package/esm/http/uploads/image-variant-cache-entries.mjs +78 -0
  304. package/esm/http/uploads/image-variant-cache-entries.mjs.map +1 -0
  305. package/esm/http/uploads/image-variant-cache.mjs +72 -30
  306. package/esm/http/uploads/image-variant-cache.mjs.map +1 -1
  307. package/esm/http/uploads/image-variant-types.d.mts +2 -0
  308. package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
  309. package/esm/http/uploads/image-variants-config-error.d.mts +3 -1
  310. package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
  311. package/esm/http/uploads/image-variants-config-error.mjs +3 -2
  312. package/esm/http/uploads/image-variants-config-error.mjs.map +1 -1
  313. package/esm/http/uploads/load-variant-source.mjs +1 -1
  314. package/esm/http/uploads/load-variant-source.mjs.map +1 -1
  315. package/esm/http/uploads/purge-image-variants.d.mts +7 -2
  316. package/esm/http/uploads/purge-image-variants.d.mts.map +1 -1
  317. package/esm/http/uploads/purge-image-variants.mjs +16 -16
  318. package/esm/http/uploads/purge-image-variants.mjs.map +1 -1
  319. package/esm/http/uploads/remote-variant-source.mjs +115 -0
  320. package/esm/http/uploads/remote-variant-source.mjs.map +1 -0
  321. package/esm/http/uploads/resolve-image-variant.d.mts +3 -4
  322. package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -1
  323. package/esm/http/uploads/resolve-image-variant.mjs +10 -18
  324. package/esm/http/uploads/resolve-image-variant.mjs.map +1 -1
  325. package/esm/http/uploads/resolve-image-variants-config.mjs +5 -3
  326. package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
  327. package/esm/http/uploads/resolve-remote-image-variant.mjs +89 -0
  328. package/esm/http/uploads/resolve-remote-image-variant.mjs.map +1 -0
  329. package/esm/http/uploads/trim-image-variant-cache.mjs +193 -0
  330. package/esm/http/uploads/trim-image-variant-cache.mjs.map +1 -0
  331. package/esm/http/uploads/uploaded-file.controller.d.mts +5 -3
  332. package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
  333. package/esm/http/uploads/uploaded-file.controller.mjs +16 -8
  334. package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
  335. package/esm/http/uploads/variant-cache-key.mjs +1 -1
  336. package/esm/http/uploads-types.d.mts +6 -2
  337. package/esm/http/uploads-types.d.mts.map +1 -1
  338. package/esm/index.d.mts +17 -6
  339. package/esm/index.mjs +14 -3
  340. package/esm/localization/parse-locale-dictionary.d.mts +2 -0
  341. package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
  342. package/esm/localization/parse-locale-dictionary.mjs +1 -0
  343. package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
  344. package/esm/mail/config.d.mts +12 -1
  345. package/esm/mail/config.d.mts.map +1 -1
  346. package/esm/mail/config.mjs +16 -1
  347. package/esm/mail/config.mjs.map +1 -1
  348. package/esm/mail/index.d.mts +1 -1
  349. package/esm/mail/index.mjs +1 -1
  350. package/esm/net/index.d.mts +2 -0
  351. package/esm/net/index.mjs +3 -0
  352. package/esm/openapi/build-openapi-document.d.mts.map +1 -1
  353. package/esm/openapi/build-openapi-document.mjs +8 -5
  354. package/esm/openapi/build-openapi-document.mjs.map +1 -1
  355. package/esm/openapi/error-responses.mjs +28 -2
  356. package/esm/openapi/error-responses.mjs.map +1 -1
  357. package/esm/openapi/postman/build-request-body.mjs.map +1 -1
  358. package/esm/openapi/postman/build-request-url.mjs.map +1 -1
  359. package/esm/openapi/postman/build-saved-responses.mjs.map +1 -1
  360. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
  361. package/esm/openapi/postman/example-from-schema.mjs.map +1 -1
  362. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
  363. package/esm/openapi/postman/openapi-to-postman-collection.mjs.map +1 -1
  364. package/esm/openapi/postman/schema-refs.mjs.map +1 -1
  365. package/esm/openapi/postman/uuid-v5.mjs.map +1 -1
  366. package/esm/openapi/request-schemas.mjs.map +1 -1
  367. package/esm/openapi/response-schemas.mjs.map +1 -1
  368. package/esm/openapi/schema-registry.d.mts +1 -0
  369. package/esm/openapi/schema-registry.mjs.map +1 -1
  370. package/esm/openapi/security.mjs.map +1 -1
  371. package/esm/openapi/types.d.mts +3 -2
  372. package/esm/openapi/types.d.mts.map +1 -1
  373. package/esm/production/assert-generated-imports.mjs +1 -0
  374. package/esm/production/assert-generated-imports.mjs.map +1 -1
  375. package/esm/production/production-builder.mjs +12 -4
  376. package/esm/production/production-builder.mjs.map +1 -1
  377. package/esm/production/resolve-build-config.mjs +1 -0
  378. package/esm/production/resolve-build-config.mjs.map +1 -1
  379. package/esm/production/route-registration-child.mjs.map +1 -1
  380. package/esm/production/route-registration-snapshot.mjs.map +1 -1
  381. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  382. package/esm/repositories/contracts/types.d.mts.map +1 -1
  383. package/esm/repositories/repository.manager.mjs.map +1 -1
  384. package/esm/resource/resource.d.mts.map +1 -1
  385. package/esm/resource/resource.mjs.map +1 -1
  386. package/esm/resource/types.d.mts.map +1 -1
  387. package/esm/restful/restful.d.mts +5 -5
  388. package/esm/restful/restful.d.mts.map +1 -1
  389. package/esm/restful/restful.mjs.map +1 -1
  390. package/esm/router/build-route-rate-limit.mjs.map +1 -1
  391. package/esm/router/dev-dispatch.mjs +31 -12
  392. package/esm/router/dev-dispatch.mjs.map +1 -1
  393. package/esm/router/index.d.mts +4 -2
  394. package/esm/router/index.mjs +2 -0
  395. package/esm/router/log-request-lifecycle.mjs.map +1 -1
  396. package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
  397. package/esm/router/positional-handler-diagnostics.mjs.map +1 -1
  398. package/esm/router/resolve-route-rate-limit.mjs +47 -0
  399. package/esm/router/resolve-route-rate-limit.mjs.map +1 -0
  400. package/esm/router/resolve-route-validation.mjs +19 -0
  401. package/esm/router/resolve-route-validation.mjs.map +1 -0
  402. package/esm/router/route-guard-names.mjs +30 -0
  403. package/esm/router/route-guard-names.mjs.map +1 -0
  404. package/esm/router/route-name-taken-error.d.mts +14 -0
  405. package/esm/router/route-name-taken-error.d.mts.map +1 -0
  406. package/esm/router/route-name-taken-error.mjs +18 -0
  407. package/esm/router/route-name-taken-error.mjs.map +1 -0
  408. package/esm/router/router.d.mts +32 -13
  409. package/esm/router/router.d.mts.map +1 -1
  410. package/esm/router/router.mjs +71 -38
  411. package/esm/router/router.mjs.map +1 -1
  412. package/esm/router/types.d.mts +137 -17
  413. package/esm/router/types.d.mts.map +1 -1
  414. package/esm/router/unguarded-route-diagnostics.d.mts +40 -0
  415. package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -0
  416. package/esm/router/unguarded-route-diagnostics.mjs +95 -0
  417. package/esm/router/unguarded-route-diagnostics.mjs.map +1 -0
  418. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  419. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  420. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  421. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  422. package/esm/storage/local-disk-roots.mjs +24 -0
  423. package/esm/storage/local-disk-roots.mjs.map +1 -0
  424. package/esm/storage/storage.d.mts +14 -0
  425. package/esm/storage/storage.d.mts.map +1 -1
  426. package/esm/storage/storage.mjs +22 -0
  427. package/esm/storage/storage.mjs.map +1 -1
  428. package/esm/storage/types.d.mts.map +1 -1
  429. package/esm/storage/utils/storage-not-initialized-error.d.mts +2 -0
  430. package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
  431. package/esm/storage/utils/storage-not-initialized-error.mjs +1 -0
  432. package/esm/storage/utils/storage-not-initialized-error.mjs.map +1 -1
  433. package/esm/tests/authenticated-test-client.d.mts +32 -0
  434. package/esm/tests/authenticated-test-client.d.mts.map +1 -0
  435. package/esm/tests/authenticated-test-client.mjs +40 -0
  436. package/esm/tests/authenticated-test-client.mjs.map +1 -0
  437. package/esm/tests/factories.d.mts +59 -0
  438. package/esm/tests/factories.d.mts.map +1 -0
  439. package/esm/tests/factories.mjs +105 -0
  440. package/esm/tests/factories.mjs.map +1 -0
  441. package/esm/tests/fakes/cache-fake.d.mts +29 -0
  442. package/esm/tests/fakes/cache-fake.d.mts.map +1 -0
  443. package/esm/tests/fakes/cache-fake.mjs +79 -0
  444. package/esm/tests/fakes/cache-fake.mjs.map +1 -0
  445. package/esm/tests/fakes/clock-fake.d.mts +32 -0
  446. package/esm/tests/fakes/clock-fake.d.mts.map +1 -0
  447. package/esm/tests/fakes/clock-fake.mjs +69 -0
  448. package/esm/tests/fakes/clock-fake.mjs.map +1 -0
  449. package/esm/tests/fakes/fake-assertion-error.d.mts +13 -0
  450. package/esm/tests/fakes/fake-assertion-error.d.mts.map +1 -0
  451. package/esm/tests/fakes/fake-assertion-error.mjs +20 -0
  452. package/esm/tests/fakes/fake-assertion-error.mjs.map +1 -0
  453. package/esm/tests/fakes/ids-fake.d.mts +22 -0
  454. package/esm/tests/fakes/ids-fake.d.mts.map +1 -0
  455. package/esm/tests/fakes/ids-fake.mjs +57 -0
  456. package/esm/tests/fakes/ids-fake.mjs.map +1 -0
  457. package/esm/tests/fakes/index.d.mts +8 -0
  458. package/esm/tests/fakes/index.mjs +10 -0
  459. package/esm/tests/fakes/mail-fake.d.mts +41 -0
  460. package/esm/tests/fakes/mail-fake.d.mts.map +1 -0
  461. package/esm/tests/fakes/mail-fake.mjs +111 -0
  462. package/esm/tests/fakes/mail-fake.mjs.map +1 -0
  463. package/esm/tests/fakes/queue-fake.d.mts +48 -0
  464. package/esm/tests/fakes/queue-fake.d.mts.map +1 -0
  465. package/esm/tests/fakes/queue-fake.mjs +134 -0
  466. package/esm/tests/fakes/queue-fake.mjs.map +1 -0
  467. package/esm/tests/fakes/storage-fake.d.mts +31 -0
  468. package/esm/tests/fakes/storage-fake.d.mts.map +1 -0
  469. package/esm/tests/fakes/storage-fake.mjs +122 -0
  470. package/esm/tests/fakes/storage-fake.mjs.map +1 -0
  471. package/esm/tests/fakes/test-fakes.d.mts +39 -0
  472. package/esm/tests/fakes/test-fakes.d.mts.map +1 -0
  473. package/esm/tests/fakes/test-fakes.mjs +90 -0
  474. package/esm/tests/fakes/test-fakes.mjs.map +1 -0
  475. package/esm/tests/index.d.mts +14 -2
  476. package/esm/tests/index.mjs +15 -2
  477. package/esm/tests/snapshot-response.d.mts +34 -0
  478. package/esm/tests/snapshot-response.d.mts.map +1 -0
  479. package/esm/tests/snapshot-response.mjs +42 -0
  480. package/esm/tests/snapshot-response.mjs.map +1 -0
  481. package/esm/tests/start-http-development-server.d.mts +22 -0
  482. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  483. package/esm/tests/start-http-development-server.mjs +36 -3
  484. package/esm/tests/start-http-development-server.mjs.map +1 -1
  485. package/esm/tests/test-helpers.d.mts +20 -1
  486. package/esm/tests/test-helpers.d.mts.map +1 -1
  487. package/esm/tests/test-helpers.mjs +40 -27
  488. package/esm/tests/test-helpers.mjs.map +1 -1
  489. package/esm/tests/test-http-server.d.mts +62 -0
  490. package/esm/tests/test-http-server.d.mts.map +1 -0
  491. package/esm/tests/test-http-server.mjs +119 -0
  492. package/esm/tests/test-http-server.mjs.map +1 -0
  493. package/esm/tests/vitest-setup.d.mts +11 -0
  494. package/esm/tests/vitest-setup.d.mts.map +1 -1
  495. package/esm/tests/vitest-setup.mjs +12 -4
  496. package/esm/tests/vitest-setup.mjs.map +1 -1
  497. package/esm/tooling/agents-md/agents-md-markers.d.mts +27 -0
  498. package/esm/tooling/agents-md/agents-md-markers.d.mts.map +1 -0
  499. package/esm/tooling/agents-md/agents-md-markers.mjs +59 -0
  500. package/esm/tooling/agents-md/agents-md-markers.mjs.map +1 -0
  501. package/esm/tooling/agents-md/agents-md-refresher.d.mts +36 -0
  502. package/esm/tooling/agents-md/agents-md-refresher.d.mts.map +1 -0
  503. package/esm/tooling/agents-md/agents-md-refresher.mjs +72 -0
  504. package/esm/tooling/agents-md/agents-md-refresher.mjs.map +1 -0
  505. package/esm/tooling/agents-md/index.mjs +7 -0
  506. package/esm/tooling/agents-md/installed-skills.d.mts +30 -0
  507. package/esm/tooling/agents-md/installed-skills.d.mts.map +1 -0
  508. package/esm/tooling/agents-md/installed-skills.mjs +74 -0
  509. package/esm/tooling/agents-md/installed-skills.mjs.map +1 -0
  510. package/esm/tooling/agents-md/render-agents-md.d.mts +33 -0
  511. package/esm/tooling/agents-md/render-agents-md.d.mts.map +1 -0
  512. package/esm/tooling/agents-md/render-agents-md.mjs +195 -0
  513. package/esm/tooling/agents-md/render-agents-md.mjs.map +1 -0
  514. package/esm/tooling/agents-md/write-agents-md.d.mts +33 -0
  515. package/esm/tooling/agents-md/write-agents-md.d.mts.map +1 -0
  516. package/esm/tooling/agents-md/write-agents-md.mjs +49 -0
  517. package/esm/tooling/agents-md/write-agents-md.mjs.map +1 -0
  518. package/esm/tooling/board/board-message.d.mts +31 -0
  519. package/esm/tooling/board/board-message.d.mts.map +1 -0
  520. package/esm/tooling/board/board-message.mjs +86 -0
  521. package/esm/tooling/board/board-message.mjs.map +1 -0
  522. package/esm/tooling/board/board.d.mts +109 -0
  523. package/esm/tooling/board/board.d.mts.map +1 -0
  524. package/esm/tooling/board/board.mjs +406 -0
  525. package/esm/tooling/board/board.mjs.map +1 -0
  526. package/esm/tooling/board/board.types.d.mts +72 -0
  527. package/esm/tooling/board/board.types.d.mts.map +1 -0
  528. package/esm/tooling/board/board.types.mjs +54 -0
  529. package/esm/tooling/board/board.types.mjs.map +1 -0
  530. package/esm/tooling/check/changed-files.d.mts +33 -0
  531. package/esm/tooling/check/changed-files.d.mts.map +1 -0
  532. package/esm/tooling/check/changed-files.mjs +73 -0
  533. package/esm/tooling/check/changed-files.mjs.map +1 -0
  534. package/esm/tooling/check/check-report.types.d.mts +62 -0
  535. package/esm/tooling/check/check-report.types.d.mts.map +1 -0
  536. package/esm/tooling/check/check-report.types.mjs +37 -0
  537. package/esm/tooling/check/check-report.types.mjs.map +1 -0
  538. package/esm/tooling/check/code-style-conventions.mjs +106 -0
  539. package/esm/tooling/check/code-style-conventions.mjs.map +1 -0
  540. package/esm/tooling/check/conventions-step.d.mts +34 -0
  541. package/esm/tooling/check/conventions-step.d.mts.map +1 -0
  542. package/esm/tooling/check/conventions-step.mjs +184 -0
  543. package/esm/tooling/check/conventions-step.mjs.map +1 -0
  544. package/esm/tooling/check/environment-step.d.mts +18 -0
  545. package/esm/tooling/check/environment-step.d.mts.map +1 -0
  546. package/esm/tooling/check/environment-step.mjs +78 -0
  547. package/esm/tooling/check/environment-step.mjs.map +1 -0
  548. package/esm/tooling/check/index.d.mts +8 -0
  549. package/esm/tooling/check/index.mjs +10 -0
  550. package/esm/tooling/check/lint-step.d.mts +19 -0
  551. package/esm/tooling/check/lint-step.d.mts.map +1 -0
  552. package/esm/tooling/check/lint-step.mjs +111 -0
  553. package/esm/tooling/check/lint-step.mjs.map +1 -0
  554. package/esm/tooling/check/request-input.mjs +132 -0
  555. package/esm/tooling/check/request-input.mjs.map +1 -0
  556. package/esm/tooling/check/run-check.d.mts +35 -0
  557. package/esm/tooling/check/run-check.d.mts.map +1 -0
  558. package/esm/tooling/check/run-check.mjs +192 -0
  559. package/esm/tooling/check/run-check.mjs.map +1 -0
  560. package/esm/tooling/check/run-tests.d.mts +48 -0
  561. package/esm/tooling/check/run-tests.d.mts.map +1 -0
  562. package/esm/tooling/check/run-tests.mjs +93 -0
  563. package/esm/tooling/check/run-tests.mjs.map +1 -0
  564. package/esm/tooling/check/security-conventions.mjs +648 -0
  565. package/esm/tooling/check/security-conventions.mjs.map +1 -0
  566. package/esm/tooling/check/source-ast.mjs +195 -0
  567. package/esm/tooling/check/source-ast.mjs.map +1 -0
  568. package/esm/tooling/check/source-files.mjs +27 -0
  569. package/esm/tooling/check/source-files.mjs.map +1 -0
  570. package/esm/tooling/check/tests-step.d.mts +34 -0
  571. package/esm/tooling/check/tests-step.d.mts.map +1 -0
  572. package/esm/tooling/check/tests-step.mjs +177 -0
  573. package/esm/tooling/check/tests-step.mjs.map +1 -0
  574. package/esm/tooling/dev-state/dev-server-state.d.mts +39 -0
  575. package/esm/tooling/dev-state/dev-server-state.d.mts.map +1 -0
  576. package/esm/tooling/dev-state/dev-server-state.mjs +67 -0
  577. package/esm/tooling/dev-state/dev-server-state.mjs.map +1 -0
  578. package/esm/tooling/devtools/devtools-client.d.mts +91 -0
  579. package/esm/tooling/devtools/devtools-client.d.mts.map +1 -0
  580. package/esm/tooling/devtools/devtools-client.mjs +155 -0
  581. package/esm/tooling/devtools/devtools-client.mjs.map +1 -0
  582. package/esm/tooling/generate/generation.d.mts +78 -0
  583. package/esm/tooling/generate/generation.d.mts.map +1 -0
  584. package/esm/tooling/generate/generation.mjs +123 -0
  585. package/esm/tooling/generate/generation.mjs.map +1 -0
  586. package/esm/tooling/generate/generator-spec.d.mts +57 -0
  587. package/esm/tooling/generate/generator-spec.d.mts.map +1 -0
  588. package/esm/tooling/generate/generator-spec.mjs +102 -0
  589. package/esm/tooling/generate/generator-spec.mjs.map +1 -0
  590. package/esm/tooling/generate/index.mjs +6 -0
  591. package/esm/tooling/generate/project-files.mjs +121 -0
  592. package/esm/tooling/generate/project-files.mjs.map +1 -0
  593. package/esm/tooling/generate/run-cli.d.mts +40 -0
  594. package/esm/tooling/generate/run-cli.d.mts.map +1 -0
  595. package/esm/tooling/generate/run-cli.mjs +93 -0
  596. package/esm/tooling/generate/run-cli.mjs.map +1 -0
  597. package/esm/tooling/generate/unified-diff.d.mts +37 -0
  598. package/esm/tooling/generate/unified-diff.d.mts.map +1 -0
  599. package/esm/tooling/generate/unified-diff.mjs +161 -0
  600. package/esm/tooling/generate/unified-diff.mjs.map +1 -0
  601. package/esm/tooling/index.d.mts +41 -0
  602. package/esm/tooling/index.mjs +45 -0
  603. package/esm/tooling/inspect/boot-for-inspect.d.mts +23 -0
  604. package/esm/tooling/inspect/boot-for-inspect.d.mts.map +1 -0
  605. package/esm/tooling/inspect/boot-for-inspect.mjs +63 -0
  606. package/esm/tooling/inspect/boot-for-inspect.mjs.map +1 -0
  607. package/esm/tooling/inspect/collect-config.mjs +77 -0
  608. package/esm/tooling/inspect/collect-config.mjs.map +1 -0
  609. package/esm/tooling/inspect/collect-models.d.mts +9 -0
  610. package/esm/tooling/inspect/collect-models.d.mts.map +1 -0
  611. package/esm/tooling/inspect/collect-models.mjs +154 -0
  612. package/esm/tooling/inspect/collect-models.mjs.map +1 -0
  613. package/esm/tooling/inspect/collect-packages.d.mts +10 -0
  614. package/esm/tooling/inspect/collect-packages.d.mts.map +1 -0
  615. package/esm/tooling/inspect/collect-packages.mjs +157 -0
  616. package/esm/tooling/inspect/collect-packages.mjs.map +1 -0
  617. package/esm/tooling/inspect/collect-pages.mjs +108 -0
  618. package/esm/tooling/inspect/collect-pages.mjs.map +1 -0
  619. package/esm/tooling/inspect/collect-routes.mjs +168 -0
  620. package/esm/tooling/inspect/collect-routes.mjs.map +1 -0
  621. package/esm/tooling/inspect/event-recorder.d.mts +37 -0
  622. package/esm/tooling/inspect/event-recorder.d.mts.map +1 -0
  623. package/esm/tooling/inspect/event-recorder.mjs +91 -0
  624. package/esm/tooling/inspect/event-recorder.mjs.map +1 -0
  625. package/esm/tooling/inspect/index.d.mts +7 -0
  626. package/esm/tooling/inspect/index.mjs +7 -0
  627. package/esm/tooling/inspect/inspect-app.d.mts +53 -0
  628. package/esm/tooling/inspect/inspect-app.d.mts.map +1 -0
  629. package/esm/tooling/inspect/inspect-app.mjs +92 -0
  630. package/esm/tooling/inspect/inspect-app.mjs.map +1 -0
  631. package/esm/tooling/inspect/inspect-report.schema.d.mts +15 -0
  632. package/esm/tooling/inspect/inspect-report.schema.d.mts.map +1 -0
  633. package/esm/tooling/inspect/inspect-report.schema.mjs +463 -0
  634. package/esm/tooling/inspect/inspect-report.schema.mjs.map +1 -0
  635. package/esm/tooling/inspect/inspect-report.types.d.mts +196 -0
  636. package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -0
  637. package/esm/tooling/inspect/inspect-report.types.mjs +33 -0
  638. package/esm/tooling/inspect/inspect-report.types.mjs.map +1 -0
  639. package/esm/tooling/mcp/create-mcp-context.d.mts +26 -0
  640. package/esm/tooling/mcp/create-mcp-context.d.mts.map +1 -0
  641. package/esm/tooling/mcp/create-mcp-context.mjs +75 -0
  642. package/esm/tooling/mcp/create-mcp-context.mjs.map +1 -0
  643. package/esm/tooling/mcp/db-schema.d.mts +49 -0
  644. package/esm/tooling/mcp/db-schema.d.mts.map +1 -0
  645. package/esm/tooling/mcp/db-schema.mjs +56 -0
  646. package/esm/tooling/mcp/db-schema.mjs.map +1 -0
  647. package/esm/tooling/mcp/docs-search.d.mts +72 -0
  648. package/esm/tooling/mcp/docs-search.d.mts.map +1 -0
  649. package/esm/tooling/mcp/docs-search.mjs +178 -0
  650. package/esm/tooling/mcp/docs-search.mjs.map +1 -0
  651. package/esm/tooling/mcp/index.mjs +9 -0
  652. package/esm/tooling/mcp/load-ai-tools.d.mts +62 -0
  653. package/esm/tooling/mcp/load-ai-tools.d.mts.map +1 -0
  654. package/esm/tooling/mcp/load-ai-tools.mjs +44 -0
  655. package/esm/tooling/mcp/load-ai-tools.mjs.map +1 -0
  656. package/esm/tooling/mcp/mcp-tools.d.mts +60 -0
  657. package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -0
  658. package/esm/tooling/mcp/mcp-tools.mjs +513 -0
  659. package/esm/tooling/mcp/mcp-tools.mjs.map +1 -0
  660. package/esm/tooling/mcp/start-mcp-server.d.mts +56 -0
  661. package/esm/tooling/mcp/start-mcp-server.d.mts.map +1 -0
  662. package/esm/tooling/mcp/start-mcp-server.mjs +126 -0
  663. package/esm/tooling/mcp/start-mcp-server.mjs.map +1 -0
  664. package/esm/tooling/mcp/tool-input.d.mts +75 -0
  665. package/esm/tooling/mcp/tool-input.d.mts.map +1 -0
  666. package/esm/tooling/mcp/tool-input.mjs +72 -0
  667. package/esm/tooling/mcp/tool-input.mjs.map +1 -0
  668. package/esm/tooling/problem.d.mts +45 -0
  669. package/esm/tooling/problem.d.mts.map +1 -0
  670. package/esm/tooling/problem.mjs +28 -0
  671. package/esm/tooling/problem.mjs.map +1 -0
  672. package/esm/tooling/trace/trace-report.types.d.mts +71 -0
  673. package/esm/tooling/trace/trace-report.types.d.mts.map +1 -0
  674. package/esm/tooling/trace/trace-report.types.mjs +7 -0
  675. package/esm/tooling/trace/trace-report.types.mjs.map +1 -0
  676. package/esm/tooling/trace/trace-request.d.mts +83 -0
  677. package/esm/tooling/trace/trace-request.d.mts.map +1 -0
  678. package/esm/tooling/trace/trace-request.mjs +241 -0
  679. package/esm/tooling/trace/trace-request.mjs.map +1 -0
  680. package/esm/tooling/typecheck/index.d.mts +1 -0
  681. package/esm/tooling/typecheck/index.mjs +3 -0
  682. package/esm/tooling/typecheck/run-typecheck.d.mts +59 -0
  683. package/esm/tooling/typecheck/run-typecheck.d.mts.map +1 -0
  684. package/esm/tooling/typecheck/run-typecheck.mjs +153 -0
  685. package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -0
  686. package/esm/upgrade/codemods/head-viewport.mjs +46 -0
  687. package/esm/upgrade/codemods/head-viewport.mjs.map +1 -0
  688. package/esm/upgrade/codemods/helpers.mjs +81 -0
  689. package/esm/upgrade/codemods/helpers.mjs.map +1 -0
  690. package/esm/upgrade/codemods/index.mjs +34 -0
  691. package/esm/upgrade/codemods/index.mjs.map +1 -0
  692. package/esm/upgrade/codemods/logger-sync-calls.mjs +57 -0
  693. package/esm/upgrade/codemods/logger-sync-calls.mjs.map +1 -0
  694. package/esm/upgrade/codemods/package-json.mjs +122 -0
  695. package/esm/upgrade/codemods/package-json.mjs.map +1 -0
  696. package/esm/upgrade/codemods/request-log-snapshot.mjs +82 -0
  697. package/esm/upgrade/codemods/request-log-snapshot.mjs.map +1 -0
  698. package/esm/upgrade/codemods/review-sites.mjs +262 -0
  699. package/esm/upgrade/codemods/review-sites.mjs.map +1 -0
  700. package/esm/upgrade/diff.mjs +119 -0
  701. package/esm/upgrade/diff.mjs.map +1 -0
  702. package/esm/upgrade/format-upgrade-report.mjs +32 -0
  703. package/esm/upgrade/format-upgrade-report.mjs.map +1 -0
  704. package/esm/upgrade/load-ts-morph.mjs +48 -0
  705. package/esm/upgrade/load-ts-morph.mjs.map +1 -0
  706. package/esm/upgrade/notes.mjs +16 -0
  707. package/esm/upgrade/notes.mjs.map +1 -0
  708. package/esm/upgrade/run-upgrade.mjs +246 -0
  709. package/esm/upgrade/run-upgrade.mjs.map +1 -0
  710. package/esm/upgrade/upgrade-command.action.mjs +37 -0
  711. package/esm/upgrade/upgrade-command.action.mjs.map +1 -0
  712. package/esm/upgrade/version.mjs +39 -0
  713. package/esm/upgrade/version.mjs.map +1 -0
  714. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  715. package/esm/utils/clock.d.mts +33 -0
  716. package/esm/utils/clock.d.mts.map +1 -0
  717. package/esm/utils/clock.mjs +27 -0
  718. package/esm/utils/clock.mjs.map +1 -0
  719. package/esm/utils/framework-vesion.mjs +1 -1
  720. package/esm/utils/framework-vesion.mjs.map +1 -1
  721. package/esm/utils/ids.d.mts +32 -0
  722. package/esm/utils/ids.d.mts.map +1 -0
  723. package/esm/utils/ids.mjs +33 -0
  724. package/esm/utils/ids.mjs.map +1 -0
  725. package/esm/utils/index.d.mts +3 -0
  726. package/esm/utils/index.mjs +3 -0
  727. package/esm/utils/runtime.d.mts +59 -0
  728. package/esm/utils/runtime.d.mts.map +1 -0
  729. package/esm/utils/runtime.mjs +85 -0
  730. package/esm/utils/runtime.mjs.map +1 -0
  731. package/esm/validation/index.d.mts +1 -1
  732. package/esm/validation/types.d.mts +57 -2
  733. package/esm/validation/types.d.mts.map +1 -1
  734. package/esm/validation/validateAll.mjs +19 -2
  735. package/esm/validation/validateAll.mjs.map +1 -1
  736. package/esm/validation/validation-failure-status.mjs +15 -0
  737. package/esm/validation/validation-failure-status.mjs.map +1 -0
  738. package/esm/validation/validators/file-validator.d.mts +0 -16
  739. package/esm/validation/validators/file-validator.d.mts.map +1 -1
  740. package/esm/warlock-config/bundle-config.mjs +1 -1
  741. package/esm/warlock-config/types.d.mts +27 -3
  742. package/esm/warlock-config/types.d.mts.map +1 -1
  743. package/llms-full.txt +3166 -736
  744. package/llms.txt +16 -6
  745. package/package.json +43 -13
  746. package/schemas/inspect-report.schema.json +554 -0
  747. package/skills/README.md +9 -0
  748. package/skills/add-connector/SKILL.md +26 -38
  749. package/skills/benchmark-code/SKILL.md +30 -24
  750. package/skills/build-restful/SKILL.md +14 -14
  751. package/skills/build-url/SKILL.md +18 -18
  752. package/skills/configure-app/SKILL.md +107 -14
  753. package/skills/create-controller/SKILL.md +25 -12
  754. package/skills/create-module/SKILL.md +3 -3
  755. package/skills/define-resource/SKILL.md +32 -29
  756. package/skills/encrypt-data/SKILL.md +21 -19
  757. package/skills/generate-openapi/SKILL.md +50 -24
  758. package/skills/hash-password/SKILL.md +2 -2
  759. package/skills/health-checks/SKILL.md +24 -7
  760. package/skills/index.md +9 -4
  761. package/skills/lower-stage3-decorators/SKILL.md +4 -4
  762. package/skills/make-endpoint/SKILL.md +110 -0
  763. package/skills/model-factories/SKILL.md +92 -0
  764. package/skills/process-image/SKILL.md +32 -30
  765. package/skills/register-route/SKILL.md +109 -10
  766. package/skills/request-memo/SKILL.md +1 -1
  767. package/skills/request-tracing/SKILL.md +4 -1
  768. package/skills/resolve-path/SKILL.md +45 -44
  769. package/skills/retry-operation/SKILL.md +20 -11
  770. package/skills/run-app/SKILL.md +106 -22
  771. package/skills/send-response/SKILL.md +179 -14
  772. package/skills/store-file/SKILL.md +93 -53
  773. package/skills/test-fakes/SKILL.md +123 -0
  774. package/skills/test-http/SKILL.md +125 -21
  775. package/skills/test-service/SKILL.md +41 -1
  776. package/skills/update-packages/SKILL.md +29 -18
  777. package/skills/upgrade-from-5-29/SKILL.md +413 -0
  778. package/skills/upload-file/SKILL.md +31 -33
  779. package/skills/use-app-context/SKILL.md +38 -31
  780. package/skills/use-middleware/SKILL.md +45 -25
  781. package/skills/use-model-transformers/SKILL.md +37 -28
  782. package/skills/use-repository/SKILL.md +2 -2
  783. package/skills/validate-input/SKILL.md +72 -28
  784. package/skills/warlock-agents-md/SKILL.md +96 -0
  785. package/skills/warlock-board/SKILL.md +123 -0
  786. package/skills/warlock-check/SKILL.md +132 -0
  787. package/skills/warlock-conventions/SKILL.md +115 -0
  788. package/skills/warlock-doctor/SKILL.md +55 -22
  789. package/skills/warlock-inspect/SKILL.md +134 -0
  790. package/skills/warlock-mcp/SKILL.md +120 -0
  791. package/skills/warlock-routes/SKILL.md +18 -11
  792. package/skills/warlock-trace/SKILL.md +81 -0
  793. package/skills/wire-socket/SKILL.md +8 -8
  794. package/skills/write-seeder/SKILL.md +46 -32
  795. package/skills/write-use-case/SKILL.md +40 -27
  796. package/esm/http/uploads/matches-if-none-match.mjs +0 -13
  797. package/esm/http/uploads/matches-if-none-match.mjs.map +0 -1
@@ -0,0 +1,46 @@
1
+ import { command } from "../../commands/cli-command.mjs";
2
+
3
+ //#region ../../packages/core/src/cli/commands/upgrade.command.ts
4
+ /**
5
+ * `warlock upgrade --to <version>` — apply the mechanical edits for every
6
+ * breaking change between the installed release and the target, and list the
7
+ * places that need a decision (`file:line` plus the reason). `--dry-run`
8
+ * prints a diff and writes nothing; `--json` prints the result as JSON.
9
+ *
10
+ * Needs no app boot: it reads source files, `package.json` and Node version
11
+ * files only. `ts-morph` (an optional peer) is loaded when the command runs.
12
+ */
13
+ const upgradeCommand = command({
14
+ name: "upgrade",
15
+ description: "Apply the code changes a Warlock upgrade needs (--to <version>), and list what to review by hand; --dry-run shows a diff, --json prints JSON",
16
+ action: async (data) => {
17
+ const { runUpgradeCommand } = await import("../../upgrade/upgrade-command.action.mjs");
18
+ await runUpgradeCommand(data.options);
19
+ },
20
+ options: [
21
+ {
22
+ text: "--to",
23
+ description: "Version to upgrade to, e.g. 5.31 or 5.31.0 (required)",
24
+ type: "string"
25
+ },
26
+ {
27
+ text: "--from",
28
+ description: "Version to upgrade from (default: the installed @warlock.js/core, so pass it once the new release is installed)",
29
+ type: "string"
30
+ },
31
+ {
32
+ text: "--dry-run",
33
+ description: "Show the diff and the review list without writing any file",
34
+ type: "boolean"
35
+ },
36
+ {
37
+ text: "--json, -j",
38
+ description: "Print the result as JSON",
39
+ type: "boolean"
40
+ }
41
+ ]
42
+ });
43
+
44
+ //#endregion
45
+ export { upgradeCommand };
46
+ //# sourceMappingURL=upgrade.command.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade.command.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/cli/commands/upgrade.command.ts"],"sourcesContent":["import { command } from \"../../commands/cli-command\";\n\n/**\n * `warlock upgrade --to <version>` — apply the mechanical edits for every\n * breaking change between the installed release and the target, and list the\n * places that need a decision (`file:line` plus the reason). `--dry-run`\n * prints a diff and writes nothing; `--json` prints the result as JSON.\n *\n * Needs no app boot: it reads source files, `package.json` and Node version\n * files only. `ts-morph` (an optional peer) is loaded when the command runs.\n */\nexport const upgradeCommand = command({\n name: \"upgrade\",\n description:\n \"Apply the code changes a Warlock upgrade needs (--to <version>), and list what to review by hand; --dry-run shows a diff, --json prints JSON\",\n action: async (data) => {\n // Loaded here so ts-morph and the codemods never join another command's graph.\n const { runUpgradeCommand } = await import(\"../../upgrade/upgrade-command.action\");\n await runUpgradeCommand(data.options);\n },\n options: [\n {\n text: \"--to\",\n description: \"Version to upgrade to, e.g. 5.31 or 5.31.0 (required)\",\n type: \"string\",\n },\n {\n text: \"--from\",\n description:\n \"Version to upgrade from (default: the installed @warlock.js/core, so pass it once the new release is installed)\",\n type: \"string\",\n },\n {\n text: \"--dry-run\",\n description: \"Show the diff and the review list without writing any file\",\n type: \"boolean\",\n },\n {\n text: \"--json, -j\",\n description: \"Print the result as JSON\",\n type: \"boolean\",\n },\n ],\n});\n"],"mappings":";;;;;;;;;;;;AAWA,MAAa,iBAAiB,QAAQ;CACpC,MAAM;CACN,aACE;CACF,QAAQ,OAAO,SAAS;EAEtB,MAAM,EAAE,sBAAsB,MAAM,OAAO;EAC3C,MAAM,kBAAkB,KAAK,OAAO;CACtC;CACA,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aACE;GACF,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC"}
@@ -0,0 +1,34 @@
1
+ //#region ../../packages/core/src/cli/flush-and-exit.ts
2
+ /** How long to wait for stdout/stderr to drain before exiting anyway. */
3
+ const FLUSH_BUDGET_MS = 500;
4
+ function drain(stream) {
5
+ return new Promise((resolve) => {
6
+ stream.write("", () => resolve());
7
+ });
8
+ }
9
+ /**
10
+ * Exit with `code` once everything already written to stdout and stderr has
11
+ * been flushed.
12
+ *
13
+ * For commands whose exit code carries meaning (`warlock check` exits 1 for
14
+ * problems in the code and 2 for problems with the machine): a bare
15
+ * `process.exit()` right after printing a large JSON report to a pipe can cut
16
+ * the report short. Awaited inside the action, so the CLI never goes on to
17
+ * print its success banner or exit 0.
18
+ *
19
+ * @param code The process exit code.
20
+ */
21
+ async function flushAndExit(code) {
22
+ process.exitCode = code;
23
+ let timer;
24
+ await Promise.race([Promise.all([drain(process.stdout), drain(process.stderr)]), new Promise((resolve) => {
25
+ timer = setTimeout(resolve, FLUSH_BUDGET_MS);
26
+ timer.unref?.();
27
+ })]);
28
+ if (timer) clearTimeout(timer);
29
+ return process.exit(code);
30
+ }
31
+
32
+ //#endregion
33
+ export { flushAndExit };
34
+ //# sourceMappingURL=flush-and-exit.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flush-and-exit.mjs","names":[],"sources":["../../../../../../../../packages/core/src/cli/flush-and-exit.ts"],"sourcesContent":["/** How long to wait for stdout/stderr to drain before exiting anyway. */\nconst FLUSH_BUDGET_MS = 500;\n\nfunction drain(stream: NodeJS.WriteStream): Promise<void> {\n return new Promise((resolve) => {\n // A zero-length write's callback fires once everything queued ahead of it\n // has been handed to the OS.\n stream.write(\"\", () => resolve());\n });\n}\n\n/**\n * Exit with `code` once everything already written to stdout and stderr has\n * been flushed.\n *\n * For commands whose exit code carries meaning (`warlock check` exits 1 for\n * problems in the code and 2 for problems with the machine): a bare\n * `process.exit()` right after printing a large JSON report to a pipe can cut\n * the report short. Awaited inside the action, so the CLI never goes on to\n * print its success banner or exit 0.\n *\n * @param code The process exit code.\n */\nexport async function flushAndExit(code: number): Promise<never> {\n process.exitCode = code;\n\n let timer: NodeJS.Timeout | undefined;\n\n await Promise.race([\n Promise.all([drain(process.stdout), drain(process.stderr)]),\n new Promise<void>((resolve) => {\n timer = setTimeout(resolve, FLUSH_BUDGET_MS);\n timer.unref?.();\n }),\n ]);\n\n if (timer) clearTimeout(timer);\n\n return process.exit(code);\n}\n"],"mappings":";;AACA,MAAM,kBAAkB;AAExB,SAAS,MAAM,QAA2C;CACxD,OAAO,IAAI,SAAS,YAAY;EAG9B,OAAO,MAAM,UAAU,QAAQ,CAAC;CAClC,CAAC;AACH;;;;;;;;;;;;;AAcA,eAAsB,aAAa,MAA8B;CAC/D,QAAQ,WAAW;CAEnB,IAAI;CAEJ,MAAM,QAAQ,KAAK,CACjB,QAAQ,IAAI,CAAC,MAAM,QAAQ,MAAM,GAAG,MAAM,QAAQ,MAAM,CAAC,CAAC,GAC1D,IAAI,SAAe,YAAY;EAC7B,QAAQ,WAAW,SAAS,eAAe;EAC3C,MAAM,QAAQ;CAChB,CAAC,CACH,CAAC;CAED,IAAI,OAAO,aAAa,KAAK;CAE7B,OAAO,QAAQ,KAAK,IAAI;AAC1B"}
@@ -1,19 +1,29 @@
1
1
  import { addCommand } from "./commands/add.command.mjs";
2
+ import { agentsMdCommand } from "./commands/agents-md.command.mjs";
3
+ import { boardCommand } from "./commands/board.command.mjs";
2
4
  import { buildCommand } from "./commands/build.command.mjs";
5
+ import { checkCommand } from "./commands/check.command.mjs";
3
6
  import { createDatabaseCommand } from "./commands/create-database.command.mjs";
4
7
  import { devServerCommand } from "./commands/dev-server.command.mjs";
5
8
  import { doctorCommand } from "./commands/doctor.command.mjs";
6
9
  import { dropTablesCommand } from "./commands/drop-tables.command.mjs";
7
- import { generateCommand, generateControllerCommand, generateMigrationCommand, generateModelCommand, generateModuleCommand, generateRepositoryCommand, generateResourceCommand, generateServiceCommand, generateUseCaseCommand } from "./commands/generate/generate.command.mjs";
10
+ import { explainCommand } from "./commands/explain.command.mjs";
11
+ import { generateCommand, generateControllerCommand, generateEndpointCommand, generateMigrationCommand, generateModelCommand, generateModuleCommand, generateRepositoryCommand, generateResourceCommand, generateServiceCommand, generateUseCaseCommand, makeCommand } from "./commands/generate/generate.command.mjs";
12
+ import { inspectCommand } from "./commands/inspect.command.mjs";
13
+ import { mcpCommand } from "./commands/mcp.command.mjs";
8
14
  import { migrateCommand } from "./commands/migrate.command.mjs";
9
15
  import { openApiGeneratorCommand } from "./commands/openapi-generator.command.mjs";
10
16
  import { postmanGeneratorCommand } from "./commands/postman-generator.command.mjs";
11
17
  import { routesCommand, routesDiffCommand } from "./commands/routes.command.mjs";
12
18
  import { seedCommand } from "./commands/seed.command.mjs";
13
19
  import { startProductionCommand } from "./commands/start-production.command.mjs";
20
+ import { traceCommand } from "./commands/trace.command.mjs";
14
21
  import { storagePutCommand } from "./commands/storage-put.command.mjs";
22
+ import { typecheckCommand } from "./commands/typecheck.command.mjs";
23
+ import { testCommand } from "./commands/test.command.mjs";
15
24
  import { typingsGeneratorCommand } from "./commands/typings-generator.command.mjs";
16
25
  import { updateCommand } from "./commands/update.command.mjs";
26
+ import { upgradeCommand } from "./commands/upgrade.command.mjs";
17
27
 
18
28
  //#region ../../packages/core/src/cli/framework-cli-commands.ts
19
29
  const frameworkCommands = [
@@ -21,9 +31,18 @@ const frameworkCommands = [
21
31
  typingsGeneratorCommand,
22
32
  openApiGeneratorCommand,
23
33
  postmanGeneratorCommand,
34
+ testCommand,
24
35
  doctorCommand,
25
36
  routesCommand,
26
37
  routesDiffCommand,
38
+ inspectCommand,
39
+ explainCommand,
40
+ checkCommand,
41
+ typecheckCommand,
42
+ mcpCommand,
43
+ traceCommand,
44
+ agentsMdCommand,
45
+ boardCommand,
27
46
  buildCommand,
28
47
  startProductionCommand,
29
48
  migrateCommand,
@@ -32,7 +51,10 @@ const frameworkCommands = [
32
51
  dropTablesCommand,
33
52
  addCommand,
34
53
  updateCommand,
54
+ upgradeCommand,
35
55
  generateCommand,
56
+ makeCommand,
57
+ generateEndpointCommand,
36
58
  generateModuleCommand,
37
59
  generateControllerCommand,
38
60
  generateServiceCommand,
@@ -1 +1 @@
1
- {"version":3,"file":"framework-cli-commands.mjs","names":[],"sources":["../../../../../../../../packages/core/src/cli/framework-cli-commands.ts"],"sourcesContent":["import { addCommand } from \"./commands/add.command\";\nimport { buildCommand } from \"./commands/build.command\";\nimport { createDatabaseCommand } from \"./commands/create-database.command\";\nimport { devServerCommand } from \"./commands/dev-server.command\";\nimport { doctorCommand } from \"./commands/doctor.command\";\nimport { dropTablesCommand } from \"./commands/drop-tables.command\";\nimport {\n generateCommand,\n generateControllerCommand,\n generateMigrationCommand,\n generateModelCommand,\n generateModuleCommand,\n generateRepositoryCommand,\n generateResourceCommand,\n generateServiceCommand,\n generateUseCaseCommand,\n} from \"./commands/generate/generate.command\";\nimport { migrateCommand } from \"./commands/migrate.command\";\nimport { openApiGeneratorCommand } from \"./commands/openapi-generator.command\";\nimport { postmanGeneratorCommand } from \"./commands/postman-generator.command\";\nimport { routesCommand, routesDiffCommand } from \"./commands/routes.command\";\nimport { seedCommand } from \"./commands/seed.command\";\nimport { startProductionCommand } from \"./commands/start-production.command\";\nimport { storagePutCommand } from \"./commands/storage-put.command\";\nimport { typingsGeneratorCommand } from \"./commands/typings-generator.command\";\nimport { updateCommand } from \"./commands/update.command\";\n\nexport const frameworkCommands = [\n // development commands\n devServerCommand,\n typingsGeneratorCommand,\n openApiGeneratorCommand,\n postmanGeneratorCommand,\n\n // diagnostics commands\n doctorCommand,\n routesCommand,\n routesDiffCommand,\n\n // production commands\n buildCommand,\n startProductionCommand,\n\n // database commands\n migrateCommand,\n seedCommand,\n createDatabaseCommand,\n dropTablesCommand,\n\n // generation/installation commands\n addCommand,\n updateCommand,\n\n // scaffolding commands\n generateCommand,\n generateModuleCommand,\n generateControllerCommand,\n generateServiceCommand,\n generateUseCaseCommand,\n generateModelCommand,\n generateRepositoryCommand,\n generateResourceCommand,\n generateMigrationCommand,\n\n // storage commands\n storagePutCommand,\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2BA,MAAa,oBAAoB;CAE/B;CACA;CACA;CACA;CAGA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;AACF"}
1
+ {"version":3,"file":"framework-cli-commands.mjs","names":[],"sources":["../../../../../../../../packages/core/src/cli/framework-cli-commands.ts"],"sourcesContent":["import { addCommand } from \"./commands/add.command\";\nimport { agentsMdCommand } from \"./commands/agents-md.command\";\nimport { boardCommand } from \"./commands/board.command\";\nimport { buildCommand } from \"./commands/build.command\";\nimport { checkCommand } from \"./commands/check.command\";\nimport { createDatabaseCommand } from \"./commands/create-database.command\";\nimport { devServerCommand } from \"./commands/dev-server.command\";\nimport { doctorCommand } from \"./commands/doctor.command\";\nimport { dropTablesCommand } from \"./commands/drop-tables.command\";\nimport { explainCommand } from \"./commands/explain.command\";\nimport {\n generateCommand,\n generateControllerCommand,\n generateEndpointCommand,\n generateMigrationCommand,\n generateModelCommand,\n generateModuleCommand,\n generateRepositoryCommand,\n generateResourceCommand,\n generateServiceCommand,\n generateUseCaseCommand,\n makeCommand,\n} from \"./commands/generate/generate.command\";\nimport { inspectCommand } from \"./commands/inspect.command\";\nimport { mcpCommand } from \"./commands/mcp.command\";\nimport { migrateCommand } from \"./commands/migrate.command\";\nimport { openApiGeneratorCommand } from \"./commands/openapi-generator.command\";\nimport { postmanGeneratorCommand } from \"./commands/postman-generator.command\";\nimport { routesCommand, routesDiffCommand } from \"./commands/routes.command\";\nimport { seedCommand } from \"./commands/seed.command\";\nimport { startProductionCommand } from \"./commands/start-production.command\";\nimport { traceCommand } from \"./commands/trace.command\";\nimport { storagePutCommand } from \"./commands/storage-put.command\";\nimport { typecheckCommand } from \"./commands/typecheck.command\";\nimport { testCommand } from \"./commands/test.command\";\nimport { typingsGeneratorCommand } from \"./commands/typings-generator.command\";\nimport { updateCommand } from \"./commands/update.command\";\nimport { upgradeCommand } from \"./commands/upgrade.command\";\n\nexport const frameworkCommands = [\n // development commands\n devServerCommand,\n typingsGeneratorCommand,\n openApiGeneratorCommand,\n postmanGeneratorCommand,\n\n // testing commands\n testCommand,\n\n // diagnostics commands\n doctorCommand,\n routesCommand,\n routesDiffCommand,\n inspectCommand,\n explainCommand,\n checkCommand,\n typecheckCommand,\n\n // agent tooling commands\n mcpCommand,\n traceCommand,\n agentsMdCommand,\n boardCommand,\n\n // production commands\n buildCommand,\n startProductionCommand,\n\n // database commands\n migrateCommand,\n seedCommand,\n createDatabaseCommand,\n dropTablesCommand,\n\n // generation/installation commands\n addCommand,\n updateCommand,\n upgradeCommand,\n\n // scaffolding commands\n generateCommand,\n makeCommand,\n generateEndpointCommand,\n generateModuleCommand,\n generateControllerCommand,\n generateServiceCommand,\n generateUseCaseCommand,\n generateModelCommand,\n generateRepositoryCommand,\n generateResourceCommand,\n generateMigrationCommand,\n\n // storage commands\n storagePutCommand,\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,MAAa,oBAAoB;CAE/B;CACA;CACA;CACA;CAGA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CACA;CAGA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;AACF"}
@@ -14,6 +14,7 @@ var CliOptionValueError = class extends Error {
14
14
  super(`Invalid value ${JSON.stringify(value)} for boolean option ${optionToken}. Expected one of: true, false, 1, 0, yes, no — or pass ${optionToken} on its own for true.`);
15
15
  this.optionToken = optionToken;
16
16
  this.value = value;
17
+ this.code = "WL7001";
17
18
  this.name = "CliOptionValueError";
18
19
  }
19
20
  };
@@ -1 +1 @@
1
- {"version":3,"file":"parse-cli-args.mjs","names":[],"sources":["../../../../../../../../packages/core/src/cli/parse-cli-args.ts"],"sourcesContent":["import { toCamelCase } from \"@mongez/reinforcements\";\n\nexport type ParsedCliArgs = {\n name: string;\n args: string[];\n options: Record<string, string | boolean>;\n};\n\n/**\n * The slice of a declared command option this parser needs.\n *\n * `CLICommand.commandOptions` (`ResolvedCLICommandOption[]`) satisfies it, but\n * the parser stays independent of the command classes so it can be unit-tested\n * and reused with a hand-written schema.\n */\nexport type CliOptionSchema = {\n name?: string;\n alias?: string;\n type?: \"string\" | \"boolean\" | \"number\";\n};\n\n/**\n * Thrown when a declared boolean option is given a value that is neither\n * true-ish nor false-ish.\n *\n * We refuse to guess. Guessing is exactly what produced #21: `--rollback=false`\n * was kept as the truthy string `\"false\"` and dropped every table. An option\n * that gates a destructive action must fail loudly on input it cannot read.\n */\nexport class CliOptionValueError extends Error {\n public constructor(\n public readonly optionToken: string,\n public readonly value: string,\n ) {\n super(\n `Invalid value ${JSON.stringify(value)} for boolean option ${optionToken}. ` +\n `Expected one of: true, false, 1, 0, yes, no — or pass ${optionToken} on its own for true.`,\n );\n\n this.name = \"CliOptionValueError\";\n }\n}\n\nconst TRUE_VALUES = new Set([\"true\", \"1\", \"yes\"]);\nconst FALSE_VALUES = new Set([\"false\", \"0\", \"no\"]);\n\n/**\n * Collect the camelCased keys (names AND aliases) of every option the command\n * declared as `type: \"boolean\"`.\n *\n * Both sides are camelCased because declared names keep their raw kebab form\n * (`\"pending-only\"`) while the parser emits camelCase keys (`pendingOnly`).\n */\nfunction collectBooleanKeys(schema: CliOptionSchema[]): Set<string> {\n const keys = new Set<string>();\n\n for (const option of schema) {\n if (option.type !== \"boolean\") continue;\n\n if (option.name) {\n keys.add(toCamelCase(option.name));\n }\n\n if (option.alias) {\n keys.add(toCamelCase(option.alias));\n }\n }\n\n return keys;\n}\n\n/**\n * Collect the declared aliases longer than one character (`-st`, `-rs`, `-pm`).\n *\n * A cluster equal to one of these is that alias, not a bundle of single-letter\n * flags, so it has to be matched before the bundle split.\n */\nfunction collectMultiCharAliases(schema: CliOptionSchema[]): Set<string> {\n const aliases = new Set<string>();\n\n for (const option of schema) {\n if (option.alias && option.alias.length > 1) {\n aliases.add(option.alias);\n }\n }\n\n return aliases;\n}\n\n/**\n * Turn the value written after `=` into a real boolean, or throw.\n */\nfunction toBoolean(optionToken: string, value: string): boolean {\n const normalized = value.toLowerCase();\n\n if (TRUE_VALUES.has(normalized)) return true;\n if (FALSE_VALUES.has(normalized)) return false;\n\n throw new CliOptionValueError(optionToken, value);\n}\n\n/**\n * Parse CLI arguments from process.argv\n *\n * Called with a `schema` (the resolved command's declared options), every\n * option declared `type: \"boolean\"` is resolved as a boolean:\n * `--flag` → true, `--flag=false|0|no` → false, `--flag=true|1|yes` → true,\n * and `--flag <token>` leaves `<token>` as a POSITIONAL instead of swallowing\n * it as the flag's value. Anything else throws {@link CliOptionValueError}.\n *\n * Called without a schema — which is how the command name is discovered,\n * before any command object exists — behaviour is unchanged: every value stays\n * a raw string and a bare `--flag` still consumes the following non-dash token.\n * Nothing is blanket-coerced here on purpose: `--name=false` on a string-typed\n * option must survive as the string `\"false\"`.\n *\n * Options the schema does not declare keep the schema-less behaviour.\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"])\n * // Returns: { name: \"migrate\", args: [], options: { rollback: \"file.ts\" } }\n *\n * @example\n * // `rollback` declared as type: \"boolean\" — the file stays a positional\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"], migrateOptions)\n * // Returns: { name: \"migrate\", args: [\"file.ts\"], options: { rollback: true } }\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"dev\", \"--port=3000\", \"--fresh\"])\n * // Returns: { name: \"dev\", args: [], options: { port: \"3000\", fresh: true } }\n */\nexport function parseCliArgs(argv: string[], schema: CliOptionSchema[] = []): ParsedCliArgs {\n // Command is at index 2 (after \"node\" and script path)\n // But if index 2 starts with \"-\", it's an option, not a command\n const potentialCommand = argv[2] || \"\";\n const isFirstArgOption = potentialCommand.startsWith(\"-\");\n const command = isFirstArgOption ? \"\" : potentialCommand;\n const args: string[] = [];\n const options: Record<string, string | boolean> = {};\n const booleanKeys = collectBooleanKeys(schema);\n const multiCharAliases = collectMultiCharAliases(schema);\n\n // Parse arguments starting from index 3 (or 2 if first arg was an option)\n const startIndex = isFirstArgOption ? 2 : 3;\n for (let i = startIndex; i < argv.length; i++) {\n const arg = argv[i];\n\n // `i < argv.length` bounds this, but the compiler does not narrow an index\n // read from a loop condition. Skipping rather than coercing: this file\n // already refuses to guess about an operator's input (see\n // `CliOptionValueError` above), and an `?? \"\"` here would silently push an\n // empty POSITIONAL onto `args` — which for a command that takes a file or\n // a table name is a scope the operator never typed.\n if (arg === undefined) continue;\n\n if (arg.startsWith(\"--\")) {\n // Long option: --key or --key=value\n const withoutDashes = arg.slice(2);\n const equalIndex = withoutDashes.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // --key=value format\n const key = toCamelCase(withoutDashes.slice(0, equalIndex));\n const value = withoutDashes.slice(equalIndex + 1);\n options[key] = booleanKeys.has(key)\n ? toBoolean(`--${withoutDashes.slice(0, equalIndex)}`, value)\n : value;\n } else {\n // --key format (check if next arg is a value)\n const key = toCamelCase(withoutDashes);\n const nextArg = argv[i + 1];\n\n // A declared boolean NEVER consumes the next token: `--rollback\n // users.ts` means \"rollback, and here is a positional\", not \"rollback\n // the file users.ts\". Swallowing it silently discarded the operator's\n // only stated scope and rolled back everything.\n if (booleanKeys.has(key)) {\n options[key] = true;\n } else if (nextArg && !nextArg.startsWith(\"-\")) {\n // If next arg exists and doesn't start with -, treat it as value\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n }\n } else if (arg.startsWith(\"-\") && arg.length > 1) {\n // Short option: -f, -t=value, or -abc (multiple flags)\n const flags = arg.slice(1);\n const equalIndex = flags.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // -t=value format\n const rawKey = flags.slice(0, equalIndex);\n const key = toCamelCase(rawKey);\n const value = flags.slice(equalIndex + 1);\n options[key] = booleanKeys.has(key) ? toBoolean(`-${rawKey}`, value) : value;\n } else if (flags.length === 1 || multiCharAliases.has(flags)) {\n // Single flag: -f, or a declared multi-character alias: -st\n const key = toCamelCase(flags);\n const nextArg = argv[i + 1];\n\n if (booleanKeys.has(key)) {\n options[key] = true;\n } else if (nextArg && !nextArg.startsWith(\"-\")) {\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n } else {\n // Multiple flags: -abc becomes { a: true, b: true, c: true }\n // A bundle carries no value and never consumes the next token, so a\n // declared boolean already resolves to `true` here.\n for (const flag of flags) {\n options[toCamelCase(flag)] = true;\n }\n }\n } else {\n // Positional argument\n args.push(arg);\n }\n }\n\n return { name: command, args, options };\n}\n"],"mappings":";;;;;;;;;;;AA6BA,IAAa,sBAAb,cAAyC,MAAM;CAC7C,AAAO,YACL,AAAgB,aAChB,AAAgB,OAChB;EACA,MACE,iBAAiB,KAAK,UAAU,KAAK,EAAE,sBAAsB,YAAY,0DACd,YAAY,sBACzE;EANgB;EACA;EAOhB,KAAK,OAAO;CACd;AACF;AAEA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAQ;CAAK;AAAK,CAAC;AAChD,MAAM,eAAe,IAAI,IAAI;CAAC;CAAS;CAAK;AAAI,CAAC;;;;;;;;AASjD,SAAS,mBAAmB,QAAwC;CAClE,MAAM,uBAAO,IAAI,IAAY;CAE7B,KAAK,MAAM,UAAU,QAAQ;EAC3B,IAAI,OAAO,SAAS,WAAW;EAE/B,IAAI,OAAO,MACT,KAAK,IAAI,YAAY,OAAO,IAAI,CAAC;EAGnC,IAAI,OAAO,OACT,KAAK,IAAI,YAAY,OAAO,KAAK,CAAC;CAEtC;CAEA,OAAO;AACT;;;;;;;AAQA,SAAS,wBAAwB,QAAwC;CACvE,MAAM,0BAAU,IAAI,IAAY;CAEhC,KAAK,MAAM,UAAU,QACnB,IAAI,OAAO,SAAS,OAAO,MAAM,SAAS,GACxC,QAAQ,IAAI,OAAO,KAAK;CAI5B,OAAO;AACT;;;;AAKA,SAAS,UAAU,aAAqB,OAAwB;CAC9D,MAAM,aAAa,MAAM,YAAY;CAErC,IAAI,YAAY,IAAI,UAAU,GAAG,OAAO;CACxC,IAAI,aAAa,IAAI,UAAU,GAAG,OAAO;CAEzC,MAAM,IAAI,oBAAoB,aAAa,KAAK;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,aAAa,MAAgB,SAA4B,CAAC,GAAkB;CAG1F,MAAM,mBAAmB,KAAK,MAAM;CACpC,MAAM,mBAAmB,iBAAiB,WAAW,GAAG;CACxD,MAAM,UAAU,mBAAmB,KAAK;CACxC,MAAM,OAAiB,CAAC;CACxB,MAAM,UAA4C,CAAC;CACnD,MAAM,cAAc,mBAAmB,MAAM;CAC7C,MAAM,mBAAmB,wBAAwB,MAAM;CAGvD,MAAM,aAAa,mBAAmB,IAAI;CAC1C,KAAK,IAAI,IAAI,YAAY,IAAI,KAAK,QAAQ,KAAK;EAC7C,MAAM,MAAM,KAAK;EAQjB,IAAI,QAAQ,QAAW;EAEvB,IAAI,IAAI,WAAW,IAAI,GAAG;GAExB,MAAM,gBAAgB,IAAI,MAAM,CAAC;GACjC,MAAM,aAAa,cAAc,QAAQ,GAAG;GAE5C,IAAI,eAAe,IAAI;IAErB,MAAM,MAAM,YAAY,cAAc,MAAM,GAAG,UAAU,CAAC;IAC1D,MAAM,QAAQ,cAAc,MAAM,aAAa,CAAC;IAChD,QAAQ,OAAO,YAAY,IAAI,GAAG,IAC9B,UAAU,KAAK,cAAc,MAAM,GAAG,UAAU,KAAK,KAAK,IAC1D;GACN,OAAO;IAEL,MAAM,MAAM,YAAY,aAAa;IACrC,MAAM,UAAU,KAAK,IAAI;IAMzB,IAAI,YAAY,IAAI,GAAG,GACrB,QAAQ,OAAO;SACV,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KAE9C,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB;EACF,OAAO,IAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG;GAEhD,MAAM,QAAQ,IAAI,MAAM,CAAC;GACzB,MAAM,aAAa,MAAM,QAAQ,GAAG;GAEpC,IAAI,eAAe,IAAI;IAErB,MAAM,SAAS,MAAM,MAAM,GAAG,UAAU;IACxC,MAAM,MAAM,YAAY,MAAM;IAC9B,MAAM,QAAQ,MAAM,MAAM,aAAa,CAAC;IACxC,QAAQ,OAAO,YAAY,IAAI,GAAG,IAAI,UAAU,IAAI,UAAU,KAAK,IAAI;GACzE,OAAO,IAAI,MAAM,WAAW,KAAK,iBAAiB,IAAI,KAAK,GAAG;IAE5D,MAAM,MAAM,YAAY,KAAK;IAC7B,MAAM,UAAU,KAAK,IAAI;IAEzB,IAAI,YAAY,IAAI,GAAG,GACrB,QAAQ,OAAO;SACV,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KAC9C,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB,OAIE,KAAK,MAAM,QAAQ,OACjB,QAAQ,YAAY,IAAI,KAAK;EAGnC,OAEE,KAAK,KAAK,GAAG;CAEjB;CAEA,OAAO;EAAE,MAAM;EAAS;EAAM;CAAQ;AACxC"}
1
+ {"version":3,"file":"parse-cli-args.mjs","names":[],"sources":["../../../../../../../../packages/core/src/cli/parse-cli-args.ts"],"sourcesContent":["import { toCamelCase } from \"@mongez/reinforcements\";\n\nexport type ParsedCliArgs = {\n name: string;\n args: string[];\n options: Record<string, string | boolean>;\n};\n\n/**\n * The slice of a declared command option this parser needs.\n *\n * `CLICommand.commandOptions` (`ResolvedCLICommandOption[]`) satisfies it, but\n * the parser stays independent of the command classes so it can be unit-tested\n * and reused with a hand-written schema.\n */\nexport type CliOptionSchema = {\n name?: string;\n alias?: string;\n type?: \"string\" | \"boolean\" | \"number\";\n};\n\n/**\n * Thrown when a declared boolean option is given a value that is neither\n * true-ish nor false-ish.\n *\n * We refuse to guess. Guessing is exactly what produced #21: `--rollback=false`\n * was kept as the truthy string `\"false\"` and dropped every table. An option\n * that gates a destructive action must fail loudly on input it cannot read.\n */\nexport class CliOptionValueError extends Error {\n /** Stable Warlock error code; `warlock explain WL7001` prints the fix. */\n public readonly code = \"WL7001\";\n\n public constructor(\n public readonly optionToken: string,\n public readonly value: string,\n ) {\n super(\n `Invalid value ${JSON.stringify(value)} for boolean option ${optionToken}. ` +\n `Expected one of: true, false, 1, 0, yes, no — or pass ${optionToken} on its own for true.`,\n );\n\n this.name = \"CliOptionValueError\";\n }\n}\n\nconst TRUE_VALUES = new Set([\"true\", \"1\", \"yes\"]);\nconst FALSE_VALUES = new Set([\"false\", \"0\", \"no\"]);\n\n/**\n * Collect the camelCased keys (names AND aliases) of every option the command\n * declared as `type: \"boolean\"`.\n *\n * Both sides are camelCased because declared names keep their raw kebab form\n * (`\"pending-only\"`) while the parser emits camelCase keys (`pendingOnly`).\n */\nfunction collectBooleanKeys(schema: CliOptionSchema[]): Set<string> {\n const keys = new Set<string>();\n\n for (const option of schema) {\n if (option.type !== \"boolean\") continue;\n\n if (option.name) {\n keys.add(toCamelCase(option.name));\n }\n\n if (option.alias) {\n keys.add(toCamelCase(option.alias));\n }\n }\n\n return keys;\n}\n\n/**\n * Collect the declared aliases longer than one character (`-st`, `-rs`, `-pm`).\n *\n * A cluster equal to one of these is that alias, not a bundle of single-letter\n * flags, so it has to be matched before the bundle split.\n */\nfunction collectMultiCharAliases(schema: CliOptionSchema[]): Set<string> {\n const aliases = new Set<string>();\n\n for (const option of schema) {\n if (option.alias && option.alias.length > 1) {\n aliases.add(option.alias);\n }\n }\n\n return aliases;\n}\n\n/**\n * Turn the value written after `=` into a real boolean, or throw.\n */\nfunction toBoolean(optionToken: string, value: string): boolean {\n const normalized = value.toLowerCase();\n\n if (TRUE_VALUES.has(normalized)) return true;\n if (FALSE_VALUES.has(normalized)) return false;\n\n throw new CliOptionValueError(optionToken, value);\n}\n\n/**\n * Parse CLI arguments from process.argv\n *\n * Called with a `schema` (the resolved command's declared options), every\n * option declared `type: \"boolean\"` is resolved as a boolean:\n * `--flag` → true, `--flag=false|0|no` → false, `--flag=true|1|yes` → true,\n * and `--flag <token>` leaves `<token>` as a POSITIONAL instead of swallowing\n * it as the flag's value. Anything else throws {@link CliOptionValueError}.\n *\n * Called without a schema — which is how the command name is discovered,\n * before any command object exists — behaviour is unchanged: every value stays\n * a raw string and a bare `--flag` still consumes the following non-dash token.\n * Nothing is blanket-coerced here on purpose: `--name=false` on a string-typed\n * option must survive as the string `\"false\"`.\n *\n * Options the schema does not declare keep the schema-less behaviour.\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"])\n * // Returns: { name: \"migrate\", args: [], options: { rollback: \"file.ts\" } }\n *\n * @example\n * // `rollback` declared as type: \"boolean\" — the file stays a positional\n * parseCliArgs([\"node\", \"warlock\", \"migrate\", \"--rollback\", \"file.ts\"], migrateOptions)\n * // Returns: { name: \"migrate\", args: [\"file.ts\"], options: { rollback: true } }\n *\n * @example\n * parseCliArgs([\"node\", \"warlock\", \"dev\", \"--port=3000\", \"--fresh\"])\n * // Returns: { name: \"dev\", args: [], options: { port: \"3000\", fresh: true } }\n */\nexport function parseCliArgs(argv: string[], schema: CliOptionSchema[] = []): ParsedCliArgs {\n // Command is at index 2 (after \"node\" and script path)\n // But if index 2 starts with \"-\", it's an option, not a command\n const potentialCommand = argv[2] || \"\";\n const isFirstArgOption = potentialCommand.startsWith(\"-\");\n const command = isFirstArgOption ? \"\" : potentialCommand;\n const args: string[] = [];\n const options: Record<string, string | boolean> = {};\n const booleanKeys = collectBooleanKeys(schema);\n const multiCharAliases = collectMultiCharAliases(schema);\n\n // Parse arguments starting from index 3 (or 2 if first arg was an option)\n const startIndex = isFirstArgOption ? 2 : 3;\n for (let i = startIndex; i < argv.length; i++) {\n const arg = argv[i];\n\n // `i < argv.length` bounds this, but the compiler does not narrow an index\n // read from a loop condition. Skipping rather than coercing: this file\n // already refuses to guess about an operator's input (see\n // `CliOptionValueError` above), and an `?? \"\"` here would silently push an\n // empty POSITIONAL onto `args` — which for a command that takes a file or\n // a table name is a scope the operator never typed.\n if (arg === undefined) continue;\n\n if (arg.startsWith(\"--\")) {\n // Long option: --key or --key=value\n const withoutDashes = arg.slice(2);\n const equalIndex = withoutDashes.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // --key=value format\n const key = toCamelCase(withoutDashes.slice(0, equalIndex));\n const value = withoutDashes.slice(equalIndex + 1);\n options[key] = booleanKeys.has(key)\n ? toBoolean(`--${withoutDashes.slice(0, equalIndex)}`, value)\n : value;\n } else {\n // --key format (check if next arg is a value)\n const key = toCamelCase(withoutDashes);\n const nextArg = argv[i + 1];\n\n // A declared boolean NEVER consumes the next token: `--rollback\n // users.ts` means \"rollback, and here is a positional\", not \"rollback\n // the file users.ts\". Swallowing it silently discarded the operator's\n // only stated scope and rolled back everything.\n if (booleanKeys.has(key)) {\n options[key] = true;\n } else if (nextArg && !nextArg.startsWith(\"-\")) {\n // If next arg exists and doesn't start with -, treat it as value\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n }\n } else if (arg.startsWith(\"-\") && arg.length > 1) {\n // Short option: -f, -t=value, or -abc (multiple flags)\n const flags = arg.slice(1);\n const equalIndex = flags.indexOf(\"=\");\n\n if (equalIndex !== -1) {\n // -t=value format\n const rawKey = flags.slice(0, equalIndex);\n const key = toCamelCase(rawKey);\n const value = flags.slice(equalIndex + 1);\n options[key] = booleanKeys.has(key) ? toBoolean(`-${rawKey}`, value) : value;\n } else if (flags.length === 1 || multiCharAliases.has(flags)) {\n // Single flag: -f, or a declared multi-character alias: -st\n const key = toCamelCase(flags);\n const nextArg = argv[i + 1];\n\n if (booleanKeys.has(key)) {\n options[key] = true;\n } else if (nextArg && !nextArg.startsWith(\"-\")) {\n options[key] = nextArg;\n i++; // Skip next arg\n } else {\n options[key] = true;\n }\n } else {\n // Multiple flags: -abc becomes { a: true, b: true, c: true }\n // A bundle carries no value and never consumes the next token, so a\n // declared boolean already resolves to `true` here.\n for (const flag of flags) {\n options[toCamelCase(flag)] = true;\n }\n }\n } else {\n // Positional argument\n args.push(arg);\n }\n }\n\n return { name: command, args, options };\n}\n"],"mappings":";;;;;;;;;;;AA6BA,IAAa,sBAAb,cAAyC,MAAM;CAI7C,AAAO,YACL,AAAgB,aAChB,AAAgB,OAChB;EACA,MACE,iBAAiB,KAAK,UAAU,KAAK,EAAE,sBAAsB,YAAY,0DACd,YAAY,sBACzE;EANgB;EACA;cAJK;EAWrB,KAAK,OAAO;CACd;AACF;AAEA,MAAM,cAAc,IAAI,IAAI;CAAC;CAAQ;CAAK;AAAK,CAAC;AAChD,MAAM,eAAe,IAAI,IAAI;CAAC;CAAS;CAAK;AAAI,CAAC;;;;;;;;AASjD,SAAS,mBAAmB,QAAwC;CAClE,MAAM,uBAAO,IAAI,IAAY;CAE7B,KAAK,MAAM,UAAU,QAAQ;EAC3B,IAAI,OAAO,SAAS,WAAW;EAE/B,IAAI,OAAO,MACT,KAAK,IAAI,YAAY,OAAO,IAAI,CAAC;EAGnC,IAAI,OAAO,OACT,KAAK,IAAI,YAAY,OAAO,KAAK,CAAC;CAEtC;CAEA,OAAO;AACT;;;;;;;AAQA,SAAS,wBAAwB,QAAwC;CACvE,MAAM,0BAAU,IAAI,IAAY;CAEhC,KAAK,MAAM,UAAU,QACnB,IAAI,OAAO,SAAS,OAAO,MAAM,SAAS,GACxC,QAAQ,IAAI,OAAO,KAAK;CAI5B,OAAO;AACT;;;;AAKA,SAAS,UAAU,aAAqB,OAAwB;CAC9D,MAAM,aAAa,MAAM,YAAY;CAErC,IAAI,YAAY,IAAI,UAAU,GAAG,OAAO;CACxC,IAAI,aAAa,IAAI,UAAU,GAAG,OAAO;CAEzC,MAAM,IAAI,oBAAoB,aAAa,KAAK;AAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,aAAa,MAAgB,SAA4B,CAAC,GAAkB;CAG1F,MAAM,mBAAmB,KAAK,MAAM;CACpC,MAAM,mBAAmB,iBAAiB,WAAW,GAAG;CACxD,MAAM,UAAU,mBAAmB,KAAK;CACxC,MAAM,OAAiB,CAAC;CACxB,MAAM,UAA4C,CAAC;CACnD,MAAM,cAAc,mBAAmB,MAAM;CAC7C,MAAM,mBAAmB,wBAAwB,MAAM;CAGvD,MAAM,aAAa,mBAAmB,IAAI;CAC1C,KAAK,IAAI,IAAI,YAAY,IAAI,KAAK,QAAQ,KAAK;EAC7C,MAAM,MAAM,KAAK;EAQjB,IAAI,QAAQ,QAAW;EAEvB,IAAI,IAAI,WAAW,IAAI,GAAG;GAExB,MAAM,gBAAgB,IAAI,MAAM,CAAC;GACjC,MAAM,aAAa,cAAc,QAAQ,GAAG;GAE5C,IAAI,eAAe,IAAI;IAErB,MAAM,MAAM,YAAY,cAAc,MAAM,GAAG,UAAU,CAAC;IAC1D,MAAM,QAAQ,cAAc,MAAM,aAAa,CAAC;IAChD,QAAQ,OAAO,YAAY,IAAI,GAAG,IAC9B,UAAU,KAAK,cAAc,MAAM,GAAG,UAAU,KAAK,KAAK,IAC1D;GACN,OAAO;IAEL,MAAM,MAAM,YAAY,aAAa;IACrC,MAAM,UAAU,KAAK,IAAI;IAMzB,IAAI,YAAY,IAAI,GAAG,GACrB,QAAQ,OAAO;SACV,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KAE9C,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB;EACF,OAAO,IAAI,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG;GAEhD,MAAM,QAAQ,IAAI,MAAM,CAAC;GACzB,MAAM,aAAa,MAAM,QAAQ,GAAG;GAEpC,IAAI,eAAe,IAAI;IAErB,MAAM,SAAS,MAAM,MAAM,GAAG,UAAU;IACxC,MAAM,MAAM,YAAY,MAAM;IAC9B,MAAM,QAAQ,MAAM,MAAM,aAAa,CAAC;IACxC,QAAQ,OAAO,YAAY,IAAI,GAAG,IAAI,UAAU,IAAI,UAAU,KAAK,IAAI;GACzE,OAAO,IAAI,MAAM,WAAW,KAAK,iBAAiB,IAAI,KAAK,GAAG;IAE5D,MAAM,MAAM,YAAY,KAAK;IAC7B,MAAM,UAAU,KAAK,IAAI;IAEzB,IAAI,YAAY,IAAI,GAAG,GACrB,QAAQ,OAAO;SACV,IAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;KAC9C,QAAQ,OAAO;KACf;IACF,OACE,QAAQ,OAAO;GAEnB,OAIE,KAAK,MAAM,QAAQ,OACjB,QAAQ,YAAY,IAAI,KAAK;EAGnC,OAEE,KAAK,KAAK,GAAG;CAEjB;CAEA,OAAO;EAAE,MAAM;EAAS;EAAM;CAAQ;AACxC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/config/config-loader.ts"],"mappings":";AAgBA;;;;AAAA,KAAY,oBAAA,IAAwB,WAAA,oBAA+B,OAAO"}
1
+ {"version":3,"file":"config-loader.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/config/config-loader.ts"],"mappings":";AAiBA;;;;AAAA,KAAY,oBAAA,IAAwB,WAAA,oBAA+B,OAAO"}
@@ -1,9 +1,10 @@
1
1
  import { configSpecialHandlers } from "./config-special-handlers.mjs";
2
+ import { InvalidConfigError, validateConfigValue } from "./config-schema.mjs";
2
3
  import { importAppModule } from "../loader/app-module-importer.mjs";
3
4
  import { configKeyFromPath } from "./config-key-from-path.mjs";
4
5
  import config from "@mongez/config";
5
- import { colors } from "@mongez/copper";
6
6
  import { pathToFileURL } from "node:url";
7
+ import { colors } from "@mongez/copper";
7
8
 
8
9
  //#region ../../packages/core/src/config/config-loader.ts
9
10
  /**
@@ -12,8 +13,16 @@ import { pathToFileURL } from "node:url";
12
13
  * Supports special handlers for configs that require additional processing
13
14
  */
14
15
  var ConfigLoader = class {
16
+ /**
17
+ * Load every config file, then throw one {@link InvalidConfigError} listing
18
+ * every value that fails its file's `configSchema`. An invalid config is
19
+ * still registered (later files may read it while loading) but its special
20
+ * handler does not run, so nothing connects with a broken configuration.
21
+ */
15
22
  async loadAll(configFiles) {
16
- for (const file of configFiles) await this.loadConfig(file);
23
+ const issues = [];
24
+ for (const file of configFiles) issues.push(...await this.loadConfigFile(file, "register-invalid"));
25
+ if (issues.length > 0) throw new InvalidConfigError(issues);
17
26
  }
18
27
  /**
19
28
  * Load a single configuration file.
@@ -22,19 +31,31 @@ var ConfigLoader = class {
22
31
  * cycle gets a fresh module — no manual cache-busting needed here.
23
32
  */
24
33
  async loadConfig(file) {
34
+ const issues = await this.loadConfigFile(file, "keep-previous");
35
+ if (issues.length > 0) throw new InvalidConfigError(issues);
36
+ }
37
+ /**
38
+ * Import, validate and register one config file. Returns the schema issues.
39
+ * On a hot reload (`keep-previous`) an invalid value is not registered, so
40
+ * the running app keeps its last valid configuration.
41
+ */
42
+ async loadConfigFile(file, whenInvalid) {
25
43
  const configName = this.getConfigName(file.relativePath);
26
- try {
27
- const fileUrl = pathToFileURL(file.absolutePath).href;
28
- const configValue = (await importAppModule(fileUrl)).default;
29
- if (configValue === void 0) {
30
- console.log(colors.red(`config error: `), `Config file ${colors.yellow(file.relativePath)} does not have a default export`);
31
- return;
32
- }
33
- config.set(configName, configValue);
34
- await configSpecialHandlers.execute(configName, configValue);
35
- } catch (error) {
36
- throw error;
44
+ const fileUrl = pathToFileURL(file.absolutePath).href;
45
+ const configModule = await importAppModule(fileUrl);
46
+ const configValue = configModule.default;
47
+ if (configValue === void 0) {
48
+ console.log(colors.red(`config error: `), `Config file ${colors.yellow(file.relativePath)} does not have a default export`);
49
+ return [];
50
+ }
51
+ const issues = await validateConfigValue(configName, configValue, configModule.configSchema);
52
+ if (issues.length > 0) {
53
+ if (whenInvalid === "register-invalid") config.set(configName, configValue);
54
+ return issues;
37
55
  }
56
+ config.set(configName, configValue);
57
+ await configSpecialHandlers.execute(configName, configValue);
58
+ return [];
38
59
  }
39
60
  async reloadConfig(file) {
40
61
  await this.loadConfig(file);
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.mjs","names":[],"sources":["../../../../../../../../packages/core/src/config/config-loader.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { colors } from \"@mongez/copper\";\nimport { pathToFileURL } from \"node:url\";\nimport type { FileManager } from \"../dev-server/file-manager\";\nimport { importAppModule } from \"../loader/app-module-importer\";\nimport { configKeyFromPath } from \"./config-key-from-path\";\nimport { configSpecialHandlers } from \"./config-special-handlers\";\n\n/**\n * Special Config Handler\n * A function that handles special configuration loading\n */\n// Returns unknown, not void: ConfigSpecialHandlers.execute() RETURNS handler(config)\n// rather than discarding it, and a test pins that (\"returns the handler's resolved\n// value\"). The implementation and the test agreed; only this type said handlers\n// produce nothing, which made any value-returning handler fail to typecheck.\nexport type SpecialConfigHandler = (configValue: any) => unknown | Promise<unknown>;\n\n/**\n * Config Loader\n * Dynamically loads all configuration files and registers them with @mongez/config\n * Supports special handlers for configs that require additional processing\n */\nexport class ConfigLoader {\n public async loadAll(configFiles: FileManager[]): Promise<void> {\n for (const file of configFiles) {\n await this.loadConfig(file);\n }\n }\n\n /**\n * Load a single configuration file.\n *\n * The ESM loader hook stamps a version token onto the URL so that each HMR\n * cycle gets a fresh module — no manual cache-busting needed here.\n */\n public async loadConfig(file: FileManager): Promise<void> {\n const configName = this.getConfigName(file.relativePath);\n\n try {\n const fileUrl = pathToFileURL(file.absolutePath).href;\n const configModule = await importAppModule(fileUrl);\n const configValue = configModule.default;\n\n if (configValue === undefined) {\n console.log(\n colors.red(`config error: `),\n `Config file ${colors.yellow(file.relativePath)} does not have a default export`,\n );\n return;\n }\n\n config.set(configName, configValue);\n await configSpecialHandlers.execute(configName, configValue);\n } catch (error) {\n throw error;\n }\n }\n\n public async reloadConfig(file: FileManager): Promise<void> {\n await this.loadConfig(file);\n }\n\n private getConfigName(relativePath: string): string {\n const configName = configKeyFromPath(relativePath);\n\n if (!configName) {\n throw new Error(`Invalid config file path: ${relativePath}`);\n }\n\n return configName;\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,IAAa,eAAb,MAA0B;CACxB,MAAa,QAAQ,aAA2C;EAC9D,KAAK,MAAM,QAAQ,aACjB,MAAM,KAAK,WAAW,IAAI;CAE9B;;;;;;;CAQA,MAAa,WAAW,MAAkC;EACxD,MAAM,aAAa,KAAK,cAAc,KAAK,YAAY;EAEvD,IAAI;GACF,MAAM,UAAU,cAAc,KAAK,YAAY,CAAC,CAAC;GAEjD,MAAM,eAAc,MADO,gBAAgB,OAAO,EAClB,CAAC;GAEjC,IAAI,gBAAgB,QAAW;IAC7B,QAAQ,IACN,OAAO,IAAI,gBAAgB,GAC3B,eAAe,OAAO,OAAO,KAAK,YAAY,EAAE,gCAClD;IACA;GACF;GAEA,OAAO,IAAI,YAAY,WAAW;GAClC,MAAM,sBAAsB,QAAQ,YAAY,WAAW;EAC7D,SAAS,OAAO;GACd,MAAM;EACR;CACF;CAEA,MAAa,aAAa,MAAkC;EAC1D,MAAM,KAAK,WAAW,IAAI;CAC5B;CAEA,AAAQ,cAAc,cAA8B;EAClD,MAAM,aAAa,kBAAkB,YAAY;EAEjD,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,6BAA6B,cAAc;EAG7D,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"config-loader.mjs","names":[],"sources":["../../../../../../../../packages/core/src/config/config-loader.ts"],"sourcesContent":["import config from \"@mongez/config\";\nimport { colors } from \"@mongez/copper\";\nimport { pathToFileURL } from \"node:url\";\nimport type { FileManager } from \"../dev-server/file-manager\";\nimport { importAppModule } from \"../loader/app-module-importer\";\nimport { configKeyFromPath } from \"./config-key-from-path\";\nimport { type ConfigIssue, InvalidConfigError, validateConfigValue } from \"./config-schema\";\nimport { configSpecialHandlers } from \"./config-special-handlers\";\n\n/**\n * Special Config Handler\n * A function that handles special configuration loading\n */\n// Returns unknown, not void: ConfigSpecialHandlers.execute() RETURNS handler(config)\n// rather than discarding it, and a test pins that (\"returns the handler's resolved\n// value\"). The implementation and the test agreed; only this type said handlers\n// produce nothing, which made any value-returning handler fail to typecheck.\nexport type SpecialConfigHandler = (configValue: any) => unknown | Promise<unknown>;\n\n/**\n * Config Loader\n * Dynamically loads all configuration files and registers them with @mongez/config\n * Supports special handlers for configs that require additional processing\n */\nexport class ConfigLoader {\n /**\n * Load every config file, then throw one {@link InvalidConfigError} listing\n * every value that fails its file's `configSchema`. An invalid config is\n * still registered (later files may read it while loading) but its special\n * handler does not run, so nothing connects with a broken configuration.\n */\n public async loadAll(configFiles: FileManager[]): Promise<void> {\n const issues: ConfigIssue[] = [];\n\n for (const file of configFiles) {\n issues.push(...(await this.loadConfigFile(file, \"register-invalid\")));\n }\n\n if (issues.length > 0) throw new InvalidConfigError(issues);\n }\n\n /**\n * Load a single configuration file.\n *\n * The ESM loader hook stamps a version token onto the URL so that each HMR\n * cycle gets a fresh module — no manual cache-busting needed here.\n */\n public async loadConfig(file: FileManager): Promise<void> {\n const issues = await this.loadConfigFile(file, \"keep-previous\");\n\n if (issues.length > 0) throw new InvalidConfigError(issues);\n }\n\n /**\n * Import, validate and register one config file. Returns the schema issues.\n * On a hot reload (`keep-previous`) an invalid value is not registered, so\n * the running app keeps its last valid configuration.\n */\n private async loadConfigFile(\n file: FileManager,\n whenInvalid: \"register-invalid\" | \"keep-previous\",\n ): Promise<ConfigIssue[]> {\n const configName = this.getConfigName(file.relativePath);\n\n const fileUrl = pathToFileURL(file.absolutePath).href;\n const configModule = await importAppModule(fileUrl);\n const configValue = configModule.default;\n\n if (configValue === undefined) {\n console.log(\n colors.red(`config error: `),\n `Config file ${colors.yellow(file.relativePath)} does not have a default export`,\n );\n return [];\n }\n\n const issues = await validateConfigValue(configName, configValue, configModule.configSchema);\n\n if (issues.length > 0) {\n if (whenInvalid === \"register-invalid\") config.set(configName, configValue);\n return issues;\n }\n\n config.set(configName, configValue);\n await configSpecialHandlers.execute(configName, configValue);\n\n return [];\n }\n\n public async reloadConfig(file: FileManager): Promise<void> {\n await this.loadConfig(file);\n }\n\n private getConfigName(relativePath: string): string {\n const configName = configKeyFromPath(relativePath);\n\n if (!configName) {\n throw new Error(`Invalid config file path: ${relativePath}`);\n }\n\n return configName;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAwBA,IAAa,eAAb,MAA0B;;;;;;;CAOxB,MAAa,QAAQ,aAA2C;EAC9D,MAAM,SAAwB,CAAC;EAE/B,KAAK,MAAM,QAAQ,aACjB,OAAO,KAAK,GAAI,MAAM,KAAK,eAAe,MAAM,kBAAkB,CAAE;EAGtE,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,mBAAmB,MAAM;CAC5D;;;;;;;CAQA,MAAa,WAAW,MAAkC;EACxD,MAAM,SAAS,MAAM,KAAK,eAAe,MAAM,eAAe;EAE9D,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,mBAAmB,MAAM;CAC5D;;;;;;CAOA,MAAc,eACZ,MACA,aACwB;EACxB,MAAM,aAAa,KAAK,cAAc,KAAK,YAAY;EAEvD,MAAM,UAAU,cAAc,KAAK,YAAY,CAAC,CAAC;EACjD,MAAM,eAAe,MAAM,gBAAgB,OAAO;EAClD,MAAM,cAAc,aAAa;EAEjC,IAAI,gBAAgB,QAAW;GAC7B,QAAQ,IACN,OAAO,IAAI,gBAAgB,GAC3B,eAAe,OAAO,OAAO,KAAK,YAAY,EAAE,gCAClD;GACA,OAAO,CAAC;EACV;EAEA,MAAM,SAAS,MAAM,oBAAoB,YAAY,aAAa,aAAa,YAAY;EAE3F,IAAI,OAAO,SAAS,GAAG;GACrB,IAAI,gBAAgB,oBAAoB,OAAO,IAAI,YAAY,WAAW;GAC1E,OAAO;EACT;EAEA,OAAO,IAAI,YAAY,WAAW;EAClC,MAAM,sBAAsB,QAAQ,YAAY,WAAW;EAE3D,OAAO,CAAC;CACV;CAEA,MAAa,aAAa,MAAkC;EAC1D,MAAM,KAAK,WAAW,IAAI;CAC5B;CAEA,AAAQ,cAAc,cAA8B;EAClD,MAAM,aAAa,kBAAkB,YAAY;EAEjD,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,6BAA6B,cAAc;EAG7D,OAAO;CACT;AACF"}
@@ -0,0 +1,67 @@
1
+ import { BaseValidator, Infer } from "@warlock.js/seal";
2
+
3
+ //#region ../../packages/core/src/config/config-schema.d.ts
4
+ declare const CONFIG_SCHEMA_MARKER: unique symbol;
5
+ type ConfigSchemaOptions = {
6
+ /**
7
+ * The environment variable each key is read from, by key path
8
+ * (`{ host: "MAIL_HOST", "smtp.password": "SMTP_PASSWORD" }`). Named in the
9
+ * boot error so the fix is obvious.
10
+ */
11
+ env?: Readonly<Record<string, string>>;
12
+ };
13
+ /** A config file's schema, as returned by {@link defineConfigSchema}. */
14
+ type ConfigSchema<TValidator extends BaseValidator = BaseValidator> = {
15
+ readonly [CONFIG_SCHEMA_MARKER]: true;
16
+ readonly validator: TValidator;
17
+ readonly env: Readonly<Record<string, string>>;
18
+ };
19
+ /** The config value a schema describes, for typing the default export. */
20
+ type ConfigOf<TSchema extends ConfigSchema> = TSchema extends ConfigSchema<infer TValidator> ? Infer.Input<TValidator> : never;
21
+ /** One problem found while validating configuration. */
22
+ type ConfigIssue = {
23
+ /** Config name (the file's key, e.g. `mail`). */config: string; /** Key path inside it (`smtp.host`); empty for the config value as a whole. */
24
+ key: string; /** What is wrong, from the schema's rule. */
25
+ message: string; /** The environment variable that feeds this key, when the schema names it. */
26
+ env?: string;
27
+ };
28
+ /**
29
+ * Declare the schema a config file's default export must satisfy. Export the
30
+ * result as `configSchema` from the same file.
31
+ */
32
+ declare function defineConfigSchema<TValidator extends BaseValidator>(validator: TValidator, options?: ConfigSchemaOptions): ConfigSchema<TValidator>;
33
+ /** Whether a value is a {@link ConfigSchema}. */
34
+ declare function isConfigSchema(value: unknown): value is ConfigSchema;
35
+ /**
36
+ * Thrown at boot when one or more config files do not satisfy their
37
+ * `configSchema`. `issues` lists every problem; the message is ready to print.
38
+ */
39
+ declare class InvalidConfigError extends Error {
40
+ readonly issues: readonly ConfigIssue[];
41
+ readonly name = "InvalidConfigError";
42
+ constructor(issues: readonly ConfigIssue[]);
43
+ }
44
+ /** Render issues as the boot error message. */
45
+ declare function formatConfigIssues(issues: readonly ConfigIssue[]): string;
46
+ /**
47
+ * Validate one config value against its schema. Returns the issues found (an
48
+ * empty list when it is valid, or when `schema` is not a config schema).
49
+ */
50
+ declare function validateConfigValue(configName: string, value: unknown, schema: unknown): Promise<ConfigIssue[]>;
51
+ /** A loaded config module: its default export and, optionally, its `configSchema`. */
52
+ type ConfigModuleEntry = {
53
+ name: string;
54
+ module: {
55
+ default?: unknown;
56
+ configSchema?: unknown;
57
+ };
58
+ };
59
+ /**
60
+ * Validate every config module that exports a `configSchema` and throw one
61
+ * {@link InvalidConfigError} listing all problems. Used by the production
62
+ * config loader `warlock build` generates.
63
+ */
64
+ declare function assertValidConfigModules(entries: readonly ConfigModuleEntry[]): Promise<void>;
65
+ //#endregion
66
+ export { ConfigIssue, ConfigModuleEntry, ConfigOf, ConfigSchema, ConfigSchemaOptions, InvalidConfigError, assertValidConfigModules, defineConfigSchema, formatConfigIssues, isConfigSchema, validateConfigValue };
67
+ //# sourceMappingURL=config-schema.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-schema.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/config/config-schema.ts"],"mappings":";;;cAmCM,oBAAA;AAAA,KAEM,mBAAA;EAaD;;;;AAAoB;EAP7B,GAAA,GAAM,QAAQ,CAAC,MAAA;AAAA;;KAIL,YAAA,oBAAgC,aAAA,GAAgB,aAAA;EAAA,UAChD,oBAAA;EAAA,SACD,SAAA,EAAW,UAAA;EAAA,SACX,GAAA,EAAK,QAAA,CAAS,MAAA;AAAA;;KAIb,QAAA,iBAAyB,YAAA,IACnC,OAAA,SAAgB,YAAA,qBAAiC,KAAA,CAAM,KAAA,CAAM,UAAA;;KAGnD,WAAA;EAHV,iDAKA,MAAA,UALmC;EAOnC,GAAA,UAPuD;EASvD,OAAA,UATuE;EAWvE,GAAA;AAAA;;;;;iBAOc,kBAAA,oBAAsC,aAAA,EACpD,SAAA,EAAW,UAAA,EACX,OAAA,GAAS,mBAAA,GACR,YAAA,CAAa,UAAA;;iBAKA,cAAA,CAAe,KAAA,YAAiB,KAAA,IAAS,YAAY;;AAfhE;AAOL;;cAoBa,kBAAA,SAA2B,KAAA;EAAA,SAGH,MAAA,WAAiB,WAAA;EAAA,SAF3B,IAAA;cAEU,MAAA,WAAiB,WAAA;AAAA;;iBAMtC,kBAAA,CAAmB,MAA8B,WAAb,WAAW;;;;;iBAgBzC,mBAAA,CACpB,UAAA,UACA,KAAA,WACA,MAAA,YACC,OAAO,CAAC,WAAA;;KAuBC,iBAAA;EACV,IAAA;EACA,MAAA;IAAU,OAAA;IAAmB,YAAA;EAAA;AAAA;;;;;;iBAQT,wBAAA,CACpB,OAAA,WAAkB,iBAAA,KACjB,OAAO"}
@@ -0,0 +1,77 @@
1
+ import { validate } from "@warlock.js/seal";
2
+
3
+ //#region ../../packages/core/src/config/config-schema.ts
4
+ const CONFIG_SCHEMA_MARKER = Symbol.for("warlock.js.configSchema");
5
+ /**
6
+ * Declare the schema a config file's default export must satisfy. Export the
7
+ * result as `configSchema` from the same file.
8
+ */
9
+ function defineConfigSchema(validator, options = {}) {
10
+ return {
11
+ [CONFIG_SCHEMA_MARKER]: true,
12
+ validator,
13
+ env: { ...options.env }
14
+ };
15
+ }
16
+ /** Whether a value is a {@link ConfigSchema}. */
17
+ function isConfigSchema(value) {
18
+ return typeof value === "object" && value !== null && value[CONFIG_SCHEMA_MARKER] === true;
19
+ }
20
+ /**
21
+ * Thrown at boot when one or more config files do not satisfy their
22
+ * `configSchema`. `issues` lists every problem; the message is ready to print.
23
+ */
24
+ var InvalidConfigError = class extends Error {
25
+ constructor(issues) {
26
+ super(formatConfigIssues(issues));
27
+ this.issues = issues;
28
+ this.name = "InvalidConfigError";
29
+ }
30
+ };
31
+ /** Render issues as the boot error message. */
32
+ function formatConfigIssues(issues) {
33
+ const lines = issues.map((issue) => {
34
+ const path = issue.key ? `${issue.config}.${issue.key}` : issue.config;
35
+ const hint = issue.env ? ` (set ${issue.env} in your environment or .env)` : "";
36
+ return ` - ${path}: ${issue.message}${hint}`;
37
+ });
38
+ return `Invalid configuration (${issues.length === 1 ? "1 problem" : `${issues.length} problems`}); the app cannot start until it is fixed:\n${lines.join("\n")}`;
39
+ }
40
+ /**
41
+ * Validate one config value against its schema. Returns the issues found (an
42
+ * empty list when it is valid, or when `schema` is not a config schema).
43
+ */
44
+ async function validateConfigValue(configName, value, schema) {
45
+ if (!isConfigSchema(schema)) return [];
46
+ const result = await validate(schema.validator, value);
47
+ if (result.isValid) return [];
48
+ if (result.errors.length === 0) return [{
49
+ config: configName,
50
+ key: "",
51
+ message: "does not match its config schema"
52
+ }];
53
+ return result.errors.map((error) => {
54
+ const key = error.input ?? "";
55
+ const env = schema.env[key];
56
+ return {
57
+ config: configName,
58
+ key,
59
+ message: error.error,
60
+ ...env !== void 0 && { env }
61
+ };
62
+ });
63
+ }
64
+ /**
65
+ * Validate every config module that exports a `configSchema` and throw one
66
+ * {@link InvalidConfigError} listing all problems. Used by the production
67
+ * config loader `warlock build` generates.
68
+ */
69
+ async function assertValidConfigModules(entries) {
70
+ const issues = [];
71
+ for (const entry of entries) issues.push(...await validateConfigValue(entry.name, entry.module.default, entry.module.configSchema));
72
+ if (issues.length > 0) throw new InvalidConfigError(issues);
73
+ }
74
+
75
+ //#endregion
76
+ export { InvalidConfigError, assertValidConfigModules, defineConfigSchema, formatConfigIssues, isConfigSchema, validateConfigValue };
77
+ //# sourceMappingURL=config-schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-schema.mjs","names":[],"sources":["../../../../../../../../packages/core/src/config/config-schema.ts"],"sourcesContent":["/**\n * Typed, validated configuration.\n *\n * A config file (`src/config/<name>.ts`) may export a `configSchema` next to\n * its default export. Before the config is registered, at `warlock dev` boot,\n * on every config hot reload, and at production start, its value is validated\n * against that schema. Every problem across every config file is collected and\n * the app refuses to start with ONE error that lists them all — key path, what\n * is wrong, and the environment variable to set when the schema names one.\n * Values are never printed, so a secret cannot end up in the boot log.\n *\n * Config files without a `configSchema` load exactly as before.\n *\n * @example\n * // src/config/mail.ts\n * import { defineConfigSchema, env, type ConfigOf } from \"@warlock.js/core\";\n * import { v } from \"@warlock.js/seal\";\n *\n * export const configSchema = defineConfigSchema(\n * v.object({ host: v.string(), port: v.int(), from: v.email() }),\n * { env: { host: \"MAIL_HOST\", port: \"MAIL_PORT\", from: \"MAIL_FROM\" } },\n * );\n *\n * const mailConfig: ConfigOf<typeof configSchema> = {\n * host: env(\"MAIL_HOST\"),\n * port: Number(env(\"MAIL_PORT\", 587)),\n * from: env(\"MAIL_FROM\"),\n * };\n *\n * export default mailConfig;\n */\n\nimport type { BaseValidator, Infer } from \"@warlock.js/seal\";\nimport { validate } from \"@warlock.js/seal\";\n\nconst CONFIG_SCHEMA_MARKER: unique symbol = Symbol.for(\"warlock.js.configSchema\");\n\nexport type ConfigSchemaOptions = {\n /**\n * The environment variable each key is read from, by key path\n * (`{ host: \"MAIL_HOST\", \"smtp.password\": \"SMTP_PASSWORD\" }`). Named in the\n * boot error so the fix is obvious.\n */\n env?: Readonly<Record<string, string>>;\n};\n\n/** A config file's schema, as returned by {@link defineConfigSchema}. */\nexport type ConfigSchema<TValidator extends BaseValidator = BaseValidator> = {\n readonly [CONFIG_SCHEMA_MARKER]: true;\n readonly validator: TValidator;\n readonly env: Readonly<Record<string, string>>;\n};\n\n/** The config value a schema describes, for typing the default export. */\nexport type ConfigOf<TSchema extends ConfigSchema> =\n TSchema extends ConfigSchema<infer TValidator> ? Infer.Input<TValidator> : never;\n\n/** One problem found while validating configuration. */\nexport type ConfigIssue = {\n /** Config name (the file's key, e.g. `mail`). */\n config: string;\n /** Key path inside it (`smtp.host`); empty for the config value as a whole. */\n key: string;\n /** What is wrong, from the schema's rule. */\n message: string;\n /** The environment variable that feeds this key, when the schema names it. */\n env?: string;\n};\n\n/**\n * Declare the schema a config file's default export must satisfy. Export the\n * result as `configSchema` from the same file.\n */\nexport function defineConfigSchema<TValidator extends BaseValidator>(\n validator: TValidator,\n options: ConfigSchemaOptions = {},\n): ConfigSchema<TValidator> {\n return { [CONFIG_SCHEMA_MARKER]: true, validator, env: { ...options.env } };\n}\n\n/** Whether a value is a {@link ConfigSchema}. */\nexport function isConfigSchema(value: unknown): value is ConfigSchema {\n return (\n typeof value === \"object\" &&\n value !== null &&\n (value as Record<PropertyKey, unknown>)[CONFIG_SCHEMA_MARKER] === true\n );\n}\n\n/**\n * Thrown at boot when one or more config files do not satisfy their\n * `configSchema`. `issues` lists every problem; the message is ready to print.\n */\nexport class InvalidConfigError extends Error {\n public override readonly name = \"InvalidConfigError\";\n\n public constructor(public readonly issues: readonly ConfigIssue[]) {\n super(formatConfigIssues(issues));\n }\n}\n\n/** Render issues as the boot error message. */\nexport function formatConfigIssues(issues: readonly ConfigIssue[]): string {\n const lines = issues.map((issue) => {\n const path = issue.key ? `${issue.config}.${issue.key}` : issue.config;\n const hint = issue.env ? ` (set ${issue.env} in your environment or .env)` : \"\";\n return ` - ${path}: ${issue.message}${hint}`;\n });\n\n const count = issues.length === 1 ? \"1 problem\" : `${issues.length} problems`;\n\n return `Invalid configuration (${count}); the app cannot start until it is fixed:\\n${lines.join(\"\\n\")}`;\n}\n\n/**\n * Validate one config value against its schema. Returns the issues found (an\n * empty list when it is valid, or when `schema` is not a config schema).\n */\nexport async function validateConfigValue(\n configName: string,\n value: unknown,\n schema: unknown,\n): Promise<ConfigIssue[]> {\n if (!isConfigSchema(schema)) return [];\n\n const result = await validate(schema.validator, value);\n if (result.isValid) return [];\n\n if (result.errors.length === 0) {\n return [{ config: configName, key: \"\", message: \"does not match its config schema\" }];\n }\n\n return result.errors.map((error) => {\n const key = error.input ?? \"\";\n const env = schema.env[key];\n return {\n config: configName,\n key,\n message: error.error,\n ...(env !== undefined && { env }),\n };\n });\n}\n\n/** A loaded config module: its default export and, optionally, its `configSchema`. */\nexport type ConfigModuleEntry = {\n name: string;\n module: { default?: unknown; configSchema?: unknown };\n};\n\n/**\n * Validate every config module that exports a `configSchema` and throw one\n * {@link InvalidConfigError} listing all problems. Used by the production\n * config loader `warlock build` generates.\n */\nexport async function assertValidConfigModules(\n entries: readonly ConfigModuleEntry[],\n): Promise<void> {\n const issues: ConfigIssue[] = [];\n\n for (const entry of entries) {\n issues.push(\n ...(await validateConfigValue(entry.name, entry.module.default, entry.module.configSchema)),\n );\n }\n\n if (issues.length > 0) throw new InvalidConfigError(issues);\n}\n"],"mappings":";;;AAmCA,MAAM,uBAAsC,OAAO,IAAI,yBAAyB;;;;;AAsChF,SAAgB,mBACd,WACA,UAA+B,CAAC,GACN;CAC1B,OAAO;GAAG,uBAAuB;EAAM;EAAW,KAAK,EAAE,GAAG,QAAQ,IAAI;CAAE;AAC5E;;AAGA,SAAgB,eAAe,OAAuC;CACpE,OACE,OAAO,UAAU,YACjB,UAAU,QACT,MAAuC,0BAA0B;AAEtE;;;;;AAMA,IAAa,qBAAb,cAAwC,MAAM;CAG5C,AAAO,YAAY,AAAgB,QAAgC;EACjE,MAAM,mBAAmB,MAAM,CAAC;EADC;cAFH;CAIhC;AACF;;AAGA,SAAgB,mBAAmB,QAAwC;CACzE,MAAM,QAAQ,OAAO,KAAK,UAAU;EAClC,MAAM,OAAO,MAAM,MAAM,GAAG,MAAM,OAAO,GAAG,MAAM,QAAQ,MAAM;EAChE,MAAM,OAAO,MAAM,MAAM,SAAS,MAAM,IAAI,iCAAiC;EAC7E,OAAO,OAAO,KAAK,IAAI,MAAM,UAAU;CACzC,CAAC;CAID,OAAO,0BAFO,OAAO,WAAW,IAAI,cAAc,GAAG,OAAO,OAAO,WAE5B,8CAA8C,MAAM,KAAK,IAAI;AACtG;;;;;AAMA,eAAsB,oBACpB,YACA,OACA,QACwB;CACxB,IAAI,CAAC,eAAe,MAAM,GAAG,OAAO,CAAC;CAErC,MAAM,SAAS,MAAM,SAAS,OAAO,WAAW,KAAK;CACrD,IAAI,OAAO,SAAS,OAAO,CAAC;CAE5B,IAAI,OAAO,OAAO,WAAW,GAC3B,OAAO,CAAC;EAAE,QAAQ;EAAY,KAAK;EAAI,SAAS;CAAmC,CAAC;CAGtF,OAAO,OAAO,OAAO,KAAK,UAAU;EAClC,MAAM,MAAM,MAAM,SAAS;EAC3B,MAAM,MAAM,OAAO,IAAI;EACvB,OAAO;GACL,QAAQ;GACR;GACA,SAAS,MAAM;GACf,GAAI,QAAQ,UAAa,EAAE,IAAI;EACjC;CACF,CAAC;AACH;;;;;;AAaA,eAAsB,yBACpB,SACe;CACf,MAAM,SAAwB,CAAC;CAE/B,KAAK,MAAM,SAAS,SAClB,OAAO,KACL,GAAI,MAAM,oBAAoB,MAAM,MAAM,MAAM,OAAO,SAAS,MAAM,OAAO,YAAY,CAC3F;CAGF,IAAI,OAAO,SAAS,GAAG,MAAM,IAAI,mBAAmB,MAAM;AAC5D"}
@@ -0,0 +1,6 @@
1
+ import { ConfigKey, ConfigKeyRegistry, ConfigName, ConfigRegistry } from "./types.mjs";
2
+ import { config } from "./config-getter.mjs";
3
+ import { registerAppConfig } from "./config-handlers.mjs";
4
+ import { ConfigIssue, ConfigModuleEntry, ConfigOf, ConfigSchema, ConfigSchemaOptions, InvalidConfigError, assertValidConfigModules, defineConfigSchema, formatConfigIssues, isConfigSchema, validateConfigValue } from "./config-schema.mjs";
5
+ import { setConfig } from "./config-setter.mjs";
6
+ import { ConfigSpecialHandlers, configSpecialHandlers } from "./config-special-handlers.mjs";
@@ -1,6 +1,7 @@
1
1
  import { config } from "./config-getter.mjs";
2
2
  import { ConfigSpecialHandlers, configSpecialHandlers } from "./config-special-handlers.mjs";
3
3
  import { registerAppConfig } from "./config-handlers.mjs";
4
+ import { InvalidConfigError, assertValidConfigModules, defineConfigSchema, formatConfigIssues, isConfigSchema, validateConfigValue } from "./config-schema.mjs";
4
5
  import { setConfig } from "./config-setter.mjs";
5
6
 
6
7
  export { };
@@ -1 +1 @@
1
- {"version":3,"file":"assert-no-reserved-connector-names.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/connectors/assert-no-reserved-connector-names.ts"],"mappings":";;;iBA+BgB,8BAAA,CAA+B,UAAuB,EAAX,SAAS"}
1
+ {"version":3,"file":"assert-no-reserved-connector-names.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/connectors/assert-no-reserved-connector-names.ts"],"mappings":";;;iBAgCgB,8BAAA,CAA+B,UAAuB,EAAX,SAAS"}
@@ -1,3 +1,4 @@
1
+ import { WarlockError } from "../errors/warlock-error.mjs";
1
2
  import { connectorsManager } from "./connectors-manager.mjs";
2
3
 
3
4
  //#region ../../packages/core/src/connectors/assert-no-reserved-connector-names.ts
@@ -36,7 +37,7 @@ function assertNoReservedConnectorNames(connectors) {
36
37
  const names = unique.map((name) => JSON.stringify(name)).join(", ");
37
38
  const subject = unique.length === 1 ? "name is" : "names are";
38
39
  const object = unique.length === 1 ? "it" : "one of them";
39
- throw new Error(`The following connector ${subject} reserved by a framework built-in connector: [${names}].\nEvery connector name must be unique, and the framework already registers a built-in connector under ${unique.length === 1 ? "that name" : "those names"}, so a custom connector carrying ${object} would be built for and then never booted. Rename the custom connector in \`warlock.config.ts > connectors\` to a name of your own.`);
40
+ throw new WarlockError("WL1009", `The following connector ${subject} reserved by a framework built-in connector: [${names}].\nEvery connector name must be unique, and the framework already registers a built-in connector under ${unique.length === 1 ? "that name" : "those names"}, so a custom connector carrying ${object} would be built for and then never booted. Rename the custom connector in \`warlock.config.ts > connectors\` to a name of your own.`);
40
41
  }
41
42
 
42
43
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"assert-no-reserved-connector-names.mjs","names":[],"sources":["../../../../../../../../packages/core/src/connectors/assert-no-reserved-connector-names.ts"],"sourcesContent":["/**\n * Refuses a `connectors` array that claims a name a framework built-in owns.\n *\n * The uniqueness check rejects a name repeated inside the array; this rejects\n * one already held by a BUILT-IN outside it. The manager registers its\n * built-ins in its own constructor, so those names are taken before any config\n * is read — and the two halves disagreed about what that meant. The build\n * drains per ENTRY and knows nothing of the manager, so it prepared the custom\n * connector's artifacts; the runtime registers per NAME and found the built-in\n * already there, so it skipped the entry. The result booted the built-in the\n * app did not ask for, never booted the connector it did, and reported success\n * from both halves.\n *\n * Refused rather than resolved in the app's favour: the built-ins are the\n * framework's own wiring — other framework code reaches for `http`, `cache`,\n * `database` by name — so letting a config replace one silently repoints\n * everything that looks it up. The name is the app's to change; the built-in's\n * is not.\n *\n * Scope, precisely: BUILT-IN names only. A name held by a PREVIOUSLY\n * CONFIGURED connector (an earlier call in the same process) is not this\n * check's business — that case is the registration skip's deliberate\n * idempotency, and stays out of both validators.\n *\n * Reads {@link ConnectorsManager.isBuiltInName}, which is the ONLY inventory of\n * built-in names, so this cannot fall out of step with what the manager\n * actually registered.\n */\nimport { connectorsManager } from \"./connectors-manager\";\nimport type { Connector } from \"./types\";\n\nexport function assertNoReservedConnectorNames(connectors: Connector[]): void {\n const reserved = connectors\n .map((connector) => connector.name)\n .filter((name) => connectorsManager.isBuiltInName(name));\n\n if (reserved.length === 0) return;\n\n const unique = [...new Set(reserved)];\n const names = unique.map((name) => JSON.stringify(name)).join(\", \");\n const subject = unique.length === 1 ? \"name is\" : \"names are\";\n const object = unique.length === 1 ? \"it\" : \"one of them\";\n\n throw new Error(\n `The following connector ${subject} reserved by a framework built-in connector: [${names}].\\n` +\n \"Every connector name must be unique, and the framework already registers a built-in connector under \" +\n `${unique.length === 1 ? \"that name\" : \"those names\"}, so a custom connector carrying ${object} ` +\n \"would be built for and then never booted. \" +\n \"Rename the custom connector in `warlock.config.ts > connectors` to a name of your own.\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BA,SAAgB,+BAA+B,YAA+B;CAC5E,MAAM,WAAW,WACd,KAAK,cAAc,UAAU,IAAI,CAAC,CAClC,QAAQ,SAAS,kBAAkB,cAAc,IAAI,CAAC;CAEzD,IAAI,SAAS,WAAW,GAAG;CAE3B,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;CACpC,MAAM,QAAQ,OAAO,KAAK,SAAS,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;CAClE,MAAM,UAAU,OAAO,WAAW,IAAI,YAAY;CAClD,MAAM,SAAS,OAAO,WAAW,IAAI,OAAO;CAE5C,MAAM,IAAI,MACR,2BAA2B,QAAQ,gDAAgD,MAAM,0GAEpF,OAAO,WAAW,IAAI,cAAc,cAAc,mCAAmC,OAAO,oIAGnG;AACF"}
1
+ {"version":3,"file":"assert-no-reserved-connector-names.mjs","names":[],"sources":["../../../../../../../../packages/core/src/connectors/assert-no-reserved-connector-names.ts"],"sourcesContent":["/**\n * Refuses a `connectors` array that claims a name a framework built-in owns.\n *\n * The uniqueness check rejects a name repeated inside the array; this rejects\n * one already held by a BUILT-IN outside it. The manager registers its\n * built-ins in its own constructor, so those names are taken before any config\n * is read — and the two halves disagreed about what that meant. The build\n * drains per ENTRY and knows nothing of the manager, so it prepared the custom\n * connector's artifacts; the runtime registers per NAME and found the built-in\n * already there, so it skipped the entry. The result booted the built-in the\n * app did not ask for, never booted the connector it did, and reported success\n * from both halves.\n *\n * Refused rather than resolved in the app's favour: the built-ins are the\n * framework's own wiring — other framework code reaches for `http`, `cache`,\n * `database` by name — so letting a config replace one silently repoints\n * everything that looks it up. The name is the app's to change; the built-in's\n * is not.\n *\n * Scope, precisely: BUILT-IN names only. A name held by a PREVIOUSLY\n * CONFIGURED connector (an earlier call in the same process) is not this\n * check's business — that case is the registration skip's deliberate\n * idempotency, and stays out of both validators.\n *\n * Reads {@link ConnectorsManager.isBuiltInName}, which is the ONLY inventory of\n * built-in names, so this cannot fall out of step with what the manager\n * actually registered.\n */\nimport { WarlockError } from \"../errors/warlock-error\";\nimport { connectorsManager } from \"./connectors-manager\";\nimport type { Connector } from \"./types\";\n\nexport function assertNoReservedConnectorNames(connectors: Connector[]): void {\n const reserved = connectors\n .map((connector) => connector.name)\n .filter((name) => connectorsManager.isBuiltInName(name));\n\n if (reserved.length === 0) return;\n\n const unique = [...new Set(reserved)];\n const names = unique.map((name) => JSON.stringify(name)).join(\", \");\n const subject = unique.length === 1 ? \"name is\" : \"names are\";\n const object = unique.length === 1 ? \"it\" : \"one of them\";\n\n throw new WarlockError(\n \"WL1009\",\n `The following connector ${subject} reserved by a framework built-in connector: [${names}].\\n` +\n \"Every connector name must be unique, and the framework already registers a built-in connector under \" +\n `${unique.length === 1 ? \"that name\" : \"those names\"}, so a custom connector carrying ${object} ` +\n \"would be built for and then never booted. \" +\n \"Rename the custom connector in `warlock.config.ts > connectors` to a name of your own.\",\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,SAAgB,+BAA+B,YAA+B;CAC5E,MAAM,WAAW,WACd,KAAK,cAAc,UAAU,IAAI,CAAC,CAClC,QAAQ,SAAS,kBAAkB,cAAc,IAAI,CAAC;CAEzD,IAAI,SAAS,WAAW,GAAG;CAE3B,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;CACpC,MAAM,QAAQ,OAAO,KAAK,SAAS,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;CAClE,MAAM,UAAU,OAAO,WAAW,IAAI,YAAY;CAClD,MAAM,SAAS,OAAO,WAAW,IAAI,OAAO;CAE5C,MAAM,IAAI,aACR,UACA,2BAA2B,QAAQ,gDAAgD,MAAM,0GAEpF,OAAO,WAAW,IAAI,cAAc,cAAc,mCAAmC,OAAO,oIAGnG;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"assert-unique-connector-names.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/connectors/assert-unique-connector-names.ts"],"mappings":";;;iBAyBgB,0BAAA,CAA2B,UAAuB,EAAX,SAAS"}
1
+ {"version":3,"file":"assert-unique-connector-names.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/connectors/assert-unique-connector-names.ts"],"mappings":";;;iBA0BgB,0BAAA,CAA2B,UAAuB,EAAX,SAAS"}
@@ -1,4 +1,29 @@
1
+ import { WarlockError } from "../errors/warlock-error.mjs";
2
+
1
3
  //#region ../../packages/core/src/connectors/assert-unique-connector-names.ts
4
+ /**
5
+ * Refuses a `connectors` array that lists the same name more than once.
6
+ *
7
+ * A name is a connector's identity across both halves of its life, and the two
8
+ * halves treat a repeat differently. The build works per ARRAY ENTRY: it drains
9
+ * the build contribution of every element, so a name listed twice contributes
10
+ * twice — files written twice, esbuild patches merged twice. The runtime works
11
+ * per NAME: the first entry registers and every later one with that name is
12
+ * skipped, because registering it again would boot and shut down the same
13
+ * connector twice.
14
+ *
15
+ * So a duplicate is half-applied: built for twice, booted once, with nothing
16
+ * reported either way. The name-set the drift check compares is identical on
17
+ * both sides, so it passes the array straight through — this asymmetry is
18
+ * invisible to it, which is why it is caught here instead.
19
+ *
20
+ * Called by both halves (the build before it drains, the registration before it
21
+ * registers) so neither can be reached with an array the other would refuse.
22
+ * It rejects duplicates WITHIN the array it is handed. A name held OUTSIDE the
23
+ * array is out of scope here: if a BUILT-IN holds it, the reserved-name check
24
+ * refuses it; if an EARLIER CALL configured it, the registration skip treats it
25
+ * as idempotency on purpose — neither validator claims that case.
26
+ */
2
27
  function assertUniqueConnectorNames(connectors) {
3
28
  const seen = /* @__PURE__ */ new Set();
4
29
  const duplicated = /* @__PURE__ */ new Set();
@@ -11,8 +36,7 @@ function assertUniqueConnectorNames(connectors) {
11
36
  }
12
37
  if (duplicated.size === 0) return;
13
38
  const names = [...duplicated].map((name) => JSON.stringify(name)).join(", ");
14
- const subject = duplicated.size === 1 ? "name is" : "names are";
15
- throw new Error(`The same connector ${subject} listed more than once in \`connectors\`: [${names}].\nEvery connector in \`warlock.config.ts > connectors\` must have a unique name. The build prepares artifacts per ENTRY — it drains the build contribution of each one, so a repeated name contributes twice — while the runtime registers each NAME once and skips the rest. A duplicate is therefore half-applied, and neither half reports it. Remove the extra entry, or give the connectors distinct names.`);
39
+ throw new WarlockError("WL1009", `The same connector ${duplicated.size === 1 ? "name is" : "names are"} listed more than once in \`connectors\`: [${names}].\nEvery connector in \`warlock.config.ts > connectors\` must have a unique name. The build prepares artifacts per ENTRY — it drains the build contribution of each one, so a repeated name contributes twice — while the runtime registers each NAME once and skips the rest. A duplicate is therefore half-applied, and neither half reports it. Remove the extra entry, or give the connectors distinct names.`);
16
40
  }
17
41
 
18
42
  //#endregion