@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,137 @@
1
+ //#region ../../packages/core/src/cli/commands/generate/utils/endpoint-schema.ts
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ /** The non-null JSON types a node allows, and whether `null` is one of them. */
6
+ function typesOf(node) {
7
+ const variants = node.anyOf ?? node.oneOf;
8
+ if (variants) {
9
+ const all = variants.map(typesOf);
10
+ return {
11
+ types: all.flatMap((entry) => entry.types),
12
+ nullable: all.some((entry) => entry.nullable)
13
+ };
14
+ }
15
+ const raw = node.type === void 0 ? [] : Array.isArray(node.type) ? node.type : [node.type];
16
+ return {
17
+ types: raw.filter((type) => type !== "null"),
18
+ nullable: raw.includes("null")
19
+ };
20
+ }
21
+ function primaryNode(node) {
22
+ const variants = node.anyOf ?? node.oneOf;
23
+ if (!variants) return node;
24
+ return variants.find((variant) => !typesOf(variant).types.every((type) => type === "null")) ?? node;
25
+ }
26
+ /** A file upload: JSON cannot carry it, so it has no sample and no cast. */
27
+ function isFileNode(node) {
28
+ return node.format === "binary" || node.contentEncoding === "binary" || node.contentMediaType !== void 0;
29
+ }
30
+ const CASTS = {
31
+ string: "string",
32
+ integer: "int",
33
+ number: "number",
34
+ boolean: "boolean",
35
+ array: "array",
36
+ object: "object"
37
+ };
38
+ /** `"string"` or `"number"` when every enum value has that type. */
39
+ function enumValuesType(node) {
40
+ if (!node.enum || node.enum.length === 0) return void 0;
41
+ if (node.enum.every((value) => typeof value === "string")) return "string";
42
+ if (node.enum.every((value) => typeof value === "number")) return "number";
43
+ }
44
+ /** The resource cast for a field, with `?` when the value may be null or absent. */
45
+ function castForNode(node, required) {
46
+ const primary = primaryNode(node);
47
+ if (isFileNode(primary)) return void 0;
48
+ const { types, nullable } = typesOf(node);
49
+ const enumType = enumValuesType(primary);
50
+ const only = types.length === 1 ? types[0] : void 0;
51
+ const base = enumType ?? (only === void 0 ? void 0 : CASTS[only]);
52
+ if (base === void 0) return void 0;
53
+ if (base === "string" && (primary.format === "date-time" || primary.format === "date")) return nullable || !required ? "date?" : "date";
54
+ return nullable || !required ? `${base}?` : base;
55
+ }
56
+ /**
57
+ * A deterministic value that satisfies `node`, or `undefined` when JSON cannot
58
+ * express one. `seed` keeps values readable and stable between runs.
59
+ */
60
+ function sampleForNode(node, seed) {
61
+ const primary = primaryNode(node);
62
+ if (isFileNode(primary)) return void 0;
63
+ if (primary.const !== void 0) return primary.const;
64
+ if (primary.enum && primary.enum.length > 0) return primary.enum[0];
65
+ const { types } = typesOf(node);
66
+ switch (types[0]) {
67
+ case "string": return sampleString(primary, seed);
68
+ case "integer": return sampleNumber(primary, true);
69
+ case "number": return sampleNumber(primary, false);
70
+ case "boolean": return true;
71
+ case "array": {
72
+ const count = primary.minItems ?? 0;
73
+ const item = primary.items ? sampleForNode(primary.items, `${seed}-item`) : void 0;
74
+ if (count > 0 && item === void 0) return void 0;
75
+ return Array.from({ length: count }, () => item);
76
+ }
77
+ case "object": return sampleObject(primary, seed);
78
+ default: return;
79
+ }
80
+ }
81
+ function sampleNumber(node, integer) {
82
+ const lower = node.minimum ?? (node.exclusiveMinimum !== void 0 ? node.exclusiveMinimum + 1 : 1);
83
+ let value = integer ? Math.ceil(lower) : lower;
84
+ if (node.maximum !== void 0 && value > node.maximum) value = node.maximum;
85
+ return value;
86
+ }
87
+ function sampleString(node, seed) {
88
+ switch (node.format) {
89
+ case "email": return `${seed.replace(/[^a-z0-9]/gi, "").toLowerCase() || "user"}@example.test`;
90
+ case "uri":
91
+ case "url": return `https://example.test/${seed}`;
92
+ case "uuid": return "00000000-0000-4000-8000-000000000001";
93
+ case "date-time": return "2026-01-01T00:00:00.000Z";
94
+ case "date": return "2026-01-01";
95
+ default: break;
96
+ }
97
+ const minLength = node.minLength ?? 1;
98
+ let value = `${seed} sample`;
99
+ while (value.length < minLength) value += " sample";
100
+ return node.maxLength !== void 0 ? value.slice(0, Math.max(node.maxLength, minLength)) : value;
101
+ }
102
+ function sampleObject(node, seed) {
103
+ const required = new Set(node.required ?? []);
104
+ const result = {};
105
+ for (const [key, child] of Object.entries(node.properties ?? {})) {
106
+ const value = sampleForNode(child, key);
107
+ if (value === void 0) {
108
+ if (required.has(key)) return void 0;
109
+ continue;
110
+ }
111
+ result[key] = value;
112
+ }
113
+ return result;
114
+ }
115
+ /** Read the top-level fields of a request schema's JSON Schema. */
116
+ function readEndpointFields(jsonSchema) {
117
+ if (!isRecord(jsonSchema)) return [];
118
+ const node = jsonSchema;
119
+ const required = new Set(node.required ?? []);
120
+ return Object.entries(node.properties ?? {}).map(([name, child]) => {
121
+ const isRequired = required.has(name);
122
+ const cast = castForNode(child, isRequired);
123
+ const sample = sampleForNode(child, name);
124
+ const field = {
125
+ name,
126
+ required: isRequired,
127
+ comparable: sample !== void 0 && cast !== void 0 && !cast.startsWith("date") && !cast.startsWith("object")
128
+ };
129
+ if (cast !== void 0) field.cast = cast;
130
+ if (sample !== void 0) field.sample = sample;
131
+ return field;
132
+ });
133
+ }
134
+
135
+ //#endregion
136
+ export { readEndpointFields };
137
+ //# sourceMappingURL=endpoint-schema.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint-schema.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/endpoint-schema.ts"],"sourcesContent":["/**\n * What the endpoint generator needs to know about a request schema, read\n * from the JSON Schema seal produces (`validator.toJsonSchema()`).\n *\n * Kept free of seal imports: it works on the plain JSON Schema object, so it\n * is unit-testable and survives seal's internals changing.\n */\n\n/** The JSON Schema subset this module reads. */\nexport type JsonSchemaNode = {\n type?: string | string[];\n format?: string;\n enum?: unknown[];\n const?: unknown;\n minimum?: number;\n exclusiveMinimum?: number;\n maximum?: number;\n minLength?: number;\n maxLength?: number;\n minItems?: number;\n items?: JsonSchemaNode;\n properties?: Record<string, JsonSchemaNode>;\n required?: string[];\n anyOf?: JsonSchemaNode[];\n oneOf?: JsonSchemaNode[];\n contentMediaType?: string;\n contentEncoding?: string;\n};\n\n/** One top-level field of the request schema. */\nexport type EndpointField = {\n name: string;\n required: boolean;\n /** The resource cast for this field, or `undefined` when it has no plain JSON shape (a file). */\n cast?: string;\n /** A deterministic valid value, or `undefined` when JSON cannot carry one (a file). */\n sample?: unknown;\n /**\n * Whether the response echoes the sample unchanged, so a generated test can\n * compare it. Dates are parsed and re-cast, so they are not comparable.\n */\n comparable: boolean;\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** The non-null JSON types a node allows, and whether `null` is one of them. */\nfunction typesOf(node: JsonSchemaNode): { types: string[]; nullable: boolean } {\n const variants = node.anyOf ?? node.oneOf;\n\n if (variants) {\n const all = variants.map(typesOf);\n\n return {\n types: all.flatMap((entry) => entry.types),\n nullable: all.some((entry) => entry.nullable),\n };\n }\n\n const raw = node.type === undefined ? [] : Array.isArray(node.type) ? node.type : [node.type];\n\n return { types: raw.filter((type) => type !== \"null\"), nullable: raw.includes(\"null\") };\n}\n\nfunction primaryNode(node: JsonSchemaNode): JsonSchemaNode {\n const variants = node.anyOf ?? node.oneOf;\n\n if (!variants) return node;\n\n return (\n variants.find((variant) => !typesOf(variant).types.every((type) => type === \"null\")) ?? node\n );\n}\n\n/** A file upload: JSON cannot carry it, so it has no sample and no cast. */\nfunction isFileNode(node: JsonSchemaNode): boolean {\n return (\n node.format === \"binary\" ||\n node.contentEncoding === \"binary\" ||\n node.contentMediaType !== undefined\n );\n}\n\nconst CASTS: Record<string, string> = {\n string: \"string\",\n integer: \"int\",\n number: \"number\",\n boolean: \"boolean\",\n array: \"array\",\n object: \"object\",\n};\n\n/** `\"string\"` or `\"number\"` when every enum value has that type. */\nfunction enumValuesType(node: JsonSchemaNode): string | undefined {\n if (!node.enum || node.enum.length === 0) return undefined;\n if (node.enum.every((value) => typeof value === \"string\")) return \"string\";\n if (node.enum.every((value) => typeof value === \"number\")) return \"number\";\n\n return undefined;\n}\n\n/** The resource cast for a field, with `?` when the value may be null or absent. */\nexport function castForNode(node: JsonSchemaNode, required: boolean): string | undefined {\n const primary = primaryNode(node);\n\n if (isFileNode(primary)) return undefined;\n\n const { types, nullable } = typesOf(node);\n const enumType = enumValuesType(primary);\n const only = types.length === 1 ? types[0] : undefined;\n const base = enumType ?? (only === undefined ? undefined : CASTS[only]);\n\n if (base === undefined) return undefined;\n\n if (base === \"string\" && (primary.format === \"date-time\" || primary.format === \"date\")) {\n return nullable || !required ? \"date?\" : \"date\";\n }\n\n return nullable || !required ? `${base}?` : base;\n}\n\n/**\n * A deterministic value that satisfies `node`, or `undefined` when JSON cannot\n * express one. `seed` keeps values readable and stable between runs.\n */\nexport function sampleForNode(node: JsonSchemaNode, seed: string): unknown {\n const primary = primaryNode(node);\n\n if (isFileNode(primary)) return undefined;\n if (primary.const !== undefined) return primary.const;\n if (primary.enum && primary.enum.length > 0) return primary.enum[0];\n\n const { types } = typesOf(node);\n const type = types[0];\n\n switch (type) {\n case \"string\":\n return sampleString(primary, seed);\n case \"integer\":\n return sampleNumber(primary, true);\n case \"number\":\n return sampleNumber(primary, false);\n case \"boolean\":\n return true;\n case \"array\": {\n const count = primary.minItems ?? 0;\n const item = primary.items ? sampleForNode(primary.items, `${seed}-item`) : undefined;\n\n if (count > 0 && item === undefined) return undefined;\n\n return Array.from({ length: count }, () => item);\n }\n case \"object\":\n return sampleObject(primary, seed);\n default:\n return undefined;\n }\n}\n\nfunction sampleNumber(node: JsonSchemaNode, integer: boolean): number {\n const lower =\n node.minimum ?? (node.exclusiveMinimum !== undefined ? node.exclusiveMinimum + 1 : 1);\n let value = integer ? Math.ceil(lower) : lower;\n\n if (node.maximum !== undefined && value > node.maximum) value = node.maximum;\n\n return value;\n}\n\nfunction sampleString(node: JsonSchemaNode, seed: string): string {\n switch (node.format) {\n case \"email\":\n return `${seed.replace(/[^a-z0-9]/gi, \"\").toLowerCase() || \"user\"}@example.test`;\n case \"uri\":\n case \"url\":\n return `https://example.test/${seed}`;\n case \"uuid\":\n return \"00000000-0000-4000-8000-000000000001\";\n case \"date-time\":\n return \"2026-01-01T00:00:00.000Z\";\n case \"date\":\n return \"2026-01-01\";\n default:\n break;\n }\n\n const minLength = node.minLength ?? 1;\n let value = `${seed} sample`;\n\n while (value.length < minLength) value += \" sample\";\n\n return node.maxLength !== undefined ? value.slice(0, Math.max(node.maxLength, minLength)) : value;\n}\n\nfunction sampleObject(node: JsonSchemaNode, seed: string): Record<string, unknown> | undefined {\n const required = new Set(node.required ?? []);\n const result: Record<string, unknown> = {};\n\n for (const [key, child] of Object.entries(node.properties ?? {})) {\n const value = sampleForNode(child, key);\n\n if (value === undefined) {\n if (required.has(key)) return undefined;\n continue;\n }\n\n result[key] = value;\n }\n\n void seed;\n\n return result;\n}\n\n/** Read the top-level fields of a request schema's JSON Schema. */\nexport function readEndpointFields(jsonSchema: unknown): EndpointField[] {\n if (!isRecord(jsonSchema)) return [];\n\n const node = jsonSchema as JsonSchemaNode;\n const required = new Set(node.required ?? []);\n\n return Object.entries(node.properties ?? {}).map(([name, child]) => {\n const isRequired = required.has(name);\n const cast = castForNode(child, isRequired);\n const sample = sampleForNode(child, name);\n const field: EndpointField = {\n name,\n required: isRequired,\n comparable:\n sample !== undefined &&\n cast !== undefined &&\n !cast.startsWith(\"date\") &&\n !cast.startsWith(\"object\"),\n };\n\n if (cast !== undefined) field.cast = cast;\n if (sample !== undefined) field.sample = sample;\n\n return field;\n });\n}\n"],"mappings":";AA4CA,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;AAGA,SAAS,QAAQ,MAA8D;CAC7E,MAAM,WAAW,KAAK,SAAS,KAAK;CAEpC,IAAI,UAAU;EACZ,MAAM,MAAM,SAAS,IAAI,OAAO;EAEhC,OAAO;GACL,OAAO,IAAI,SAAS,UAAU,MAAM,KAAK;GACzC,UAAU,IAAI,MAAM,UAAU,MAAM,QAAQ;EAC9C;CACF;CAEA,MAAM,MAAM,KAAK,SAAS,SAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,IAAI,IAAI,KAAK,OAAO,CAAC,KAAK,IAAI;CAE5F,OAAO;EAAE,OAAO,IAAI,QAAQ,SAAS,SAAS,MAAM;EAAG,UAAU,IAAI,SAAS,MAAM;CAAE;AACxF;AAEA,SAAS,YAAY,MAAsC;CACzD,MAAM,WAAW,KAAK,SAAS,KAAK;CAEpC,IAAI,CAAC,UAAU,OAAO;CAEtB,OACE,SAAS,MAAM,YAAY,CAAC,QAAQ,OAAO,CAAC,CAAC,MAAM,OAAO,SAAS,SAAS,MAAM,CAAC,KAAK;AAE5F;;AAGA,SAAS,WAAW,MAA+B;CACjD,OACE,KAAK,WAAW,YAChB,KAAK,oBAAoB,YACzB,KAAK,qBAAqB;AAE9B;AAEA,MAAM,QAAgC;CACpC,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,SAAS;CACT,OAAO;CACP,QAAQ;AACV;;AAGA,SAAS,eAAe,MAA0C;CAChE,IAAI,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW,GAAG,OAAO;CACjD,IAAI,KAAK,KAAK,OAAO,UAAU,OAAO,UAAU,QAAQ,GAAG,OAAO;CAClE,IAAI,KAAK,KAAK,OAAO,UAAU,OAAO,UAAU,QAAQ,GAAG,OAAO;AAGpE;;AAGA,SAAgB,YAAY,MAAsB,UAAuC;CACvF,MAAM,UAAU,YAAY,IAAI;CAEhC,IAAI,WAAW,OAAO,GAAG,OAAO;CAEhC,MAAM,EAAE,OAAO,aAAa,QAAQ,IAAI;CACxC,MAAM,WAAW,eAAe,OAAO;CACvC,MAAM,OAAO,MAAM,WAAW,IAAI,MAAM,KAAK;CAC7C,MAAM,OAAO,aAAa,SAAS,SAAY,SAAY,MAAM;CAEjE,IAAI,SAAS,QAAW,OAAO;CAE/B,IAAI,SAAS,aAAa,QAAQ,WAAW,eAAe,QAAQ,WAAW,SAC7E,OAAO,YAAY,CAAC,WAAW,UAAU;CAG3C,OAAO,YAAY,CAAC,WAAW,GAAG,KAAK,KAAK;AAC9C;;;;;AAMA,SAAgB,cAAc,MAAsB,MAAuB;CACzE,MAAM,UAAU,YAAY,IAAI;CAEhC,IAAI,WAAW,OAAO,GAAG,OAAO;CAChC,IAAI,QAAQ,UAAU,QAAW,OAAO,QAAQ;CAChD,IAAI,QAAQ,QAAQ,QAAQ,KAAK,SAAS,GAAG,OAAO,QAAQ,KAAK;CAEjE,MAAM,EAAE,UAAU,QAAQ,IAAI;CAG9B,QAFa,MAAM,IAEnB;EACE,KAAK,UACH,OAAO,aAAa,SAAS,IAAI;EACnC,KAAK,WACH,OAAO,aAAa,SAAS,IAAI;EACnC,KAAK,UACH,OAAO,aAAa,SAAS,KAAK;EACpC,KAAK,WACH,OAAO;EACT,KAAK,SAAS;GACZ,MAAM,QAAQ,QAAQ,YAAY;GAClC,MAAM,OAAO,QAAQ,QAAQ,cAAc,QAAQ,OAAO,GAAG,KAAK,MAAM,IAAI;GAE5E,IAAI,QAAQ,KAAK,SAAS,QAAW,OAAO;GAE5C,OAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,SAAS,IAAI;EACjD;EACA,KAAK,UACH,OAAO,aAAa,SAAS,IAAI;EACnC,SACE;CACJ;AACF;AAEA,SAAS,aAAa,MAAsB,SAA0B;CACpE,MAAM,QACJ,KAAK,YAAY,KAAK,qBAAqB,SAAY,KAAK,mBAAmB,IAAI;CACrF,IAAI,QAAQ,UAAU,KAAK,KAAK,KAAK,IAAI;CAEzC,IAAI,KAAK,YAAY,UAAa,QAAQ,KAAK,SAAS,QAAQ,KAAK;CAErE,OAAO;AACT;AAEA,SAAS,aAAa,MAAsB,MAAsB;CAChE,QAAQ,KAAK,QAAb;EACE,KAAK,SACH,OAAO,GAAG,KAAK,QAAQ,eAAe,EAAE,CAAC,CAAC,YAAY,KAAK,OAAO;EACpE,KAAK;EACL,KAAK,OACH,OAAO,wBAAwB;EACjC,KAAK,QACH,OAAO;EACT,KAAK,aACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,SACE;CACJ;CAEA,MAAM,YAAY,KAAK,aAAa;CACpC,IAAI,QAAQ,GAAG,KAAK;CAEpB,OAAO,MAAM,SAAS,WAAW,SAAS;CAE1C,OAAO,KAAK,cAAc,SAAY,MAAM,MAAM,GAAG,KAAK,IAAI,KAAK,WAAW,SAAS,CAAC,IAAI;AAC9F;AAEA,SAAS,aAAa,MAAsB,MAAmD;CAC7F,MAAM,WAAW,IAAI,IAAI,KAAK,YAAY,CAAC,CAAC;CAC5C,MAAM,SAAkC,CAAC;CAEzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,cAAc,CAAC,CAAC,GAAG;EAChE,MAAM,QAAQ,cAAc,OAAO,GAAG;EAEtC,IAAI,UAAU,QAAW;GACvB,IAAI,SAAS,IAAI,GAAG,GAAG,OAAO;GAC9B;EACF;EAEA,OAAO,OAAO;CAChB;CAIA,OAAO;AACT;;AAGA,SAAgB,mBAAmB,YAAsC;CACvE,IAAI,CAAC,SAAS,UAAU,GAAG,OAAO,CAAC;CAEnC,MAAM,OAAO;CACb,MAAM,WAAW,IAAI,IAAI,KAAK,YAAY,CAAC,CAAC;CAE5C,OAAO,OAAO,QAAQ,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,WAAW;EAClE,MAAM,aAAa,SAAS,IAAI,IAAI;EACpC,MAAM,OAAO,YAAY,OAAO,UAAU;EAC1C,MAAM,SAAS,cAAc,OAAO,IAAI;EACxC,MAAM,QAAuB;GAC3B;GACA,UAAU;GACV,YACE,WAAW,UACX,SAAS,UACT,CAAC,KAAK,WAAW,MAAM,KACvB,CAAC,KAAK,WAAW,QAAQ;EAC7B;EAEA,IAAI,SAAS,QAAW,MAAM,OAAO;EACrC,IAAI,WAAW,QAAW,MAAM,SAAS;EAEzC,OAAO;CACT,CAAC;AACH"}
@@ -10,7 +10,7 @@ import pluralize from "pluralize-esm";
10
10
  */
