@warlock.js/core 5.31.0 → 5.32.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 (1018) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/esm/application/app.d.mts +3 -3
  3. package/esm/application/app.d.mts.map +1 -1
  4. package/esm/application/application-config-types.d.mts +1 -2
  5. package/esm/application/application-config-types.d.mts.map +1 -1
  6. package/esm/application/application.d.mts +5 -7
  7. package/esm/application/application.d.mts.map +1 -1
  8. package/esm/application/application.mjs +3 -1
  9. package/esm/application/application.mjs.map +1 -1
  10. package/esm/application/boot-signal.d.mts +14 -12
  11. package/esm/application/boot-signal.d.mts.map +1 -1
  12. package/esm/application/index.d.mts +2 -1
  13. package/esm/application/index.mjs +1 -1
  14. package/esm/application/public-url.d.mts +1 -2
  15. package/esm/application/public-url.d.mts.map +1 -1
  16. package/esm/application/roles.d.mts +10 -11
  17. package/esm/application/roles.d.mts.map +1 -1
  18. package/esm/benchmark/benchmark-snapshots.d.mts +1 -3
  19. package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
  20. package/esm/benchmark/benchmark.d.mts +1 -3
  21. package/esm/benchmark/benchmark.d.mts.map +1 -1
  22. package/esm/benchmark/channels/console.channel.d.mts +1 -3
  23. package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
  24. package/esm/benchmark/channels/noop.channel.d.mts +1 -3
  25. package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
  26. package/esm/benchmark/index.mjs +1 -1
  27. package/esm/benchmark/profiler.d.mts +1 -3
  28. package/esm/benchmark/profiler.d.mts.map +1 -1
  29. package/esm/benchmark/profiler.mjs +2 -1
  30. package/esm/benchmark/profiler.mjs.map +1 -1
  31. package/esm/benchmark/types.d.mts +22 -17
  32. package/esm/benchmark/types.d.mts.map +1 -1
  33. package/esm/bootstrap/setup.d.mts +1 -2
  34. package/esm/bootstrap/setup.d.mts.map +1 -1
  35. package/esm/bootstrap.d.mts +1 -2
  36. package/esm/bootstrap.d.mts.map +1 -1
  37. package/esm/cache/database-cache-driver.d.mts +3 -5
  38. package/esm/cache/database-cache-driver.d.mts.map +1 -1
  39. package/esm/cache/database-cache-driver.mjs +1 -1
  40. package/esm/cache/index.d.mts +2 -1
  41. package/esm/cache/index.mjs +1 -1
  42. package/esm/cli/cli-commands.manager.mjs +6 -3
  43. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  44. package/esm/cli/commands/agents-md/agents-md-command.action.mjs +3 -2
  45. package/esm/cli/commands/agents-md/agents-md-command.action.mjs.map +1 -1
  46. package/esm/cli/commands/board/board-command.action.mjs +1 -1
  47. package/esm/cli/commands/check/check-command.action.mjs +1 -1
  48. package/esm/cli/commands/check/child-typecheck.mjs +1 -1
  49. package/esm/cli/commands/check/child-typecheck.mjs.map +1 -1
  50. package/esm/cli/commands/check/format-problems.mjs +1 -1
  51. package/esm/cli/commands/dev-server.command.mjs +3 -2
  52. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  53. package/esm/cli/commands/doctor/check.types.d.mts +29 -16
  54. package/esm/cli/commands/doctor/check.types.d.mts.map +1 -1
  55. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +22 -27
  56. package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
  57. package/esm/cli/commands/doctor/doctor-command.action.mjs +2 -1
  58. package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
  59. package/esm/cli/commands/explain/explain-command.action.mjs +1 -1
  60. package/esm/cli/commands/generate/generators/controller.generator.mjs +5 -2
  61. package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
  62. package/esm/cli/commands/generate/generators/endpoint.generator.mjs +5 -3
  63. package/esm/cli/commands/generate/generators/endpoint.generator.mjs.map +1 -1
  64. package/esm/cli/commands/generate/generators/model.generator.mjs +3 -2
  65. package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
  66. package/esm/cli/commands/generate/generators/repository.generator.mjs +3 -1
  67. package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
  68. package/esm/cli/commands/generate/generators/resource.generator.mjs +3 -1
  69. package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
  70. package/esm/cli/commands/generate/generators/service.generator.mjs +3 -1
  71. package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
  72. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs +2 -2
  73. package/esm/cli/commands/generate/templates/endpoint-stubs.mjs.map +1 -1
  74. package/esm/cli/commands/generate/utils/endpoint-schema.mjs +1 -2
  75. package/esm/cli/commands/generate/utils/endpoint-schema.mjs.map +1 -1
  76. package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
  77. package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
  78. package/esm/cli/commands/inspect/inspect-command.action.mjs +3 -2
  79. package/esm/cli/commands/inspect/inspect-command.action.mjs.map +1 -1
  80. package/esm/cli/commands/issue/collect-environment.mjs +187 -0
  81. package/esm/cli/commands/issue/collect-environment.mjs.map +1 -0
  82. package/esm/cli/commands/issue/issue-command.action.mjs +70 -0
  83. package/esm/cli/commands/issue/issue-command.action.mjs.map +1 -0
  84. package/esm/cli/commands/issue.command.mjs +31 -0
  85. package/esm/cli/commands/issue.command.mjs.map +1 -0
  86. package/esm/cli/commands/mcp/mcp-command.action.mjs +15 -14
  87. package/esm/cli/commands/mcp/mcp-command.action.mjs.map +1 -1
  88. package/esm/cli/commands/openapi-generator.action.mjs +1 -1
  89. package/esm/cli/commands/postman-generator.action.mjs +1 -1
  90. package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
  91. package/esm/cli/commands/routes/route-row.mjs +1 -1
  92. package/esm/cli/commands/routes/routes-diff.action.mjs +2 -2
  93. package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
  94. package/esm/cli/commands/test.command.mjs +1 -1
  95. package/esm/cli/commands/trace/trace-command.action.mjs +1 -1
  96. package/esm/cli/commands-loader.mjs +1 -1
  97. package/esm/cli/framework-cli-commands.mjs +2 -0
  98. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  99. package/esm/cli/parse-cli-args.mjs +2 -2
  100. package/esm/cli/parse-cli-args.mjs.map +1 -1
  101. package/esm/cli/start.d.mts +1 -1
  102. package/esm/cli/string-similarity.mjs +1 -1
  103. package/esm/commands/cli-command.d.mts +2 -4
  104. package/esm/commands/cli-command.d.mts.map +1 -1
  105. package/esm/commands/index.d.mts +2 -1
  106. package/esm/commands/index.mjs +1 -1
  107. package/esm/commands/types.d.mts +8 -8
  108. package/esm/commands/types.d.mts.map +1 -1
  109. package/esm/config/config-getter.d.mts +2 -3
  110. package/esm/config/config-getter.d.mts.map +1 -1
  111. package/esm/config/config-getter.mjs +5 -5
  112. package/esm/config/config-getter.mjs.map +1 -1
  113. package/esm/config/config-handlers.d.mts +1 -3
  114. package/esm/config/config-handlers.d.mts.map +1 -1
  115. package/esm/config/config-loader.d.mts +1 -2
  116. package/esm/config/config-loader.d.mts.map +1 -1
  117. package/esm/config/config-loader.mjs +3 -3
  118. package/esm/config/config-loader.mjs.map +1 -1
  119. package/esm/config/config-manager.mjs +1 -1
  120. package/esm/config/config-schema.d.mts +19 -16
  121. package/esm/config/config-schema.d.mts.map +1 -1
  122. package/esm/config/config-setter.d.mts +2 -4
  123. package/esm/config/config-setter.d.mts.map +1 -1
  124. package/esm/config/config-setter.mjs +2 -2
  125. package/esm/config/config-setter.mjs.map +1 -1
  126. package/esm/config/config-special-handlers.d.mts +2 -4
  127. package/esm/config/config-special-handlers.d.mts.map +1 -1
  128. package/esm/config/index.d.mts +2 -1
  129. package/esm/config/index.mjs +1 -1
  130. package/esm/config/types.d.mts +4 -5
  131. package/esm/config/types.d.mts.map +1 -1
  132. package/esm/connectors/access-connector.d.mts +1 -3
  133. package/esm/connectors/access-connector.d.mts.map +1 -1
  134. package/esm/connectors/access-connector.mjs +2 -2
  135. package/esm/connectors/access-connector.mjs.map +1 -1
  136. package/esm/connectors/ai-connector.d.mts +1 -3
  137. package/esm/connectors/ai-connector.d.mts.map +1 -1
  138. package/esm/connectors/ai-connector.mjs +2 -2
  139. package/esm/connectors/ai-connector.mjs.map +1 -1
  140. package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -3
  141. package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
  142. package/esm/connectors/assert-unique-connector-names.d.mts +1 -3
  143. package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
  144. package/esm/connectors/assert-unique-connector-names.mjs +2 -1
  145. package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
  146. package/esm/connectors/base-connector.d.mts +1 -3
  147. package/esm/connectors/base-connector.d.mts.map +1 -1
  148. package/esm/connectors/cache-connector.d.mts +1 -3
  149. package/esm/connectors/cache-connector.d.mts.map +1 -1
  150. package/esm/connectors/cache-connector.mjs +3 -3
  151. package/esm/connectors/cache-connector.mjs.map +1 -1
  152. package/esm/connectors/connectors-manager.d.mts +2 -4
  153. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  154. package/esm/connectors/connectors-manager.mjs +2 -2
  155. package/esm/connectors/connectors-manager.mjs.map +1 -1
  156. package/esm/connectors/database-connector.d.mts +1 -3
  157. package/esm/connectors/database-connector.d.mts.map +1 -1
  158. package/esm/connectors/database-connector.mjs +2 -2
  159. package/esm/connectors/database-connector.mjs.map +1 -1
  160. package/esm/connectors/describe-server-address.mjs +4 -4
  161. package/esm/connectors/describe-server-address.mjs.map +1 -1
  162. package/esm/connectors/herald-connector.d.mts +1 -3
  163. package/esm/connectors/herald-connector.d.mts.map +1 -1
  164. package/esm/connectors/herald-connector.mjs +2 -2
  165. package/esm/connectors/herald-connector.mjs.map +1 -1
  166. package/esm/connectors/http-connector.d.mts +1 -3
  167. package/esm/connectors/http-connector.d.mts.map +1 -1
  168. package/esm/connectors/http-connector.mjs +8 -7
  169. package/esm/connectors/http-connector.mjs.map +1 -1
  170. package/esm/connectors/index.d.mts +2 -1
  171. package/esm/connectors/index.mjs +1 -1
  172. package/esm/connectors/logger-connector.d.mts +1 -3
  173. package/esm/connectors/logger-connector.d.mts.map +1 -1
  174. package/esm/connectors/logger-connector.mjs +2 -2
  175. package/esm/connectors/logger-connector.mjs.map +1 -1
  176. package/esm/connectors/mail-connector.d.mts +1 -3
  177. package/esm/connectors/mail-connector.d.mts.map +1 -1
  178. package/esm/connectors/mail-connector.mjs +2 -2
  179. package/esm/connectors/mail-connector.mjs.map +1 -1
  180. package/esm/connectors/notifications-connector.d.mts +1 -3
  181. package/esm/connectors/notifications-connector.d.mts.map +1 -1
  182. package/esm/connectors/notifications-connector.mjs +2 -2
  183. package/esm/connectors/notifications-connector.mjs.map +1 -1
  184. package/esm/connectors/register-configured-connectors.d.mts +2 -4
  185. package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
  186. package/esm/connectors/socket-connector.d.mts +1 -3
  187. package/esm/connectors/socket-connector.d.mts.map +1 -1
  188. package/esm/connectors/socket-connector.mjs +12 -10
  189. package/esm/connectors/socket-connector.mjs.map +1 -1
  190. package/esm/connectors/storage.connector.d.mts +1 -3
  191. package/esm/connectors/storage.connector.d.mts.map +1 -1
  192. package/esm/connectors/storage.connector.mjs +2 -2
  193. package/esm/connectors/storage.connector.mjs.map +1 -1
  194. package/esm/connectors/types.d.mts +17 -14
  195. package/esm/connectors/types.d.mts.map +1 -1
  196. package/esm/container/container-instance-registry.mjs.map +1 -1
  197. package/esm/container/development-app-modules.d.mts +7 -5
  198. package/esm/container/development-app-modules.d.mts.map +1 -1
  199. package/esm/container/development-model-modules.d.mts +6 -5
  200. package/esm/container/development-model-modules.d.mts.map +1 -1
  201. package/esm/container/index.d.mts +4 -4
  202. package/esm/container/index.d.mts.map +1 -1
  203. package/esm/database/index.d.mts +3 -1
  204. package/esm/database/index.mjs +1 -1
  205. package/esm/database/migrate-action.mjs +1 -1
  206. package/esm/database/models/database-log/database-log.d.mts +2 -3
  207. package/esm/database/models/database-log/database-log.d.mts.map +1 -1
  208. package/esm/database/models/database-log/index.d.mts +2 -1
  209. package/esm/database/models/database-log/index.mjs +1 -1
  210. package/esm/database/seed-command-action.mjs +1 -1
  211. package/esm/database/seeds/seeder.d.mts +2 -4
  212. package/esm/database/seeds/seeder.d.mts.map +1 -1
  213. package/esm/database/seeds/seeder.errors.d.mts +2 -3
  214. package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
  215. package/esm/database/seeds/seeders.manager.mjs +2 -1
  216. package/esm/database/seeds/seeders.manager.mjs.map +1 -1
  217. package/esm/database/seeds/types.d.mts +7 -8
  218. package/esm/database/seeds/types.d.mts.map +1 -1
  219. package/esm/database/utils.d.mts +4 -5
  220. package/esm/database/utils.d.mts.map +1 -1
  221. package/esm/dev-server/app-module-registry.mjs +1 -1
  222. package/esm/dev-server/create-worker.mjs +5 -3
  223. package/esm/dev-server/create-worker.mjs.map +1 -1
  224. package/esm/dev-server/dependency-graph.d.mts +1 -3
  225. package/esm/dev-server/dependency-graph.d.mts.map +1 -1
  226. package/esm/dev-server/dependency-graph.mjs +1 -1
  227. package/esm/dev-server/dependency-graph.mjs.map +1 -1
  228. package/esm/dev-server/extract-translation-keys.mjs +16 -17
  229. package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
  230. package/esm/dev-server/file-manager.d.mts +3 -7
  231. package/esm/dev-server/file-manager.d.mts.map +1 -1
  232. package/esm/dev-server/file-operations.d.mts +1 -3
  233. package/esm/dev-server/file-operations.d.mts.map +1 -1
  234. package/esm/dev-server/files-watcher.mjs +12 -11
  235. package/esm/dev-server/files-watcher.mjs.map +1 -1
  236. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +36 -115
  237. package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
  238. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +5 -5
  239. package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
  240. package/esm/dev-server/health-checker/file-health-result.d.mts +2 -2
  241. package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
  242. package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -0
  243. package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
  244. package/esm/dev-server/health-checker/oxlint-runner.mjs +6 -5
  245. package/esm/dev-server/health-checker/oxlint-runner.mjs.map +1 -1
  246. package/esm/dev-server/health-checker/workers/eslint-health.worker.d.mts +1 -1
  247. package/esm/dev-server/health-checker/workers/oxlint-health.worker.d.mts +1 -1
  248. package/esm/dev-server/health-checker/workers/ts-health.worker.d.mts +1 -1
  249. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +40 -174
  250. package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
  251. package/esm/dev-server/loader/hook-thread.d.mts +4 -8
  252. package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
  253. package/esm/dev-server/loader/load-hook.d.mts +10 -6
  254. package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
  255. package/esm/dev-server/loader/load-hook.mjs +4 -3
  256. package/esm/dev-server/loader/load-hook.mjs.map +1 -1
  257. package/esm/dev-server/loader/own-resolver.mjs +1 -1
  258. package/esm/dev-server/loader/register-loader.mjs +3 -2
  259. package/esm/dev-server/loader/register-loader.mjs.map +1 -1
  260. package/esm/dev-server/loader/resolve-hook.d.mts +2 -2
  261. package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
  262. package/esm/dev-server/loader/resolve-hook.mjs +2 -1
  263. package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
  264. package/esm/dev-server/loader/transpile-cache.mjs +2 -1
  265. package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
  266. package/esm/dev-server/manifest-manager.d.mts +1 -3
  267. package/esm/dev-server/manifest-manager.d.mts.map +1 -1
  268. package/esm/dev-server/model-module-registry.mjs +3 -3
  269. package/esm/dev-server/model-module-registry.mjs.map +1 -1
  270. package/esm/dev-server/model-resource-typings.mjs +40 -47
  271. package/esm/dev-server/model-resource-typings.mjs.map +1 -1
  272. package/esm/dev-server/module-loader.mjs +2 -2
  273. package/esm/dev-server/module-loader.mjs.map +1 -1
  274. package/esm/dev-server/package-json-manager.mjs +1 -1
  275. package/esm/dev-server/parse-imports.mjs +6 -38
  276. package/esm/dev-server/parse-imports.mjs.map +1 -1
  277. package/esm/dev-server/read-config-ast.mjs +3 -33
  278. package/esm/dev-server/read-config-ast.mjs.map +1 -1
  279. package/esm/dev-server/ready-block.mjs +1 -1
  280. package/esm/dev-server/shortcuts.mjs +1 -1
  281. package/esm/dev-server/special-files-collector.d.mts +2 -4
  282. package/esm/dev-server/special-files-collector.d.mts.map +1 -1
  283. package/esm/dev-server/supervisor.mjs +1 -1
  284. package/esm/dev-server/tsconfig-manager.mjs +3 -3
  285. package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
  286. package/esm/dev-server/type-generator.mjs +28 -35
  287. package/esm/dev-server/type-generator.mjs.map +1 -1
  288. package/esm/dev-server/types.d.mts +3 -4
  289. package/esm/dev-server/types.d.mts.map +1 -1
  290. package/esm/dev-server/update-check-cache.mjs +2 -2
  291. package/esm/dev-server/update-check-cache.mjs.map +1 -1
  292. package/esm/encryption/encrypt.d.mts +2 -3
  293. package/esm/encryption/encrypt.d.mts.map +1 -1
  294. package/esm/encryption/hash.d.mts +1 -2
  295. package/esm/encryption/hash.d.mts.map +1 -1
  296. package/esm/encryption/index.mjs +1 -1
  297. package/esm/encryption/password.d.mts +2 -3
  298. package/esm/encryption/password.d.mts.map +1 -1
  299. package/esm/encryption/types.d.mts +2 -3
  300. package/esm/encryption/types.d.mts.map +1 -1
  301. package/esm/errors/error-codes.d.mts +29 -22
  302. package/esm/errors/error-codes.d.mts.map +1 -1
  303. package/esm/errors/warlock-error.d.mts +1 -3
  304. package/esm/errors/warlock-error.d.mts.map +1 -1
  305. package/esm/generations/add-command.action.mjs +3 -2
  306. package/esm/generations/add-command.action.mjs.map +1 -1
  307. package/esm/generations/features/bull-board.feature.mjs +2 -1
  308. package/esm/generations/features/bull-board.feature.mjs.map +1 -1
  309. package/esm/generations/features/notifications.feature.mjs +2 -1
  310. package/esm/generations/features/notifications.feature.mjs.map +1 -1
  311. package/esm/generations/features/shared/merge-web-sitemap-config.mjs +16 -23
  312. package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
  313. package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
  314. package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
  315. package/esm/generations/features/sitemap.feature.mjs +2 -1
  316. package/esm/generations/features/sitemap.feature.mjs.map +1 -1
  317. package/esm/generations/generation-fs.mjs +1 -1
  318. package/esm/generations/generation-run.mjs +1 -1
  319. package/esm/generations/stubs.mjs +1 -1
  320. package/esm/generations/stubs.mjs.map +1 -1
  321. package/esm/http/boot-port-preflight.d.mts +4 -5
  322. package/esm/http/boot-port-preflight.d.mts.map +1 -1
  323. package/esm/http/boot-port-preflight.mjs +2 -2
  324. package/esm/http/boot-port-preflight.mjs.map +1 -1
  325. package/esm/http/bounded-stream-queue.d.mts +4 -4
  326. package/esm/http/bounded-stream-queue.d.mts.map +1 -1
  327. package/esm/http/bounded-stream-queue.mjs +1 -1
  328. package/esm/http/bounded-stream-queue.mjs.map +1 -1
  329. package/esm/http/build-cors-options.mjs +2 -2
  330. package/esm/http/build-cors-options.mjs.map +1 -1
  331. package/esm/http/build-rate-limit-options.d.mts +2 -3
  332. package/esm/http/build-rate-limit-options.d.mts.map +1 -1
  333. package/esm/http/build-rate-limit-options.mjs +1 -1
  334. package/esm/http/build-rate-limit-options.mjs.map +1 -1
  335. package/esm/http/conditional-request.d.mts +14 -13
  336. package/esm/http/conditional-request.d.mts.map +1 -1
  337. package/esm/http/config.d.mts +2 -4
  338. package/esm/http/config.d.mts.map +1 -1
  339. package/esm/http/config.mjs +2 -2
  340. package/esm/http/config.mjs.map +1 -1
  341. package/esm/http/context/request-context.d.mts +6 -7
  342. package/esm/http/context/request-context.d.mts.map +1 -1
  343. package/esm/http/context/request-memo.d.mts +1 -2
  344. package/esm/http/context/request-memo.d.mts.map +1 -1
  345. package/esm/http/createHttpApplication.d.mts +2 -3
  346. package/esm/http/createHttpApplication.d.mts.map +1 -1
  347. package/esm/http/createHttpApplication.mjs +2 -2
  348. package/esm/http/createHttpApplication.mjs.map +1 -1
  349. package/esm/http/csp.d.mts +10 -12
  350. package/esm/http/csp.d.mts.map +1 -1
  351. package/esm/http/csp.mjs +2 -2
  352. package/esm/http/csp.mjs.map +1 -1
  353. package/esm/http/csrf-default-guard.d.mts +2 -4
  354. package/esm/http/csrf-default-guard.d.mts.map +1 -1
  355. package/esm/http/csrf-default-guard.mjs +1 -1
  356. package/esm/http/csrf-default-guard.mjs.map +1 -1
  357. package/esm/http/csrf-origin-policy.d.mts +7 -9
  358. package/esm/http/csrf-origin-policy.d.mts.map +1 -1
  359. package/esm/http/csrf-origin-policy.mjs +2 -2
  360. package/esm/http/csrf-origin-policy.mjs.map +1 -1
  361. package/esm/http/database/RequestLog.d.mts +2 -3
  362. package/esm/http/database/RequestLog.d.mts.map +1 -1
  363. package/esm/http/error-codes.d.mts +1 -2
  364. package/esm/http/error-codes.d.mts.map +1 -1
  365. package/esm/http/error-mapper.d.mts +2 -4
  366. package/esm/http/error-mapper.d.mts.map +1 -1
  367. package/esm/http/error-mapper.mjs +2 -2
  368. package/esm/http/error-mapper.mjs.map +1 -1
  369. package/esm/http/errors/errors.d.mts +28 -29
  370. package/esm/http/errors/errors.d.mts.map +1 -1
  371. package/esm/http/escape-header-value.d.mts +1 -2
  372. package/esm/http/escape-header-value.d.mts.map +1 -1
  373. package/esm/http/events.d.mts +2 -4
  374. package/esm/http/events.d.mts.map +1 -1
  375. package/esm/http/health.d.mts +4 -4
  376. package/esm/http/health.d.mts.map +1 -1
  377. package/esm/http/index.d.mts +4 -1
  378. package/esm/http/index.mjs +1 -1
  379. package/esm/http/middleware/cache-response-middleware.d.mts +2 -4
  380. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  381. package/esm/http/middleware/concurrency-limit.middleware.d.mts +3 -3
  382. package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
  383. package/esm/http/middleware/idempotency.middleware.d.mts +3 -3
  384. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  385. package/esm/http/middleware/idempotency.middleware.mjs +6 -6
  386. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  387. package/esm/http/middleware/index.d.mts +3 -1
  388. package/esm/http/middleware/index.mjs +1 -1
  389. package/esm/http/middleware/inject-request-context.d.mts +2 -4
  390. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  391. package/esm/http/middleware/inject-request-context.mjs +3 -3
  392. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  393. package/esm/http/middleware/ip-filter.middleware.d.mts +3 -3
  394. package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
  395. package/esm/http/middleware/maintenance.middleware.d.mts +3 -3
  396. package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
  397. package/esm/http/middleware/maintenance.middleware.mjs +4 -4
  398. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  399. package/esm/http/middleware/max-body-size.middleware.d.mts +2 -2
  400. package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
  401. package/esm/http/middleware/middleware-list.d.mts +1 -3
  402. package/esm/http/middleware/middleware-list.d.mts.map +1 -1
  403. package/esm/http/middleware/rate-limit.middleware.d.mts +3 -3
  404. package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
  405. package/esm/http/middleware/rate-limit.middleware.mjs +2 -2
  406. package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
  407. package/esm/http/middleware/utils/cidr-match.d.mts +2 -3
  408. package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
  409. package/esm/http/middleware/utils/idempotency-key.d.mts +3 -5
  410. package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
  411. package/esm/http/middleware/utils/index.d.mts +2 -1
  412. package/esm/http/middleware/utils/parse-size.d.mts +1 -2
  413. package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
  414. package/esm/http/middleware/utils/parse-size.mjs +2 -2
  415. package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
  416. package/esm/http/plugins.d.mts +2 -4
  417. package/esm/http/plugins.d.mts.map +1 -1
  418. package/esm/http/plugins.mjs +10 -10
  419. package/esm/http/plugins.mjs.map +1 -1
  420. package/esm/http/port-preflight.d.mts +3 -4
  421. package/esm/http/port-preflight.d.mts.map +1 -1
  422. package/esm/http/rate-limit-cache-store.mjs +4 -3
  423. package/esm/http/rate-limit-cache-store.mjs.map +1 -1
  424. package/esm/http/ready-report.d.mts +15 -10
  425. package/esm/http/ready-report.d.mts.map +1 -1
  426. package/esm/http/request-controller.d.mts +1 -3
  427. package/esm/http/request-controller.d.mts.map +1 -1
  428. package/esm/http/request-log-snapshot.d.mts +20 -16
  429. package/esm/http/request-log-snapshot.d.mts.map +1 -1
  430. package/esm/http/request-log-snapshot.mjs +3 -3
  431. package/esm/http/request-log-snapshot.mjs.map +1 -1
  432. package/esm/http/request.d.mts +8 -7
  433. package/esm/http/request.d.mts.map +1 -1
  434. package/esm/http/request.mjs +8 -7
  435. package/esm/http/request.mjs.map +1 -1
  436. package/esm/http/response.d.mts +12 -11
  437. package/esm/http/response.d.mts.map +1 -1
  438. package/esm/http/response.mjs +7 -7
  439. package/esm/http/response.mjs.map +1 -1
  440. package/esm/http/safe-redirect.d.mts +3 -4
  441. package/esm/http/safe-redirect.d.mts.map +1 -1
  442. package/esm/http/serialized.d.mts +12 -13
  443. package/esm/http/serialized.d.mts.map +1 -1
  444. package/esm/http/server-rebuilt.d.mts +3 -5
  445. package/esm/http/server-rebuilt.d.mts.map +1 -1
  446. package/esm/http/server.d.mts +9 -9
  447. package/esm/http/server.d.mts.map +1 -1
  448. package/esm/http/server.mjs +4 -4
  449. package/esm/http/server.mjs.map +1 -1
  450. package/esm/http/stream-react-response.d.mts +7 -7
  451. package/esm/http/stream-react-response.d.mts.map +1 -1
  452. package/esm/http/tracing/index.mjs +1 -1
  453. package/esm/http/tracing/trace-id.d.mts +2 -3
  454. package/esm/http/tracing/trace-id.d.mts.map +1 -1
  455. package/esm/http/tracing/tracing-dispatcher.d.mts +10 -11
  456. package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
  457. package/esm/http/tracing/tracing-dispatcher.mjs +2 -2
  458. package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
  459. package/esm/http/tracing/tracing.type.d.mts +11 -9
  460. package/esm/http/tracing/tracing.type.d.mts.map +1 -1
  461. package/esm/http/types.d.mts +49 -43
  462. package/esm/http/types.d.mts.map +1 -1
  463. package/esm/http/uploaded-file.d.mts +6 -5
  464. package/esm/http/uploaded-file.d.mts.map +1 -1
  465. package/esm/http/uploads/generate-image-variants.d.mts +6 -6
  466. package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
  467. package/esm/http/uploads/generate-image-variants.mjs +1 -1
  468. package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
  469. package/esm/http/uploads/image-variant-cache-entries.mjs +1 -1
  470. package/esm/http/uploads/image-variant-cache.mjs +8 -8
  471. package/esm/http/uploads/image-variant-cache.mjs.map +1 -1
  472. package/esm/http/uploads/image-variant-types.d.mts +7 -9
  473. package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
  474. package/esm/http/uploads/image-variants-config-error.d.mts +1 -2
  475. package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
  476. package/esm/http/uploads/index.d.mts +2 -1
  477. package/esm/http/uploads/index.mjs +1 -1
  478. package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
  479. package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
  480. package/esm/http/uploads/purge-image-variants.d.mts +2 -4
  481. package/esm/http/uploads/purge-image-variants.d.mts.map +1 -1
  482. package/esm/http/uploads/resolve-image-variant.d.mts +3 -5
  483. package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -1
  484. package/esm/http/uploads/resolve-image-variants-config.mjs +4 -4
  485. package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
  486. package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
  487. package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
  488. package/esm/http/uploads/trim-image-variant-cache.mjs +3 -3
  489. package/esm/http/uploads/trim-image-variant-cache.mjs.map +1 -1
  490. package/esm/http/uploads/uploaded-file.controller.d.mts +6 -5
  491. package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
  492. package/esm/http/uploads/uploaded-file.controller.mjs +2 -1
  493. package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
  494. package/esm/http/uploads/variant-cache-key.mjs +1 -1
  495. package/esm/http/uploads-config.d.mts +2 -4
  496. package/esm/http/uploads-config.d.mts.map +1 -1
  497. package/esm/http/uploads-types.d.mts +19 -17
  498. package/esm/http/uploads-types.d.mts.map +1 -1
  499. package/esm/http/xmlable.d.mts +1 -2
  500. package/esm/http/xmlable.d.mts.map +1 -1
  501. package/esm/image/image.d.mts +6 -7
  502. package/esm/image/image.d.mts.map +1 -1
  503. package/esm/image/image.mjs.map +1 -1
  504. package/esm/image/index.d.mts +2 -1
  505. package/esm/image/index.mjs +1 -1
  506. package/esm/index.d.mts +21 -0
  507. package/esm/loader/app-module-importer.d.mts +1 -2
  508. package/esm/loader/app-module-importer.d.mts.map +1 -1
  509. package/esm/localization/index.mjs +1 -1
  510. package/esm/localization/parse-locale-dictionary.d.mts +4 -5
  511. package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
  512. package/esm/localization/parse-locale-dictionary.mjs +1 -1
  513. package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
  514. package/esm/localization/register-locale-dictionary.d.mts +3 -4
  515. package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
  516. package/esm/localization/register-locale-dictionary.mjs +2 -2
  517. package/esm/localization/register-locale-dictionary.mjs.map +1 -1
  518. package/esm/logger/fatal-visibility.d.mts +1 -2
  519. package/esm/logger/fatal-visibility.d.mts.map +1 -1
  520. package/esm/logger/index.d.mts +2 -1
  521. package/esm/logger/index.mjs +1 -1
  522. package/esm/logger/logger.d.mts +1 -3
  523. package/esm/logger/logger.d.mts.map +1 -1
  524. package/esm/logger/types.d.mts +2 -3
  525. package/esm/logger/types.d.mts.map +1 -1
  526. package/esm/mail/config.d.mts +12 -14
  527. package/esm/mail/config.d.mts.map +1 -1
  528. package/esm/mail/events.d.mts +4 -6
  529. package/esm/mail/events.d.mts.map +1 -1
  530. package/esm/mail/index.d.mts +2 -1
  531. package/esm/mail/index.mjs +1 -1
  532. package/esm/mail/mail.d.mts +1 -3
  533. package/esm/mail/mail.d.mts.map +1 -1
  534. package/esm/mail/mailer-pool.d.mts +5 -7
  535. package/esm/mail/mailer-pool.d.mts.map +1 -1
  536. package/esm/mail/react-mail.d.mts +1 -3
  537. package/esm/mail/react-mail.d.mts.map +1 -1
  538. package/esm/mail/send-mail.d.mts +1 -3
  539. package/esm/mail/send-mail.d.mts.map +1 -1
  540. package/esm/mail/send-mail.mjs +2 -1
  541. package/esm/mail/send-mail.mjs.map +1 -1
  542. package/esm/mail/test-mailbox.d.mts +11 -13
  543. package/esm/mail/test-mailbox.d.mts.map +1 -1
  544. package/esm/mail/types.d.mts +17 -18
  545. package/esm/mail/types.d.mts.map +1 -1
  546. package/esm/manifest/manifest-manager.mjs +1 -1
  547. package/esm/openapi/build-openapi-document.d.mts +2 -4
  548. package/esm/openapi/build-openapi-document.d.mts.map +1 -1
  549. package/esm/openapi/cast-schema.mjs +1 -1
  550. package/esm/openapi/development-openapi-provider.d.mts +5 -6
  551. package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
  552. package/esm/openapi/index.d.mts +3 -1
  553. package/esm/openapi/index.mjs +1 -1
  554. package/esm/openapi/openapi-child-output.mjs +2 -2
  555. package/esm/openapi/openapi-child-output.mjs.map +1 -1
  556. package/esm/openapi/postman/build-request-url.mjs +1 -1
  557. package/esm/openapi/postman/example-from-schema.d.mts +1 -3
  558. package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
  559. package/esm/openapi/postman/index.d.mts +2 -1
  560. package/esm/openapi/postman/openapi-to-postman-collection.d.mts +3 -5
  561. package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
  562. package/esm/openapi/postman/postman-types.d.mts +19 -18
  563. package/esm/openapi/postman/postman-types.d.mts.map +1 -1
  564. package/esm/openapi/postman/schema-refs.d.mts +1 -3
  565. package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
  566. package/esm/openapi/postman/uuid-v5.mjs +1 -1
  567. package/esm/openapi/schema-registry.d.mts +1 -1
  568. package/esm/openapi/security.mjs +1 -1
  569. package/esm/openapi/types.d.mts +23 -21
  570. package/esm/openapi/types.d.mts.map +1 -1
  571. package/esm/production/assert-generated-imports.mjs +1 -1
  572. package/esm/production/build-contributions.mjs +1 -1
  573. package/esm/production/bundle-framework-dependencies.mjs +1 -1
  574. package/esm/production/dist-build-manifest.mjs +1 -1
  575. package/esm/production/esbuild-plugins.mjs.map +1 -1
  576. package/esm/production/esbuild-preflight.mjs +1 -1
  577. package/esm/production/production-builder.mjs +2 -1
  578. package/esm/production/production-builder.mjs.map +1 -1
  579. package/esm/production/production-supervisor.mjs +1 -1
  580. package/esm/production/registration-child-runner.mjs +4 -3
  581. package/esm/production/registration-child-runner.mjs.map +1 -1
  582. package/esm/production/resolve-build-config.d.mts +4 -4
  583. package/esm/production/resolve-build-config.d.mts.map +1 -1
  584. package/esm/production/resolve-build-config.mjs +1 -1
  585. package/esm/production/route-registration-child.d.mts +1 -1
  586. package/esm/production/route-registration-child.mjs +8 -7
  587. package/esm/production/route-registration-child.mjs.map +1 -1
  588. package/esm/production/tsconfig-path-aliases.mjs +1 -1
  589. package/esm/react/index.d.mts +1 -3
  590. package/esm/react/index.d.mts.map +1 -1
  591. package/esm/react/index.mjs.map +1 -1
  592. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +3 -4
  593. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
  594. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +2 -3
  595. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
  596. package/esm/repositories/adapters/cascade/filter-applicator.mjs +10 -9
  597. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  598. package/esm/repositories/adapters/cascade/index.d.mts +2 -1
  599. package/esm/repositories/adapters/cascade/index.mjs +1 -1
  600. package/esm/repositories/contracts/index.d.mts +2 -1
  601. package/esm/repositories/contracts/query-builder.contract.d.mts +4 -6
  602. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  603. package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -3
  604. package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
  605. package/esm/repositories/contracts/types.d.mts +23 -25
  606. package/esm/repositories/contracts/types.d.mts.map +1 -1
  607. package/esm/repositories/index.d.mts +4 -1
  608. package/esm/repositories/index.mjs +1 -1
  609. package/esm/repositories/repository.manager.d.mts +2 -3
  610. package/esm/repositories/repository.manager.d.mts.map +1 -1
  611. package/esm/repositories/repository.manager.mjs +2 -2
  612. package/esm/repositories/repository.manager.mjs.map +1 -1
  613. package/esm/resource/define-resource.d.mts +3 -5
  614. package/esm/resource/define-resource.d.mts.map +1 -1
  615. package/esm/resource/index.d.mts +2 -1
  616. package/esm/resource/index.mjs +1 -1
  617. package/esm/resource/nullable-resource.d.mts +5 -7
  618. package/esm/resource/nullable-resource.d.mts.map +1 -1
  619. package/esm/resource/register-resource.d.mts +1 -3
  620. package/esm/resource/register-resource.d.mts.map +1 -1
  621. package/esm/resource/resource-field-builder.d.mts +1 -3
  622. package/esm/resource/resource-field-builder.d.mts.map +1 -1
  623. package/esm/resource/resource.d.mts +3 -5
  624. package/esm/resource/resource.d.mts.map +1 -1
  625. package/esm/resource/resource.mjs +4 -2
  626. package/esm/resource/resource.mjs.map +1 -1
  627. package/esm/resource/types.d.mts +21 -21
  628. package/esm/resource/types.d.mts.map +1 -1
  629. package/esm/restful/index.d.mts +2 -1
  630. package/esm/restful/index.mjs +1 -1
  631. package/esm/restful/restful.d.mts +12 -32
  632. package/esm/restful/restful.d.mts.map +1 -1
  633. package/esm/router/index.d.mts +2 -1
  634. package/esm/router/index.mjs +1 -1
  635. package/esm/router/named-api-routes-with-responses.mjs +2 -1
  636. package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
  637. package/esm/router/normalize-request-path.d.mts +1 -2
  638. package/esm/router/normalize-request-path.d.mts.map +1 -1
  639. package/esm/router/normalize-route-path.d.mts +1 -2
  640. package/esm/router/normalize-route-path.d.mts.map +1 -1
  641. package/esm/router/positional-handler-diagnostics.d.mts +15 -13
  642. package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
  643. package/esm/router/resolve-route-rate-limit.mjs +3 -3
  644. package/esm/router/resolve-route-rate-limit.mjs.map +1 -1
  645. package/esm/router/route-builder.d.mts +1 -3
  646. package/esm/router/route-builder.d.mts.map +1 -1
  647. package/esm/router/route-guard-names.mjs +1 -1
  648. package/esm/router/route-guard-names.mjs.map +1 -1
  649. package/esm/router/route-name-method-suffix.d.mts +2 -3
  650. package/esm/router/route-name-method-suffix.d.mts.map +1 -1
  651. package/esm/router/route-name-taken-error.d.mts +1 -3
  652. package/esm/router/route-name-taken-error.d.mts.map +1 -1
  653. package/esm/router/route-registry.d.mts +1 -3
  654. package/esm/router/route-registry.d.mts.map +1 -1
  655. package/esm/router/router.d.mts +2 -4
  656. package/esm/router/router.d.mts.map +1 -1
  657. package/esm/router/router.mjs +8 -6
  658. package/esm/router/router.mjs.map +1 -1
  659. package/esm/router/types.d.mts +25 -26
  660. package/esm/router/types.d.mts.map +1 -1
  661. package/esm/router/unguarded-route-diagnostics.d.mts +6 -8
  662. package/esm/router/unguarded-route-diagnostics.d.mts.map +1 -1
  663. package/esm/socket/index.d.mts +2 -1
  664. package/esm/socket/index.mjs +1 -1
  665. package/esm/socket/types.d.mts +2 -4
  666. package/esm/socket/types.d.mts.map +1 -1
  667. package/esm/socket/utils.d.mts +1 -3
  668. package/esm/socket/utils.d.mts.map +1 -1
  669. package/esm/storage/config.d.mts +4 -6
  670. package/esm/storage/config.d.mts.map +1 -1
  671. package/esm/storage/context/storage-driver-context.d.mts +3 -4
  672. package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
  673. package/esm/storage/drivers/cloud-driver.d.mts +2 -4
  674. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  675. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  676. package/esm/storage/drivers/do-spaces-driver.d.mts +1 -3
  677. package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
  678. package/esm/storage/drivers/local-driver.d.mts +2 -3
  679. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  680. package/esm/storage/drivers/local-driver.mjs +8 -3
  681. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  682. package/esm/storage/drivers/r2-driver.d.mts +1 -3
  683. package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
  684. package/esm/storage/drivers/s3-driver.d.mts +1 -3
  685. package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
  686. package/esm/storage/index.d.mts +2 -1
  687. package/esm/storage/index.mjs +1 -1
  688. package/esm/storage/local-disk-roots.mjs +2 -2
  689. package/esm/storage/local-disk-roots.mjs.map +1 -1
  690. package/esm/storage/scoped-storage.d.mts +2 -3
  691. package/esm/storage/scoped-storage.d.mts.map +1 -1
  692. package/esm/storage/storage-file.d.mts +1 -3
  693. package/esm/storage/storage-file.d.mts.map +1 -1
  694. package/esm/storage/storage.d.mts +3 -4
  695. package/esm/storage/storage.d.mts.map +1 -1
  696. package/esm/storage/types.d.mts +36 -36
  697. package/esm/storage/types.d.mts.map +1 -1
  698. package/esm/storage/utils/classify-ip-address.d.mts +1 -2
  699. package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
  700. package/esm/storage/utils/contain-path.d.mts +1 -2
  701. package/esm/storage/utils/contain-path.d.mts.map +1 -1
  702. package/esm/storage/utils/mime.d.mts +2 -3
  703. package/esm/storage/utils/mime.d.mts.map +1 -1
  704. package/esm/storage/utils/safe-fetch.d.mts +6 -6
  705. package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
  706. package/esm/storage/utils/safe-fetch.mjs +3 -3
  707. package/esm/storage/utils/safe-fetch.mjs.map +1 -1
  708. package/esm/storage/utils/storage-capability-error.d.mts +1 -3
  709. package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
  710. package/esm/storage/utils/storage-error.d.mts +2 -3
  711. package/esm/storage/utils/storage-error.d.mts.map +1 -1
  712. package/esm/storage/utils/storage-not-initialized-error.d.mts +1 -2
  713. package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
  714. package/esm/tests/authenticated-test-client.d.mts +5 -6
  715. package/esm/tests/authenticated-test-client.d.mts.map +1 -1
  716. package/esm/tests/factories.d.mts +38 -23
  717. package/esm/tests/factories.d.mts.map +1 -1
  718. package/esm/tests/fakes/cache-fake.d.mts +14 -9
  719. package/esm/tests/fakes/cache-fake.d.mts.map +1 -1
  720. package/esm/tests/fakes/clock-fake.d.mts +13 -8
  721. package/esm/tests/fakes/clock-fake.d.mts.map +1 -1
  722. package/esm/tests/fakes/fake-assertion-error.d.mts +2 -3
  723. package/esm/tests/fakes/fake-assertion-error.d.mts.map +1 -1
  724. package/esm/tests/fakes/ids-fake.d.mts +5 -4
  725. package/esm/tests/fakes/ids-fake.d.mts.map +1 -1
  726. package/esm/tests/fakes/index.d.mts +2 -1
  727. package/esm/tests/fakes/index.mjs +1 -1
  728. package/esm/tests/fakes/mail-fake.d.mts +21 -13
  729. package/esm/tests/fakes/mail-fake.d.mts.map +1 -1
  730. package/esm/tests/fakes/queue-fake.d.mts +21 -13
  731. package/esm/tests/fakes/queue-fake.d.mts.map +1 -1
  732. package/esm/tests/fakes/storage-fake.d.mts +12 -8
  733. package/esm/tests/fakes/storage-fake.d.mts.map +1 -1
  734. package/esm/tests/fakes/storage-fake.mjs +1 -1
  735. package/esm/tests/fakes/test-fakes.d.mts +8 -9
  736. package/esm/tests/fakes/test-fakes.d.mts.map +1 -1
  737. package/esm/tests/fakes/test-fakes.mjs +1 -1
  738. package/esm/tests/fakes/test-fakes.mjs.map +1 -1
  739. package/esm/tests/index.d.mts +1 -0
  740. package/esm/tests/snapshot-response.d.mts +4 -5
  741. package/esm/tests/snapshot-response.d.mts.map +1 -1
  742. package/esm/tests/start-http-development-server.d.mts +4 -6
  743. package/esm/tests/start-http-development-server.d.mts.map +1 -1
  744. package/esm/tests/start-http-development-server.mjs +5 -5
  745. package/esm/tests/start-http-development-server.mjs.map +1 -1
  746. package/esm/tests/test-connectors-selection.d.mts +2 -2
  747. package/esm/tests/test-connectors-selection.d.mts.map +1 -1
  748. package/esm/tests/test-connectors-selection.mjs +1 -1
  749. package/esm/tests/test-helpers.d.mts +11 -12
  750. package/esm/tests/test-helpers.d.mts.map +1 -1
  751. package/esm/tests/test-http-server.d.mts +14 -10
  752. package/esm/tests/test-http-server.d.mts.map +1 -1
  753. package/esm/tests/test-lifecycle-state.mjs +1 -1
  754. package/esm/tests/vitest-setup.d.mts +6 -7
  755. package/esm/tests/vitest-setup.d.mts.map +1 -1
  756. package/esm/tooling/agents-md/agents-md-markers.d.mts +4 -5
  757. package/esm/tooling/agents-md/agents-md-markers.d.mts.map +1 -1
  758. package/esm/tooling/agents-md/agents-md-markers.mjs +2 -1
  759. package/esm/tooling/agents-md/agents-md-markers.mjs.map +1 -1
  760. package/esm/tooling/agents-md/agents-md-refresher.d.mts +19 -12
  761. package/esm/tooling/agents-md/agents-md-refresher.d.mts.map +1 -1
  762. package/esm/tooling/agents-md/installed-skills.d.mts +13 -9
  763. package/esm/tooling/agents-md/installed-skills.d.mts.map +1 -1
  764. package/esm/tooling/agents-md/render-agents-md.d.mts +8 -7
  765. package/esm/tooling/agents-md/render-agents-md.d.mts.map +1 -1
  766. package/esm/tooling/agents-md/render-agents-md.mjs +2 -2
  767. package/esm/tooling/agents-md/render-agents-md.mjs.map +1 -1
  768. package/esm/tooling/agents-md/write-agents-md.d.mts +17 -12
  769. package/esm/tooling/agents-md/write-agents-md.d.mts.map +1 -1
  770. package/esm/tooling/board/board-message.d.mts +4 -6
  771. package/esm/tooling/board/board-message.d.mts.map +1 -1
  772. package/esm/tooling/board/board.d.mts +50 -38
  773. package/esm/tooling/board/board.d.mts.map +1 -1
  774. package/esm/tooling/board/board.mjs +4 -3
  775. package/esm/tooling/board/board.mjs.map +1 -1
  776. package/esm/tooling/board/board.types.d.mts +32 -23
  777. package/esm/tooling/board/board.types.d.mts.map +1 -1
  778. package/esm/tooling/check/changed-files.d.mts +4 -6
  779. package/esm/tooling/check/changed-files.d.mts.map +1 -1
  780. package/esm/tooling/check/changed-files.mjs +2 -2
  781. package/esm/tooling/check/changed-files.mjs.map +1 -1
  782. package/esm/tooling/check/check-report.types.d.mts +22 -17
  783. package/esm/tooling/check/check-report.types.d.mts.map +1 -1
  784. package/esm/tooling/check/code-style-conventions.mjs +25 -25
  785. package/esm/tooling/check/code-style-conventions.mjs.map +1 -1
  786. package/esm/tooling/check/conventions-step.d.mts +4 -6
  787. package/esm/tooling/check/conventions-step.d.mts.map +1 -1
  788. package/esm/tooling/check/conventions-step.mjs +7 -18
  789. package/esm/tooling/check/conventions-step.mjs.map +1 -1
  790. package/esm/tooling/check/environment-step.d.mts +2 -4
  791. package/esm/tooling/check/environment-step.d.mts.map +1 -1
  792. package/esm/tooling/check/environment-step.mjs +1 -1
  793. package/esm/tooling/check/index.mjs +1 -1
  794. package/esm/tooling/check/lint-step.d.mts +4 -5
  795. package/esm/tooling/check/lint-step.d.mts.map +1 -1
  796. package/esm/tooling/check/lint-step.mjs +2 -1
  797. package/esm/tooling/check/lint-step.mjs.map +1 -1
  798. package/esm/tooling/check/request-input.mjs +15 -15
  799. package/esm/tooling/check/request-input.mjs.map +1 -1
  800. package/esm/tooling/check/run-check.d.mts +22 -14
  801. package/esm/tooling/check/run-check.d.mts.map +1 -1
  802. package/esm/tooling/check/run-tests.d.mts +22 -15
  803. package/esm/tooling/check/run-tests.d.mts.map +1 -1
  804. package/esm/tooling/check/security-conventions.mjs +133 -131
  805. package/esm/tooling/check/security-conventions.mjs.map +1 -1
  806. package/esm/tooling/check/source-ast.mjs +92 -132
  807. package/esm/tooling/check/source-ast.mjs.map +1 -1
  808. package/esm/tooling/check/tests-step.d.mts +7 -8
  809. package/esm/tooling/check/tests-step.d.mts.map +1 -1
  810. package/esm/tooling/check/tests-step.mjs +3 -3
  811. package/esm/tooling/check/tests-step.mjs.map +1 -1
  812. package/esm/tooling/dev-state/dev-server-state.d.mts +17 -13
  813. package/esm/tooling/dev-state/dev-server-state.d.mts.map +1 -1
  814. package/esm/tooling/devtools/devtools-client.d.mts +29 -20
  815. package/esm/tooling/devtools/devtools-client.d.mts.map +1 -1
  816. package/esm/tooling/generate/generation.d.mts +34 -22
  817. package/esm/tooling/generate/generation.d.mts.map +1 -1
  818. package/esm/tooling/generate/generation.mjs +9 -5
  819. package/esm/tooling/generate/generation.mjs.map +1 -1
  820. package/esm/tooling/generate/generator-spec.d.mts +9 -9
  821. package/esm/tooling/generate/generator-spec.d.mts.map +1 -1
  822. package/esm/tooling/generate/index.mjs +1 -1
  823. package/esm/tooling/generate/project-files.mjs +3 -3
  824. package/esm/tooling/generate/project-files.mjs.map +1 -1
  825. package/esm/tooling/generate/run-cli.d.mts +14 -11
  826. package/esm/tooling/generate/run-cli.d.mts.map +1 -1
  827. package/esm/tooling/generate/run-cli.mjs +2 -2
  828. package/esm/tooling/generate/run-cli.mjs.map +1 -1
  829. package/esm/tooling/generate/unified-diff.d.mts +10 -7
  830. package/esm/tooling/generate/unified-diff.d.mts.map +1 -1
  831. package/esm/tooling/index.d.mts +1 -0
  832. package/esm/tooling/inspect/boot-for-inspect.d.mts +7 -7
  833. package/esm/tooling/inspect/boot-for-inspect.d.mts.map +1 -1
  834. package/esm/tooling/inspect/collect-config.mjs +3 -3
  835. package/esm/tooling/inspect/collect-config.mjs.map +1 -1
  836. package/esm/tooling/inspect/collect-models.d.mts +4 -3
  837. package/esm/tooling/inspect/collect-models.d.mts.map +1 -1
  838. package/esm/tooling/inspect/collect-models.mjs +1 -1
  839. package/esm/tooling/inspect/collect-packages.d.mts +1 -2
  840. package/esm/tooling/inspect/collect-packages.d.mts.map +1 -1
  841. package/esm/tooling/inspect/collect-pages.mjs +10 -10
  842. package/esm/tooling/inspect/collect-pages.mjs.map +1 -1
  843. package/esm/tooling/inspect/collect-routes.mjs +1 -1
  844. package/esm/tooling/inspect/event-recorder.d.mts +7 -7
  845. package/esm/tooling/inspect/event-recorder.d.mts.map +1 -1
  846. package/esm/tooling/inspect/index.d.mts +2 -1
  847. package/esm/tooling/inspect/index.mjs +1 -1
  848. package/esm/tooling/inspect/inspect-app.d.mts +25 -16
  849. package/esm/tooling/inspect/inspect-app.d.mts.map +1 -1
  850. package/esm/tooling/inspect/inspect-report.schema.d.mts +1 -2
  851. package/esm/tooling/inspect/inspect-report.schema.d.mts.map +1 -1
  852. package/esm/tooling/inspect/inspect-report.types.d.mts +86 -54
  853. package/esm/tooling/inspect/inspect-report.types.d.mts.map +1 -1
  854. package/esm/tooling/mcp/create-mcp-context.d.mts +11 -8
  855. package/esm/tooling/mcp/create-mcp-context.d.mts.map +1 -1
  856. package/esm/tooling/mcp/db-schema.d.mts +10 -9
  857. package/esm/tooling/mcp/db-schema.d.mts.map +1 -1
  858. package/esm/tooling/mcp/docs-search.d.mts +20 -15
  859. package/esm/tooling/mcp/docs-search.d.mts.map +1 -1
  860. package/esm/tooling/mcp/index.mjs +1 -1
  861. package/esm/tooling/mcp/load-ai-tools.d.mts +7 -8
  862. package/esm/tooling/mcp/load-ai-tools.d.mts.map +1 -1
  863. package/esm/tooling/mcp/load-ai-tools.mjs +2 -1
  864. package/esm/tooling/mcp/load-ai-tools.mjs.map +1 -1
  865. package/esm/tooling/mcp/mcp-tools.d.mts +29 -19
  866. package/esm/tooling/mcp/mcp-tools.d.mts.map +1 -1
  867. package/esm/tooling/mcp/mcp-tools.mjs +3 -2
  868. package/esm/tooling/mcp/mcp-tools.mjs.map +1 -1
  869. package/esm/tooling/mcp/start-mcp-server.d.mts +24 -17
  870. package/esm/tooling/mcp/start-mcp-server.d.mts.map +1 -1
  871. package/esm/tooling/mcp/start-mcp-server.mjs +1 -1
  872. package/esm/tooling/mcp/start-mcp-server.mjs.map +1 -1
  873. package/esm/tooling/mcp/tool-input.d.mts +7 -7
  874. package/esm/tooling/mcp/tool-input.d.mts.map +1 -1
  875. package/esm/tooling/problem.d.mts +27 -17
  876. package/esm/tooling/problem.d.mts.map +1 -1
  877. package/esm/tooling/syntax/ast.mjs +230 -0
  878. package/esm/tooling/syntax/ast.mjs.map +1 -0
  879. package/esm/tooling/syntax/imports.mjs +34 -0
  880. package/esm/tooling/syntax/imports.mjs.map +1 -0
  881. package/esm/tooling/trace/trace-report.types.d.mts +36 -22
  882. package/esm/tooling/trace/trace-report.types.d.mts.map +1 -1
  883. package/esm/tooling/trace/trace-request.d.mts +27 -20
  884. package/esm/tooling/trace/trace-request.d.mts.map +1 -1
  885. package/esm/tooling/trace/trace-request.mjs +2 -2
  886. package/esm/tooling/trace/trace-request.mjs.map +1 -1
  887. package/esm/tooling/typecheck/index.mjs +1 -1
  888. package/esm/tooling/typecheck/run-typecheck.d.mts +15 -48
  889. package/esm/tooling/typecheck/run-typecheck.d.mts.map +1 -1
  890. package/esm/tooling/typecheck/run-typecheck.mjs +42 -105
  891. package/esm/tooling/typecheck/run-typecheck.mjs.map +1 -1
  892. package/esm/tooling/typescript/compiler.d.mts +31 -0
  893. package/esm/tooling/typescript/compiler.d.mts.map +1 -0
  894. package/esm/tooling/typescript/compiler.mjs +120 -0
  895. package/esm/tooling/typescript/compiler.mjs.map +1 -0
  896. package/esm/updater/update-warlock-packages.mjs +3 -2
  897. package/esm/updater/update-warlock-packages.mjs.map +1 -1
  898. package/esm/upgrade/codemods/index.mjs +1 -1
  899. package/esm/upgrade/codemods/logger-sync-calls.mjs +1 -1
  900. package/esm/upgrade/codemods/logger-sync-calls.mjs.map +1 -1
  901. package/esm/upgrade/codemods/request-log-snapshot.mjs +1 -1
  902. package/esm/upgrade/codemods/request-log-snapshot.mjs.map +1 -1
  903. package/esm/upgrade/diff.mjs +1 -1
  904. package/esm/upgrade/diff.mjs.map +1 -1
  905. package/esm/upgrade/load-ts-morph.mjs +3 -2
  906. package/esm/upgrade/load-ts-morph.mjs.map +1 -1
  907. package/esm/upgrade/run-upgrade.mjs +1 -1
  908. package/esm/use-cases/index.d.mts +2 -1
  909. package/esm/use-cases/index.mjs +1 -1
  910. package/esm/use-cases/types.d.mts +116 -63
  911. package/esm/use-cases/types.d.mts.map +1 -1
  912. package/esm/use-cases/use-case-broadcast.d.mts +1 -3
  913. package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
  914. package/esm/use-cases/use-case-events.d.mts +3 -5
  915. package/esm/use-cases/use-case-events.d.mts.map +1 -1
  916. package/esm/use-cases/use-case-pipeline.d.mts +6 -6
  917. package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
  918. package/esm/use-cases/use-case.d.mts +2 -4
  919. package/esm/use-cases/use-case.d.mts.map +1 -1
  920. package/esm/use-cases/use-case.errors.d.mts +1 -3
  921. package/esm/use-cases/use-case.errors.d.mts.map +1 -1
  922. package/esm/use-cases/use-cases-registry.d.mts +8 -10
  923. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  924. package/esm/utils/app-log.d.mts +1 -2
  925. package/esm/utils/app-log.d.mts.map +1 -1
  926. package/esm/utils/clock.d.mts +8 -6
  927. package/esm/utils/clock.d.mts.map +1 -1
  928. package/esm/utils/database-log.d.mts +3 -4
  929. package/esm/utils/database-log.d.mts.map +1 -1
  930. package/esm/utils/environment.d.mts +4 -5
  931. package/esm/utils/environment.d.mts.map +1 -1
  932. package/esm/utils/framework-vesion.mjs.map +1 -1
  933. package/esm/utils/get-localized.d.mts +2 -3
  934. package/esm/utils/get-localized.d.mts.map +1 -1
  935. package/esm/utils/ids.d.mts +9 -6
  936. package/esm/utils/ids.d.mts.map +1 -1
  937. package/esm/utils/index.d.mts +2 -1
  938. package/esm/utils/index.mjs +1 -1
  939. package/esm/utils/normalized-path.d.mts +1 -2
  940. package/esm/utils/normalized-path.d.mts.map +1 -1
  941. package/esm/utils/npm-registry.d.mts +1 -2
  942. package/esm/utils/npm-registry.d.mts.map +1 -1
  943. package/esm/utils/paths.d.mts +13 -14
  944. package/esm/utils/paths.d.mts.map +1 -1
  945. package/esm/utils/paths.mjs +2 -2
  946. package/esm/utils/paths.mjs.map +1 -1
  947. package/esm/utils/promise-all-object.d.mts +1 -2
  948. package/esm/utils/promise-all-object.d.mts.map +1 -1
  949. package/esm/utils/queue.d.mts +1 -2
  950. package/esm/utils/queue.d.mts.map +1 -1
  951. package/esm/utils/runtime.d.mts +11 -10
  952. package/esm/utils/runtime.d.mts.map +1 -1
  953. package/esm/utils/sleep.d.mts +1 -2
  954. package/esm/utils/sleep.d.mts.map +1 -1
  955. package/esm/utils/sluggable.d.mts +1 -3
  956. package/esm/utils/sluggable.d.mts.map +1 -1
  957. package/esm/utils/to-json.d.mts +1 -2
  958. package/esm/utils/to-json.d.mts.map +1 -1
  959. package/esm/utils/types.d.mts +1 -2
  960. package/esm/utils/types.d.mts.map +1 -1
  961. package/esm/utils/urls.d.mts +5 -6
  962. package/esm/utils/urls.d.mts.map +1 -1
  963. package/esm/utils/version-compare.d.mts +1 -2
  964. package/esm/utils/version-compare.d.mts.map +1 -1
  965. package/esm/validation/database/exists-except-current-id.d.mts +2 -3
  966. package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
  967. package/esm/validation/database/exists-except-current-user.d.mts +2 -3
  968. package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
  969. package/esm/validation/database/index.d.mts +2 -1
  970. package/esm/validation/database/index.mjs +1 -1
  971. package/esm/validation/database/types.d.mts +14 -10
  972. package/esm/validation/database/types.d.mts.map +1 -1
  973. package/esm/validation/database/unique-except-current-id.d.mts +2 -3
  974. package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
  975. package/esm/validation/database/unique-except-current-user.d.mts +2 -3
  976. package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
  977. package/esm/validation/file/file.d.mts +4 -6
  978. package/esm/validation/file/file.d.mts.map +1 -1
  979. package/esm/validation/file/index.d.mts +2 -1
  980. package/esm/validation/file/index.mjs +1 -1
  981. package/esm/validation/index.d.mts +5 -1
  982. package/esm/validation/index.mjs +1 -1
  983. package/esm/validation/plugins/index.mjs +1 -1
  984. package/esm/validation/types.d.mts +6 -4
  985. package/esm/validation/types.d.mts.map +1 -1
  986. package/esm/validation/validateAll.mjs +2 -2
  987. package/esm/validation/validateAll.mjs.map +1 -1
  988. package/esm/validation/validation-failure-status.mjs +2 -2
  989. package/esm/validation/validation-failure-status.mjs.map +1 -1
  990. package/esm/validation/validators/file-validator.d.mts +2 -4
  991. package/esm/validation/validators/file-validator.d.mts.map +1 -1
  992. package/esm/validation/validators/index.d.mts +2 -1
  993. package/esm/validation/validators/index.mjs +1 -1
  994. package/esm/vite/lower-stage3-decorators.d.mts +2 -3
  995. package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
  996. package/esm/warlock-config/define-config.d.mts +1 -3
  997. package/esm/warlock-config/define-config.d.mts.map +1 -1
  998. package/esm/warlock-config/define-config.mjs +3 -2
  999. package/esm/warlock-config/define-config.mjs.map +1 -1
  1000. package/esm/warlock-config/index.d.mts +2 -1
  1001. package/esm/warlock-config/index.mjs +1 -1
  1002. package/esm/warlock-config/types.d.mts +6 -5
  1003. package/esm/warlock-config/types.d.mts.map +1 -1
  1004. package/esm/warlock-config/warlock-config.manager.d.mts +5 -7
  1005. package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
  1006. package/esm/warlock-config/warlock-config.manager.mjs +2 -1
  1007. package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
  1008. package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
  1009. package/llms-full.txt +55 -5
  1010. package/package.json +17 -15
  1011. package/skills/create-module/SKILL.md +7 -0
  1012. package/skills/index.md +2 -0
  1013. package/skills/report-framework-issue.md +154 -0
  1014. package/skills/run-app/SKILL.md +6 -5
  1015. package/skills/upgrade-from-5-29/SKILL.md +41 -0
  1016. package/skills/warlock-check/SKILL.md +1 -0
  1017. package/esm/tooling/check/index.d.mts +0 -8
  1018. package/esm/tooling/typecheck/index.d.mts +0 -1