11
11
  function parseModulePath(input) {
12
12
  const parts = input.split("/");
13
- if (parts.length === 1) return { name: parts[0] };
13
+ if (parts.length === 1) return { name: input };
14
14
  return {
15
15
  module: parts[0],
16
16
  name: parts.slice(1).join("/")
@@ -1 +1 @@
1
- {"version":3,"file":"name-parser.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/name-parser.ts"],"sourcesContent":["import { toCamelCase, toKebabCase, toSnakeCase, toStudlyCase } from \"@mongez/reinforcements\";\nimport pluralize from \"pluralize-esm\";\nimport type { ParsedName } from \"../types\";\n\n/**\n * Parse module path from input\n * Examples:\n * - \"users/create-user\" → { module: \"users\", name: \"create-user\" }\n * - \"create-user\" → { module: undefined, name: \"create-user\" }\n */\nexport function parseModulePath(input: string): { module?: string; name: string } {\n const parts = input.split(\"/\");\n\n if (parts.length === 1) {\n return { name: parts[0] };\n }\n\n return {\n module: parts[0],\n name: parts.slice(1).join(\"/\"),\n };\n}\n\n/**\n * Parse name into all case variants\n */\n// Returns the Name class, which is what it has always constructed. Annotating it as\n// ParsedName understated the result: Name carries `plural` and `singular` getters that\n// the CRUD stubs need, and a protected member that makes it nominal in practice — so\n// four generators could not pass this value to a stub expecting a Name, even though\n// that is exactly what they had. Name still satisfies ParsedName for callers that only\n// want the cased strings.\nexport function parseName(input: string): Name {\n return new Name(input);\n}\n\n/**\n * Get plural name\n */\nexport function pluralName(name: string) {\n return new Name(pluralize(name));\n}\n\n/**\n * Get singular name\n */\nexport function singularName(name: string) {\n return new Name(pluralize.singular(name));\n}\n\nexport class Name {\n protected parsedData: {\n kebab: string;\n camel: string;\n snake: string;\n studly: string;\n };\n\n public constructor(public readonly raw: string) {\n this.parsedData = {\n kebab: toKebabCase(raw),\n camel: toCamelCase(raw),\n snake: toSnakeCase(raw),\n studly: toStudlyCase(raw),\n };\n }\n\n public get plural() {\n return new Name(pluralize(this.raw));\n }\n\n public get singular() {\n return new Name(pluralize.singular(this.raw));\n }\n\n public get pascal(): string {\n return this.parsedData.studly;\n }\n\n public get camel(): string {\n return this.parsedData.camel;\n }\n\n public get kebab(): string {\n return this.parsedData.kebab;\n }\n\n public get snake(): string {\n return this.parsedData.snake;\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,gBAAgB,OAAkD;CAChF,MAAM,QAAQ,MAAM,MAAM,GAAG;CAE7B,IAAI,MAAM,WAAW,GACnB,OAAO,EAAE,MAAM,MAAM,GAAG;CAG1B,OAAO;EACL,QAAQ,MAAM;EACd,MAAM,MAAM,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG;CAC/B;AACF;;;;AAWA,SAAgB,UAAU,OAAqB;CAC7C,OAAO,IAAI,KAAK,KAAK;AACvB;;;;AAKA,SAAgB,WAAW,MAAc;CACvC,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC;AACjC;;;;AAKA,SAAgB,aAAa,MAAc;CACzC,OAAO,IAAI,KAAK,UAAU,SAAS,IAAI,CAAC;AAC1C;AAEA,IAAa,OAAb,MAAa,KAAK;CAQhB,AAAO,YAAY,AAAgB,KAAa;EAAb;EACjC,KAAK,aAAa;GAChB,OAAO,YAAY,GAAG;GACtB,OAAO,YAAY,GAAG;GACtB,OAAO,YAAY,GAAG;GACtB,QAAQ,aAAa,GAAG;EAC1B;CACF;CAEA,IAAW,SAAS;EAClB,OAAO,IAAI,KAAK,UAAU,KAAK,GAAG,CAAC;CACrC;CAEA,IAAW,WAAW;EACpB,OAAO,IAAI,KAAK,UAAU,SAAS,KAAK,GAAG,CAAC;CAC9C;CAEA,IAAW,SAAiB;EAC1B,OAAO,KAAK,WAAW;CACzB;CAEA,IAAW,QAAgB;EACzB,OAAO,KAAK,WAAW;CACzB;CAEA,IAAW,QAAgB;EACzB,OAAO,KAAK,WAAW;CACzB;CAEA,IAAW,QAAgB;EACzB,OAAO,KAAK,WAAW;CACzB;AACF"}
1
+ {"version":3,"file":"name-parser.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/name-parser.ts"],"sourcesContent":["import { toCamelCase, toKebabCase, toSnakeCase, toStudlyCase } from \"@mongez/reinforcements\";\nimport pluralize from \"pluralize-esm\";\n\n/**\n * Parse module path from input\n * Examples:\n * - \"users/create-user\" → { module: \"users\", name: \"create-user\" }\n * - \"create-user\" → { module: undefined, name: \"create-user\" }\n */\nexport function parseModulePath(input: string): { module?: string; name: string } {\n const parts = input.split(\"/\");\n\n if (parts.length === 1) {\n return { name: input };\n }\n\n return {\n module: parts[0],\n name: parts.slice(1).join(\"/\"),\n };\n}\n\n/**\n * Parse name into all case variants\n */\n// Returns the Name class, which is what it has always constructed. Annotating it as\n// ParsedName understated the result: Name carries `plural` and `singular` getters that\n// the CRUD stubs need, and a protected member that makes it nominal in practice — so\n// four generators could not pass this value to a stub expecting a Name, even though\n// that is exactly what they had. Name still satisfies ParsedName for callers that only\n// want the cased strings.\nexport function parseName(input: string): Name {\n return new Name(input);\n}\n\n/**\n * Get plural name\n */\nexport function pluralName(name: string) {\n return new Name(pluralize(name));\n}\n\n/**\n * Get singular name\n */\nexport function singularName(name: string) {\n return new Name(pluralize.singular(name));\n}\n\nexport class Name {\n protected parsedData: {\n kebab: string;\n camel: string;\n snake: string;\n studly: string;\n };\n\n public constructor(public readonly raw: string) {\n this.parsedData = {\n kebab: toKebabCase(raw),\n camel: toCamelCase(raw),\n snake: toSnakeCase(raw),\n studly: toStudlyCase(raw),\n };\n }\n\n public get plural() {\n return new Name(pluralize(this.raw));\n }\n\n public get singular() {\n return new Name(pluralize.singular(this.raw));\n }\n\n public get pascal(): string {\n return this.parsedData.studly;\n }\n\n public get camel(): string {\n return this.parsedData.camel;\n }\n\n public get kebab(): string {\n return this.parsedData.kebab;\n }\n\n public get snake(): string {\n return this.parsedData.snake;\n }\n}\n"],"mappings":";;;;;;;;;;AASA,SAAgB,gBAAgB,OAAkD;CAChF,MAAM,QAAQ,MAAM,MAAM,GAAG;CAE7B,IAAI,MAAM,WAAW,GACnB,OAAO,EAAE,MAAM,MAAM;CAGvB,OAAO;EACL,QAAQ,MAAM;EACd,MAAM,MAAM,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG;CAC/B;AACF;;;;AAWA,SAAgB,UAAU,OAAqB;CAC7C,OAAO,IAAI,KAAK,KAAK;AACvB;;;;AAKA,SAAgB,WAAW,MAAc;CACvC,OAAO,IAAI,KAAK,UAAU,IAAI,CAAC;AACjC;;;;AAKA,SAAgB,aAAa,MAAc;CACzC,OAAO,IAAI,KAAK,UAAU,SAAS,IAAI,CAAC;AAC1C;AAEA,IAAa,OAAb,MAAa,KAAK;CAQhB,AAAO,YAAY,AAAgB,KAAa;EAAb;EACjC,KAAK,aAAa;GAChB,OAAO,YAAY,GAAG;GACtB,OAAO,YAAY,GAAG;GACtB,OAAO,YAAY,GAAG;GACtB,QAAQ,aAAa,GAAG;EAC1B;CACF;CAEA,IAAW,SAAS;EAClB,OAAO,IAAI,KAAK,UAAU,KAAK,GAAG,CAAC;CACrC;CAEA,IAAW,WAAW;EACpB,OAAO,IAAI,KAAK,UAAU,SAAS,KAAK,GAAG,CAAC;CAC9C;CAEA,IAAW,SAAiB;EAC1B,OAAO,KAAK,WAAW;CACzB;CAEA,IAAW,QAAgB;EACzB,OAAO,KAAK,WAAW;CACzB;CAEA,IAAW,QAAgB;EACzB,OAAO,KAAK,WAAW;CACzB;CAEA,IAAW,QAAgB;EACzB,OAAO,KAAK,WAAW;CACzB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/prompt.ts"],"sourcesContent":["import readline from \"node:readline\";\n\n/**\n * Prompt user for confirmation\n */\nexport async function confirm(message: string, defaultValue = false): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n const defaultText = defaultValue ? \"Y/n\" : \"y/N\";\n rl.question(`${message} (${defaultText}): `, (answer) => {\n rl.close();\n\n if (!answer.trim()) {\n resolve(defaultValue);\n return;\n }\n\n const normalized = answer.toLowerCase().trim();\n resolve(normalized === \"y\" || normalized === \"yes\");\n });\n });\n}\n\n/**\n * Prompt user for text input\n */\nexport async function input(message: string, defaultValue?: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n const prompt = defaultValue ? `${message} (${defaultValue}): ` : `${message}: `;\n\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer.trim() || defaultValue || \"\");\n });\n });\n}\n\n/**\n * Prompt user to select from choices\n */\nexport async function select(message: string, choices: string[]): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(message);\n choices.forEach((choice, index) => {\n console.log(` ${index + 1}. ${choice}`);\n });\n\n rl.question(\"Select (1-\" + choices.length + \"): \", (answer) => {\n rl.close();\n\n const index = parseInt(answer.trim(), 10) - 1;\n\n if (index >= 0 && index < choices.length) {\n resolve(choices[index]);\n } else {\n resolve(choices[0]);\n }\n });\n });\n}\n"],"mappings":";;;;;;AAKA,eAAsB,QAAQ,SAAiB,eAAe,OAAyB;CACrF,MAAM,KAAK,SAAS,gBAAgB;EAClC,OAAO,QAAQ;EACf,QAAQ,QAAQ;CAClB,CAAC;CAED,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,cAAc,eAAe,QAAQ;EAC3C,GAAG,SAAS,GAAG,QAAQ,IAAI,YAAY,OAAO,WAAW;GACvD,GAAG,MAAM;GAET,IAAI,CAAC,OAAO,KAAK,GAAG;IAClB,QAAQ,YAAY;IACpB;GACF;GAEA,MAAM,aAAa,OAAO,YAAY,CAAC,CAAC,KAAK;GAC7C,QAAQ,eAAe,OAAO,eAAe,KAAK;EACpD,CAAC;CACH,CAAC;AACH"}
1
+ {"version":3,"file":"prompt.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/prompt.ts"],"sourcesContent":["import readline from \"node:readline\";\n\n/**\n * Prompt user for confirmation\n */\nexport async function confirm(message: string, defaultValue = false): Promise<boolean> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n const defaultText = defaultValue ? \"Y/n\" : \"y/N\";\n rl.question(`${message} (${defaultText}): `, (answer) => {\n rl.close();\n\n if (!answer.trim()) {\n resolve(defaultValue);\n return;\n }\n\n const normalized = answer.toLowerCase().trim();\n resolve(normalized === \"y\" || normalized === \"yes\");\n });\n });\n}\n\n/**\n * Prompt user for text input\n */\nexport async function input(message: string, defaultValue?: string): Promise<string> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n const prompt = defaultValue ? `${message} (${defaultValue}): ` : `${message}: `;\n\n rl.question(prompt, (answer) => {\n rl.close();\n resolve(answer.trim() || defaultValue || \"\");\n });\n });\n}\n\n/**\n * Prompt user to select from choices\n */\nexport async function select(message: string, choices: string[]): Promise<string> {\n if (choices.length === 0) throw new RangeError(\"Selection requires at least one choice.\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n console.log(message);\n choices.forEach((choice, index) => {\n console.log(` ${index + 1}. ${choice}`);\n });\n\n rl.question(\"Select (1-\" + choices.length + \"): \", (answer) => {\n rl.close();\n\n const index = parseInt(answer.trim(), 10) - 1;\n\n if (index >= 0 && index < choices.length) {\n resolve(choices[index]!);\n } else {\n resolve(choices[0]!);\n }\n });\n });\n}\n"],"mappings":";;;;;;AAKA,eAAsB,QAAQ,SAAiB,eAAe,OAAyB;CACrF,MAAM,KAAK,SAAS,gBAAgB;EAClC,OAAO,QAAQ;EACf,QAAQ,QAAQ;CAClB,CAAC;CAED,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,cAAc,eAAe,QAAQ;EAC3C,GAAG,SAAS,GAAG,QAAQ,IAAI,YAAY,OAAO,WAAW;GACvD,GAAG,MAAM;GAET,IAAI,CAAC,OAAO,KAAK,GAAG;IAClB,QAAQ,YAAY;IACpB;GACF;GAEA,MAAM,aAAa,OAAO,YAAY,CAAC,CAAC,KAAK;GAC7C,QAAQ,eAAe,OAAO,eAAe,KAAK;EACpD,CAAC;CACH,CAAC;AACH"}
@@ -1,21 +1,23 @@
1
- import path from "node:path";
1
+ import { isGenerationDryRun, pendingGeneratedContent, recordGeneratedFile, recordSkippedFile, setPendingGeneratedContent, toReportPath } from "../../../../generations/generation-run.mjs";
2
+ import { existsSync, readFileSync } from "node:fs";
2
3
  import { colors } from "@mongez/copper";
3
4
  import { ensureDirectoryAsync, putFileAsync } from "@warlock.js/fs";
4
- import { existsSync, readFileSync } from "node:fs";
5
5
 
6
6
  //#region ../../packages/core/src/cli/commands/generate/utils/writer.ts
7
7
  /**
8
8
  * Dry-run state for the `generate.*` command family.
9
9
  *
10
10
  * When enabled (via `--dry-run`), every generator write becomes a no-op
11
- * that instead reports the file it *would* have created — letting a
12
- * developer preview a scaffold (especially `generate.module --crud`,
13
- * which writes ~25 files) before anything touches disk.
11
+ * that instead reports the file it *would* have created, overwritten or
12
+ * skipped — letting a developer preview a scaffold (especially
13
+ * `generate.module`, which writes ~25 files) before anything touches disk.
14
14
  *
15
15
  * The flag is process-wide module state: the CLI runs one command per
16
16
  * process, and a top-level generator (e.g. `generateModule`) sets it
17
17
  * once, so nested helpers (`createMigrationFile`, `ensureComponentDirectory`)
18
18
  * inherit it without threading a parameter through every signature.
19
+ * A generation run started by `runGenerationCommand` (`--json`) is honoured
20
+ * too, and records every file for the report.
19
21
  */
20
22
  let dryRun = false;