@@ -19,16 +19,20 @@
19
19
  /**
20
20
  * A module the boot pass could not import, and why.
21
21
  */
22
- type ModuleFailure = {
23
- /** Project-relative path of the file that failed. */file: string; /** The underlying error message (the cause, not the wrapper). */
22
+ export type ModuleFailure = {
23
+ /** Project-relative path of the file that failed. */
24
+ file: string;
25
+ /** The underlying error message (the cause, not the wrapper). */
24
26
  message: string;
25
27
  };
26
28
  /**
27
29
  * A model module the boot pass imported, with its exports — what `warlock
28
30
  * inspect` reads the app's model classes from.
29
31
  */
30
- type ModelModule = {
31
- /** Project-relative path of the model file. */file: string; /** The module's exports (a shallow copy of its namespace). */
32
+ export type ModelModule = {
33
+ /** Project-relative path of the model file. */
34
+ file: string;
35
+ /** The module's exports (a shallow copy of its namespace). */
32
36
  exports: Record<string, unknown>;
33
37
  };
34
38
  /**
@@ -36,30 +40,40 @@ type ModelModule = {
36
40
  * anything itself — and so the report cannot contain two checks that booted the
37
41
  * app differently and disagreed about it.
38
42
  */
39
- type DoctorBootContext = {
43
+ export type DoctorBootContext = {
40
44
  /**
41
45
  * Whether the pass completed. `false` means app discovery itself failed and
42
46
  * every app-dependent check must say so rather than report a zero.
43
47
  */
44
- booted: boolean; /** Number of `src/app/<module>/routes.ts` files found on disk. */
45
- routeModules: number; /** Routes registered by app modules alone, before late connectors booted. */
46
- appRoutes: number; /** Routes on the app router once every connector had booted. */
47
- totalRoutes: number; /** Every app module that failed to import, in load order. */
48
- moduleFailures: ModuleFailure[]; /** The model modules that imported, with their exports, in load order. */
49
- modelModules: ModelModule[]; /** What happened to the connectors. */
48
+ booted: boolean;
49
+ /** Number of `src/app/<module>/routes.ts` files found on disk. */
50
+ routeModules: number;
51
+ /** Routes registered by app modules alone, before late connectors booted. */
52
+ appRoutes: number;
53
+ /** Routes on the app router once every connector had booted. */
54
+ totalRoutes: number;
55
+ /** Every app module that failed to import, in load order. */
56
+ moduleFailures: ModuleFailure[];
57
+ /** The model modules that imported, with their exports, in load order. */
58
+ modelModules: ModelModule[];
59
+ /** What happened to the connectors. */
50
60
  connectors: {
51
- /** Names of every registered connector (built-ins + the app's own). */registered: string[];
61
+ /** Names of every registered connector (built-ins + the app's own). */
62
+ registered: string[];
52
63
  /**
53
64
  * The connectors the APP configured, i.e. registered names that are not
54
65
  * framework built-ins. This is the part of the list that varies between
55
66
  * projects — the built-in count is a constant and diagnoses nothing.
56
67
  */
57
- configured: string[]; /** Names that booted without throwing. */
58
- booted: string[]; /** Connectors doctor deliberately did not boot, with the reason. */
68
+ configured: string[];
69
+ /** Names that booted without throwing. */
70
+ booted: string[];
71
+ /** Connectors doctor deliberately did not boot, with the reason. */
59
72
  skipped: {
60
73
  name: string;
61
74
  reason: string;
62
- }[]; /** Connectors whose `boot()` threw, with the message. */
75
+ }[];
76
+ /** Connectors whose `boot()` threw, with the message. */
63
77
  failures: {
64
78
  name: string;
65
79
  message: string;
@@ -72,5 +86,4 @@ type DoctorBootContext = {
72
86
  };
73
87
  };
74
88
  //#endregion
75
- export { DoctorBootContext };
76
89
  //# sourceMappingURL=check.types.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"check.types.d.mts","names":[],"sources":["../../../../../../../../../../packages/core/src/cli/commands/doctor/check.types.ts"],"mappings":";AAuBA;;;;AAKS;AAOT;;;;;;;;AAKiB;AAQjB;;;;;;KAzBY,aAAA;EAuCV,qDArCA,IAAA,UAwCgB;EArChB,OAAO;AAAA;;;;;KAOG,WAAA;EAmDG,+CAjDb,IAAA,UAoDE;EAjDF,OAAA,EAAS,MAAM;AAAA;;;AAuDI;;;KA/CT,iBAAA;;;;;EAKV,MAAA;EAGA,YAAA;EAGA,SAAA;EAGA,WAAA;EAGA,cAAA,EAAgB,aAAA;EAGhB,YAAA,EAAc,WAAW;EAGzB,UAAA;2EAEE,UAAA;;;;;;IAOA,UAAA;IAGA,MAAA;IAGA,OAAA;MAAW,IAAA;MAAc,MAAA;IAAA;IAGzB,QAAA;MAAY,IAAA;MAAc,OAAA;IAAA;;;;;IAM1B,iBAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"check.types.d.mts","names":[],"sources":["../../../../../../../../../../packages/core/src/cli/commands/doctor/check.types.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;YAuBY;;EAEV;;EAGA;;;;;;YAOU;;EAEV;;EAGA,SAAS;;;;;;;YAQC;;;;;EAKV;;EAGA;;EAGA;;EAGA;;EAGA,gBAAgB;;EAGhB,cAAc;;EAGd;;IAEE;;;;;;IAOA;;IAGA;;IAGA;MAAW;MAAc;;;IAGzB;MAAY;MAAc;;;;;;IAM1B"}
@@ -1,9 +1,10 @@
1
1
  import { config } from "../../../../config/config-getter.mjs";
2
2
  import { appPath, rootPath } from "../../../../utils/paths.mjs";
3
3
  import { parseLocaleDictionary } from "../../../../localization/parse-locale-dictionary.mjs";
4
+ import { isExpressionStatement, isIdentifier, isNumericLiteral, isPropertyAssignment, isStringLiteral, keyName, parseSourceFile, valueText } from "../../../../tooling/syntax/ast.mjs";
4
5
  import path from "node:path";
5
6
  import { existsSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from "node:fs";
6
- import ts from "typescript";
7
+ import { parseSync } from "oxc-parser";
7
8
 
8
9
  //#region ../../packages/core/src/cli/commands/doctor/checks/locales-ts-deprecated.check.ts
9
10
  function localeSources() {
@@ -14,23 +15,19 @@ function localeSources() {
14
15
  module: entry.name
15
16
  })).filter(({ file }) => existsSync(file));
16
17
  }
17
- function propertyName(property) {
18
- if (ts.isIdentifier(property.name) || ts.isStringLiteral(property.name)) return property.name.text;
19
- }
20
18
  function literalObject(node) {
21
- if (!ts.isObjectLiteralExpression(node)) return void 0;
19
+ if (node?.type !== "ObjectExpression") return void 0;
22
20
  const value = Object.create(null);
23
21
  for (const member of node.properties) {
24
- if (!ts.isPropertyAssignment(member)) return void 0;
25
- const key = propertyName(member);
22
+ if (!isPropertyAssignment(member)) return void 0;
23
+ const key = keyName(member.key);
26
24
  if (key === void 0) return void 0;
27
- if (ts.isStringLiteral(member.initializer) || ts.isNumericLiteral(member.initializer)) {
28
- value[key] = ts.isNumericLiteral(member.initializer) ? Number(member.initializer.text) : member.initializer.text;
29
- continue;
25
+ if (isStringLiteral(member.value) || isNumericLiteral(member.value)) value[key] = member.value.value;
26
+ else {
27
+ const nested = literalObject(member.value);
28
+ if (nested === void 0) return void 0;
29
+ value[key] = nested;
30
30
  }
31
- const nested = literalObject(member.initializer);
32
- if (nested === void 0) return void 0;
33
- value[key] = nested;
34
31
  }
35
32
  return value;
36
33
  }
@@ -46,40 +43,38 @@ function flattenLiteral(value, group, entries) {
46
43
  return Object.entries(value).every(([key, nested]) => flattenLiteral(nested, group === "" ? key : `${group}.${key}`, entries));
47
44
  }
48
45
  function inspect(source) {
49
- if (existsSync(path.join(path.dirname(source.file), "locales.json"))) return {
46
+ const jsonFile = path.join(path.dirname(source.file), "locales.json");
47
+ if (existsSync(jsonFile)) return {
50
48
  ...source,
51
49
  convertible: false,
52
50
  reason: "locales.json already exists"
53
51
  };
54
52
  const text = readFileSync(source.file, "utf8");
55
- const program = ts.createSourceFile(source.file, text, ts.ScriptTarget.Latest, true);
56
- const syntaxDiagnostics = ts.transpileModule(text, {
57
- fileName: source.file,
58
- reportDiagnostics: true
59
- }).diagnostics;
60
- if (syntaxDiagnostics !== void 0 && syntaxDiagnostics.length > 0) return {
53
+ const program = parseSourceFile(source.file, text);
54
+ if (parseSync(source.file, text).errors.length > 0) return {
61
55
  ...source,
62
56
  convertible: false,
63
57
  reason: "TypeScript syntax is invalid"
64
58
  };
65
- const [importStatement, callStatement] = program.statements;
66
- if (!importStatement || !ts.isImportDeclaration(importStatement) || !ts.isStringLiteral(importStatement.moduleSpecifier) || importStatement.moduleSpecifier.text !== "@warlock.js/core" || !importStatement.importClause || importStatement.importClause.isTypeOnly || importStatement.importClause.name || !importStatement.importClause.namedBindings || !ts.isNamedImports(importStatement.importClause.namedBindings) || importStatement.importClause.namedBindings.elements.length !== 1 || importStatement.importClause.namedBindings.elements[0]?.name.text !== "groupedTranslations" || importStatement.importClause.namedBindings.elements[0]?.propertyName) return {
59
+ const [importStatement, callStatement] = program.body;
60
+ const binding = importStatement?.type === "ImportDeclaration" ? importStatement.specifiers[0] : void 0;
61
+ if (importStatement?.type !== "ImportDeclaration" || importStatement.source.value !== "@warlock.js/core" || importStatement.importKind === "type" || importStatement.specifiers.length !== 1 || binding?.type !== "ImportSpecifier" || binding.importKind === "type" || binding.local.name !== "groupedTranslations" || valueText(binding.imported) !== "groupedTranslations") return {
67
62
  ...source,
68
63
  convertible: false,
69
64
  reason: "must import only groupedTranslations from @warlock.js/core"
70
65
  };
71
- if (program.statements.length !== 2) return {
66
+ if (program.body.length !== 2) return {
72
67
  ...source,
73
68
  convertible: false,
74
69
  reason: "must contain only the groupedTranslations import and one call"
75
70
  };
76
- if (!callStatement || !ts.isExpressionStatement(callStatement) || !ts.isCallExpression(callStatement.expression)) return {
71
+ if (!callStatement || !isExpressionStatement(callStatement) || callStatement.expression.type !== "CallExpression") return {
77
72
  ...source,
78
73
  convertible: false,
79
74
  reason: "must contain one top-level groupedTranslations call"
80
75
  };
81
76
  const call = callStatement.expression;
82
- if (!ts.isIdentifier(call.expression) || call.expression.text !== "groupedTranslations" || call.arguments.length !== 2 || !ts.isStringLiteral(call.arguments[0])) return {
77
+ if (!isIdentifier(call.callee) || valueText(call.callee) !== "groupedTranslations" || call.arguments.length !== 2 || !call.arguments[0] || !isStringLiteral(call.arguments[0])) return {
83
78
  ...source,
84
79
  convertible: false,
85
80
  reason: "must call groupedTranslations with a string group and object"
@@ -90,7 +85,7 @@ function inspect(source) {
90
85
  convertible: false,
91
86
  reason: "translation object must contain only literal keys, objects, strings, or numbers"
92
87
  };
93
- const group = call.arguments[0].text;
88
+ const group = call.arguments[0].value;
94
89
  const entries = Object.create(null);
95
90
  if (!flattenLiteral(dictionary, group, entries)) return {
96
91
  ...source,
@@ -167,5 +162,5 @@ const localesTsDeprecatedCheck = {
167
162
  };
168
163
 
169
164
  //#endregion
170
- export { fixLocaleSources, localesTsDeprecatedCheck };
165
+ export { fixLocaleSources, inspectLocaleSources, localesTsDeprecatedCheck };
171
166
  //# sourceMappingURL=locales-ts-deprecated.check.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"locales-ts-deprecated.check.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/doctor/checks/locales-ts-deprecated.check.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport ts from \"typescript\";\nimport { config } from \"../../../../config/config-getter\";\nimport {\n parseLocaleDictionary,\n type LocaleDictionaryEntries,\n} from \"../../../../localization/parse-locale-dictionary\";\nimport { appPath, rootPath } from \"../../../../utils/paths\";\nimport type { DoctorCheck } from \"../check.types\";\n\ntype LocaleSource = {\n file: string;\n module: string;\n};\n\nexport type LocaleInspection = LocaleSource & {\n convertible: boolean;\n reason: string;\n group?: string;\n dictionary?: Record<string, unknown>;\n entries?: LocaleDictionaryEntries;\n};\n\nfunction localeSources(): LocaleSource[] {\n const appDirectory = appPath();\n if (!existsSync(appDirectory)) return [];\n\n return readdirSync(appDirectory, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => ({\n file: path.join(appDirectory, entry.name, \"utils\", \"locales.ts\"),\n module: entry.name,\n }))\n .filter(({ file }) => existsSync(file));\n}\n\nfunction propertyName(property: ts.PropertyAssignment): string | undefined {\n if (ts.isIdentifier(property.name) || ts.isStringLiteral(property.name))\n return property.name.text;\n return undefined;\n}\n\nfunction literalObject(node: ts.Expression): Record<string, unknown> | undefined {\n if (!ts.isObjectLiteralExpression(node)) return undefined;\n const value: Record<string, unknown> = Object.create(null);\n for (const member of node.properties) {\n if (!ts.isPropertyAssignment(member)) return undefined;\n const key = propertyName(member);\n if (key === undefined) return undefined;\n if (ts.isStringLiteral(member.initializer) || ts.isNumericLiteral(member.initializer)) {\n value[key] = ts.isNumericLiteral(member.initializer)\n ? Number(member.initializer.text)\n : member.initializer.text;\n continue;\n }\n const nested = literalObject(member.initializer);\n if (nested === undefined) return undefined;\n value[key] = nested;\n }\n return value;\n}\n\nfunction flattenLiteral(\n value: Record<string, unknown>,\n group: string,\n entries: LocaleDictionaryEntries,\n): boolean {\n const values = Object.values(value);\n if (values.every((item) => typeof item === \"string\" || typeof item === \"number\")) {\n if (group === \"\") return false;\n if (!values.every((item) => typeof item === \"string\")) return false;\n entries[group] = value as Record<string, string>;\n return true;\n }\n if (!values.every((item) => item !== null && typeof item === \"object\" && !Array.isArray(item)))\n return false;\n return Object.entries(value).every(([key, nested]) =>\n flattenLiteral(\n nested as Record<string, unknown>,\n group === \"\" ? key : `${group}.${key}`,\n entries,\n ),\n );\n}\n\nfunction inspect(source: LocaleSource): LocaleInspection {\n const jsonFile = path.join(path.dirname(source.file), \"locales.json\");\n if (existsSync(jsonFile))\n return { ...source, convertible: false, reason: \"locales.json already exists\" };\n\n const text = readFileSync(source.file, \"utf8\");\n const program = ts.createSourceFile(source.file, text, ts.ScriptTarget.Latest, true);\n const syntaxDiagnostics = ts.transpileModule(text, {\n fileName: source.file,\n reportDiagnostics: true,\n }).diagnostics;\n if (syntaxDiagnostics !== undefined && syntaxDiagnostics.length > 0)\n return { ...source, convertible: false, reason: \"TypeScript syntax is invalid\" };\n const [importStatement, callStatement] = program.statements;\n if (\n !importStatement ||\n !ts.isImportDeclaration(importStatement) ||\n !ts.isStringLiteral(importStatement.moduleSpecifier) ||\n importStatement.moduleSpecifier.text !== \"@warlock.js/core\" ||\n !importStatement.importClause ||\n importStatement.importClause.isTypeOnly ||\n importStatement.importClause.name ||\n !importStatement.importClause.namedBindings ||\n !ts.isNamedImports(importStatement.importClause.namedBindings) ||\n importStatement.importClause.namedBindings.elements.length !== 1 ||\n importStatement.importClause.namedBindings.elements[0]?.name.text !== \"groupedTranslations\" ||\n importStatement.importClause.namedBindings.elements[0]?.propertyName\n )\n return {\n ...source,\n convertible: false,\n reason: \"must import only groupedTranslations from @warlock.js/core\",\n };\n\n if (program.statements.length !== 2)\n return {\n ...source,\n convertible: false,\n reason: \"must contain only the groupedTranslations import and one call\",\n };\n\n if (\n !callStatement ||\n !ts.isExpressionStatement(callStatement) ||\n !ts.isCallExpression(callStatement.expression)\n )\n return {\n ...source,\n convertible: false,\n reason: \"must contain one top-level groupedTranslations call\",\n };\n const call = callStatement.expression;\n if (\n !ts.isIdentifier(call.expression) ||\n call.expression.text !== \"groupedTranslations\" ||\n call.arguments.length !== 2 ||\n !ts.isStringLiteral(call.arguments[0]!)\n )\n return {\n ...source,\n convertible: false,\n reason: \"must call groupedTranslations with a string group and object\",\n };\n const dictionary = literalObject(call.arguments[1]!);\n if (!dictionary)\n return {\n ...source,\n convertible: false,\n reason: \"translation object must contain only literal keys, objects, strings, or numbers\",\n };\n const group = call.arguments[0].text;\n const entries: LocaleDictionaryEntries = Object.create(null);\n if (!flattenLiteral(dictionary, group, entries))\n return {\n ...source,\n convertible: false,\n reason: \"translation object has no valid literal locale entries\",\n };\n return {\n ...source,\n convertible: true,\n reason: \"pure groupedTranslations literal\",\n group,\n dictionary,\n entries,\n };\n}\n\nexport function inspectLocaleSources(): LocaleInspection[] {\n return localeSources().map(inspect);\n}\n\nfunction localeCodes(): readonly string[] | undefined {\n const configured = config.key<unknown>(\"app.localeCodes\");\n return Array.isArray(configured) && configured.every((code) => typeof code === \"string\")\n ? configured\n : undefined;\n}\n\nfunction sameEntries(left: LocaleDictionaryEntries, right: LocaleDictionaryEntries): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\n/** Convert safe legacy locale sources, retaining a TS file whenever verification cannot prove equivalence. */\nexport function fixLocaleSources(): LocaleInspection[] {\n return inspectLocaleSources().map((result) => {\n if (!result.convertible || !result.group || !result.dictionary || !result.entries)\n return result;\n const jsonFile = path.join(path.dirname(result.file), \"locales.json\");\n const document: Record<string, unknown> =\n result.group === result.module\n ? result.dictionary\n : { $group: result.group, ...result.dictionary };\n const json = `${JSON.stringify(document, null, 2)}\\n`;\n writeFileSync(jsonFile, json);\n try {\n const parsed = parseLocaleDictionary({\n sourceFile: rootPath(path.relative(process.cwd(), jsonFile)),\n source: json,\n defaultNamespace: result.module,\n localeCodes: localeCodes(),\n });\n if (!sameEntries(result.entries, parsed.entries)) throw new Error(\"flattened entries differ\");\n } catch (error) {\n unlinkSync(jsonFile);\n return {\n ...result,\n convertible: false,\n reason: `verification failed: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n unlinkSync(result.file);\n return {\n ...result,\n reason: \"converted (comments in the TypeScript source are not retained)\",\n };\n });\n}\n\nexport const localesTsDeprecatedCheck: DoctorCheck = {\n name: \"locales-ts-deprecated\",\n run: () => {\n const sources = inspectLocaleSources();\n if (sources.length === 0) return undefined;\n const details = sources.map((source) => {\n const label = path.relative(process.cwd(), source.file).replaceAll(\"\\\\\", \"/\");\n return `${label}: ${source.convertible ? \"auto-convertible\" : \"manual\"} (${source.reason})`;\n });\n return {\n name: \"locales-ts-deprecated\",\n status: \"warn\",\n code: \"WL9101\",\n detail:\n `${details.join(\"; \")}. Auto-loaded locales.ts goes away in v6; ` +\n \"run `warlock doctor --fix` to convert auto-convertible files.\",\n };\n },\n};\n"],"mappings":";;;;;;;;AAwBA,SAAS,gBAAgC;CACvC,MAAM,eAAe,QAAQ;CAC7B,IAAI,CAAC,WAAW,YAAY,GAAG,OAAO,CAAC;CAEvC,OAAO,YAAY,cAAc,EAAE,eAAe,KAAK,CAAC,CAAC,CACtD,QAAQ,UAAU,MAAM,YAAY,CAAC,CAAC,CACtC,KAAK,WAAW;EACf,MAAM,KAAK,KAAK,cAAc,MAAM,MAAM,SAAS,YAAY;EAC/D,QAAQ,MAAM;CAChB,EAAE,CAAC,CACF,QAAQ,EAAE,WAAW,WAAW,IAAI,CAAC;AAC1C;AAEA,SAAS,aAAa,UAAqD;CACzE,IAAI,GAAG,aAAa,SAAS,IAAI,KAAK,GAAG,gBAAgB,SAAS,IAAI,GACpE,OAAO,SAAS,KAAK;AAEzB;AAEA,SAAS,cAAc,MAA0D;CAC/E,IAAI,CAAC,GAAG,0BAA0B,IAAI,GAAG,OAAO;CAChD,MAAM,QAAiC,OAAO,OAAO,IAAI;CACzD,KAAK,MAAM,UAAU,KAAK,YAAY;EACpC,IAAI,CAAC,GAAG,qBAAqB,MAAM,GAAG,OAAO;EAC7C,MAAM,MAAM,aAAa,MAAM;EAC/B,IAAI,QAAQ,QAAW,OAAO;EAC9B,IAAI,GAAG,gBAAgB,OAAO,WAAW,KAAK,GAAG,iBAAiB,OAAO,WAAW,GAAG;GACrF,MAAM,OAAO,GAAG,iBAAiB,OAAO,WAAW,IAC/C,OAAO,OAAO,YAAY,IAAI,IAC9B,OAAO,YAAY;GACvB;EACF;EACA,MAAM,SAAS,cAAc,OAAO,WAAW;EAC/C,IAAI,WAAW,QAAW,OAAO;EACjC,MAAM,OAAO;CACf;CACA,OAAO;AACT;AAEA,SAAS,eACP,OACA,OACA,SACS;CACT,MAAM,SAAS,OAAO,OAAO,KAAK;CAClC,IAAI,OAAO,OAAO,SAAS,OAAO,SAAS,YAAY,OAAO,SAAS,QAAQ,GAAG;EAChF,IAAI,UAAU,IAAI,OAAO;EACzB,IAAI,CAAC,OAAO,OAAO,SAAS,OAAO,SAAS,QAAQ,GAAG,OAAO;EAC9D,QAAQ,SAAS;EACjB,OAAO;CACT;CACA,IAAI,CAAC,OAAO,OAAO,SAAS,SAAS,QAAQ,OAAO,SAAS,YAAY,CAAC,MAAM,QAAQ,IAAI,CAAC,GAC3F,OAAO;CACT,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,YACxC,eACE,QACA,UAAU,KAAK,MAAM,GAAG,MAAM,GAAG,OACjC,OACF,CACF;AACF;AAEA,SAAS,QAAQ,QAAwC;CAEvD,IAAI,WADa,KAAK,KAAK,KAAK,QAAQ,OAAO,IAAI,GAAG,cAChC,CAAC,GACrB,OAAO;EAAE,GAAG;EAAQ,aAAa;EAAO,QAAQ;CAA8B;CAEhF,MAAM,OAAO,aAAa,OAAO,MAAM,MAAM;CAC7C,MAAM,UAAU,GAAG,iBAAiB,OAAO,MAAM,MAAM,GAAG,aAAa,QAAQ,IAAI;CACnF,MAAM,oBAAoB,GAAG,gBAAgB,MAAM;EACjD,UAAU,OAAO;EACjB,mBAAmB;CACrB,CAAC,CAAC,CAAC;CACH,IAAI,sBAAsB,UAAa,kBAAkB,SAAS,GAChE,OAAO;EAAE,GAAG;EAAQ,aAAa;EAAO,QAAQ;CAA+B;CACjF,MAAM,CAAC,iBAAiB,iBAAiB,QAAQ;CACjD,IACE,CAAC,mBACD,CAAC,GAAG,oBAAoB,eAAe,KACvC,CAAC,GAAG,gBAAgB,gBAAgB,eAAe,KACnD,gBAAgB,gBAAgB,SAAS,sBACzC,CAAC,gBAAgB,gBACjB,gBAAgB,aAAa,cAC7B,gBAAgB,aAAa,QAC7B,CAAC,gBAAgB,aAAa,iBAC9B,CAAC,GAAG,eAAe,gBAAgB,aAAa,aAAa,KAC7D,gBAAgB,aAAa,cAAc,SAAS,WAAW,KAC/D,gBAAgB,aAAa,cAAc,SAAS,EAAE,EAAE,KAAK,SAAS,yBACtE,gBAAgB,aAAa,cAAc,SAAS,EAAE,EAAE,cAExD,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;CACV;CAEF,IAAI,QAAQ,WAAW,WAAW,GAChC,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;CACV;CAEF,IACE,CAAC,iBACD,CAAC,GAAG,sBAAsB,aAAa,KACvC,CAAC,GAAG,iBAAiB,cAAc,UAAU,GAE7C,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;CACV;CACF,MAAM,OAAO,cAAc;CAC3B,IACE,CAAC,GAAG,aAAa,KAAK,UAAU,KAChC,KAAK,WAAW,SAAS,yBACzB,KAAK,UAAU,WAAW,KAC1B,CAAC,GAAG,gBAAgB,KAAK,UAAU,EAAG,GAEtC,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;CACV;CACF,MAAM,aAAa,cAAc,KAAK,UAAU,EAAG;CACnD,IAAI,CAAC,YACH,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;CACV;CACF,MAAM,QAAQ,KAAK,UAAU,EAAE,CAAC;CAChC,MAAM,UAAmC,OAAO,OAAO,IAAI;CAC3D,IAAI,CAAC,eAAe,YAAY,OAAO,OAAO,GAC5C,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;CACV;CACF,OAAO;EACL,GAAG;EACH,aAAa;EACb,QAAQ;EACR;EACA;EACA;CACF;AACF;AAEA,SAAgB,uBAA2C;CACzD,OAAO,cAAc,CAAC,CAAC,IAAI,OAAO;AACpC;AAEA,SAAS,cAA6C;CACpD,MAAM,aAAa,OAAO,IAAa,iBAAiB;CACxD,OAAO,MAAM,QAAQ,UAAU,KAAK,WAAW,OAAO,SAAS,OAAO,SAAS,QAAQ,IACnF,aACA;AACN;AAEA,SAAS,YAAY,MAA+B,OAAyC;CAC3F,OAAO,KAAK,UAAU,IAAI,MAAM,KAAK,UAAU,KAAK;AACtD;;AAGA,SAAgB,mBAAuC;CACrD,OAAO,qBAAqB,CAAC,CAAC,KAAK,WAAW;EAC5C,IAAI,CAAC,OAAO,eAAe,CAAC,OAAO,SAAS,CAAC,OAAO,cAAc,CAAC,OAAO,SACxE,OAAO;EACT,MAAM,WAAW,KAAK,KAAK,KAAK,QAAQ,OAAO,IAAI,GAAG,cAAc;EACpE,MAAM,WACJ,OAAO,UAAU,OAAO,SACpB,OAAO,aACP;GAAE,QAAQ,OAAO;GAAO,GAAG,OAAO;EAAW;EACnD,MAAM,OAAO,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE;EAClD,cAAc,UAAU,IAAI;EAC5B,IAAI;GACF,MAAM,SAAS,sBAAsB;IACnC,YAAY,SAAS,KAAK,SAAS,QAAQ,IAAI,GAAG,QAAQ,CAAC;IAC3D,QAAQ;IACR,kBAAkB,OAAO;IACzB,aAAa,YAAY;GAC3B,CAAC;GACD,IAAI,CAAC,YAAY,OAAO,SAAS,OAAO,OAAO,GAAG,MAAM,IAAI,MAAM,0BAA0B;EAC9F,SAAS,OAAO;GACd,WAAW,QAAQ;GACnB,OAAO;IACL,GAAG;IACH,aAAa;IACb,QAAQ,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GACvF;EACF;EACA,WAAW,OAAO,IAAI;EACtB,OAAO;GACL,GAAG;GACH,QAAQ;EACV;CACF,CAAC;AACH;AAEA,MAAa,2BAAwC;CACnD,MAAM;CACN,WAAW;EACT,MAAM,UAAU,qBAAqB;EACrC,IAAI,QAAQ,WAAW,GAAG,OAAO;EAKjC,OAAO;GACL,MAAM;GACN,QAAQ;GACR,MAAM;GACN,QACE,GATY,QAAQ,KAAK,WAAW;IAEtC,OAAO,GADO,KAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,IAAI,CAAC,CAAC,WAAW,MAAM,GAC3D,EAAE,IAAI,OAAO,cAAc,qBAAqB,SAAS,IAAI,OAAO,OAAO;GAC3F,CAMa,CAAC,CAAC,KAAK,IAAI,EAAE;EAE1B;CACF;AACF"}
1
+ {"version":3,"file":"locales-ts-deprecated.check.mjs","names":["ast.isPropertyAssignment","ast.keyName","ast.isStringLiteral","ast.isNumericLiteral","ast.parseSourceFile","ast.valueText","ast.isExpressionStatement","ast.isIdentifier"],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/doctor/checks/locales-ts-deprecated.check.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { parseSync } from \"oxc-parser\";\nimport * as ast from \"../../../../tooling/syntax/ast\";\nimport { config } from \"../../../../config/config-getter\";\nimport {\n parseLocaleDictionary,\n type LocaleDictionaryEntries,\n} from \"../../../../localization/parse-locale-dictionary\";\nimport { appPath, rootPath } from \"../../../../utils/paths\";\nimport type { DoctorCheck } from \"../check.types\";\n\ntype LocaleSource = {\n file: string;\n module: string;\n};\n\nexport type LocaleInspection = LocaleSource & {\n convertible: boolean;\n reason: string;\n group?: string;\n dictionary?: Record<string, unknown>;\n entries?: LocaleDictionaryEntries;\n};\n\nfunction localeSources(): LocaleSource[] {\n const appDirectory = appPath();\n if (!existsSync(appDirectory)) return [];\n\n return readdirSync(appDirectory, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => ({\n file: path.join(appDirectory, entry.name, \"utils\", \"locales.ts\"),\n module: entry.name,\n }))\n .filter(({ file }) => existsSync(file));\n}\n\nfunction literalObject(node: ast.Node | undefined): Record<string, unknown> | undefined {\n if (node?.type !== \"ObjectExpression\") return undefined;\n const value: Record<string, unknown> = Object.create(null);\n for (const member of node.properties) {\n if (!ast.isPropertyAssignment(member)) return undefined;\n const key = ast.keyName(member.key);\n if (key === undefined) return undefined;\n if (ast.isStringLiteral(member.value) || ast.isNumericLiteral(member.value))\n value[key] = member.value.value;\n else {\n const nested = literalObject(member.value);\n if (nested === undefined) return undefined;\n value[key] = nested;\n }\n }\n return value;\n}\n\nfunction flattenLiteral(\n value: Record<string, unknown>,\n group: string,\n entries: LocaleDictionaryEntries,\n): boolean {\n const values = Object.values(value);\n if (values.every((item) => typeof item === \"string\" || typeof item === \"number\")) {\n if (group === \"\") return false;\n if (!values.every((item) => typeof item === \"string\")) return false;\n entries[group] = value as Record<string, string>;\n return true;\n }\n if (!values.every((item) => item !== null && typeof item === \"object\" && !Array.isArray(item)))\n return false;\n return Object.entries(value).every(([key, nested]) =>\n flattenLiteral(\n nested as Record<string, unknown>,\n group === \"\" ? key : `${group}.${key}`,\n entries,\n ),\n );\n}\n\nfunction inspect(source: LocaleSource): LocaleInspection {\n const jsonFile = path.join(path.dirname(source.file), \"locales.json\");\n if (existsSync(jsonFile))\n return { ...source, convertible: false, reason: \"locales.json already exists\" };\n\n const text = readFileSync(source.file, \"utf8\");\n const program = ast.parseSourceFile(source.file, text);\n if (parseSync(source.file, text).errors.length > 0)\n return { ...source, convertible: false, reason: \"TypeScript syntax is invalid\" };\n const [importStatement, callStatement] = program.body;\n const binding =\n importStatement?.type === \"ImportDeclaration\" ? importStatement.specifiers[0] : undefined;\n if (\n importStatement?.type !== \"ImportDeclaration\" ||\n importStatement.source.value !== \"@warlock.js/core\" ||\n importStatement.importKind === \"type\" ||\n importStatement.specifiers.length !== 1 ||\n binding?.type !== \"ImportSpecifier\" ||\n binding.importKind === \"type\" ||\n binding.local.name !== \"groupedTranslations\" ||\n ast.valueText(binding.imported) !== \"groupedTranslations\"\n )\n return {\n ...source,\n convertible: false,\n reason: \"must import only groupedTranslations from @warlock.js/core\",\n };\n\n if (program.body.length !== 2)\n return {\n ...source,\n convertible: false,\n reason: \"must contain only the groupedTranslations import and one call\",\n };\n\n if (\n !callStatement ||\n !ast.isExpressionStatement(callStatement) ||\n callStatement.expression.type !== \"CallExpression\"\n )\n return {\n ...source,\n convertible: false,\n reason: \"must contain one top-level groupedTranslations call\",\n };\n const call = callStatement.expression;\n if (\n !ast.isIdentifier(call.callee) ||\n ast.valueText(call.callee) !== \"groupedTranslations\" ||\n call.arguments.length !== 2 ||\n !call.arguments[0] ||\n !ast.isStringLiteral(call.arguments[0])\n )\n return {\n ...source,\n convertible: false,\n reason: \"must call groupedTranslations with a string group and object\",\n };\n const dictionary = literalObject(call.arguments[1]);\n if (!dictionary)\n return {\n ...source,\n convertible: false,\n reason: \"translation object must contain only literal keys, objects, strings, or numbers\",\n };\n const group = call.arguments[0].value;\n const entries: LocaleDictionaryEntries = Object.create(null);\n if (!flattenLiteral(dictionary, group, entries))\n return {\n ...source,\n convertible: false,\n reason: \"translation object has no valid literal locale entries\",\n };\n return {\n ...source,\n convertible: true,\n reason: \"pure groupedTranslations literal\",\n group,\n dictionary,\n entries,\n };\n}\n\nexport function inspectLocaleSources(): LocaleInspection[] {\n return localeSources().map(inspect);\n}\n\nfunction localeCodes(): readonly string[] | undefined {\n const configured = config.key<unknown>(\"app.localeCodes\");\n return Array.isArray(configured) && configured.every((code) => typeof code === \"string\")\n ? configured\n : undefined;\n}\n\nfunction sameEntries(left: LocaleDictionaryEntries, right: LocaleDictionaryEntries): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\n/** Convert safe legacy locale sources, retaining a TS file whenever verification cannot prove equivalence. */\nexport function fixLocaleSources(): LocaleInspection[] {\n return inspectLocaleSources().map((result) => {\n if (!result.convertible || !result.group || !result.dictionary || !result.entries)\n return result;\n const jsonFile = path.join(path.dirname(result.file), \"locales.json\");\n const document: Record<string, unknown> =\n result.group === result.module\n ? result.dictionary\n : { $group: result.group, ...result.dictionary };\n const json = `${JSON.stringify(document, null, 2)}\\n`;\n writeFileSync(jsonFile, json);\n try {\n const parsed = parseLocaleDictionary({\n sourceFile: rootPath(path.relative(process.cwd(), jsonFile)),\n source: json,\n defaultNamespace: result.module,\n localeCodes: localeCodes(),\n });\n if (!sameEntries(result.entries, parsed.entries)) throw new Error(\"flattened entries differ\");\n } catch (error) {\n unlinkSync(jsonFile);\n return {\n ...result,\n convertible: false,\n reason: `verification failed: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n unlinkSync(result.file);\n return {\n ...result,\n reason: \"converted (comments in the TypeScript source are not retained)\",\n };\n });\n}\n\nexport const localesTsDeprecatedCheck: DoctorCheck = {\n name: \"locales-ts-deprecated\",\n run: () => {\n const sources = inspectLocaleSources();\n if (sources.length === 0) return undefined;\n const details = sources.map((source) => {\n const label = path.relative(process.cwd(), source.file).replaceAll(\"\\\\\", \"/\");\n return `${label}: ${source.convertible ? \"auto-convertible\" : \"manual\"} (${source.reason})`;\n });\n return {\n name: \"locales-ts-deprecated\",\n status: \"warn\",\n code: \"WL9101\",\n detail:\n `${details.join(\"; \")}. Auto-loaded locales.ts goes away in v6; ` +\n \"run `warlock doctor --fix` to convert auto-convertible files.\",\n };\n },\n};\n"],"mappings":"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"}
@@ -40,7 +40,8 @@ async function doctorCommandAction(data) {
40
40
  const file = result.file.replace(process.cwd(), ".").replaceAll("\\", "/");
41
41
  log(`${result.convertible ? "converted" : "manual"} ${file}: ${result.reason}`);
42
42
  }
43
- const report = await runChecks(defaultDoctorChecks, json ? await withConsoleOnStderr(bootForDiagnostics) : await bootForDiagnostics());
43
+ const context = json ? await withConsoleOnStderr(bootForDiagnostics) : await bootForDiagnostics();
44
+ const report = await runChecks(defaultDoctorChecks, context);
44
45
  if (json) console.log(JSON.stringify(toDoctorJson(report), null, 2));
45
46
  else printReport(report);
46
47
  if (report.hasFailures) await flushAndExit(report.exitCode);
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-command.action.mjs","names":[],"sources":["../../../../../../../../../../packages/core/src/cli/commands/doctor/doctor-command.action.ts"],"sourcesContent":["import type { CommandActionData } from \"../../../commands/types\";\nimport { bootForDiagnostics } from \"./boot-for-diagnostics\";\nimport { defaultDoctorChecks } from \"./checks\";\nimport { fixLocaleSources } from \"./checks/locales-ts-deprecated.check\";\nimport { flushAndExit } from \"../../flush-and-exit\";\nimport { withConsoleOnStderr } from \"../routes/with-console-on-stderr\";\nimport { printReport, toDoctorJson } from \"./format-report\";\nimport { runChecks } from \"./run-checks\";\n\n/**\n * Action behind `warlock doctor`.\n *\n * Two steps, in this order and for a reason: ONE boot pass, then every check\n * against what that pass observed. The checks never boot anything themselves,\n * so the report cannot contain two lines that inspected the app at different\n * moments and contradicted each other — which is exactly what it used to\n * contain (`routes: 0 registered` beside `health: /health + /ready\n * registered`, in the same run, on an app serving fourteen routes).\n *\n * The pass boots every connector and starts none, so no database, cache or\n * socket connection is opened and no port is bound. See\n * `boot-for-diagnostics.ts`.\n *\n * A failing check is REPORTED (a line in the report + a non-zero exit), never\n * thrown: the runner converts any thrown check into a `fail` result first.\n *\n * On success this simply returns; the CLI manager then prints its own success\n * banner and exits zero — which also disposes of the handles the boot pass\n * left open (a Fastify instance, a Vite dev server for `web` apps).\n *\n * With `--json` the report is printed as JSON (see `toDoctorJson`): every\n * finding carries its stable `WL` code, `hint`, `skill` and `docs`.\n *\n * @param data Parsed CLI args: the optional safe migration flag and `--json`.\n */\nexport async function doctorCommandAction(data: CommandActionData): Promise<void> {\n const json = data.options.json === true;\n\n // With `--json`, stdout carries the report alone: the fix log and the boot's\n // progress lines go to stderr.\n const log = json ? console.error : console.log;\n\n if (data.options.fix === true) {\n for (const result of fixLocaleSources()) {\n const file = result.file.replace(process.cwd(), \".\").replaceAll(\"\\\\\", \"/\");\n log(`${result.convertible ? \"converted\" : \"manual\"} ${file}: ${result.reason}`);\n }\n }\n\n const context = json ? await withConsoleOnStderr(bootForDiagnostics) : await bootForDiagnostics();\n\n const report = await runChecks(defaultDoctorChecks, context);\n\n if (json) {\n console.log(JSON.stringify(toDoctorJson(report), null, 2));\n } else {\n printReport(report);\n }\n\n if (report.hasFailures) {\n await flushAndExit(report.exitCode);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,eAAsB,oBAAoB,MAAwC;CAChF,MAAM,OAAO,KAAK,QAAQ,SAAS;CAInC,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CAE3C,IAAI,KAAK,QAAQ,QAAQ,MACvB,KAAK,MAAM,UAAU,iBAAiB,GAAG;EACvC,MAAM,OAAO,OAAO,KAAK,QAAQ,QAAQ,IAAI,GAAG,GAAG,CAAC,CAAC,WAAW,MAAM,GAAG;EACzE,IAAI,GAAG,OAAO,cAAc,cAAc,SAAS,GAAG,KAAK,IAAI,OAAO,QAAQ;CAChF;CAKF,MAAM,SAAS,MAAM,UAAU,qBAFf,OAAO,MAAM,oBAAoB,kBAAkB,IAAI,MAAM,mBAAmB,CAErC;CAE3D,IAAI,MACF,QAAQ,IAAI,KAAK,UAAU,aAAa,MAAM,GAAG,MAAM,CAAC,CAAC;MAEzD,YAAY,MAAM;CAGpB,IAAI,OAAO,aACT,MAAM,aAAa,OAAO,QAAQ;AAEtC"}
1
+ {"version":3,"file":"doctor-command.action.mjs","names":[],"sources":["../../../../../../../../../../packages/core/src/cli/commands/doctor/doctor-command.action.ts"],"sourcesContent":["import type { CommandActionData } from \"../../../commands/types\";\nimport { bootForDiagnostics } from \"./boot-for-diagnostics\";\nimport { defaultDoctorChecks } from \"./checks\";\nimport { fixLocaleSources } from \"./checks/locales-ts-deprecated.check\";\nimport { flushAndExit } from \"../../flush-and-exit\";\nimport { withConsoleOnStderr } from \"../routes/with-console-on-stderr\";\nimport { printReport, toDoctorJson } from \"./format-report\";\nimport { runChecks } from \"./run-checks\";\n\n/**\n * Action behind `warlock doctor`.\n *\n * Two steps, in this order and for a reason: ONE boot pass, then every check\n * against what that pass observed. The checks never boot anything themselves,\n * so the report cannot contain two lines that inspected the app at different\n * moments and contradicted each other — which is exactly what it used to\n * contain (`routes: 0 registered` beside `health: /health + /ready\n * registered`, in the same run, on an app serving fourteen routes).\n *\n * The pass boots every connector and starts none, so no database, cache or\n * socket connection is opened and no port is bound. See\n * `boot-for-diagnostics.ts`.\n *\n * A failing check is REPORTED (a line in the report + a non-zero exit), never\n * thrown: the runner converts any thrown check into a `fail` result first.\n *\n * On success this simply returns; the CLI manager then prints its own success\n * banner and exits zero — which also disposes of the handles the boot pass\n * left open (a Fastify instance, a Vite dev server for `web` apps).\n *\n * With `--json` the report is printed as JSON (see `toDoctorJson`): every\n * finding carries its stable `WL` code, `hint`, `skill` and `docs`.\n *\n * @param data Parsed CLI args: the optional safe migration flag and `--json`.\n */\nexport async function doctorCommandAction(data: CommandActionData): Promise<void> {\n const json = data.options.json === true;\n\n // With `--json`, stdout carries the report alone: the fix log and the boot's\n // progress lines go to stderr.\n const log = json ? console.error : console.log;\n\n if (data.options.fix === true) {\n for (const result of fixLocaleSources()) {\n const file = result.file.replace(process.cwd(), \".\").replaceAll(\"\\\\\", \"/\");\n log(`${result.convertible ? \"converted\" : \"manual\"} ${file}: ${result.reason}`);\n }\n }\n\n const context = json ? await withConsoleOnStderr(bootForDiagnostics) : await bootForDiagnostics();\n\n const report = await runChecks(defaultDoctorChecks, context);\n\n if (json) {\n console.log(JSON.stringify(toDoctorJson(report), null, 2));\n } else {\n printReport(report);\n }\n\n if (report.hasFailures) {\n await flushAndExit(report.exitCode);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,eAAsB,oBAAoB,MAAwC;CAChF,MAAM,OAAO,KAAK,QAAQ,SAAS;CAInC,MAAM,MAAM,OAAO,QAAQ,QAAQ,QAAQ;CAE3C,IAAI,KAAK,QAAQ,QAAQ,MACvB,KAAK,MAAM,UAAU,iBAAiB,GAAG;EACvC,MAAM,OAAO,OAAO,KAAK,QAAQ,QAAQ,IAAI,GAAG,GAAG,CAAC,CAAC,WAAW,MAAM,GAAG;EACzE,IAAI,GAAG,OAAO,cAAc,cAAc,SAAS,GAAG,KAAK,IAAI,OAAO,QAAQ;CAChF;CAGF,MAAM,UAAU,OAAO,MAAM,oBAAoB,kBAAkB,IAAI,MAAM,mBAAmB;CAEhG,MAAM,SAAS,MAAM,UAAU,qBAAqB,OAAO;CAE3D,IAAI,MACF,QAAQ,IAAI,KAAK,UAAU,aAAa,MAAM,GAAG,MAAM,CAAC,CAAC;MAEzD,YAAY,MAAM;CAGpB,IAAI,OAAO,aACT,MAAM,aAAa,OAAO,QAAQ;AAEtC"}
@@ -60,5 +60,5 @@ async function explainCommandAction({ args, options }) {
60
60
  }
61
61
 
62
62
  //#endregion
63
- export { explainCommandAction };
63
+ export { explainCommandAction, formatCodeList, formatExplanation };
64
64
  //# sourceMappingURL=explain-command.action.mjs.map
@@ -35,10 +35,13 @@ async function generateController(data) {
35
35
  process.exit(1);
36
36
  }
37
37
  await ensureComponentDirectory(module, "controllers");
38
- await putFileAsync(controllerPath, controllerStub(name, { withValidation: !!withValidation }));
38
+ const controllerContent = controllerStub(name, { withValidation: !!withValidation });
39
+ await putFileAsync(controllerPath, controllerContent);
39
40
  if (withValidation) {
40
41
  await ensureComponentDirectory(module, "schema");
41
- await putFileAsync(resolveComponentPath(module, "schema", `${name.kebab}.schema`), schemaStub(name));
42
+ const schemaPath = resolveComponentPath(module, "schema", `${name.kebab}.schema`);
43
+ const schemaContent = schemaStub(name);
44
+ await putFileAsync(schemaPath, schemaContent);
42
45
  }
43
46
  console.log(colors.cyan(`\nController "${name.camel}" generated successfully!`));
44
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"controller.generator.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/controller.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { controllerStub, schemaStub } from \"../templates/stubs\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\n\nexport async function generateController(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Controller name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.controller users/create-user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const withValidation = data.options.withValidation || data.options.v;\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if controller already exists\n const controllerPath = resolveComponentPath(module, \"controllers\", `${name.kebab}.controller`);\n if ((await componentExists(module, \"controllers\", `${name.kebab}.controller`)) && !force) {\n console.log(colors.red(`Error: Controller \"${name.kebab}.controller.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"controllers\");\n\n // Generate controller\n const controllerContent = controllerStub(name, { withValidation: !!withValidation });\n await putFileAsync(controllerPath, controllerContent);\n\n // Generate the validation schema alongside the controller if requested.\n // The controller imports the schema's exported type + value directly —\n // there is no separate `requests/` alias file.\n if (withValidation) {\n await ensureComponentDirectory(module, \"schema\");\n\n const schemaPath = resolveComponentPath(module, \"schema\", `${name.kebab}.schema`);\n const schemaContent = schemaStub(name);\n\n await putFileAsync(schemaPath, schemaContent);\n }\n\n console.log(colors.cyan(`\\nController \"${name.camel}\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,wDAAwD,CAAC;EACnF,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,iBAAiB,KAAK,QAAQ,kBAAkB,KAAK,QAAQ;CACnE,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,MAAM,iBAAiB,qBAAqB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY;CAC7F,IAAK,MAAM,gBAAgB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACxF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,aAAa;CAIpD,MAAM,aAAa,gBADO,eAAe,MAAM,EAAE,gBAAgB,CAAC,CAAC,eAAe,CAC/B,CAAC;CAKpD,IAAI,gBAAgB;EAClB,MAAM,yBAAyB,QAAQ,QAAQ;EAK/C,MAAM,aAHa,qBAAqB,QAAQ,UAAU,GAAG,KAAK,MAAM,QAG5C,GAFN,WAAW,IAEU,CAAC;CAC9C;CAEA,QAAQ,IAAI,OAAO,KAAK,iBAAiB,KAAK,MAAM,0BAA0B,CAAC;AACjF"}
1
+ {"version":3,"file":"controller.generator.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/controller.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { controllerStub, schemaStub } from \"../templates/stubs\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\n\nexport async function generateController(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Controller name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.controller users/create-user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const withValidation = data.options.withValidation || data.options.v;\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if controller already exists\n const controllerPath = resolveComponentPath(module, \"controllers\", `${name.kebab}.controller`);\n if ((await componentExists(module, \"controllers\", `${name.kebab}.controller`)) && !force) {\n console.log(colors.red(`Error: Controller \"${name.kebab}.controller.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"controllers\");\n\n // Generate controller\n const controllerContent = controllerStub(name, { withValidation: !!withValidation });\n await putFileAsync(controllerPath, controllerContent);\n\n // Generate the validation schema alongside the controller if requested.\n // The controller imports the schema's exported type + value directly —\n // there is no separate `requests/` alias file.\n if (withValidation) {\n await ensureComponentDirectory(module, \"schema\");\n\n const schemaPath = resolveComponentPath(module, \"schema\", `${name.kebab}.schema`);\n const schemaContent = schemaStub(name);\n\n await putFileAsync(schemaPath, schemaContent);\n }\n\n console.log(colors.cyan(`\\nController \"${name.camel}\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,wDAAwD,CAAC;EACnF,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,iBAAiB,KAAK,QAAQ,kBAAkB,KAAK,QAAQ;CACnE,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,MAAM,iBAAiB,qBAAqB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY;CAC7F,IAAK,MAAM,gBAAgB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACxF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,aAAa;CAGpD,MAAM,oBAAoB,eAAe,MAAM,EAAE,gBAAgB,CAAC,CAAC,eAAe,CAAC;CACnF,MAAM,aAAa,gBAAgB,iBAAiB;CAKpD,IAAI,gBAAgB;EAClB,MAAM,yBAAyB,QAAQ,QAAQ;EAE/C,MAAM,aAAa,qBAAqB,QAAQ,UAAU,GAAG,KAAK,MAAM,QAAQ;EAChF,MAAM,gBAAgB,WAAW,IAAI;EAErC,MAAM,aAAa,YAAY,aAAa;CAC9C;CAEA,QAAQ,IAAI,OAAO,KAAK,iBAAiB,KAAK,MAAM,0BAA0B,CAAC;AACjF"}
@@ -80,7 +80,8 @@ function schemaModuleFromFile(options) {
80
80
  return `${header}\n${exportName === "default" ? `import source from "${specifier}";` : `import { ${exportName} } from "${specifier}";`}\n\nexport const ${valueName} = ${local};\n\n${footer}`;
81
81
  }
82
82
  let content = source.replace(/(from\s+|import\s*\(\s*|import\s+)(["'])(\.{1,2}\/[^"']+)\2/g, (_match, prefix, quote, specifier) => {
83
- return `${prefix}${quote}${toImportSpecifier(targetDirectory, path.resolve(path.dirname(sourcePath), specifier))}${quote}`;
83
+ const resolved = path.resolve(path.dirname(sourcePath), specifier);
84
+ return `${prefix}${quote}${toImportSpecifier(targetDirectory, resolved)}${quote}`;
84
85
  });
85
86
  if (exportName === "default") content = content.replace(/export\s+default\s+/, `export const ${valueName} = `);
86
87
  else if (exportName !== valueName) content = `${content.trimEnd()}\n\nexport const ${valueName} = ${exportName};\n`;
@@ -174,7 +175,8 @@ async function registerRoute(spec, routesPath) {
174
175
  }
175
176
  }
176
177
  lines.splice(lastImport + 1, 0, ...imports);
177
- await putFileAsync(routesPath, `${lines.join("\n").trimEnd()}\n\n${endpointRouteRegistration(spec)}`);
178
+ const updated = `${lines.join("\n").trimEnd()}\n\n${endpointRouteRegistration(spec)}`;
179
+ await putFileAsync(routesPath, updated);
178
180
  logEdit(routesPath, "updated");
179
181
  }
180
182
  /** Merge the endpoint's message into `utils/locales.json`; existing keys win. */
@@ -307,5 +309,5 @@ function createEndpointGenerator(loadSchemaModule = loadSchemaModuleWithAppLoade
307
309
  const generateEndpoint = createEndpointGenerator();
308
310
 
309
311
  //#endregion
310
- export { generateEndpoint };
312
+ export { createEndpointGenerator, generateEndpoint, pickSchemaExport, readEndpointInput, schemaModuleFromFile };
311
313
  //# sourceMappingURL=endpoint.generator.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.generator.mjs","names":["putFileAsync","putEditedFileAsync"],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/endpoint.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport {\n fileExistsAsync,\n getFileAsync,\n putFileAsync as putEditedFileAsync,\n} from \"../../../../generations/generation-fs\";\nimport { recordSkippedFile, setGenerationDetail } from \"../../../../generations/generation-run\";\nimport { importAppModule } from \"../../../../loader/app-module-importer\";\nimport { appPath, srcPath } from \"../../../../utils\";\nimport {\n type EndpointAccess,\n type EndpointMethod,\n type EndpointSpec,\n endpointControllerStub,\n endpointLabel,\n endpointLocaleEntries,\n endpointResourceStub,\n endpointRouteImports,\n endpointRouteRegistration,\n endpointRoutesFileStub,\n endpointSchemaStub,\n endpointServiceStub,\n endpointTestStub,\n} from \"../templates/endpoint-stubs\";\nimport { readEndpointFields } from \"../utils/endpoint-schema\";\nimport { parseModulePath, parseName, singularName } from \"../utils/name-parser\";\nimport { isDryRun, putFileAsync, setDryRun } from \"../utils/writer\";\n\nconst METHODS: readonly EndpointMethod[] = [\"get\", \"post\", \"put\", \"patch\", \"delete\"];\n\nconst USAGE =\n \"Usage: warlock make endpoint <module>/<name> [--method post] [--path /posts] [--schema ./schema.ts] [--resource Post] [--auth | --public]\";\n\n/** Loads the `--schema` file and returns its exports. Replaceable in tests. */\nexport type SchemaModuleLoader = (absolutePath: string) => Promise<Record<string, unknown>>;\n\n/**\n * Import an app TypeScript file from the CLI: register the framework's\n * loader (path aliases, TypeScript) first, as `warlock dev` does.\n */\nconst loadSchemaModuleWithAppLoader: SchemaModuleLoader = async (absolutePath) => {\n const { filesOrchestrator } = await import(\"../../../../dev-server/files-orchestrator\");\n const { warlockConfigManager } =\n await import(\"../../../../warlock-config/warlock-config.manager\");\n\n await warlockConfigManager.load();\n await filesOrchestrator.init();\n\n return (await importAppModule(pathToFileURL(absolutePath).href)) as Record<string, unknown>;\n};\n\n/** A seal object validator, recognised structurally so a second seal copy still counts. */\ntype SchemaLike = { toJsonSchema(target?: string): unknown; schema: unknown };\n\nfunction isSchemaLike(value: unknown): value is SchemaLike {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"toJsonSchema\" in value &&\n typeof value.toJsonSchema === \"function\" &&\n \"schema\" in value &&\n typeof value.schema === \"object\"\n );\n}\n\nclass EndpointInputError extends Error {}\n\nfunction fail(message: string): never {\n throw new EndpointInputError(message);\n}\n\n/** Pick the request schema out of the `--schema` module's exports. */\nexport function pickSchemaExport(\n exports: Record<string, unknown>,\n preferredName: string,\n): { exportName: string; schema: SchemaLike } {\n const preferred = exports[preferredName];\n\n if (isSchemaLike(preferred)) return { exportName: preferredName, schema: preferred };\n\n const candidates = Object.entries(exports).filter(\n (entry): entry is [string, SchemaLike] => entry[0] !== \"default\" && isSchemaLike(entry[1]),\n );\n\n if (candidates.length === 1 && candidates[0]) {\n return { exportName: candidates[0][0], schema: candidates[0][1] };\n }\n\n const fallback = exports.default;\n\n if (candidates.length === 0 && isSchemaLike(fallback)) {\n return { exportName: \"default\", schema: fallback };\n }\n\n const names = candidates.map(([name]) => name);\n\n return fail(\n names.length === 0\n ? `The schema file exports no seal object schema (v.object(...)). Export one, e.g. \\`export const ${preferredName} = v.object({ ... })\\`.`\n : `The schema file exports several object schemas (${names.join(\", \")}). Name the one for this endpoint \\`${preferredName}\\`.`,\n );\n}\n\n/**\n * The `schema/<name>.schema.ts` content for a `--schema` file.\n *\n * A file already under `src/` is imported where it lives (one source of\n * truth). A file outside `src/` — a scratch spec — is copied in, with its\n * relative imports re-pointed at the new location. Either way the module\n * exports `<name>Schema` and its `<Name>Schema` type, the names the\n * controller and service import.\n */\nexport function schemaModuleFromFile(options: {\n sourcePath: string;\n source: string;\n exportName: string;\n targetPath: string;\n valueName: string;\n typeName: string;\n}): string {\n const { sourcePath, source, exportName, targetPath, valueName, typeName } = options;\n const targetDirectory = path.dirname(targetPath);\n\n if (isInside(srcPath(), sourcePath)) {\n const specifier = toImportSpecifier(targetDirectory, sourcePath);\n const header = `import type { Infer } from \"@warlock.js/seal\";`;\n const footer = `export type ${typeName} = Infer<typeof ${valueName}>;\\n`;\n\n if (exportName === valueName) {\n return `${header}\\nimport { ${valueName} } from \"${specifier}\";\\n\\nexport { ${valueName} };\\n\\n${footer}`;\n }\n\n const local = exportName === \"default\" ? \"source\" : exportName;\n const importLine =\n exportName === \"default\"\n ? `import source from \"${specifier}\";`\n : `import { ${exportName} } from \"${specifier}\";`;\n\n return `${header}\\n${importLine}\\n\\nexport const ${valueName} = ${local};\\n\\n${footer}`;\n }\n\n let content = source.replace(\n /(from\\s+|import\\s*\\(\\s*|import\\s+)([\"'])(\\.{1,2}\\/[^\"']+)\\2/g,\n (_match, prefix: string, quote: string, specifier: string) => {\n const resolved = path.resolve(path.dirname(sourcePath), specifier);\n\n return `${prefix}${quote}${toImportSpecifier(targetDirectory, resolved)}${quote}`;\n },\n );\n\n if (exportName === \"default\") {\n content = content.replace(/export\\s+default\\s+/, `export const ${valueName} = `);\n } else if (exportName !== valueName) {\n content = `${content.trimEnd()}\\n\\nexport const ${valueName} = ${exportName};\\n`;\n }\n\n const hasType = new RegExp(`export\\\\s+type\\\\s+${typeName}\\\\b`).test(content);\n\n if (!hasType) {\n const importsInfer = /\\bInfer\\b/.test(\n content\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"import\"))\n .join(\"\\n\"),\n );\n\n if (!importsInfer) content = `import type { Infer } from \"@warlock.js/seal\";\\n${content}`;\n\n content = `${content.trimEnd()}\\n\\nexport type ${typeName} = Infer<typeof ${valueName}>;\\n`;\n }\n\n return content;\n}\n\nfunction isInside(directory: string, file: string): boolean {\n const relative = path.relative(directory, file);\n\n return relative !== \"\" && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n\n/** A relative, extensionless, `/`-separated import specifier from `fromDirectory` to `file`. */\nfunction toImportSpecifier(fromDirectory: string, file: string): string {\n const withoutExtension = file.replace(/\\.(?:ts|tsx|mts|js|mjs)$/, \"\");\n const relative = path.relative(fromDirectory, withoutExtension).split(path.sep).join(\"/\");\n\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n}\n\n/** Parse and check the command input. Throws {@link EndpointInputError} with a fix. */\nexport function readEndpointInput(data: CommandActionData): {\n module: string;\n name: string;\n method: EndpointMethod;\n path: string;\n access: EndpointAccess;\n resource: string;\n schemaFile?: string;\n force: boolean;\n} {\n const input = data.args[0];\n\n if (!input) fail(`Endpoint name is required.\\n${USAGE}`);\n\n const { module, name } = parseModulePath(input);\n\n if (!module || !name)\n fail(`Write the endpoint as <module>/<name>, e.g. posts/create-post.\\n${USAGE}`);\n\n const moduleName = parseName(module).kebab;\n const rawMethod = String(data.options.method ?? \"post\").toLowerCase();\n const method = METHODS.find((candidate) => candidate === rawMethod);\n\n if (!method) fail(`Unknown --method \"${rawMethod}\". Use one of: ${METHODS.join(\", \")}.`);\n\n const wantsAuth = data.options.auth === true;\n const wantsPublic = data.options.public === true;\n\n if (wantsAuth && wantsPublic) fail(\"Pass either --auth or --public, not both.\");\n\n const rawPath = typeof data.options.path === \"string\" ? data.options.path : undefined;\n const defaultPath =\n method === \"get\" || method === \"post\" ? `/${moduleName}` : `/${moduleName}/:id`;\n const routePath = rawPath ? (rawPath.startsWith(\"/\") ? rawPath : `/${rawPath}`) : defaultPath;\n const resource =\n typeof data.options.resource === \"string\" && data.options.resource.trim() !== \"\"\n ? data.options.resource.trim()\n : singularName(moduleName).pascal;\n const schemaFile =\n typeof data.options.schema === \"string\" && data.options.schema.trim() !== \"\"\n ? data.options.schema.trim()\n : undefined;\n\n return {\n module: moduleName,\n name,\n method,\n path: routePath,\n // Guarded unless the caller says, in so many words, that it is public.\n access: wantsPublic ? \"public\" : \"guarded\",\n resource,\n schemaFile,\n force: data.options.force === true || data.options.f === true,\n };\n}\n\n/**\n * Write a whole generated file unless it exists. Without `--force` an\n * existing file is the app's own code: it is skipped and reported, never\n * overwritten.\n */\nasync function writeNewFile(target: string, content: string, force: boolean): Promise<void> {\n if (!force && (await fileExistsAsync(target))) {\n recordSkippedFile(target, \"exists (pass --force to overwrite)\");\n console.log(`${colors.yellow(\"-\")} skipped ${colors.gray(displayPath(target))} (exists)`);\n return;\n }\n\n await putFileAsync(target, content);\n}\n\nfunction displayPath(target: string): string {\n return path.relative(process.cwd(), target).split(path.sep).join(\"/\");\n}\n\n/** Append the endpoint to the module's `routes.ts`, creating the file if needed. */\nasync function registerRoute(spec: EndpointSpec, routesPath: string): Promise<void> {\n if (!existsSync(routesPath)) {\n await putEditedFileAsync(routesPath, endpointRoutesFileStub(spec));\n logEdit(routesPath, \"created\");\n return;\n }\n\n const current = await getFileAsync(routesPath);\n const controller = `${spec.name.camel}Controller`;\n\n if (new RegExp(`\\\\b${controller}\\\\b`).test(current)) {\n recordSkippedFile(routesPath, `${controller} is already registered`);\n console.log(\n `${colors.yellow(\"-\")} skipped ${colors.gray(displayPath(routesPath))} (${controller} is already registered)`,\n );\n return;\n }\n\n const imports = [...endpointRouteImports(spec)];\n\n if (!/import\\s*\\{[^}]*\\brouter\\b[^}]*\\}\\s*from\\s*[\"']@warlock\\.js\\/core[\"']/.test(current)) {\n imports.unshift(`import { router } from \"@warlock.js/core\";`);\n }\n\n if (spec.access === \"guarded\" && !/\\bguarded\\b/.test(current)) {\n imports.unshift(`import { guarded } from \"app/shared/utils/router\";`);\n }\n\n const lines = current.split(\"\\n\");\n let lastImport = -1;\n let inImport = false;\n\n // An import may span lines; new imports go after the last statement ends.\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n\n if (/^import\\s/.test(line)) inImport = true;\n\n if (inImport && (/;\\s*$/.test(line) || /from\\s+[\"'][^\"']+[\"']\\s*$/.test(line))) {\n lastImport = index;\n inImport = false;\n }\n }\n\n lines.splice(lastImport + 1, 0, ...imports);\n\n const updated = `${lines.join(\"\\n\").trimEnd()}\\n\\n${endpointRouteRegistration(spec)}`;\n\n await putEditedFileAsync(routesPath, updated);\n logEdit(routesPath, \"updated\");\n}\n\n/** Merge the endpoint's message into `utils/locales.json`; existing keys win. */\nasync function registerLocales(spec: EndpointSpec, localesPath: string): Promise<void> {\n const entries = endpointLocaleEntries(spec);\n\n if (!existsSync(localesPath)) {\n await putEditedFileAsync(localesPath, `${JSON.stringify(entries, null, 2)}\\n`);\n logEdit(localesPath, \"created\");\n return;\n }\n\n let dictionary: Record<string, unknown>;\n\n try {\n const parsed: unknown = JSON.parse(await getFileAsync(localesPath));\n\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error();\n\n dictionary = parsed as Record<string, unknown>;\n } catch {\n recordSkippedFile(localesPath, \"not a JSON object; add the message key by hand\");\n console.log(\n colors.yellow(\n `! ${displayPath(localesPath)} is not a JSON object; add ${Object.keys(entries).join(\", \")} by hand.`,\n ),\n );\n return;\n }\n\n if (dictionary.$group !== undefined && dictionary.$group !== spec.module) {\n recordSkippedFile(localesPath, `declares $group \"${String(dictionary.$group)}\"`);\n console.log(\n colors.yellow(\n `! ${displayPath(localesPath)} declares another $group; add ${spec.module}.${Object.keys(entries).join(\", \")} by hand.`,\n ),\n );\n return;\n }\n\n const missing = Object.keys(entries).filter((key) => dictionary[key] === undefined);\n\n if (missing.length === 0) {\n recordSkippedFile(localesPath, \"message key already present\");\n return;\n }\n\n for (const key of missing) dictionary[key] = entries[key];\n\n await putEditedFileAsync(localesPath, `${JSON.stringify(dictionary, null, 2)}\\n`);\n logEdit(localesPath, \"updated\");\n}\n\nfunction logEdit(target: string, verb: \"created\" | \"updated\"): void {\n const prefix = isDryRun()\n ? `${colors.cyan(\"○\")} would ${verb === \"created\" ? \"create\" : \"update\"}`\n : `${colors.green(\"✓\")} ${verb}`;\n\n console.log(`${prefix} ${colors.gray(displayPath(target))}`);\n}\n\n/**\n * `warlock make endpoint <module>/<name>` — a spec-first endpoint.\n *\n * Writes, under `src/app/<module>/`: the request schema (from `--schema` or a\n * stub), a service, the resource (unless it exists), one controller with its\n * validation and OpenAPI `responseSchema`, the route (guarded, or\n * `public: true` with `--public`), the success message in `utils/locales.json`,\n * and `tests/<name>.test.ts`, which requests the endpoint over the real HTTP\n * stack. Existing files are skipped and reported unless `--force`.\n */\nexport function createEndpointGenerator(\n loadSchemaModule: SchemaModuleLoader = loadSchemaModuleWithAppLoader,\n): (data: CommandActionData) => Promise<void> {\n return async (data) => {\n let input: ReturnType<typeof readEndpointInput>;\n\n try {\n input = readEndpointInput(data);\n } catch (error) {\n if (!(error instanceof EndpointInputError)) throw error;\n\n console.log(colors.red(`Error: ${error.message}`));\n process.exit(1);\n }\n\n setDryRun(data.options.dryRun === true);\n\n const name = parseName(input.name);\n const modulePath = appPath(input.module);\n const schemaPath = path.join(modulePath, \"schema\", `${name.kebab}.schema.ts`);\n const valueName = `${name.camel}Schema`;\n const typeName = `${name.pascal}Schema`;\n\n let jsonSchema: unknown;\n let schemaContent: string | undefined;\n\n if (input.schemaFile) {\n const sourcePath = path.resolve(process.cwd(), input.schemaFile);\n\n if (!existsSync(sourcePath)) {\n console.log(colors.red(`Error: Schema file not found: ${input.schemaFile}`));\n process.exit(1);\n }\n\n let exports: Record<string, unknown>;\n\n try {\n exports = await loadSchemaModule(sourcePath);\n } catch (error) {\n console.log(\n colors.red(\n `Error: Could not load ${input.schemaFile} to read its fields: ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n process.exit(1);\n }\n\n let picked: ReturnType<typeof pickSchemaExport>;\n\n try {\n picked = pickSchemaExport(exports, valueName);\n } catch (error) {\n console.log(colors.red(`Error: ${error instanceof Error ? error.message : String(error)}`));\n process.exit(1);\n }\n\n jsonSchema = picked.schema.toJsonSchema(\"draft-2020-12\");\n\n if (path.resolve(sourcePath) !== path.resolve(schemaPath)) {\n schemaContent = schemaModuleFromFile({\n sourcePath,\n source: readFileSync(sourcePath, \"utf8\"),\n exportName: picked.exportName,\n targetPath: schemaPath,\n valueName,\n typeName,\n });\n }\n }\n\n const spec: EndpointSpec = {\n module: input.module,\n name,\n method: input.method,\n path: input.path,\n access: input.access,\n resource: parseName(input.resource),\n fields: readEndpointFields(jsonSchema),\n };\n\n const resourcePath = path.join(\n modulePath,\n \"resources\",\n `${spec.resource.singular.kebab}.resource.ts`,\n );\n const testPath = path.join(modulePath, \"tests\", `${name.kebab}.test.ts`);\n\n setGenerationDetail(\"endpoint\", {\n method: spec.method.toUpperCase(),\n path: spec.path,\n access: spec.access,\n controller: `${name.camel}Controller`,\n resource: `${spec.resource.pascal}Resource`,\n fields: spec.fields.map((field) => field.name),\n test: displayPath(testPath),\n });\n\n console.log(colors.cyan(`\\nGenerating ${endpointLabel(spec)} in src/app/${spec.module}\\n`));\n\n if (input.schemaFile === undefined) {\n await writeNewFile(schemaPath, endpointSchemaStub(spec), input.force);\n } else if (schemaContent !== undefined) {\n await writeNewFile(schemaPath, schemaContent, input.force);\n }\n\n await writeNewFile(\n path.join(modulePath, \"services\", `${name.kebab}.service.ts`),\n endpointServiceStub(spec),\n input.force,\n );\n await writeNewFile(resourcePath, endpointResourceStub(spec), input.force);\n await writeNewFile(\n path.join(modulePath, \"controllers\", `${name.kebab}.controller.ts`),\n endpointControllerStub(spec),\n input.force,\n );\n await registerRoute(spec, path.join(modulePath, \"routes.ts\"));\n await registerLocales(spec, path.join(modulePath, \"utils\", \"locales.json\"));\n await writeNewFile(testPath, endpointTestStub(spec), input.force);\n\n console.log(\n colors.cyan(\n `\\n${endpointLabel(spec)} ${isDryRun() ? \"previewed\" : \"generated\"} (${spec.access === \"public\" ? \"public: true\" : \"guarded\"}).`,\n ),\n );\n console.log(\n colors.gray(\n `Next: fill in services/${name.kebab}.service.ts, then run the test with \\`warlock test --related ${displayPath(testPath)}\\`.`,\n ),\n );\n };\n}\n\nexport const generateEndpoint = createEndpointGenerator();\n"],"mappings":"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"}
1
+ {"version":3,"file":"endpoint.generator.mjs","names":["putFileAsync","putEditedFileAsync"],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/endpoint.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport {\n fileExistsAsync,\n getFileAsync,\n putFileAsync as putEditedFileAsync,\n} from \"../../../../generations/generation-fs\";\nimport { recordSkippedFile, setGenerationDetail } from \"../../../../generations/generation-run\";\nimport { importAppModule } from \"../../../../loader/app-module-importer\";\nimport { appPath, srcPath } from \"../../../../utils\";\nimport {\n type EndpointAccess,\n type EndpointMethod,\n type EndpointSpec,\n endpointControllerStub,\n endpointLabel,\n endpointLocaleEntries,\n endpointResourceStub,\n endpointRouteImports,\n endpointRouteRegistration,\n endpointRoutesFileStub,\n endpointSchemaStub,\n endpointServiceStub,\n endpointTestStub,\n} from \"../templates/endpoint-stubs\";\nimport { readEndpointFields } from \"../utils/endpoint-schema\";\nimport { parseModulePath, parseName, singularName } from \"../utils/name-parser\";\nimport { isDryRun, putFileAsync, setDryRun } from \"../utils/writer\";\n\nconst METHODS: readonly EndpointMethod[] = [\"get\", \"post\", \"put\", \"patch\", \"delete\"];\n\nconst USAGE =\n \"Usage: warlock make endpoint <module>/<name> [--method post] [--path /posts] [--schema ./schema.ts] [--resource Post] [--auth | --public]\";\n\n/** Loads the `--schema` file and returns its exports. Replaceable in tests. */\nexport type SchemaModuleLoader = (absolutePath: string) => Promise<Record<string, unknown>>;\n\n/**\n * Import an app TypeScript file from the CLI: register the framework's\n * loader (path aliases, TypeScript) first, as `warlock dev` does.\n */\nconst loadSchemaModuleWithAppLoader: SchemaModuleLoader = async (absolutePath) => {\n const { filesOrchestrator } = await import(\"../../../../dev-server/files-orchestrator\");\n const { warlockConfigManager } =\n await import(\"../../../../warlock-config/warlock-config.manager\");\n\n await warlockConfigManager.load();\n await filesOrchestrator.init();\n\n return (await importAppModule(pathToFileURL(absolutePath).href)) as Record<string, unknown>;\n};\n\n/** A seal object validator, recognised structurally so a second seal copy still counts. */\ntype SchemaLike = { toJsonSchema(target?: string): unknown; schema: unknown };\n\nfunction isSchemaLike(value: unknown): value is SchemaLike {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"toJsonSchema\" in value &&\n typeof value.toJsonSchema === \"function\" &&\n \"schema\" in value &&\n typeof value.schema === \"object\"\n );\n}\n\nclass EndpointInputError extends Error {}\n\nfunction fail(message: string): never {\n throw new EndpointInputError(message);\n}\n\n/** Pick the request schema out of the `--schema` module's exports. */\nexport function pickSchemaExport(\n exports: Record<string, unknown>,\n preferredName: string,\n): { exportName: string; schema: SchemaLike } {\n const preferred = exports[preferredName];\n\n if (isSchemaLike(preferred)) return { exportName: preferredName, schema: preferred };\n\n const candidates = Object.entries(exports).filter(\n (entry): entry is [string, SchemaLike] => entry[0] !== \"default\" && isSchemaLike(entry[1]),\n );\n\n if (candidates.length === 1 && candidates[0]) {\n return { exportName: candidates[0][0], schema: candidates[0][1] };\n }\n\n const fallback = exports.default;\n\n if (candidates.length === 0 && isSchemaLike(fallback)) {\n return { exportName: \"default\", schema: fallback };\n }\n\n const names = candidates.map(([name]) => name);\n\n return fail(\n names.length === 0\n ? `The schema file exports no seal object schema (v.object(...)). Export one, e.g. \\`export const ${preferredName} = v.object({ ... })\\`.`\n : `The schema file exports several object schemas (${names.join(\", \")}). Name the one for this endpoint \\`${preferredName}\\`.`,\n );\n}\n\n/**\n * The `schema/<name>.schema.ts` content for a `--schema` file.\n *\n * A file already under `src/` is imported where it lives (one source of\n * truth). A file outside `src/` — a scratch spec — is copied in, with its\n * relative imports re-pointed at the new location. Either way the module\n * exports `<name>Schema` and its `<Name>Schema` type, the names the\n * controller and service import.\n */\nexport function schemaModuleFromFile(options: {\n sourcePath: string;\n source: string;\n exportName: string;\n targetPath: string;\n valueName: string;\n typeName: string;\n}): string {\n const { sourcePath, source, exportName, targetPath, valueName, typeName } = options;\n const targetDirectory = path.dirname(targetPath);\n\n if (isInside(srcPath(), sourcePath)) {\n const specifier = toImportSpecifier(targetDirectory, sourcePath);\n const header = `import type { Infer } from \"@warlock.js/seal\";`;\n const footer = `export type ${typeName} = Infer<typeof ${valueName}>;\\n`;\n\n if (exportName === valueName) {\n return `${header}\\nimport { ${valueName} } from \"${specifier}\";\\n\\nexport { ${valueName} };\\n\\n${footer}`;\n }\n\n const local = exportName === \"default\" ? \"source\" : exportName;\n const importLine =\n exportName === \"default\"\n ? `import source from \"${specifier}\";`\n : `import { ${exportName} } from \"${specifier}\";`;\n\n return `${header}\\n${importLine}\\n\\nexport const ${valueName} = ${local};\\n\\n${footer}`;\n }\n\n let content = source.replace(\n /(from\\s+|import\\s*\\(\\s*|import\\s+)([\"'])(\\.{1,2}\\/[^\"']+)\\2/g,\n (_match, prefix: string, quote: string, specifier: string) => {\n const resolved = path.resolve(path.dirname(sourcePath), specifier);\n\n return `${prefix}${quote}${toImportSpecifier(targetDirectory, resolved)}${quote}`;\n },\n );\n\n if (exportName === \"default\") {\n content = content.replace(/export\\s+default\\s+/, `export const ${valueName} = `);\n } else if (exportName !== valueName) {\n content = `${content.trimEnd()}\\n\\nexport const ${valueName} = ${exportName};\\n`;\n }\n\n const hasType = new RegExp(`export\\\\s+type\\\\s+${typeName}\\\\b`).test(content);\n\n if (!hasType) {\n const importsInfer = /\\bInfer\\b/.test(\n content\n .split(\"\\n\")\n .filter((line) => line.startsWith(\"import\"))\n .join(\"\\n\"),\n );\n\n if (!importsInfer) content = `import type { Infer } from \"@warlock.js/seal\";\\n${content}`;\n\n content = `${content.trimEnd()}\\n\\nexport type ${typeName} = Infer<typeof ${valueName}>;\\n`;\n }\n\n return content;\n}\n\nfunction isInside(directory: string, file: string): boolean {\n const relative = path.relative(directory, file);\n\n return relative !== \"\" && !relative.startsWith(\"..\") && !path.isAbsolute(relative);\n}\n\n/** A relative, extensionless, `/`-separated import specifier from `fromDirectory` to `file`. */\nfunction toImportSpecifier(fromDirectory: string, file: string): string {\n const withoutExtension = file.replace(/\\.(?:ts|tsx|mts|js|mjs)$/, \"\");\n const relative = path.relative(fromDirectory, withoutExtension).split(path.sep).join(\"/\");\n\n return relative.startsWith(\".\") ? relative : `./${relative}`;\n}\n\n/** Parse and check the command input. Throws {@link EndpointInputError} with a fix. */\nexport function readEndpointInput(data: CommandActionData): {\n module: string;\n name: string;\n method: EndpointMethod;\n path: string;\n access: EndpointAccess;\n resource: string;\n schemaFile?: string;\n force: boolean;\n} {\n const input = data.args[0];\n\n if (!input) fail(`Endpoint name is required.\\n${USAGE}`);\n\n const { module, name } = parseModulePath(input);\n\n if (!module || !name)\n fail(`Write the endpoint as <module>/<name>, e.g. posts/create-post.\\n${USAGE}`);\n\n const moduleName = parseName(module).kebab;\n const rawMethod = String(data.options.method ?? \"post\").toLowerCase();\n const method = METHODS.find((candidate) => candidate === rawMethod);\n\n if (!method) fail(`Unknown --method \"${rawMethod}\". Use one of: ${METHODS.join(\", \")}.`);\n\n const wantsAuth = data.options.auth === true;\n const wantsPublic = data.options.public === true;\n\n if (wantsAuth && wantsPublic) fail(\"Pass either --auth or --public, not both.\");\n\n const rawPath = typeof data.options.path === \"string\" ? data.options.path : undefined;\n const defaultPath =\n method === \"get\" || method === \"post\" ? `/${moduleName}` : `/${moduleName}/:id`;\n const routePath = rawPath ? (rawPath.startsWith(\"/\") ? rawPath : `/${rawPath}`) : defaultPath;\n const resource =\n typeof data.options.resource === \"string\" && data.options.resource.trim() !== \"\"\n ? data.options.resource.trim()\n : singularName(moduleName).pascal;\n const schemaFile =\n typeof data.options.schema === \"string\" && data.options.schema.trim() !== \"\"\n ? data.options.schema.trim()\n : undefined;\n\n return {\n module: moduleName,\n name,\n method,\n path: routePath,\n // Guarded unless the caller says, in so many words, that it is public.\n access: wantsPublic ? \"public\" : \"guarded\",\n resource,\n schemaFile,\n force: data.options.force === true || data.options.f === true,\n };\n}\n\n/**\n * Write a whole generated file unless it exists. Without `--force` an\n * existing file is the app's own code: it is skipped and reported, never\n * overwritten.\n */\nasync function writeNewFile(target: string, content: string, force: boolean): Promise<void> {\n if (!force && (await fileExistsAsync(target))) {\n recordSkippedFile(target, \"exists (pass --force to overwrite)\");\n console.log(`${colors.yellow(\"-\")} skipped ${colors.gray(displayPath(target))} (exists)`);\n return;\n }\n\n await putFileAsync(target, content);\n}\n\nfunction displayPath(target: string): string {\n return path.relative(process.cwd(), target).split(path.sep).join(\"/\");\n}\n\n/** Append the endpoint to the module's `routes.ts`, creating the file if needed. */\nasync function registerRoute(spec: EndpointSpec, routesPath: string): Promise<void> {\n if (!existsSync(routesPath)) {\n await putEditedFileAsync(routesPath, endpointRoutesFileStub(spec));\n logEdit(routesPath, \"created\");\n return;\n }\n\n const current = await getFileAsync(routesPath);\n const controller = `${spec.name.camel}Controller`;\n\n if (new RegExp(`\\\\b${controller}\\\\b`).test(current)) {\n recordSkippedFile(routesPath, `${controller} is already registered`);\n console.log(\n `${colors.yellow(\"-\")} skipped ${colors.gray(displayPath(routesPath))} (${controller} is already registered)`,\n );\n return;\n }\n\n const imports = [...endpointRouteImports(spec)];\n\n if (!/import\\s*\\{[^}]*\\brouter\\b[^}]*\\}\\s*from\\s*[\"']@warlock\\.js\\/core[\"']/.test(current)) {\n imports.unshift(`import { router } from \"@warlock.js/core\";`);\n }\n\n if (spec.access === \"guarded\" && !/\\bguarded\\b/.test(current)) {\n imports.unshift(`import { guarded } from \"app/shared/utils/router\";`);\n }\n\n const lines = current.split(\"\\n\");\n let lastImport = -1;\n let inImport = false;\n\n // An import may span lines; new imports go after the last statement ends.\n for (let index = 0; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n\n if (/^import\\s/.test(line)) inImport = true;\n\n if (inImport && (/;\\s*$/.test(line) || /from\\s+[\"'][^\"']+[\"']\\s*$/.test(line))) {\n lastImport = index;\n inImport = false;\n }\n }\n\n lines.splice(lastImport + 1, 0, ...imports);\n\n const updated = `${lines.join(\"\\n\").trimEnd()}\\n\\n${endpointRouteRegistration(spec)}`;\n\n await putEditedFileAsync(routesPath, updated);\n logEdit(routesPath, \"updated\");\n}\n\n/** Merge the endpoint's message into `utils/locales.json`; existing keys win. */\nasync function registerLocales(spec: EndpointSpec, localesPath: string): Promise<void> {\n const entries = endpointLocaleEntries(spec);\n\n if (!existsSync(localesPath)) {\n await putEditedFileAsync(localesPath, `${JSON.stringify(entries, null, 2)}\\n`);\n logEdit(localesPath, \"created\");\n return;\n }\n\n let dictionary: Record<string, unknown>;\n\n try {\n const parsed: unknown = JSON.parse(await getFileAsync(localesPath));\n\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error();\n\n dictionary = parsed as Record<string, unknown>;\n } catch {\n recordSkippedFile(localesPath, \"not a JSON object; add the message key by hand\");\n console.log(\n colors.yellow(\n `! ${displayPath(localesPath)} is not a JSON object; add ${Object.keys(entries).join(\", \")} by hand.`,\n ),\n );\n return;\n }\n\n if (dictionary.$group !== undefined && dictionary.$group !== spec.module) {\n recordSkippedFile(localesPath, `declares $group \"${String(dictionary.$group)}\"`);\n console.log(\n colors.yellow(\n `! ${displayPath(localesPath)} declares another $group; add ${spec.module}.${Object.keys(entries).join(\", \")} by hand.`,\n ),\n );\n return;\n }\n\n const missing = Object.keys(entries).filter((key) => dictionary[key] === undefined);\n\n if (missing.length === 0) {\n recordSkippedFile(localesPath, \"message key already present\");\n return;\n }\n\n for (const key of missing) dictionary[key] = entries[key];\n\n await putEditedFileAsync(localesPath, `${JSON.stringify(dictionary, null, 2)}\\n`);\n logEdit(localesPath, \"updated\");\n}\n\nfunction logEdit(target: string, verb: \"created\" | \"updated\"): void {\n const prefix = isDryRun()\n ? `${colors.cyan(\"○\")} would ${verb === \"created\" ? \"create\" : \"update\"}`\n : `${colors.green(\"✓\")} ${verb}`;\n\n console.log(`${prefix} ${colors.gray(displayPath(target))}`);\n}\n\n/**\n * `warlock make endpoint <module>/<name>` — a spec-first endpoint.\n *\n * Writes, under `src/app/<module>/`: the request schema (from `--schema` or a\n * stub), a service, the resource (unless it exists), one controller with its\n * validation and OpenAPI `responseSchema`, the route (guarded, or\n * `public: true` with `--public`), the success message in `utils/locales.json`,\n * and `tests/<name>.test.ts`, which requests the endpoint over the real HTTP\n * stack. Existing files are skipped and reported unless `--force`.\n */\nexport function createEndpointGenerator(\n loadSchemaModule: SchemaModuleLoader = loadSchemaModuleWithAppLoader,\n): (data: CommandActionData) => Promise<void> {\n return async (data) => {\n let input: ReturnType<typeof readEndpointInput>;\n\n try {\n input = readEndpointInput(data);\n } catch (error) {\n if (!(error instanceof EndpointInputError)) throw error;\n\n console.log(colors.red(`Error: ${error.message}`));\n process.exit(1);\n }\n\n setDryRun(data.options.dryRun === true);\n\n const name = parseName(input.name);\n const modulePath = appPath(input.module);\n const schemaPath = path.join(modulePath, \"schema\", `${name.kebab}.schema.ts`);\n const valueName = `${name.camel}Schema`;\n const typeName = `${name.pascal}Schema`;\n\n let jsonSchema: unknown;\n let schemaContent: string | undefined;\n\n if (input.schemaFile) {\n const sourcePath = path.resolve(process.cwd(), input.schemaFile);\n\n if (!existsSync(sourcePath)) {\n console.log(colors.red(`Error: Schema file not found: ${input.schemaFile}`));\n process.exit(1);\n }\n\n let exports: Record<string, unknown>;\n\n try {\n exports = await loadSchemaModule(sourcePath);\n } catch (error) {\n console.log(\n colors.red(\n `Error: Could not load ${input.schemaFile} to read its fields: ${error instanceof Error ? error.message : String(error)}`,\n ),\n );\n process.exit(1);\n }\n\n let picked: ReturnType<typeof pickSchemaExport>;\n\n try {\n picked = pickSchemaExport(exports, valueName);\n } catch (error) {\n console.log(colors.red(`Error: ${error instanceof Error ? error.message : String(error)}`));\n process.exit(1);\n }\n\n jsonSchema = picked.schema.toJsonSchema(\"draft-2020-12\");\n\n if (path.resolve(sourcePath) !== path.resolve(schemaPath)) {\n schemaContent = schemaModuleFromFile({\n sourcePath,\n source: readFileSync(sourcePath, \"utf8\"),\n exportName: picked.exportName,\n targetPath: schemaPath,\n valueName,\n typeName,\n });\n }\n }\n\n const spec: EndpointSpec = {\n module: input.module,\n name,\n method: input.method,\n path: input.path,\n access: input.access,\n resource: parseName(input.resource),\n fields: readEndpointFields(jsonSchema),\n };\n\n const resourcePath = path.join(\n modulePath,\n \"resources\",\n `${spec.resource.singular.kebab}.resource.ts`,\n );\n const testPath = path.join(modulePath, \"tests\", `${name.kebab}.test.ts`);\n\n setGenerationDetail(\"endpoint\", {\n method: spec.method.toUpperCase(),\n path: spec.path,\n access: spec.access,\n controller: `${name.camel}Controller`,\n resource: `${spec.resource.pascal}Resource`,\n fields: spec.fields.map((field) => field.name),\n test: displayPath(testPath),\n });\n\n console.log(colors.cyan(`\\nGenerating ${endpointLabel(spec)} in src/app/${spec.module}\\n`));\n\n if (input.schemaFile === undefined) {\n await writeNewFile(schemaPath, endpointSchemaStub(spec), input.force);\n } else if (schemaContent !== undefined) {\n await writeNewFile(schemaPath, schemaContent, input.force);\n }\n\n await writeNewFile(\n path.join(modulePath, \"services\", `${name.kebab}.service.ts`),\n endpointServiceStub(spec),\n input.force,\n );\n await writeNewFile(resourcePath, endpointResourceStub(spec), input.force);\n await writeNewFile(\n path.join(modulePath, \"controllers\", `${name.kebab}.controller.ts`),\n endpointControllerStub(spec),\n input.force,\n );\n await registerRoute(spec, path.join(modulePath, \"routes.ts\"));\n await registerLocales(spec, path.join(modulePath, \"utils\", \"locales.json\"));\n await writeNewFile(testPath, endpointTestStub(spec), input.force);\n\n console.log(\n colors.cyan(\n `\\n${endpointLabel(spec)} ${isDryRun() ? \"previewed\" : \"generated\"} (${spec.access === \"public\" ? \"public: true\" : \"guarded\"}).`,\n ),\n );\n console.log(\n colors.gray(\n `Next: fill in services/${name.kebab}.service.ts, then run the test with \\`warlock test --related ${displayPath(testPath)}\\`.`,\n ),\n );\n };\n}\n\nexport const generateEndpoint = createEndpointGenerator();\n"],"mappings":"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"}
@@ -42,10 +42,11 @@ async function generateModel(data) {
42
42
  }
43
43
  await ensureDirectoryAsync(modelDir);
44
44
  await ensureDirectoryAsync(path.join(modelDir, "migrations"));
45
- await putFileAsync(modelPath, modelStub(name, {
45
+ const modelContent = modelStub(name, {
46
46
  tableName,
47
47
  withResource: !!withResource
48
- }));
48
+ });
49
+ await putFileAsync(modelPath, modelContent);
49
50
  if (withResource) {
50
51
  const resourceFile = `${name.singular.kebab}.resource`;
51
52
  if (force || !await componentExists(module, "resources", resourceFile)) {
@@ -1 +1 @@
1
- {"version":3,"file":"model.generator.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/model.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { existsSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { migrationTimestamp } from \"../../../../generations/features/shared/migration-timestamp\";\nimport { migrationStub, modelStub, resourceStub } from \"../templates/stubs\";\nimport { parseModulePath, singularName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n resolveModulePath,\n} from \"../utils/path-resolver\";\nimport {\n ensureDirectoryAsync,\n putFileAsync,\n reportSkippedFiles,\n setDryRun,\n setSkipExisting,\n} from \"../utils/writer\";\n\nexport async function generateModel(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Model name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.model users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = singularName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n // --force only creates what is missing; replacing edited files needs --overwrite too\n setSkipExisting(!data.options.overwrite);\n const withResource = data.options.withResource || data.options.rs;\n const tableName = (data.options.table as string) || name.plural.snake;\n\n // Check if model already exists\n const modelDir = path.join(resolveModulePath(module), \"models\", name.kebab);\n const modelPath = path.join(modelDir, `${name.kebab}.model.ts`);\n\n if ((await componentExists(module, `models/${name.kebab}`, `${name.kebab}.model`)) && !force) {\n console.log(colors.red(`Error: Model \"${name.kebab}\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureDirectoryAsync(modelDir);\n await ensureDirectoryAsync(path.join(modelDir, \"migrations\"));\n\n // Generate model\n const modelContent = modelStub(name, { tableName, withResource: !!withResource });\n await putFileAsync(modelPath, modelContent);\n\n // The model imports ../../resources/<name>.resource, so that file must exist\n if (withResource) {\n const resourceFile = `${name.singular.kebab}.resource`;\n\n if (force || !(await componentExists(module, \"resources\", resourceFile))) {\n await ensureComponentDirectory(module, \"resources\");\n await putFileAsync(\n resolveComponentPath(module, \"resources\", resourceFile),\n resourceStub(name),\n );\n }\n }\n\n // Generate index.ts\n const indexContent = `export * from \"./${name.kebab}.model\";\n`;\n await putFileAsync(path.join(modelDir, \"index.ts\"), indexContent);\n\n // Generate migration (skip when one already exists, e.g. on --force)\n const migrationsDir = path.join(modelDir, \"migrations\");\n const hasMigration =\n existsSync(migrationsDir) &&\n readdirSync(migrationsDir).some((file) => file.endsWith(\".migration.ts\"));\n const timestamp = migrationTimestamp();\n const migrationPath = path.join(\n modelDir,\n \"migrations\",\n `${timestamp}-${name.kebab}.migration.ts`,\n );\n\n const migrationContent = migrationStub(name, {\n timestamps:\n data.options.timestamps !== \"false\" &&\n data.options.timestamps !== false &&\n !data.options.noTimestamps,\n });\n\n if (!hasMigration) {\n await putFileAsync(migrationPath, migrationContent);\n }\n\n reportSkippedFiles();\n\n console.log(colors.cyan(`\\n✨ Model \"${name.pascal}\" generated successfully!`));\n console.log(colors.gray(`\\nNext steps:`));\n console.log(colors.gray(` 1. Update model schema in ${name.kebab}.model.ts`));\n console.log(\n colors.gray(\n hasMigration\n ? ` 2. Existing migration kept; add changes with: warlock gen.migration ${module}/${name.kebab} --add ...`\n : ` 2. Update migration in migrations/${timestamp}-${name.kebab}.migration.ts`,\n ),\n );\n console.log(colors.gray(` 3. Run migration: warlock migrate`));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"model.generator.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/model.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { existsSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { migrationTimestamp } from \"../../../../generations/features/shared/migration-timestamp\";\nimport { migrationStub, modelStub, resourceStub } from \"../templates/stubs\";\nimport { parseModulePath, singularName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n resolveModulePath,\n} from \"../utils/path-resolver\";\nimport {\n ensureDirectoryAsync,\n putFileAsync,\n reportSkippedFiles,\n setDryRun,\n setSkipExisting,\n} from \"../utils/writer\";\n\nexport async function generateModel(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Model name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.model users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = singularName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n // --force only creates what is missing; replacing edited files needs --overwrite too\n setSkipExisting(!data.options.overwrite);\n const withResource = data.options.withResource || data.options.rs;\n const tableName = (data.options.table as string) || name.plural.snake;\n\n // Check if model already exists\n const modelDir = path.join(resolveModulePath(module), \"models\", name.kebab);\n const modelPath = path.join(modelDir, `${name.kebab}.model.ts`);\n\n if ((await componentExists(module, `models/${name.kebab}`, `${name.kebab}.model`)) && !force) {\n console.log(colors.red(`Error: Model \"${name.kebab}\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureDirectoryAsync(modelDir);\n await ensureDirectoryAsync(path.join(modelDir, \"migrations\"));\n\n // Generate model\n const modelContent = modelStub(name, { tableName, withResource: !!withResource });\n await putFileAsync(modelPath, modelContent);\n\n // The model imports ../../resources/<name>.resource, so that file must exist\n if (withResource) {\n const resourceFile = `${name.singular.kebab}.resource`;\n\n if (force || !(await componentExists(module, \"resources\", resourceFile))) {\n await ensureComponentDirectory(module, \"resources\");\n await putFileAsync(\n resolveComponentPath(module, \"resources\", resourceFile),\n resourceStub(name),\n );\n }\n }\n\n // Generate index.ts\n const indexContent = `export * from \"./${name.kebab}.model\";\n`;\n await putFileAsync(path.join(modelDir, \"index.ts\"), indexContent);\n\n // Generate migration (skip when one already exists, e.g. on --force)\n const migrationsDir = path.join(modelDir, \"migrations\");\n const hasMigration =\n existsSync(migrationsDir) &&\n readdirSync(migrationsDir).some((file) => file.endsWith(\".migration.ts\"));\n const timestamp = migrationTimestamp();\n const migrationPath = path.join(\n modelDir,\n \"migrations\",\n `${timestamp}-${name.kebab}.migration.ts`,\n );\n\n const migrationContent = migrationStub(name, {\n timestamps:\n data.options.timestamps !== \"false\" &&\n data.options.timestamps !== false &&\n !data.options.noTimestamps,\n });\n\n if (!hasMigration) {\n await putFileAsync(migrationPath, migrationContent);\n }\n\n reportSkippedFiles();\n\n console.log(colors.cyan(`\\n✨ Model \"${name.pascal}\" generated successfully!`));\n console.log(colors.gray(`\\nNext steps:`));\n console.log(colors.gray(` 1. Update model schema in ${name.kebab}.model.ts`));\n console.log(\n colors.gray(\n hasMigration\n ? ` 2. Existing migration kept; add changes with: warlock gen.migration ${module}/${name.kebab} --add ...`\n : ` 2. Update migration in migrations/${timestamp}-${name.kebab}.migration.ts`,\n ),\n );\n console.log(colors.gray(` 3. Run migration: warlock migrate`));\n}\n"],"mappings":"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"}
@@ -33,7 +33,9 @@ async function generateRepository(data) {
33
33
  process.exit(1);
34
34
  }
35
35
  await ensureComponentDirectory(module, "repositories");
36
- await putFileAsync(resolveComponentPath(module, "repositories", `${name.kebab}.repository`), repositoryStub(name));
36
+ const repositoryPath = resolveComponentPath(module, "repositories", `${name.kebab}.repository`);
37
+ const repositoryContent = repositoryStub(name);
38
+ await putFileAsync(repositoryPath, repositoryContent);
37
39
  console.log(colors.cyan(`\nRepository "${name.pascal}Repository" generated successfully!`));
38
40
  }
39
41
 
@@ -1 +1 @@
1
- {"version":3,"file":"repository.generator.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/repository.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { repositoryStub } from \"../templates/stubs\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\n\nexport async function generateRepository(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Repository name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.repository users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if repository already exists\n if ((await componentExists(module, \"repositories\", `${name.kebab}.repository`)) && !force) {\n console.log(colors.red(`Error: Repository \"${name.kebab}.repository.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"repositories\");\n\n // Generate repository\n const repositoryPath = resolveComponentPath(module, \"repositories\", `${name.kebab}.repository`);\n const repositoryContent = repositoryStub(name);\n\n await putFileAsync(repositoryPath, repositoryContent);\n\n console.log(colors.cyan(`\\nRepository \"${name.pascal}Repository\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,iDAAiD,CAAC;EAC5E,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,IAAK,MAAM,gBAAgB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACzF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,cAAc;CAMrD,MAAM,aAHiB,qBAAqB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAGlD,GAFN,eAAe,IAEU,CAAC;CAEpD,QAAQ,IAAI,OAAO,KAAK,iBAAiB,KAAK,OAAO,oCAAoC,CAAC;AAC5F"}
1
+ {"version":3,"file":"repository.generator.mjs","names":[],"sources":["../../../../../../../../../../../packages/core/src/cli/commands/generate/generators/repository.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { repositoryStub } from \"../templates/stubs\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\n\nexport async function generateRepository(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Repository name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.repository users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if repository already exists\n if ((await componentExists(module, \"repositories\", `${name.kebab}.repository`)) && !force) {\n console.log(colors.red(`Error: Repository \"${name.kebab}.repository.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"repositories\");\n\n // Generate repository\n const repositoryPath = resolveComponentPath(module, \"repositories\", `${name.kebab}.repository`);\n const repositoryContent = repositoryStub(name);\n\n await putFileAsync(repositoryPath, repositoryContent);\n\n console.log(colors.cyan(`\\nRepository \"${name.pascal}Repository\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,iDAAiD,CAAC;EAC5E,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,IAAK,MAAM,gBAAgB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACzF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,cAAc;CAGrD,MAAM,iBAAiB,qBAAqB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAAY;CAC9F,MAAM,oBAAoB,eAAe,IAAI;CAE7C,MAAM,aAAa,gBAAgB,iBAAiB;CAEpD,QAAQ,IAAI,OAAO,KAAK,iBAAiB,KAAK,OAAO,oCAAoC,CAAC;AAC5F"}