21
23
  /**
@@ -45,40 +47,63 @@ function reportSkippedFiles() {
45
47
  for (const file of skippedFiles) console.log(` ${colors.gray(file)}`);
46
48
  skippedFiles.length = 0;
47
49
  }
50
+ function isDryRun() {
51
+ return dryRun || isGenerationDryRun();
52
+ }
48
53
  /** Render an absolute path relative to the cwd for tidy logs. */
49
54
  function relativePath(target) {
50
- return path.relative(process.cwd(), target) || target;
55
+ return toReportPath(target);
56
+ }
57
+ /** The content at `target`: what this dry run already "wrote", else the disk. */
58
+ function existingContent(target) {
59
+ const pending = pendingGeneratedContent(target);
60
+ if (pending !== void 0) return pending;
61
+ return existsSync(target) ? readFileSync(target, "utf8") : void 0;
51
62
  }
52
63
  /**
53
64
  * Write a generated file — or, in dry-run, report what *would* be
54
65
  * written. Owns the per-file log so call sites stay a single line.
55
66
  *
67
+ * A file that already holds exactly the generated content is left alone.
68
+ * With `setSkipExisting(true)` an existing file that differs is skipped and
69
+ * listed; otherwise it is overwritten (generators refuse to reach this point
70
+ * for an existing file unless `--force` was given).
71
+ *
56
72
  * @example
57
73
  * await putFileAsync(controllerPath, controllerContent);
58
74
  * // normal: ✓ created src/app/users/controllers/create-user.controller.ts
59
75
  * // dry-run: ○ would create src/app/users/controllers/create-user.controller.ts
60
76
  */
61
77
  async function putFileAsync$1(target, content) {
62
- if (dryRun) {
63
- console.log(`${colors.cyan("○")} would create ${colors.gray(relativePath(target))}`);
78
+ const current = existingContent(target);
79
+ if (current !== void 0 && current === content) {
80
+ recordGeneratedFile(target, "unchanged");
81
+ return;
82
+ }
83
+ if (current !== void 0 && skipExisting) {
84
+ skippedFiles.push(relativePath(target));
85
+ recordSkippedFile(target, "exists and differs from the generated output");
64
86
  return;
65
87
  }
66
- if (skipExisting && existsSync(target)) {
67
- if (readFileSync(target, "utf8") !== content) skippedFiles.push(relativePath(target));
88
+ const type = current === void 0 ? "create" : "overwrite";
89
+ recordGeneratedFile(target, type);
90
+ if (isDryRun()) {
91
+ setPendingGeneratedContent(target, content);
92
+ console.log(`${colors.cyan("○")} would ${type} ${colors.gray(relativePath(target))}`);
68
93
  return;
69
94
  }
70
95
  await putFileAsync(target, content);
71
- console.log(`${colors.green("✓")} created ${colors.gray(relativePath(target))}`);
96
+ console.log(`${colors.green("✓")} ${type === "create" ? "created" : "overwrote"} ${colors.gray(relativePath(target))}`);
72
97
  }
73
98
  /**
74
99
  * Ensure a directory exists. Silent no-op in dry-run so a preview never
75
100
  * leaves empty folders behind.
76
101
  */
77
102
  async function ensureDirectoryAsync$1(target) {
78
- if (dryRun) return;
103
+ if (isDryRun()) return;
79
104
  await ensureDirectoryAsync(target);
80
105
  }
81
106
 
82
107
  //#endregion
83
- export { ensureDirectoryAsync$1 as ensureDirectoryAsync, putFileAsync$1 as putFileAsync, reportSkippedFiles, setDryRun, setSkipExisting };
108
+ export { ensureDirectoryAsync$1 as ensureDirectoryAsync, isDryRun, putFileAsync$1 as putFileAsync, reportSkippedFiles, setDryRun, setSkipExisting };
84
109
  //# sourceMappingURL=writer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"writer.mjs","names":["putFileAsync","fsPutFileAsync","ensureDirectoryAsync","fsEnsureDirectoryAsync"],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/writer.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n ensureDirectoryAsync as fsEnsureDirectoryAsync,\n putFileAsync as fsPutFileAsync,\n} from \"@warlock.js/fs\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Dry-run state for the `generate.*` command family.\n *\n * When enabled (via `--dry-run`), every generator write becomes a no-op\n * that instead reports the file it *would* have created — letting a\n * developer preview a scaffold (especially `generate.module --crud`,\n * which writes ~25 files) before anything touches disk.\n *\n * The flag is process-wide module state: the CLI runs one command per\n * process, and a top-level generator (e.g. `generateModule`) sets it\n * once, so nested helpers (`createMigrationFile`, `ensureComponentDirectory`)\n * inherit it without threading a parameter through every signature.\n */\nlet dryRun = false;\n\n/**\n * Toggle dry-run mode. Call once at the start of a generator action,\n * e.g. `setDryRun(Boolean(data.options.dryRun))`.\n */\nexport function setDryRun(value: boolean): void {\n dryRun = value;\n\n if (value) {\n console.log(\n colors.yellowBright(\"\\n○ Dry run — previewing planned files. Nothing will be written.\\n\"),\n );\n }\n}\n\n/**\n * When true, a file that already exists and differs from the generated\n * content is left untouched (and reported) instead of overwritten.\n * Model/module generators enable it unless `--force --overwrite` is given.\n */\nlet skipExisting = false;\nconst skippedFiles: string[] = [];\n\nexport function setSkipExisting(value: boolean): void {\n skipExisting = value;\n skippedFiles.length = 0;\n}\n\n/** Print the files skipped because they exist and differ. No-op when none. */\nexport function reportSkippedFiles(): void {\n if (skippedFiles.length === 0) return;\n\n console.log(\n colors.yellow(\n `\n! Skipped ${skippedFiles.length} existing file(s) that differ from the generated output (pass --force --overwrite to replace them):`,\n ),\n );\n\n for (const file of skippedFiles) {\n console.log(` ${colors.gray(file)}`);\n }\n\n skippedFiles.length = 0;\n}\n\nexport function isDryRun(): boolean {\n return dryRun;\n}\n\n/** Render an absolute path relative to the cwd for tidy logs. */\nfunction relativePath(target: string): string {\n return path.relative(process.cwd(), target) || target;\n}\n\n/**\n * Write a generated file — or, in dry-run, report what *would* be\n * written. Owns the per-file log so call sites stay a single line.\n *\n * @example\n * await putFileAsync(controllerPath, controllerContent);\n * // normal: ✓ created src/app/users/controllers/create-user.controller.ts\n * // dry-run: ○ would create src/app/users/controllers/create-user.controller.ts\n */\nexport async function putFileAsync(target: string, content: string): Promise<void> {\n if (dryRun) {\n console.log(`${colors.cyan(\"○\")} would create ${colors.gray(relativePath(target))}`);\n return;\n }\n\n if (skipExisting && existsSync(target)) {\n if (readFileSync(target, \"utf8\") !== content) {\n skippedFiles.push(relativePath(target));\n }\n\n return;\n }\n\n await fsPutFileAsync(target, content);\n console.log(`${colors.green(\"✓\")} created ${colors.gray(relativePath(target))}`);\n}\n\n/**\n * Ensure a directory exists. Silent no-op in dry-run so a preview never\n * leaves empty folders behind.\n */\nexport async function ensureDirectoryAsync(target: string): Promise<void> {\n if (dryRun) return;\n\n await fsEnsureDirectoryAsync(target);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAqBA,IAAI,SAAS;;;;;AAMb,SAAgB,UAAU,OAAsB;CAC9C,SAAS;CAET,IAAI,OACF,QAAQ,IACN,OAAO,aAAa,oEAAoE,CAC1F;AAEJ;;;;;;AAOA,IAAI,eAAe;AACnB,MAAM,eAAyB,CAAC;AAEhC,SAAgB,gBAAgB,OAAsB;CACpD,eAAe;CACf,aAAa,SAAS;AACxB;;AAGA,SAAgB,qBAA2B;CACzC,IAAI,aAAa,WAAW,GAAG;CAE/B,QAAQ,IACN,OAAO,OACL;YACM,aAAa,OAAO,oGAC5B,CACF;CAEA,KAAK,MAAM,QAAQ,cACjB,QAAQ,IAAI,KAAK,OAAO,KAAK,IAAI,GAAG;CAGtC,aAAa,SAAS;AACxB;;AAOA,SAAS,aAAa,QAAwB;CAC5C,OAAO,KAAK,SAAS,QAAQ,IAAI,GAAG,MAAM,KAAK;AACjD;;;;;;;;;;AAWA,eAAsBA,eAAa,QAAgB,SAAgC;CACjF,IAAI,QAAQ;EACV,QAAQ,IAAI,GAAG,OAAO,KAAK,GAAG,EAAE,gBAAgB,OAAO,KAAK,aAAa,MAAM,CAAC,GAAG;EACnF;CACF;CAEA,IAAI,gBAAgB,WAAW,MAAM,GAAG;EACtC,IAAI,aAAa,QAAQ,MAAM,MAAM,SACnC,aAAa,KAAK,aAAa,MAAM,CAAC;EAGxC;CACF;CAEA,MAAMC,aAAe,QAAQ,OAAO;CACpC,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,WAAW,OAAO,KAAK,aAAa,MAAM,CAAC,GAAG;AACjF;;;;;AAMA,eAAsBC,uBAAqB,QAA+B;CACxE,IAAI,QAAQ;CAEZ,MAAMC,qBAAuB,MAAM;AACrC"}
1
+ {"version":3,"file":"writer.mjs","names":["putFileAsync","fsPutFileAsync","ensureDirectoryAsync","fsEnsureDirectoryAsync"],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/utils/writer.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n ensureDirectoryAsync as fsEnsureDirectoryAsync,\n putFileAsync as fsPutFileAsync,\n} from \"@warlock.js/fs\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport {\n isGenerationDryRun,\n pendingGeneratedContent,\n recordGeneratedFile,\n recordSkippedFile,\n setPendingGeneratedContent,\n toReportPath,\n} from \"../../../../generations/generation-run\";\n\n/**\n * Dry-run state for the `generate.*` command family.\n *\n * When enabled (via `--dry-run`), every generator write becomes a no-op\n * that instead reports the file it *would* have created, overwritten or\n * skipped — letting a developer preview a scaffold (especially\n * `generate.module`, which writes ~25 files) before anything touches disk.\n *\n * The flag is process-wide module state: the CLI runs one command per\n * process, and a top-level generator (e.g. `generateModule`) sets it\n * once, so nested helpers (`createMigrationFile`, `ensureComponentDirectory`)\n * inherit it without threading a parameter through every signature.\n * A generation run started by `runGenerationCommand` (`--json`) is honoured\n * too, and records every file for the report.\n */\nlet dryRun = false;\n\n/**\n * Toggle dry-run mode. Call once at the start of a generator action,\n * e.g. `setDryRun(Boolean(data.options.dryRun))`.\n */\nexport function setDryRun(value: boolean): void {\n dryRun = value;\n\n if (value) {\n console.log(\n colors.yellowBright(\"\\n○ Dry run — previewing planned files. Nothing will be written.\\n\"),\n );\n }\n}\n\n/**\n * When true, a file that already exists and differs from the generated\n * content is left untouched (and reported) instead of overwritten.\n * Model/module generators enable it unless `--force --overwrite` is given.\n */\nlet skipExisting = false;\nconst skippedFiles: string[] = [];\n\nexport function setSkipExisting(value: boolean): void {\n skipExisting = value;\n skippedFiles.length = 0;\n}\n\n/** Print the files skipped because they exist and differ. No-op when none. */\nexport function reportSkippedFiles(): void {\n if (skippedFiles.length === 0) return;\n\n console.log(\n colors.yellow(\n `\n! Skipped ${skippedFiles.length} existing file(s) that differ from the generated output (pass --force --overwrite to replace them):`,\n ),\n );\n\n for (const file of skippedFiles) {\n console.log(` ${colors.gray(file)}`);\n }\n\n skippedFiles.length = 0;\n}\n\nexport function isDryRun(): boolean {\n return dryRun || isGenerationDryRun();\n}\n\n/** Render an absolute path relative to the cwd for tidy logs. */\nfunction relativePath(target: string): string {\n return toReportPath(target);\n}\n\n/** The content at `target`: what this dry run already \"wrote\", else the disk. */\nfunction existingContent(target: string): string | undefined {\n const pending = pendingGeneratedContent(target);\n\n if (pending !== undefined) return pending;\n\n return existsSync(target) ? readFileSync(target, \"utf8\") : undefined;\n}\n\n/**\n * Write a generated file — or, in dry-run, report what *would* be\n * written. Owns the per-file log so call sites stay a single line.\n *\n * A file that already holds exactly the generated content is left alone.\n * With `setSkipExisting(true)` an existing file that differs is skipped and\n * listed; otherwise it is overwritten (generators refuse to reach this point\n * for an existing file unless `--force` was given).\n *\n * @example\n * await putFileAsync(controllerPath, controllerContent);\n * // normal: ✓ created src/app/users/controllers/create-user.controller.ts\n * // dry-run: ○ would create src/app/users/controllers/create-user.controller.ts\n */\nexport async function putFileAsync(target: string, content: string): Promise<void> {\n const current = existingContent(target);\n\n if (current !== undefined && current === content) {\n recordGeneratedFile(target, \"unchanged\");\n return;\n }\n\n if (current !== undefined && skipExisting) {\n skippedFiles.push(relativePath(target));\n recordSkippedFile(target, \"exists and differs from the generated output\");\n return;\n }\n\n const type = current === undefined ? \"create\" : \"overwrite\";\n\n recordGeneratedFile(target, type);\n\n if (isDryRun()) {\n setPendingGeneratedContent(target, content);\n console.log(`${colors.cyan(\"○\")} would ${type} ${colors.gray(relativePath(target))}`);\n return;\n }\n\n await fsPutFileAsync(target, content);\n console.log(\n `${colors.green(\"✓\")} ${type === \"create\" ? \"created\" : \"overwrote\"} ${colors.gray(relativePath(target))}`,\n );\n}\n\n/**\n * Ensure a directory exists. Silent no-op in dry-run so a preview never\n * leaves empty folders behind.\n */\nexport async function ensureDirectoryAsync(target: string): Promise<void> {\n if (isDryRun()) return;\n\n await fsEnsureDirectoryAsync(target);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA8BA,IAAI,SAAS;;;;;AAMb,SAAgB,UAAU,OAAsB;CAC9C,SAAS;CAET,IAAI,OACF,QAAQ,IACN,OAAO,aAAa,oEAAoE,CAC1F;AAEJ;;;;;;AAOA,IAAI,eAAe;AACnB,MAAM,eAAyB,CAAC;AAEhC,SAAgB,gBAAgB,OAAsB;CACpD,eAAe;CACf,aAAa,SAAS;AACxB;;AAGA,SAAgB,qBAA2B;CACzC,IAAI,aAAa,WAAW,GAAG;CAE/B,QAAQ,IACN,OAAO,OACL;YACM,aAAa,OAAO,oGAC5B,CACF;CAEA,KAAK,MAAM,QAAQ,cACjB,QAAQ,IAAI,KAAK,OAAO,KAAK,IAAI,GAAG;CAGtC,aAAa,SAAS;AACxB;AAEA,SAAgB,WAAoB;CAClC,OAAO,UAAU,mBAAmB;AACtC;;AAGA,SAAS,aAAa,QAAwB;CAC5C,OAAO,aAAa,MAAM;AAC5B;;AAGA,SAAS,gBAAgB,QAAoC;CAC3D,MAAM,UAAU,wBAAwB,MAAM;CAE9C,IAAI,YAAY,QAAW,OAAO;CAElC,OAAO,WAAW,MAAM,IAAI,aAAa,QAAQ,MAAM,IAAI;AAC7D;;;;;;;;;;;;;;;AAgBA,eAAsBA,eAAa,QAAgB,SAAgC;CACjF,MAAM,UAAU,gBAAgB,MAAM;CAEtC,IAAI,YAAY,UAAa,YAAY,SAAS;EAChD,oBAAoB,QAAQ,WAAW;EACvC;CACF;CAEA,IAAI,YAAY,UAAa,cAAc;EACzC,aAAa,KAAK,aAAa,MAAM,CAAC;EACtC,kBAAkB,QAAQ,8CAA8C;EACxE;CACF;CAEA,MAAM,OAAO,YAAY,SAAY,WAAW;CAEhD,oBAAoB,QAAQ,IAAI;CAEhC,IAAI,SAAS,GAAG;EACd,2BAA2B,QAAQ,OAAO;EAC1C,QAAQ,IAAI,GAAG,OAAO,KAAK,GAAG,EAAE,SAAS,KAAK,GAAG,OAAO,KAAK,aAAa,MAAM,CAAC,GAAG;EACpF;CACF;CAEA,MAAMC,aAAe,QAAQ,OAAO;CACpC,QAAQ,IACN,GAAG,OAAO,MAAM,GAAG,EAAE,GAAG,SAAS,WAAW,YAAY,YAAY,GAAG,OAAO,KAAK,aAAa,MAAM,CAAC,GACzG;AACF;;;;;AAMA,eAAsBC,uBAAqB,QAA+B;CACxE,IAAI,SAAS,GAAG;CAEhB,MAAMC,qBAAuB,MAAM;AACrC"}
@@ -0,0 +1,72 @@
1
+ import { bootForInspect, inspectOptionsFromBoot } from "../../../tooling/inspect/boot-for-inspect.mjs";
2
+ import { inspectApp, parseInspectSections } from "../../../tooling/inspect/inspect-app.mjs";
3
+ import { withConsoleOnStderr } from "../routes/with-console-on-stderr.mjs";
4
+ import { colors } from "@mongez/copper";
5
+
6
+ //#region ../../packages/core/src/cli/commands/inspect/inspect-command.action.ts
7
+ function stringOption(value) {
8
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
9
+ }
10
+ /**
11
+ * The human summary `warlock inspect` prints without `--json`: one count per
12
+ * section, the routes as `METHOD path [auth] name`, and the warnings.
13
+ * Returned as lines so it is testable.
14
+ */
15
+ function formatInspectSummary(report) {
16
+ const lines = [`${report.app.name ?? "app"}${report.app.version ? `@${report.app.version}` : ""} (${report.app.runtimeStrategy}, Node ${report.app.node})`, ""];
17
+ const counts = [
18
+ ["routes", report.routes?.length],
19
+ ["models", report.models?.length],
20
+ ["resources", report.resources?.length],
21
+ ["config keys", report.config?.length],
22
+ ["events", report.events?.length],
23
+ ["pages", report.pages?.length],
24
+ ["jobs", report.jobs?.length],
25
+ ["schedules", report.schedules?.length],
26
+ ["packages", report.packages?.length]
27
+ ];
28
+ for (const [label, count] of counts) if (count !== void 0) lines.push(` ${label.padEnd(12)} ${count}`);
29
+ if (report.routes && report.routes.length > 0) {
30
+ lines.push("", "Routes:");
31
+ for (const route of report.routes) {
32
+ const guard = route.auth.required ? " [auth]" : "";
33
+ const name = route.name ? ` ${route.name}` : "";
34
+ lines.push(` ${route.method.padEnd(7)} ${route.path}${guard}${name}`);
35
+ }
36
+ }
37
+ if (report.warnings.length > 0) {
38
+ lines.push("", `${report.warnings.length} warning(s):`);
39
+ for (const warning of report.warnings) lines.push(` - ${warning.code ? `${warning.code} ` : ""}${warning.message}`);
40
+ }
41
+ lines.push("", "Run `warlock inspect --json` for the full report.");
42
+ return lines;
43
+ }
44
+ /**
45
+ * Action behind `warlock inspect`.
46
+ *
47
+ * Boots the app read-only (the `warlock doctor` boot pass: connectors booted,
48
+ * none started, no connection, no port), then describes it with
49
+ * `inspectApp()`. With `--json`, stdout carries exactly the report and the
50
+ * boot's progress lines go to stderr.
51
+ *
52
+ * @param data Parsed CLI args: `options.json`, `options.section`.
53
+ */
54
+ async function inspectCommandAction({ options }) {
55
+ const sections = parseInspectSections(stringOption(options.section));
56
+ const json = options.json === true;
57
+ const report = await inspectApp({
58
+ ...inspectOptionsFromBoot(json ? await withConsoleOnStderr(() => bootForInspect()) : await bootForInspect()),
59
+ sections
60
+ });
61
+ if (json) {
62
+ console.log(JSON.stringify(report, null, 2));
63
+ return;
64
+ }
65
+ const [heading, ...rest] = formatInspectSummary(report);
66
+ console.log(colors.bold(heading ?? ""));
67
+ for (const line of rest) console.log(line);
68
+ }
69
+
70
+ //#endregion
71
+ export { inspectCommandAction };
72
+ //# sourceMappingURL=inspect-command.action.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect-command.action.mjs","names":[],"sources":["../../../../../../../../../../packages/core/src/cli/commands/inspect/inspect-command.action.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../commands/types\";\nimport { bootForInspect, inspectOptionsFromBoot } from \"../../../tooling/inspect/boot-for-inspect\";\nimport { inspectApp, parseInspectSections } from \"../../../tooling/inspect/inspect-app\";\nimport type { InspectReport } from \"../../../tooling/inspect/inspect-report.types\";\nimport { withConsoleOnStderr } from \"../routes/with-console-on-stderr\";\n\nfunction stringOption(value: string | number | boolean | undefined): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\n/**\n * The human summary `warlock inspect` prints without `--json`: one count per\n * section, the routes as `METHOD path [auth] name`, and the warnings.\n * Returned as lines so it is testable.\n */\nexport function formatInspectSummary(report: InspectReport): string[] {\n const lines: string[] = [\n `${report.app.name ?? \"app\"}${report.app.version ? `@${report.app.version}` : \"\"} (${report.app.runtimeStrategy}, Node ${report.app.node})`,\n \"\",\n ];\n\n const counts: [string, number | undefined][] = [\n [\"routes\", report.routes?.length],\n [\"models\", report.models?.length],\n [\"resources\", report.resources?.length],\n [\"config keys\", report.config?.length],\n [\"events\", report.events?.length],\n [\"pages\", report.pages?.length],\n [\"jobs\", report.jobs?.length],\n [\"schedules\", report.schedules?.length],\n [\"packages\", report.packages?.length],\n ];\n\n for (const [label, count] of counts) {\n if (count !== undefined) lines.push(` ${label.padEnd(12)} ${count}`);\n }\n\n if (report.routes && report.routes.length > 0) {\n lines.push(\"\", \"Routes:\");\n\n for (const route of report.routes) {\n const guard = route.auth.required ? \" [auth]\" : \"\";\n const name = route.name ? ` ${route.name}` : \"\";\n\n lines.push(` ${route.method.padEnd(7)} ${route.path}${guard}${name}`);\n }\n }\n\n if (report.warnings.length > 0) {\n lines.push(\"\", `${report.warnings.length} warning(s):`);\n\n for (const warning of report.warnings) {\n lines.push(` - ${warning.code ? `${warning.code} ` : \"\"}${warning.message}`);\n }\n }\n\n lines.push(\"\", \"Run `warlock inspect --json` for the full report.\");\n\n return lines;\n}\n\n/**\n * Action behind `warlock inspect`.\n *\n * Boots the app read-only (the `warlock doctor` boot pass: connectors booted,\n * none started, no connection, no port), then describes it with\n * `inspectApp()`. With `--json`, stdout carries exactly the report and the\n * boot's progress lines go to stderr.\n *\n * @param data Parsed CLI args: `options.json`, `options.section`.\n */\nexport async function inspectCommandAction({ options }: CommandActionData): Promise<void> {\n // Parsed first, so a typo fails before the app boots.\n const sections = parseInspectSections(stringOption(options.section));\n const json = options.json === true;\n const boot = json ? await withConsoleOnStderr(() => bootForInspect()) : await bootForInspect();\n const report = await inspectApp({ ...inspectOptionsFromBoot(boot), sections });\n\n if (json) {\n console.log(JSON.stringify(report, null, 2));\n return;\n }\n\n const [heading, ...rest] = formatInspectSummary(report);\n\n console.log(colors.bold(heading ?? \"\"));\n\n for (const line of rest) {\n console.log(line);\n }\n}\n"],"mappings":";;;;;;AAOA,SAAS,aAAa,OAAkE;CACtF,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;;;;;;AAOA,SAAgB,qBAAqB,QAAiC;CACpE,MAAM,QAAkB,CACtB,GAAG,OAAO,IAAI,QAAQ,QAAQ,OAAO,IAAI,UAAU,IAAI,OAAO,IAAI,YAAY,GAAG,IAAI,OAAO,IAAI,gBAAgB,SAAS,OAAO,IAAI,KAAK,IACzI,EACF;CAEA,MAAM,SAAyC;EAC7C,CAAC,UAAU,OAAO,QAAQ,MAAM;EAChC,CAAC,UAAU,OAAO,QAAQ,MAAM;EAChC,CAAC,aAAa,OAAO,WAAW,MAAM;EACtC,CAAC,eAAe,OAAO,QAAQ,MAAM;EACrC,CAAC,UAAU,OAAO,QAAQ,MAAM;EAChC,CAAC,SAAS,OAAO,OAAO,MAAM;EAC9B,CAAC,QAAQ,OAAO,MAAM,MAAM;EAC5B,CAAC,aAAa,OAAO,WAAW,MAAM;EACtC,CAAC,YAAY,OAAO,UAAU,MAAM;CACtC;CAEA,KAAK,MAAM,CAAC,OAAO,UAAU,QAC3B,IAAI,UAAU,QAAW,MAAM,KAAK,KAAK,MAAM,OAAO,EAAE,EAAE,GAAG,OAAO;CAGtE,IAAI,OAAO,UAAU,OAAO,OAAO,SAAS,GAAG;EAC7C,MAAM,KAAK,IAAI,SAAS;EAExB,KAAK,MAAM,SAAS,OAAO,QAAQ;GACjC,MAAM,QAAQ,MAAM,KAAK,WAAW,YAAY;GAChD,MAAM,OAAO,MAAM,OAAO,KAAK,MAAM,SAAS;GAE9C,MAAM,KAAK,KAAK,MAAM,OAAO,OAAO,CAAC,EAAE,GAAG,MAAM,OAAO,QAAQ,MAAM;EACvE;CACF;CAEA,IAAI,OAAO,SAAS,SAAS,GAAG;EAC9B,MAAM,KAAK,IAAI,GAAG,OAAO,SAAS,OAAO,aAAa;EAEtD,KAAK,MAAM,WAAW,OAAO,UAC3B,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG,QAAQ,KAAK,KAAK,KAAK,QAAQ,SAAS;CAEhF;CAEA,MAAM,KAAK,IAAI,mDAAmD;CAElE,OAAO;AACT;;;;;;;;;;;AAYA,eAAsB,qBAAqB,EAAE,WAA6C;CAExF,MAAM,WAAW,qBAAqB,aAAa,QAAQ,OAAO,CAAC;CACnE,MAAM,OAAO,QAAQ,SAAS;CAE9B,MAAM,SAAS,MAAM,WAAW;EAAE,GAAG,uBADxB,OAAO,MAAM,0BAA0B,eAAe,CAAC,IAAI,MAAM,eAAe,CAC7B;EAAG;CAAS,CAAC;CAE7E,IAAI,MAAM;EACR,QAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;EAC3C;CACF;CAEA,MAAM,CAAC,SAAS,GAAG,QAAQ,qBAAqB,MAAM;CAEtD,QAAQ,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;CAEtC,KAAK,MAAM,QAAQ,MACjB,QAAQ,IAAI,IAAI;AAEpB"}
@@ -0,0 +1,39 @@
1
+ import { command } from "../../commands/cli-command.mjs";
2
+ import { inspectCommandAction } from "./inspect/inspect-command.action.mjs";
3
+
4
+ //#region ../../packages/core/src/cli/commands/inspect.command.ts
5
+ /**
6
+ * `warlock inspect` — print the app's facts from its booted registries:
7
+ * routes (middleware, guard, rate limit, logging, request/response schemas),
8
+ * models, resources, config keys, event listeners, pages, queue jobs,
9
+ * scheduled tasks and installed `@warlock.js/*` versions. `--json` prints the
10
+ * versioned report (`schemaVersion: 1`); `--section` limits it.
11
+ *
12
+ * Boots like `warlock doctor`: connectors boot (routes register) but none
13
+ * starts, so no database, cache or socket connection opens and no port binds.
14
+ * `runtimeStrategy: "development"` for the same reason doctor declares it.
15
+ */
16
+ const inspectCommand = command({
17
+ name: "inspect",
18
+ description: "Print the app's routes, models, resources, config keys, events, pages, jobs, schedules and package versions (read-only); --json for the versioned report",
19
+ action: inspectCommandAction,
20
+ preload: {
21
+ runtimeStrategy: "development",
22
+ config: true,
23
+ env: true,
24
+ bootstrap: true
25
+ },
26
+ options: [{
27
+ text: "--json, -j",
28
+ description: "Print the report as JSON (schemaVersion 1)",
29
+ type: "boolean"
30
+ }, {
31
+ text: "--section, -s",
32
+ description: "Comma-separated sections: routes, models, resources, config, events, pages, jobs, schedules, packages",
33
+ type: "string"
34
+ }]
35
+ });
36
+
37
+ //#endregion
38
+ export { inspectCommand };
39
+ //# sourceMappingURL=inspect.command.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.command.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/cli/commands/inspect.command.ts"],"sourcesContent":["import { command } from \"../../commands/cli-command\";\nimport { inspectCommandAction } from \"./inspect/inspect-command.action\";\n\n/**\n * `warlock inspect` — print the app's facts from its booted registries:\n * routes (middleware, guard, rate limit, logging, request/response schemas),\n * models, resources, config keys, event listeners, pages, queue jobs,\n * scheduled tasks and installed `@warlock.js/*` versions. `--json` prints the\n * versioned report (`schemaVersion: 1`); `--section` limits it.\n *\n * Boots like `warlock doctor`: connectors boot (routes register) but none\n * starts, so no database, cache or socket connection opens and no port binds.\n * `runtimeStrategy: \"development\"` for the same reason doctor declares it.\n */\nexport const inspectCommand = command({\n name: \"inspect\",\n description:\n \"Print the app's routes, models, resources, config keys, events, pages, jobs, schedules and package versions (read-only); --json for the versioned report\",\n action: inspectCommandAction,\n preload: {\n runtimeStrategy: \"development\",\n config: true,\n env: true,\n bootstrap: true,\n },\n options: [\n {\n text: \"--json, -j\",\n description: \"Print the report as JSON (schemaVersion 1)\",\n type: \"boolean\",\n },\n {\n text: \"--section, -s\",\n description:\n \"Comma-separated sections: routes, models, resources, config, events, pages, jobs, schedules, packages\",\n type: \"string\",\n },\n ],\n});\n"],"mappings":";;;;;;;;;;;;;;;AAcA,MAAa,iBAAiB,QAAQ;CACpC,MAAM;CACN,aACE;CACF,QAAQ;CACR,SAAS;EACP,iBAAiB;EACjB,QAAQ;EACR,KAAK;EACL,WAAW;CACb;CACA,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aACE;EACF,MAAM;CACR,CACF;AACF,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { getWarlockVersion } from "../../../utils/framework-vesion.mjs";
2
+ import { featuresMap } from "../../../generations/features/index.mjs";
3
+ import { bootForInspect, inspectOptionsFromBoot } from "../../../tooling/inspect/boot-for-inspect.mjs";
4
+ import { inspectApp } from "../../../tooling/inspect/inspect-app.mjs";
5
+ import { flushAndExit } from "../../flush-and-exit.mjs";
6
+ import { createMcpContext } from "../../../tooling/mcp/create-mcp-context.mjs";
7
+ import { resolveMcpTransport, startWarlockMcpServer } from "../../../tooling/mcp/start-mcp-server.mjs";
8
+
9
+ //#region ../../packages/core/src/cli/commands/mcp/mcp-command.action.ts
10
+ function stringOption(value) {
11
+ if (typeof value === "number") return String(value);
12
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
13
+ }
14
+ /**
15
+ * The transport `warlock mcp` options describe: stdio by default, HTTP with
16
+ * `--http` (and `--host`, `--port`, `--path`, `--token` / `WARLOCK_MCP_TOKEN`).
17
+ * Throws on a port that is not a number.
18
+ */
19
+ function mcpTransportFromOptions(options, env = process.env) {
20
+ if (!(options.http === true || stringOption(options.host) !== void 0 || options.port !== void 0)) return { type: "stdio" };
21
+ const portText = stringOption(options.port);
22
+ const port = portText === void 0 ? 0 : Number(portText);
23
+ if (!Number.isInteger(port) || port < 0 || port > 65535) throw new Error(`--port must be a number from 0 to 65535, got ${JSON.stringify(portText)}.`);
24
+ return {
25
+ type: "http",
26
+ host: stringOption(options.host) ?? "127.0.0.1",
27
+ port,
28
+ path: stringOption(options.path) ?? "/mcp",
29
+ token: stringOption(options.token) ?? stringOption(env.WARLOCK_MCP_TOKEN)
30
+ };
31
+ }
32
+ /**
33
+ * Send `console.log` / `console.info` / `console.debug` to stderr for the rest
34
+ * of the process: over stdio, stdout carries only JSON-RPC, so a stray log
35
+ * line from the app (or the framework's logger) would corrupt the stream.
36
+ */
37
+ function routeConsoleToStderr() {
38
+ const { log, info, debug } = console;
39
+ const toStderr = (...args) => console.error(...args);
40
+ console.log = toStderr;
41
+ console.info = toStderr;
42
+ console.debug = toStderr;
43
+ return () => {
44
+ console.log = log;
45
+ console.info = info;
46
+ console.debug = debug;
47
+ };
48
+ }
49
+ /** The read-only boot, run once on the first tool call that needs the app. */
50
+ function lazyInspectOptions() {
51
+ let boot;
52
+ return () => {
53
+ boot ??= bootForInspect().then(inspectOptionsFromBoot);
54
+ return boot;
55
+ };
56
+ }
57
+ /**
58
+ * Action behind `warlock mcp`.
59
+ *
60
+ * Serves the app's tools over MCP. The app is booted the `warlock inspect`
61
+ * way — connectors booted, none started, no connection, no port — on the
62
+ * first call that needs it, so the server answers `initialize` at once.
63
+ * Runs until stdin closes (stdio) or SIGINT/SIGTERM.
64
+ */
65
+ async function mcpCommandAction({ options }) {
66
+ const transport = mcpTransportFromOptions(options);
67
+ resolveMcpTransport(transport);
68
+ if (transport.type === "stdio") routeConsoleToStderr();
69
+ const allowWrites = options.allowWrites === true;
70
+ const inspectOptions = lazyInspectOptions();
71
+ const server = await startWarlockMcpServer({
72
+ context: createMcpContext({
73
+ allowWrites,
74
+ inspect: async (sections) => inspectApp({
75
+ ...await inspectOptions(),
76
+ sections
77
+ }),
78
+ ...process.argv[1] ? { cliEntry: process.argv[1] } : {},
79
+ devtools: {
80
+ ...stringOption(options.url) ? { url: stringOption(options.url) } : {},
81
+ ...stringOption(options.devtoolsPath) ? { devtoolsPath: stringOption(options.devtoolsPath) } : {}
82
+ },
83
+ features: Object.keys(featuresMap)
84
+ }),
85
+ transport,
86
+ version: await getWarlockVersion()
87
+ });
88
+ console.error(`warlock mcp: ${server.tools.length} tools on ${server.url ?? "stdio"} (${allowWrites ? "writes allowed" : "read-only"})`);
89
+ let closing = false;
90
+ const stop = async () => {
91
+ if (closing) return;
92
+ closing = true;
93
+ await server.close();
94
+ await flushAndExit(0);
95
+ };
96
+ process.once("SIGINT", () => void stop());
97
+ process.once("SIGTERM", () => void stop());
98
+ if (transport.type === "stdio") process.stdin.once("end", () => void stop());
99
+ }
100
+
101
+ //#endregion
102
+ export { mcpCommandAction, routeConsoleToStderr };
103
+ //# sourceMappingURL=mcp-command.action.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-command.action.mjs","names":[],"sources":["../../../../../../../../../../packages/core/src/cli/commands/mcp/mcp-command.action.ts"],"sourcesContent":["import type { CommandActionData } from \"../../../commands/types\";\nimport { featuresMap } from \"../../../generations/features\";\nimport { bootForInspect, inspectOptionsFromBoot } from \"../../../tooling/inspect/boot-for-inspect\";\nimport { inspectApp, type InspectOptions } from \"../../../tooling/inspect/inspect-app\";\nimport { createMcpContext } from \"../../../tooling/mcp/create-mcp-context\";\nimport {\n resolveMcpTransport,\n startWarlockMcpServer,\n type WarlockMcpTransport,\n} from \"../../../tooling/mcp/start-mcp-server\";\nimport { getWarlockVersion } from \"../../../utils/framework-vesion\";\nimport { flushAndExit } from \"../../flush-and-exit\";\n\nfunction stringOption(value: string | number | boolean | undefined): string | undefined {\n if (typeof value === \"number\") return String(value);\n\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\n/**\n * The transport `warlock mcp` options describe: stdio by default, HTTP with\n * `--http` (and `--host`, `--port`, `--path`, `--token` / `WARLOCK_MCP_TOKEN`).\n * Throws on a port that is not a number.\n */\nexport function mcpTransportFromOptions(\n options: CommandActionData[\"options\"],\n env: NodeJS.ProcessEnv = process.env,\n): WarlockMcpTransport {\n const http =\n options.http === true || stringOption(options.host) !== undefined || options.port !== undefined;\n\n if (!http) return { type: \"stdio\" };\n\n const portText = stringOption(options.port);\n const port = portText === undefined ? 0 : Number(portText);\n\n if (!Number.isInteger(port) || port < 0 || port > 65_535) {\n throw new Error(`--port must be a number from 0 to 65535, got ${JSON.stringify(portText)}.`);\n }\n\n return {\n type: \"http\",\n host: stringOption(options.host) ?? \"127.0.0.1\",\n port,\n path: stringOption(options.path) ?? \"/mcp\",\n token: stringOption(options.token) ?? stringOption(env.WARLOCK_MCP_TOKEN),\n };\n}\n\n/**\n * Send `console.log` / `console.info` / `console.debug` to stderr for the rest\n * of the process: over stdio, stdout carries only JSON-RPC, so a stray log\n * line from the app (or the framework's logger) would corrupt the stream.\n */\nexport function routeConsoleToStderr(): () => void {\n const { log, info, debug } = console;\n const toStderr = (...args: unknown[]) => console.error(...args);\n\n console.log = toStderr;\n console.info = toStderr;\n console.debug = toStderr;\n\n return () => {\n console.log = log;\n console.info = info;\n console.debug = debug;\n };\n}\n\n/** The read-only boot, run once on the first tool call that needs the app. */\nfunction lazyInspectOptions(): () => Promise<InspectOptions> {\n let boot: Promise<InspectOptions> | undefined;\n\n return () => {\n boot ??= bootForInspect().then(inspectOptionsFromBoot);\n\n return boot;\n };\n}\n\n/**\n * Action behind `warlock mcp`.\n *\n * Serves the app's tools over MCP. The app is booted the `warlock inspect`\n * way — connectors booted, none started, no connection, no port — on the\n * first call that needs it, so the server answers `initialize` at once.\n * Runs until stdin closes (stdio) or SIGINT/SIGTERM.\n */\nexport async function mcpCommandAction({ options }: CommandActionData): Promise<void> {\n const transport = mcpTransportFromOptions(options);\n\n // Refuse an unsafe bind before anything boots.\n resolveMcpTransport(transport);\n\n if (transport.type === \"stdio\") routeConsoleToStderr();\n\n const allowWrites = options.allowWrites === true;\n const inspectOptions = lazyInspectOptions();\n const context = createMcpContext({\n allowWrites,\n inspect: async (sections) => inspectApp({ ...(await inspectOptions()), sections }),\n ...(process.argv[1] ? { cliEntry: process.argv[1] } : {}),\n devtools: {\n ...(stringOption(options.url) ? { url: stringOption(options.url) } : {}),\n ...(stringOption(options.devtoolsPath)\n ? { devtoolsPath: stringOption(options.devtoolsPath) }\n : {}),\n },\n features: Object.keys(featuresMap),\n });\n\n const server = await startWarlockMcpServer({\n context,\n transport,\n version: await getWarlockVersion(),\n });\n\n console.error(\n `warlock mcp: ${server.tools.length} tools on ${server.url ?? \"stdio\"} (${allowWrites ? \"writes allowed\" : \"read-only\"})`,\n );\n\n let closing = false;\n\n const stop = async () => {\n if (closing) return;\n closing = true;\n await server.close();\n await flushAndExit(0);\n };\n\n process.once(\"SIGINT\", () => void stop());\n process.once(\"SIGTERM\", () => void stop());\n\n if (transport.type === \"stdio\") {\n process.stdin.once(\"end\", () => void stop());\n }\n}\n"],"mappings":";;;;;;;;;AAaA,SAAS,aAAa,OAAkE;CACtF,IAAI,OAAO,UAAU,UAAU,OAAO,OAAO,KAAK;CAElD,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;;;;;;AAOA,SAAgB,wBACd,SACA,MAAyB,QAAQ,KACZ;CAIrB,IAAI,EAFF,QAAQ,SAAS,QAAQ,aAAa,QAAQ,IAAI,MAAM,UAAa,QAAQ,SAAS,SAE7E,OAAO,EAAE,MAAM,QAAQ;CAElC,MAAM,WAAW,aAAa,QAAQ,IAAI;CAC1C,MAAM,OAAO,aAAa,SAAY,IAAI,OAAO,QAAQ;CAEzD,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAChD,MAAM,IAAI,MAAM,gDAAgD,KAAK,UAAU,QAAQ,EAAE,EAAE;CAG7F,OAAO;EACL,MAAM;EACN,MAAM,aAAa,QAAQ,IAAI,KAAK;EACpC;EACA,MAAM,aAAa,QAAQ,IAAI,KAAK;EACpC,OAAO,aAAa,QAAQ,KAAK,KAAK,aAAa,IAAI,iBAAiB;CAC1E;AACF;;;;;;AAOA,SAAgB,uBAAmC;CACjD,MAAM,EAAE,KAAK,MAAM,UAAU;CAC7B,MAAM,YAAY,GAAG,SAAoB,QAAQ,MAAM,GAAG,IAAI;CAE9D,QAAQ,MAAM;CACd,QAAQ,OAAO;CACf,QAAQ,QAAQ;CAEhB,aAAa;EACX,QAAQ,MAAM;EACd,QAAQ,OAAO;EACf,QAAQ,QAAQ;CAClB;AACF;;AAGA,SAAS,qBAAoD;CAC3D,IAAI;CAEJ,aAAa;EACX,SAAS,eAAe,CAAC,CAAC,KAAK,sBAAsB;EAErD,OAAO;CACT;AACF;;;;;;;;;AAUA,eAAsB,iBAAiB,EAAE,WAA6C;CACpF,MAAM,YAAY,wBAAwB,OAAO;CAGjD,oBAAoB,SAAS;CAE7B,IAAI,UAAU,SAAS,SAAS,qBAAqB;CAErD,MAAM,cAAc,QAAQ,gBAAgB;CAC5C,MAAM,iBAAiB,mBAAmB;CAc1C,MAAM,SAAS,MAAM,sBAAsB;EACzC,SAdc,iBAAiB;GAC/B;GACA,SAAS,OAAO,aAAa,WAAW;IAAE,GAAI,MAAM,eAAe;IAAI;GAAS,CAAC;GACjF,GAAI,QAAQ,KAAK,KAAK,EAAE,UAAU,QAAQ,KAAK,GAAG,IAAI,CAAC;GACvD,UAAU;IACR,GAAI,aAAa,QAAQ,GAAG,IAAI,EAAE,KAAK,aAAa,QAAQ,GAAG,EAAE,IAAI,CAAC;IACtE,GAAI,aAAa,QAAQ,YAAY,IACjC,EAAE,cAAc,aAAa,QAAQ,YAAY,EAAE,IACnD,CAAC;GACP;GACA,UAAU,OAAO,KAAK,WAAW;EACnC,CAGQ;EACN;EACA,SAAS,MAAM,kBAAkB;CACnC,CAAC;CAED,QAAQ,MACN,gBAAgB,OAAO,MAAM,OAAO,YAAY,OAAO,OAAO,QAAQ,IAAI,cAAc,mBAAmB,YAAY,EACzH;CAEA,IAAI,UAAU;CAEd,MAAM,OAAO,YAAY;EACvB,IAAI,SAAS;EACb,UAAU;EACV,MAAM,OAAO,MAAM;EACnB,MAAM,aAAa,CAAC;CACtB;CAEA,QAAQ,KAAK,gBAAgB,KAAK,KAAK,CAAC;CACxC,QAAQ,KAAK,iBAAiB,KAAK,KAAK,CAAC;CAEzC,IAAI,UAAU,SAAS,SACrB,QAAQ,MAAM,KAAK,aAAa,KAAK,KAAK,CAAC;AAE/C"}