@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
@@ -34,27 +34,35 @@
34
34
  * it imports nothing.
35
35
  */
36
36
  /** The area a code belongs to, matching its first digit. */
37
- type ErrorCodeArea = "config" | "boot" | "routing" | "validation" | "http" | "database" | "cli" | "environment" | "convention";
37
+ export type ErrorCodeArea = "config" | "boot" | "routing" | "validation" | "http" | "database" | "cli" | "environment" | "convention";
38
38
  /**
39
39
  * Who has to act: `code` problems are fixed in the project's source or config,
40
40
  * `environment` problems on the machine running it.
41
41
  */
42
- type ErrorCodeCategory = "code" | "environment";
42
+ export type ErrorCodeCategory = "code" | "environment";
43
43
  /** One registry entry. */
44
- type ErrorCodeDefinition = {
45
- /** The stable code, e.g. `"WL3001"`. */readonly code: string; /** The area, matching the first digit. */
46
- readonly area: ErrorCodeArea; /** Whether the project or the machine has to change. */
47
- readonly category: ErrorCodeCategory; /** One-line name of the problem. */
48
- readonly title: string; /** One-line "what to do". */
49
- readonly fix: string; /** Slug of the skill that explains the fix (`packages/<pkg>/skills/<slug>/SKILL.md`). */
50
- readonly skill: string; /** Names of the error classes that carry this code, when an error class does. */
51
- readonly errorNames?: readonly string[]; /** Set when the code is no longer emitted. Retired codes are never reused. */
44
+ export type ErrorCodeDefinition = {
45
+ /** The stable code, e.g. `"WL3001"`. */
46
+ readonly code: string;
47
+ /** The area, matching the first digit. */
48
+ readonly area: ErrorCodeArea;
49
+ /** Whether the project or the machine has to change. */
50
+ readonly category: ErrorCodeCategory;
51
+ /** One-line name of the problem. */
52
+ readonly title: string;
53
+ /** One-line "what to do". */
54
+ readonly fix: string;
55
+ /** Slug of the skill that explains the fix (`packages/<pkg>/skills/<slug>/SKILL.md`). */
56
+ readonly skill: string;
57
+ /** Names of the error classes that carry this code, when an error class does. */
58
+ readonly errorNames?: readonly string[];
59
+ /** Set when the code is no longer emitted. Retired codes are never reused. */
52
60
  readonly retired?: true;
53
61
  };
54
62
  /** Base URL of the error-code reference; each code is an anchor on that page. */
55
- declare const ERROR_CODES_DOCS_URL = "https://warlock.js.org/v/latest/core/cli/error-codes/";
63
+ export declare const ERROR_CODES_DOCS_URL = "https://warlock.js.org/v/latest/core/cli/error-codes/";
56
64
  /** The registry, keyed by code. */
57
- declare const ERROR_CODES: {
65
+ export declare const ERROR_CODES: {
58
66
  readonly WL1001: {
59
67
  readonly code: "WL1001";
60
68
  readonly area: "config";
@@ -76,7 +84,7 @@ declare const ERROR_CODES: {
76
84
  readonly area: "config";
77
85
  readonly category: "code";
78
86
  readonly title: "The rate-limit store cannot use the configured cache driver";
79
- readonly fix: "Use a redis, pg or memory cache driver for http.rateLimit store \"cache\", or set store: \"memory\".";
87
+ readonly fix: 'Use a redis, pg or memory cache driver for http.rateLimit store "cache", or set store: "memory".';
80
88
  readonly skill: "configure-app";
81
89
  readonly errorNames: readonly ["UnsupportedRateLimitDriverError"];
82
90
  };
@@ -181,7 +189,7 @@ declare const ERROR_CODES: {
181
189
  readonly area: "boot";
182
190
  readonly category: "code";
183
191
  readonly title: "Storage was used before the storage connector ran";
184
- readonly fix: "Add src/config/storage.ts; in a custom command add \"storage\" to preload.connectors.";
192
+ readonly fix: 'Add src/config/storage.ts; in a custom command add "storage" to preload.connectors.';
185
193
  readonly skill: "store-file";
186
194
  readonly errorNames: readonly ["StorageNotInitializedError"];
187
195
  };
@@ -198,7 +206,7 @@ declare const ERROR_CODES: {
198
206
  readonly area: "routing";
199
207
  readonly category: "code";
200
208
  readonly title: "A route name is already taken";
201
- readonly fix: "Rename one of the two routes with the \"name\" route option; pages and API routes share one namespace.";
209
+ readonly fix: 'Rename one of the two routes with the "name" route option; pages and API routes share one namespace.';
202
210
  readonly skill: "register-route";
203
211
  readonly errorNames: readonly ["RouteNameTakenError"];
204
212
  };
@@ -534,7 +542,7 @@ declare const ERROR_CODES: {
534
542
  readonly area: "convention";
535
543
  readonly category: "code";
536
544
  readonly title: "tsconfig.json enables legacy experimentalDecorators";
537
- readonly fix: "Remove \"experimentalDecorators\": true from tsconfig.json; Cascade uses standard decorators.";
545
+ readonly fix: 'Remove "experimentalDecorators": true from tsconfig.json; Cascade uses standard decorators.';
538
546
  readonly skill: "lower-stage3-decorators";
539
547
  };
540
548
  readonly WL9005: {
@@ -627,16 +635,16 @@ declare const ERROR_CODES: {
627
635
  };
628
636
  };
629
637
  /** Every registered code, as a union. */
630
- type WarlockErrorCode = keyof typeof ERROR_CODES;
638
+ export type WarlockErrorCode = keyof typeof ERROR_CODES;
631
639
  /** Whether `value` is a registered code. */
632
- declare function isWarlockErrorCode(value: unknown): value is WarlockErrorCode;
640
+ export declare function isWarlockErrorCode(value: unknown): value is WarlockErrorCode;
633
641
  /**
634
642
  * The registry entry for a code, or `undefined` for an unknown one. Case and
635
643
  * surrounding whitespace are ignored, so `explainErrorCode(" wl3001 ")` works.
636
644
  */
637
- declare function explainErrorCode(code: string): ErrorCodeDefinition | undefined;
645
+ export declare function explainErrorCode(code: string): ErrorCodeDefinition | undefined;
638
646
  /** The docs URL of a code: the reference page with the code as its anchor. */
639
- declare function errorCodeDocsUrl(code: WarlockErrorCode): string;
647
+ export declare function errorCodeDocsUrl(code: WarlockErrorCode): string;
640
648
  /**
641
649
  * The Warlock code of a thrown value, or `undefined` when it has none.
642
650
  *
@@ -647,7 +655,6 @@ declare function errorCodeDocsUrl(code: WarlockErrorCode): string;
647
655
  * by name rather than `instanceof` keeps the answer right when two copies of
648
656
  * core are loaded.
649
657
  */
650
- declare function errorCodeOf(error: unknown): WarlockErrorCode | undefined;
658
+ export declare function errorCodeOf(error: unknown): WarlockErrorCode | undefined;
651
659
  //#endregion
652
- export { ERROR_CODES, ERROR_CODES_DOCS_URL, ErrorCodeArea, ErrorCodeCategory, ErrorCodeDefinition, WarlockErrorCode, errorCodeDocsUrl, errorCodeOf, explainErrorCode, isWarlockErrorCode };
653
660
  //# sourceMappingURL=error-codes.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"error-codes.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/errors/error-codes.ts"],"mappings":";;AAoCA;;;;AAAyB;AAezB;;;;AAA6B;AAG7B;;;;;;;;;;;;;;;AAgBkB;AAIlB;;;;AAAiC;AAGjC;;;KAzCY,aAAA;;;;;KAeA,iBAAA;;KAGA,mBAAA;mDAED,IAAA;WAEA,IAAA,EAAM,aAAA;WAEN,QAAA,EAAU,iBAAiB;WAE3B,KAAA;WAEA,GAAA;WAEA,KAAA;WAEA,UAAA;WAEA,OAAA;AAAA;;cAIE,oBAAA;;cAGA,WAAA;EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+kBD,gBAAA,gBAAgC,WAAW;;iBAGvC,kBAAA,CAAmB,KAAA,YAAiB,KAAA,IAAS,gBAAgB;;;;;iBAQ7D,gBAAA,CAAiB,IAAA,WAAe,mBAAmB;;iBAOnD,gBAAA,CAAiB,IAAsB,EAAhB,gBAAgB;;;;;;;;;;;iBA8BvC,WAAA,CAAY,KAAA,YAAiB,gBAAgB"}
1
+ {"version":3,"file":"error-codes.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/errors/error-codes.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAoCY;;;;;YAeA;;YAGA;;WAED;;WAEA,MAAM;;WAEN,UAAU;;WAEV;;WAEA;;WAEA;;WAEA;;WAEA;;;qBAIE;;qBAGA;;aAGT;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAKA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;aAGA;aACA;aACA;aACA;aACA;aACA;;;;YAKQ,gCAAgC;;wBAG5B,mBAAmB,iBAAiB,SAAS;;;;;wBAQ7C,iBAAiB,eAAe;;wBAOhC,iBAAiB,MAAM;;;;;;;;;;;wBA8BvB,YAAY,iBAAiB"}
@@ -1,5 +1,4 @@
1
1
  import { WarlockErrorCode } from "./error-codes.mjs";
2
-
3
2
  //#region ../../packages/core/src/errors/warlock-error.d.ts
4
3
  /**
5
4
  * A framework error with a stable {@link WarlockErrorCode}.
@@ -11,7 +10,7 @@ import { WarlockErrorCode } from "./error-codes.mjs";
11
10
  * @example
12
11
  * throw new WarlockError("WL3003", `Route name "${name}" not found`);
13
12
  */
14
- declare class WarlockError extends Error {
13
+ export declare class WarlockError extends Error {
15
14
  /** Stable Warlock error code; `warlock explain <code>` prints the fix. */
16
15
  readonly code: WarlockErrorCode;
17
16
  constructor(code: WarlockErrorCode, message: string, options?: {
@@ -19,5 +18,4 @@ declare class WarlockError extends Error {
19
18
  });
20
19
  }
21
20
  //#endregion
22
- export { WarlockError };
23
21
  //# sourceMappingURL=warlock-error.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"warlock-error.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/errors/warlock-error.ts"],"mappings":";;;;;AAYA;;;;;;;;cAAa,YAAA,SAAqB,KAAA;EAEhB;EAAA,SAAA,IAAA,EAAM,gBAAA;cAEH,IAAA,EAAM,gBAAA,EAAkB,OAAA,UAAiB,OAAA;IAAY,KAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"warlock-error.d.mts","names":[],"sources":["../../../../../../../../packages/core/src/errors/warlock-error.ts"],"mappings":";;;;;;;;;;;;qBAYa,qBAAqB;;WAEhB,MAAM;EAEtB,YAAmB,MAAM,kBAAkB,iBAAiB;IAAY"}
@@ -138,7 +138,8 @@ async function approvePnpmSharpBuild() {
138
138
  const layout = pnpmBuildApprovalLayout(getPnpmVersion(rootPath()));
139
139
  if (layout === "packageJson") {
140
140
  const packageJsonPath = rootPath("package.json");
141
- await putJsonFileAsync(packageJsonPath, mergePackageJsonBuildApprovals(await getJsonFileAsync(packageJsonPath), ["sharp"]));
141
+ const packageJson = await getJsonFileAsync(packageJsonPath);
142
+ await putJsonFileAsync(packageJsonPath, mergePackageJsonBuildApprovals(packageJson, ["sharp"]));
142
143
  return;
143
144
  }
144
145
  const current = hasWorkspaceFile ? await getFileAsync(workspacePath) : "";
@@ -207,5 +208,5 @@ function validateFeatures(features) {
207
208
  }
208
209
 
209
210
  //#endregion
210
- export { addCommandAction };
211
+ export { addCommandAction, allowedFeatures, featuresMap, installDependencies, resolveWarlockDependencyVersions };
211
212
  //# sourceMappingURL=add-command.action.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"add-command.action.mjs","names":[],"sources":["../../../../../../../../packages/core/src/generations/add-command.action.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n fileExistsAsync,\n getFileAsync,\n getJsonFileAsync,\n putFileAsync,\n putJsonFileAsync,\n recordSkippedFile,\n} from \"./generation-fs\";\nimport { isGenerationDryRun, setGenerationDetail } from \"./generation-run\";\nimport { execSync } from \"node:child_process\";\nimport type { CommandActionData } from \"../commands/types\";\nimport {\n detectPackageManager,\n getAddCommand,\n getExactAddCommand,\n type PackageManager,\n} from \"../updater/package-manager\";\nimport { rootPath, srcPath } from \"../utils\";\nimport { getWarlockVersion } from \"../utils/framework-vesion\";\nimport { featuresMap } from \"./features\";\nimport {\n getPnpmVersion,\n isInsideParentPnpmWorkspace,\n mergeOnlyBuiltDependencies,\n mergePackageJsonBuildApprovals,\n mergePnpmSharpApproval,\n pnpmBuildApprovalLayout,\n} from \"./pnpm-build-approvals\";\n\nexport { featuresMap };\nexport type { FeatureDefinition } from \"./features\";\n\n/**\n * The parts of a project `package.json` this action reads or writes. Deliberately\n * partial — it describes what we touch, not the whole manifest.\n */\ntype ProjectPackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n};\n\nexport const allowedFeatures = Object.keys(featuresMap);\n\nfunction isWarlockPackage(packageName: string): boolean {\n return packageName.startsWith(\"@warlock.js/\");\n}\n\n/**\n * Resolve the internal feature-map placeholder to the version of Core that is\n * actually executing the command. Every @warlock.js package is lockstep, so\n * Core is the single source of truth; non-Warlock dependencies are untouched.\n */\nexport function resolveWarlockDependencyVersions(\n dependencies: Record<string, string>,\n frameworkVersion: string,\n): void {\n for (const dependency of Object.keys(dependencies)) {\n if (isWarlockPackage(dependency)) {\n dependencies[dependency] = frameworkVersion;\n }\n }\n}\n\nfunction resolveFeatures(features: string[], visited = new Set<string>()): string[] {\n const resolved: string[] = [];\n\n for (const feature of features) {\n if (visited.has(feature)) continue;\n visited.add(feature);\n\n const def = featuresMap[feature];\n\n // `addCommandAction` runs `validateFeatures()` before calling this, and the\n // recursive calls below pass `requires` entries that come out of the map\n // itself — so every lookup resolves. Skipping an unresolvable one keeps a\n // typo from crashing the command with `Cannot read properties of\n // undefined`, which names neither the feature nor the fact that it was the\n // ARGUMENT that was wrong.\n if (def === undefined) continue;\n\n if (def.requires?.length) {\n resolved.push(...resolveFeatures(def.requires, visited));\n }\n\n resolved.push(feature);\n }\n\n return resolved;\n}\n\nexport async function addCommandAction(options: CommandActionData) {\n const features = options.args;\n const { packageManager, list, noInstall } = options.options;\n\n if (list) {\n setGenerationDetail(\n \"features\",\n allowedFeatures.map((feature) => ({\n name: feature,\n description: featuresMap[feature]?.description ?? \"\",\n })),\n );\n\n console.log(\"Available Features:\");\n\n for (const feature of allowedFeatures) {\n const definition = featuresMap[feature];\n\n // `allowedFeatures` is derived from this same map, so this resolves.\n if (definition === undefined) continue;\n\n console.log(`- ${colors.yellowBright(feature)}: ${colors.green(definition.description)}`);\n }\n\n process.exit(0);\n }\n\n validateFeatures(features);\n\n const resolvedFeatures = resolveFeatures(features);\n\n const dependencies: Record<string, string> = {};\n const devDependencies: Record<string, string> = {};\n const ejectConfigs: Record<string, { content: string; name: string }> = {};\n const scripts: Record<string, string> = {};\n\n for (const feature of resolvedFeatures) {\n const featurePackages = featuresMap[feature as keyof typeof featuresMap];\n\n // Validated upstream; see the note in resolveFeatures above.\n if (featurePackages === undefined) continue;\n\n Object.assign(dependencies, featurePackages.dependencies);\n if (featurePackages.devDependencies) {\n Object.assign(devDependencies, featurePackages.devDependencies);\n }\n\n if (featurePackages.ejectConfig) {\n ejectConfigs[featurePackages.ejectConfig.name] = featurePackages.ejectConfig;\n }\n\n if (featurePackages.script) {\n Object.assign(scripts, featurePackages.script);\n }\n }\n\n // Pin every @warlock.js/* feature package to the INSTALLED framework version so\n // a scaffolded project's features match its core version instead of drifting to\n // the feature map's static range.\n const frameworkVersion = await getWarlockVersion();\n resolveWarlockDependencyVersions(dependencies, frameworkVersion);\n resolveWarlockDependencyVersions(devDependencies, frameworkVersion);\n\n const currentPackageJson = await getJsonFileAsync<ProjectPackageJson>(rootPath(\"package.json\"));\n\n // Fresh templates may omit one of the maps — guard before reading.\n currentPackageJson.dependencies = currentPackageJson.dependencies ?? {};\n currentPackageJson.devDependencies = currentPackageJson.devDependencies ?? {};\n\n // Skip anything already present so we never downgrade an existing pin.\n for (const dependency of Object.keys(dependencies)) {\n if (currentPackageJson.dependencies[dependency]) {\n console.log(`${colors.yellowBright(dependency)} is already installed, skipping...`);\n delete dependencies[dependency];\n }\n }\n\n for (const devDependency of Object.keys(devDependencies)) {\n if (currentPackageJson.devDependencies[devDependency]) {\n console.log(`${colors.yellowBright(devDependency)} is already installed, skipping...`);\n delete devDependencies[devDependency];\n }\n }\n\n setGenerationDetail(\"features\", resolvedFeatures);\n setGenerationDetail(\"dependencies\", { ...dependencies });\n setGenerationDetail(\"devDependencies\", { ...devDependencies });\n\n if (isGenerationDryRun()) {\n // A preview installs nothing; package.json is \"edited\" in the overlay so\n // the report lists it, and later steps read the previewed manifest.\n console.log(\n `Dry run: would install ${colors.magenta(Object.keys({ ...dependencies, ...devDependencies }).join(\", \") || \"nothing\")}`,\n );\n await recordDependencies(dependencies, devDependencies);\n } else if (noInstall) {\n await recordDependencies(dependencies, devDependencies);\n } else {\n const resolvedPackageManager =\n (packageManager as PackageManager | undefined) ?? (await detectPackageManager());\n if (resolvedPackageManager === \"pnpm\" && dependencies.sharp !== undefined) {\n await approvePnpmSharpBuild();\n }\n await installDependencies(\n packageManager as PackageManager | undefined,\n dependencies,\n devDependencies,\n );\n }\n\n for (const [name, config] of Object.entries(ejectConfigs)) {\n if (await fileExistsAsync(srcPath(`config/${name}.ts`))) {\n recordSkippedFile(srcPath(`config/${name}.ts`), \"exists\");\n console.log(`${colors.yellowBright(name)} config already exists, skipping...`);\n continue;\n }\n\n console.log(`Creating ${colors.magenta(name)} config...`);\n\n await putFileAsync(srcPath(`config/${name}.ts`), config.content);\n\n console.log(`${colors.green(name)} config created successfully`);\n }\n\n // now loop again over features to execute onExecuting\n for (const feature of resolvedFeatures) {\n const featurePackages = featuresMap[feature as keyof typeof featuresMap];\n\n if (featurePackages?.onExecuting) {\n await featurePackages.onExecuting(options);\n }\n }\n\n setGenerationDetail(\"scripts\", { ...scripts });\n\n if (Object.keys(scripts).length > 0) {\n console.log(`Adding scripts ${colors.magenta(Object.keys(scripts).join(\", \"))}`);\n const packageJsonPath = rootPath(\"package.json\");\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(packageJsonPath);\n packageJson.scripts = { ...(packageJson.scripts ?? {}), ...scripts };\n await putJsonFileAsync(packageJsonPath, packageJson);\n\n console.log(`Scripts added successfully ${colors.green(Object.keys(scripts).join(\", \"))}`);\n }\n}\n\n/**\n * Let pnpm run sharp's install script, written where the INSTALLED pnpm reads\n * approvals (see `pnpmBuildApprovalLayout`). pnpm 9 and 10.0–10.4 reject a\n * settings-only `pnpm-workspace.yaml`, so for them the approval goes into\n * package.json and no workspace file is created.\n *\n * An app inside a parent pnpm workspace gets no per-app policy: the parent's\n * workspace owns it, and a nested workspace file would make a second root.\n */\nasync function approvePnpmSharpBuild(): Promise<void> {\n const workspacePath = rootPath(\"pnpm-workspace.yaml\");\n const hasWorkspaceFile = await fileExistsAsync(workspacePath);\n\n if (!hasWorkspaceFile && isInsideParentPnpmWorkspace(rootPath())) {\n console.log(\n `${colors.yellowBright(\"sharp\")} needs its install script approved in the parent pnpm workspace's settings.`,\n );\n return;\n }\n\n const layout = pnpmBuildApprovalLayout(getPnpmVersion(rootPath()));\n\n if (layout === \"packageJson\") {\n const packageJsonPath = rootPath(\"package.json\");\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(packageJsonPath);\n\n await putJsonFileAsync(packageJsonPath, mergePackageJsonBuildApprovals(packageJson, [\"sharp\"]));\n return;\n }\n\n const current = hasWorkspaceFile ? await getFileAsync(workspacePath) : \"\";\n const updated =\n layout === \"onlyBuiltDependencies\"\n ? mergeOnlyBuiltDependencies(current, [\"sharp\"])\n : mergePnpmSharpApproval(current);\n\n if (updated !== current) await putFileAsync(workspacePath, updated);\n}\n\n/**\n * Install the resolved dependency sets through the project's package manager.\n * Runs two passes (prod then dev) so each lands in the correct section.\n */\nexport async function installDependencies(\n packageManager: PackageManager | undefined,\n dependencies: Record<string, string>,\n devDependencies: Record<string, string>,\n exec: (command: string, options: { cwd: string; stdio: \"inherit\" }) => unknown = execSync,\n) {\n // `--package-manager` is optional; without it, fall back to the lockfile.\n const resolvedPackageManager = packageManager ?? (await detectPackageManager());\n const packageManagerCommand = getAddCommand(resolvedPackageManager);\n const exactPackageManagerCommand = getExactAddCommand(resolvedPackageManager);\n\n const installDependencySet = (dependencySet: Record<string, string>, development: boolean) => {\n const regularSpecs: string[] = [];\n const exactWarlockSpecs: string[] = [];\n\n for (const [name, version] of Object.entries(dependencySet)) {\n const spec = `${name}@${version}`;\n (isWarlockPackage(name) ? exactWarlockSpecs : regularSpecs).push(spec);\n }\n\n const developmentFlag = development ? \" -D\" : \"\";\n const runInstall = (command: string, specs: string[]) => {\n if (specs.length === 0) return;\n\n exec(`${command} ${specs.join(\" \")}${developmentFlag}`, {\n cwd: process.cwd(),\n stdio: \"inherit\",\n });\n };\n\n runInstall(packageManagerCommand, regularSpecs);\n runInstall(exactPackageManagerCommand, exactWarlockSpecs);\n };\n\n if (Object.keys(dependencies).length > 0) {\n console.log(`Installing dependencies ${colors.magenta(Object.keys(dependencies).join(\", \"))}`);\n\n installDependencySet(dependencies, false);\n\n console.log(\n `Dependencies installed successfully ${colors.green(Object.keys(dependencies).join(\", \"))}`,\n );\n }\n\n if (Object.keys(devDependencies).length > 0) {\n console.log(\n `Installing dev dependencies ${colors.magenta(Object.keys(devDependencies).join(\", \"))}`,\n );\n\n installDependencySet(devDependencies, true);\n\n console.log(\n `Dev dependencies installed successfully ${colors.green(Object.keys(devDependencies).join(\", \"))}`,\n );\n }\n}\n\n/**\n * Write the resolved dependency sets into package.json without installing.\n * Used by `--no-install` so a scaffolder can batch every feature into one\n * install pass after the command returns. Versions come from the feature map.\n */\nasync function recordDependencies(\n dependencies: Record<string, string>,\n devDependencies: Record<string, string>,\n) {\n if (Object.keys(dependencies).length === 0 && Object.keys(devDependencies).length === 0) {\n return;\n }\n\n const packageJsonPath = rootPath(\"package.json\");\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(packageJsonPath);\n\n packageJson.dependencies = packageJson.dependencies ?? {};\n packageJson.devDependencies = packageJson.devDependencies ?? {};\n\n Object.assign(packageJson.dependencies, dependencies);\n Object.assign(packageJson.devDependencies, devDependencies);\n\n await putJsonFileAsync(packageJsonPath, packageJson);\n\n const recorded = [...Object.keys(dependencies), ...Object.keys(devDependencies)];\n\n console.log(\n `Recorded ${colors.green(recorded.join(\", \"))} in package.json (${isGenerationDryRun() ? \"dry run: nothing installed\" : \"install skipped via --no-install\"})`,\n );\n}\n\nfunction validateFeatures(features: string[]) {\n for (const feature of features) {\n if (!allowedFeatures.includes(feature)) {\n console.log(\n `Feature ${colors.redBright(feature)} is not allowed, allowed features are: ${colors.green(allowedFeatures.join(\", \"))}`,\n );\n process.exit(1);\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"add-command.action.mjs","names":[],"sources":["../../../../../../../../packages/core/src/generations/add-command.action.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport {\n fileExistsAsync,\n getFileAsync,\n getJsonFileAsync,\n putFileAsync,\n putJsonFileAsync,\n recordSkippedFile,\n} from \"./generation-fs\";\nimport { isGenerationDryRun, setGenerationDetail } from \"./generation-run\";\nimport { execSync } from \"node:child_process\";\nimport type { CommandActionData } from \"../commands/types\";\nimport {\n detectPackageManager,\n getAddCommand,\n getExactAddCommand,\n type PackageManager,\n} from \"../updater/package-manager\";\nimport { rootPath, srcPath } from \"../utils\";\nimport { getWarlockVersion } from \"../utils/framework-vesion\";\nimport { featuresMap } from \"./features\";\nimport {\n getPnpmVersion,\n isInsideParentPnpmWorkspace,\n mergeOnlyBuiltDependencies,\n mergePackageJsonBuildApprovals,\n mergePnpmSharpApproval,\n pnpmBuildApprovalLayout,\n} from \"./pnpm-build-approvals\";\n\nexport { featuresMap };\nexport type { FeatureDefinition } from \"./features\";\n\n/**\n * The parts of a project `package.json` this action reads or writes. Deliberately\n * partial — it describes what we touch, not the whole manifest.\n */\ntype ProjectPackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n scripts?: Record<string, string>;\n};\n\nexport const allowedFeatures = Object.keys(featuresMap);\n\nfunction isWarlockPackage(packageName: string): boolean {\n return packageName.startsWith(\"@warlock.js/\");\n}\n\n/**\n * Resolve the internal feature-map placeholder to the version of Core that is\n * actually executing the command. Every @warlock.js package is lockstep, so\n * Core is the single source of truth; non-Warlock dependencies are untouched.\n */\nexport function resolveWarlockDependencyVersions(\n dependencies: Record<string, string>,\n frameworkVersion: string,\n): void {\n for (const dependency of Object.keys(dependencies)) {\n if (isWarlockPackage(dependency)) {\n dependencies[dependency] = frameworkVersion;\n }\n }\n}\n\nfunction resolveFeatures(features: string[], visited = new Set<string>()): string[] {\n const resolved: string[] = [];\n\n for (const feature of features) {\n if (visited.has(feature)) continue;\n visited.add(feature);\n\n const def = featuresMap[feature];\n\n // `addCommandAction` runs `validateFeatures()` before calling this, and the\n // recursive calls below pass `requires` entries that come out of the map\n // itself — so every lookup resolves. Skipping an unresolvable one keeps a\n // typo from crashing the command with `Cannot read properties of\n // undefined`, which names neither the feature nor the fact that it was the\n // ARGUMENT that was wrong.\n if (def === undefined) continue;\n\n if (def.requires?.length) {\n resolved.push(...resolveFeatures(def.requires, visited));\n }\n\n resolved.push(feature);\n }\n\n return resolved;\n}\n\nexport async function addCommandAction(options: CommandActionData) {\n const features = options.args;\n const { packageManager, list, noInstall } = options.options;\n\n if (list) {\n setGenerationDetail(\n \"features\",\n allowedFeatures.map((feature) => ({\n name: feature,\n description: featuresMap[feature]?.description ?? \"\",\n })),\n );\n\n console.log(\"Available Features:\");\n\n for (const feature of allowedFeatures) {\n const definition = featuresMap[feature];\n\n // `allowedFeatures` is derived from this same map, so this resolves.\n if (definition === undefined) continue;\n\n console.log(`- ${colors.yellowBright(feature)}: ${colors.green(definition.description)}`);\n }\n\n process.exit(0);\n }\n\n validateFeatures(features);\n\n const resolvedFeatures = resolveFeatures(features);\n\n const dependencies: Record<string, string> = {};\n const devDependencies: Record<string, string> = {};\n const ejectConfigs: Record<string, { content: string; name: string }> = {};\n const scripts: Record<string, string> = {};\n\n for (const feature of resolvedFeatures) {\n const featurePackages = featuresMap[feature as keyof typeof featuresMap];\n\n // Validated upstream; see the note in resolveFeatures above.\n if (featurePackages === undefined) continue;\n\n Object.assign(dependencies, featurePackages.dependencies);\n if (featurePackages.devDependencies) {\n Object.assign(devDependencies, featurePackages.devDependencies);\n }\n\n if (featurePackages.ejectConfig) {\n ejectConfigs[featurePackages.ejectConfig.name] = featurePackages.ejectConfig;\n }\n\n if (featurePackages.script) {\n Object.assign(scripts, featurePackages.script);\n }\n }\n\n // Pin every @warlock.js/* feature package to the INSTALLED framework version so\n // a scaffolded project's features match its core version instead of drifting to\n // the feature map's static range.\n const frameworkVersion = await getWarlockVersion();\n resolveWarlockDependencyVersions(dependencies, frameworkVersion);\n resolveWarlockDependencyVersions(devDependencies, frameworkVersion);\n\n const currentPackageJson = await getJsonFileAsync<ProjectPackageJson>(rootPath(\"package.json\"));\n\n // Fresh templates may omit one of the maps — guard before reading.\n currentPackageJson.dependencies = currentPackageJson.dependencies ?? {};\n currentPackageJson.devDependencies = currentPackageJson.devDependencies ?? {};\n\n // Skip anything already present so we never downgrade an existing pin.\n for (const dependency of Object.keys(dependencies)) {\n if (currentPackageJson.dependencies[dependency]) {\n console.log(`${colors.yellowBright(dependency)} is already installed, skipping...`);\n delete dependencies[dependency];\n }\n }\n\n for (const devDependency of Object.keys(devDependencies)) {\n if (currentPackageJson.devDependencies[devDependency]) {\n console.log(`${colors.yellowBright(devDependency)} is already installed, skipping...`);\n delete devDependencies[devDependency];\n }\n }\n\n setGenerationDetail(\"features\", resolvedFeatures);\n setGenerationDetail(\"dependencies\", { ...dependencies });\n setGenerationDetail(\"devDependencies\", { ...devDependencies });\n\n if (isGenerationDryRun()) {\n // A preview installs nothing; package.json is \"edited\" in the overlay so\n // the report lists it, and later steps read the previewed manifest.\n console.log(\n `Dry run: would install ${colors.magenta(Object.keys({ ...dependencies, ...devDependencies }).join(\", \") || \"nothing\")}`,\n );\n await recordDependencies(dependencies, devDependencies);\n } else if (noInstall) {\n await recordDependencies(dependencies, devDependencies);\n } else {\n const resolvedPackageManager =\n (packageManager as PackageManager | undefined) ?? (await detectPackageManager());\n if (resolvedPackageManager === \"pnpm\" && dependencies.sharp !== undefined) {\n await approvePnpmSharpBuild();\n }\n await installDependencies(\n packageManager as PackageManager | undefined,\n dependencies,\n devDependencies,\n );\n }\n\n for (const [name, config] of Object.entries(ejectConfigs)) {\n if (await fileExistsAsync(srcPath(`config/${name}.ts`))) {\n recordSkippedFile(srcPath(`config/${name}.ts`), \"exists\");\n console.log(`${colors.yellowBright(name)} config already exists, skipping...`);\n continue;\n }\n\n console.log(`Creating ${colors.magenta(name)} config...`);\n\n await putFileAsync(srcPath(`config/${name}.ts`), config.content);\n\n console.log(`${colors.green(name)} config created successfully`);\n }\n\n // now loop again over features to execute onExecuting\n for (const feature of resolvedFeatures) {\n const featurePackages = featuresMap[feature as keyof typeof featuresMap];\n\n if (featurePackages?.onExecuting) {\n await featurePackages.onExecuting(options);\n }\n }\n\n setGenerationDetail(\"scripts\", { ...scripts });\n\n if (Object.keys(scripts).length > 0) {\n console.log(`Adding scripts ${colors.magenta(Object.keys(scripts).join(\", \"))}`);\n const packageJsonPath = rootPath(\"package.json\");\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(packageJsonPath);\n packageJson.scripts = { ...(packageJson.scripts ?? {}), ...scripts };\n await putJsonFileAsync(packageJsonPath, packageJson);\n\n console.log(`Scripts added successfully ${colors.green(Object.keys(scripts).join(\", \"))}`);\n }\n}\n\n/**\n * Let pnpm run sharp's install script, written where the INSTALLED pnpm reads\n * approvals (see `pnpmBuildApprovalLayout`). pnpm 9 and 10.0–10.4 reject a\n * settings-only `pnpm-workspace.yaml`, so for them the approval goes into\n * package.json and no workspace file is created.\n *\n * An app inside a parent pnpm workspace gets no per-app policy: the parent's\n * workspace owns it, and a nested workspace file would make a second root.\n */\nasync function approvePnpmSharpBuild(): Promise<void> {\n const workspacePath = rootPath(\"pnpm-workspace.yaml\");\n const hasWorkspaceFile = await fileExistsAsync(workspacePath);\n\n if (!hasWorkspaceFile && isInsideParentPnpmWorkspace(rootPath())) {\n console.log(\n `${colors.yellowBright(\"sharp\")} needs its install script approved in the parent pnpm workspace's settings.`,\n );\n return;\n }\n\n const layout = pnpmBuildApprovalLayout(getPnpmVersion(rootPath()));\n\n if (layout === \"packageJson\") {\n const packageJsonPath = rootPath(\"package.json\");\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(packageJsonPath);\n\n await putJsonFileAsync(packageJsonPath, mergePackageJsonBuildApprovals(packageJson, [\"sharp\"]));\n return;\n }\n\n const current = hasWorkspaceFile ? await getFileAsync(workspacePath) : \"\";\n const updated =\n layout === \"onlyBuiltDependencies\"\n ? mergeOnlyBuiltDependencies(current, [\"sharp\"])\n : mergePnpmSharpApproval(current);\n\n if (updated !== current) await putFileAsync(workspacePath, updated);\n}\n\n/**\n * Install the resolved dependency sets through the project's package manager.\n * Runs two passes (prod then dev) so each lands in the correct section.\n */\nexport async function installDependencies(\n packageManager: PackageManager | undefined,\n dependencies: Record<string, string>,\n devDependencies: Record<string, string>,\n exec: (command: string, options: { cwd: string; stdio: \"inherit\" }) => unknown = execSync,\n) {\n // `--package-manager` is optional; without it, fall back to the lockfile.\n const resolvedPackageManager = packageManager ?? (await detectPackageManager());\n const packageManagerCommand = getAddCommand(resolvedPackageManager);\n const exactPackageManagerCommand = getExactAddCommand(resolvedPackageManager);\n\n const installDependencySet = (dependencySet: Record<string, string>, development: boolean) => {\n const regularSpecs: string[] = [];\n const exactWarlockSpecs: string[] = [];\n\n for (const [name, version] of Object.entries(dependencySet)) {\n const spec = `${name}@${version}`;\n (isWarlockPackage(name) ? exactWarlockSpecs : regularSpecs).push(spec);\n }\n\n const developmentFlag = development ? \" -D\" : \"\";\n const runInstall = (command: string, specs: string[]) => {\n if (specs.length === 0) return;\n\n exec(`${command} ${specs.join(\" \")}${developmentFlag}`, {\n cwd: process.cwd(),\n stdio: \"inherit\",\n });\n };\n\n runInstall(packageManagerCommand, regularSpecs);\n runInstall(exactPackageManagerCommand, exactWarlockSpecs);\n };\n\n if (Object.keys(dependencies).length > 0) {\n console.log(`Installing dependencies ${colors.magenta(Object.keys(dependencies).join(\", \"))}`);\n\n installDependencySet(dependencies, false);\n\n console.log(\n `Dependencies installed successfully ${colors.green(Object.keys(dependencies).join(\", \"))}`,\n );\n }\n\n if (Object.keys(devDependencies).length > 0) {\n console.log(\n `Installing dev dependencies ${colors.magenta(Object.keys(devDependencies).join(\", \"))}`,\n );\n\n installDependencySet(devDependencies, true);\n\n console.log(\n `Dev dependencies installed successfully ${colors.green(Object.keys(devDependencies).join(\", \"))}`,\n );\n }\n}\n\n/**\n * Write the resolved dependency sets into package.json without installing.\n * Used by `--no-install` so a scaffolder can batch every feature into one\n * install pass after the command returns. Versions come from the feature map.\n */\nasync function recordDependencies(\n dependencies: Record<string, string>,\n devDependencies: Record<string, string>,\n) {\n if (Object.keys(dependencies).length === 0 && Object.keys(devDependencies).length === 0) {\n return;\n }\n\n const packageJsonPath = rootPath(\"package.json\");\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(packageJsonPath);\n\n packageJson.dependencies = packageJson.dependencies ?? {};\n packageJson.devDependencies = packageJson.devDependencies ?? {};\n\n Object.assign(packageJson.dependencies, dependencies);\n Object.assign(packageJson.devDependencies, devDependencies);\n\n await putJsonFileAsync(packageJsonPath, packageJson);\n\n const recorded = [...Object.keys(dependencies), ...Object.keys(devDependencies)];\n\n console.log(\n `Recorded ${colors.green(recorded.join(\", \"))} in package.json (${isGenerationDryRun() ? \"dry run: nothing installed\" : \"install skipped via --no-install\"})`,\n );\n}\n\nfunction validateFeatures(features: string[]) {\n for (const feature of features) {\n if (!allowedFeatures.includes(feature)) {\n console.log(\n `Feature ${colors.redBright(feature)} is not allowed, allowed features are: ${colors.green(allowedFeatures.join(\", \"))}`,\n );\n process.exit(1);\n }\n }\n}\n"],"mappings":"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"}
@@ -22,7 +22,8 @@ async function addDashboardConfigBlock() {
22
22
  `);
23
23
  return;
24
24
  }
25
- const insertion = insertQueueDashboardBlock(await getFileAsync(configPath));
25
+ const current = await getFileAsync(configPath);
26
+ const insertion = insertQueueDashboardBlock(current);
26
27
  if (insertion.status === "already-present") {
27
28
  console.log(`${colors.yellowBright("dashboard")} config already present in src/config/queue.ts, skipping...`);
28
29
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"bull-board.feature.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/generations/features/bull-board.feature.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { fileExistsAsync, getFileAsync, getJsonFileAsync, putFileAsync } from \"../generation-fs\";\nimport type { CommandActionData } from \"../../commands/types\";\nimport { rootPath, srcPath } from \"../../utils\";\nimport { insertQueueDashboardBlock } from \"./shared/insert-queue-dashboard-block\";\nimport type { FeatureDefinition } from \"./types\";\n\n/** The parts of `package.json` this feature reads to check for its prerequisite. */\ntype ProjectPackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n};\n\n/**\n * Defensive floor: `requires: [\"queue\"]` normally installs queue first, so\n * this only fires when the dashboard step runs without it (e.g. called\n * directly), and then fails loudly instead of writing a half-wired config.\n */\nasync function isQueueInstalled(): Promise<boolean> {\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(rootPath(\"package.json\"));\n\n return Boolean(\n packageJson.dependencies?.[\"@warlock.js/queue\"] ||\n packageJson.devDependencies?.[\"@warlock.js/queue\"],\n );\n}\n\n/** Insert the `dashboard` block into `src/config/queue.ts`, without reformatting it. */\nasync function addDashboardConfigBlock(): Promise<void> {\n const configPath = srcPath(\"config/queue.ts\");\n\n if (!(await fileExistsAsync(configPath))) {\n console.log(\n `${colors.yellowBright(\"src/config/queue.ts\")} not found — add this to your queue config yourself:\\n` +\n ' dashboard: { enabled: true, path: \"/admin/queues\", middleware: [] },\\n',\n );\n\n return;\n }\n\n const current = await getFileAsync(configPath);\n const insertion = insertQueueDashboardBlock(current);\n\n if (insertion.status === \"already-present\") {\n console.log(\n `${colors.yellowBright(\"dashboard\")} config already present in src/config/queue.ts, skipping...`,\n );\n\n return;\n }\n\n if (insertion.status === \"unrecognised\") {\n console.log(\n `${colors.yellowBright(\"!\")} src/config/queue.ts has no recognisable ${colors.yellowBright(\"queueConfig\")} object — ` +\n \"add the dashboard block yourself:\\n\" +\n ' dashboard: { enabled: true, path: \"/admin/queues\", middleware: [] },\\n',\n );\n\n return;\n }\n\n await putFileAsync(configPath, insertion.next);\n console.log(`${colors.green(\"✓\")} Added dashboard config to src/config/queue.ts`);\n}\n\n/**\n * Wire the dashboard into the app: verify queue is installed, then add the\n * `dashboard` block to its config.\n */\nasync function completeBullBoardInstallation(_options: CommandActionData): Promise<void> {\n if (!(await isQueueInstalled())) {\n console.log(\n `${colors.redBright(\"✗\")} @warlock.js/queue is not installed — run ` +\n `${colors.yellowBright(\"warlock add queue\")} first, then ${colors.yellowBright(\"warlock add bull-board\")}.`,\n );\n process.exitCode = 1;\n\n return;\n }\n\n await addDashboardConfigBlock();\n\n console.log(\n \"\\nNext: guard the dashboard with a middleware before it ships to production — an empty \" +\n 'middleware list throws QueueDashboardUnguardedError at boot when NODE_ENV is \"production\".',\n );\n}\n\n/** `warlock add bull-board` — a config-driven bull-board dashboard for @warlock.js/queue. */\nexport const bullBoardFeature: FeatureDefinition = {\n description:\n \"Installs @bull-board/api and @bull-board/fastify and adds a dashboard block to src/config/queue.ts. Adds the queue feature first when it is missing.\",\n requires: [\"queue\"],\n dependencies: {\n \"@bull-board/api\": \"^9.10.2\",\n \"@bull-board/fastify\": \"^9.10.2\",\n },\n onExecuting: completeBullBoardInstallation,\n};\n"],"mappings":";;;;;;;;;;;;AAkBA,eAAe,mBAAqC;CAClD,MAAM,cAAc,MAAM,iBAAqC,SAAS,cAAc,CAAC;CAEvF,OAAO,QACL,YAAY,eAAe,wBAC3B,YAAY,kBAAkB,oBAChC;AACF;;AAGA,eAAe,0BAAyC;CACtD,MAAM,aAAa,QAAQ,iBAAiB;CAE5C,IAAI,CAAE,MAAM,gBAAgB,UAAU,GAAI;EACxC,QAAQ,IACN,GAAG,OAAO,aAAa,qBAAqB,EAAE;CAEhD;EAEA;CACF;CAGA,MAAM,YAAY,0BAA0B,MADtB,aAAa,UAAU,CACM;CAEnD,IAAI,UAAU,WAAW,mBAAmB;EAC1C,QAAQ,IACN,GAAG,OAAO,aAAa,WAAW,EAAE,4DACtC;EAEA;CACF;CAEA,IAAI,UAAU,WAAW,gBAAgB;EACvC,QAAQ,IACN,GAAG,OAAO,aAAa,GAAG,EAAE,2CAA2C,OAAO,aAAa,aAAa,EAAE;;CAG5G;EAEA;CACF;CAEA,MAAM,aAAa,YAAY,UAAU,IAAI;CAC7C,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,+CAA+C;AAClF;;;;;AAMA,eAAe,8BAA8B,UAA4C;CACvF,IAAI,CAAE,MAAM,iBAAiB,GAAI;EAC/B,QAAQ,IACN,GAAG,OAAO,UAAU,GAAG,EAAE,4CACpB,OAAO,aAAa,mBAAmB,EAAE,eAAe,OAAO,aAAa,wBAAwB,EAAE,EAC7G;EACA,QAAQ,WAAW;EAEnB;CACF;CAEA,MAAM,wBAAwB;CAE9B,QAAQ,IACN,qLAEF;AACF;;AAGA,MAAa,mBAAsC;CACjD,aACE;CACF,UAAU,CAAC,OAAO;CAClB,cAAc;EACZ,mBAAmB;EACnB,uBAAuB;CACzB;CACA,aAAa;AACf"}
1
+ {"version":3,"file":"bull-board.feature.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/generations/features/bull-board.feature.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { fileExistsAsync, getFileAsync, getJsonFileAsync, putFileAsync } from \"../generation-fs\";\nimport type { CommandActionData } from \"../../commands/types\";\nimport { rootPath, srcPath } from \"../../utils\";\nimport { insertQueueDashboardBlock } from \"./shared/insert-queue-dashboard-block\";\nimport type { FeatureDefinition } from \"./types\";\n\n/** The parts of `package.json` this feature reads to check for its prerequisite. */\ntype ProjectPackageJson = {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n};\n\n/**\n * Defensive floor: `requires: [\"queue\"]` normally installs queue first, so\n * this only fires when the dashboard step runs without it (e.g. called\n * directly), and then fails loudly instead of writing a half-wired config.\n */\nasync function isQueueInstalled(): Promise<boolean> {\n const packageJson = await getJsonFileAsync<ProjectPackageJson>(rootPath(\"package.json\"));\n\n return Boolean(\n packageJson.dependencies?.[\"@warlock.js/queue\"] ||\n packageJson.devDependencies?.[\"@warlock.js/queue\"],\n );\n}\n\n/** Insert the `dashboard` block into `src/config/queue.ts`, without reformatting it. */\nasync function addDashboardConfigBlock(): Promise<void> {\n const configPath = srcPath(\"config/queue.ts\");\n\n if (!(await fileExistsAsync(configPath))) {\n console.log(\n `${colors.yellowBright(\"src/config/queue.ts\")} not found — add this to your queue config yourself:\\n` +\n ' dashboard: { enabled: true, path: \"/admin/queues\", middleware: [] },\\n',\n );\n\n return;\n }\n\n const current = await getFileAsync(configPath);\n const insertion = insertQueueDashboardBlock(current);\n\n if (insertion.status === \"already-present\") {\n console.log(\n `${colors.yellowBright(\"dashboard\")} config already present in src/config/queue.ts, skipping...`,\n );\n\n return;\n }\n\n if (insertion.status === \"unrecognised\") {\n console.log(\n `${colors.yellowBright(\"!\")} src/config/queue.ts has no recognisable ${colors.yellowBright(\"queueConfig\")} object — ` +\n \"add the dashboard block yourself:\\n\" +\n ' dashboard: { enabled: true, path: \"/admin/queues\", middleware: [] },\\n',\n );\n\n return;\n }\n\n await putFileAsync(configPath, insertion.next);\n console.log(`${colors.green(\"✓\")} Added dashboard config to src/config/queue.ts`);\n}\n\n/**\n * Wire the dashboard into the app: verify queue is installed, then add the\n * `dashboard` block to its config.\n */\nasync function completeBullBoardInstallation(_options: CommandActionData): Promise<void> {\n if (!(await isQueueInstalled())) {\n console.log(\n `${colors.redBright(\"✗\")} @warlock.js/queue is not installed — run ` +\n `${colors.yellowBright(\"warlock add queue\")} first, then ${colors.yellowBright(\"warlock add bull-board\")}.`,\n );\n process.exitCode = 1;\n\n return;\n }\n\n await addDashboardConfigBlock();\n\n console.log(\n \"\\nNext: guard the dashboard with a middleware before it ships to production — an empty \" +\n 'middleware list throws QueueDashboardUnguardedError at boot when NODE_ENV is \"production\".',\n );\n}\n\n/** `warlock add bull-board` — a config-driven bull-board dashboard for @warlock.js/queue. */\nexport const bullBoardFeature: FeatureDefinition = {\n description:\n \"Installs @bull-board/api and @bull-board/fastify and adds a dashboard block to src/config/queue.ts. Adds the queue feature first when it is missing.\",\n requires: [\"queue\"],\n dependencies: {\n \"@bull-board/api\": \"^9.10.2\",\n \"@bull-board/fastify\": \"^9.10.2\",\n },\n onExecuting: completeBullBoardInstallation,\n};\n"],"mappings":";;;;;;;;;;;;AAkBA,eAAe,mBAAqC;CAClD,MAAM,cAAc,MAAM,iBAAqC,SAAS,cAAc,CAAC;CAEvF,OAAO,QACL,YAAY,eAAe,wBAC3B,YAAY,kBAAkB,oBAChC;AACF;;AAGA,eAAe,0BAAyC;CACtD,MAAM,aAAa,QAAQ,iBAAiB;CAE5C,IAAI,CAAE,MAAM,gBAAgB,UAAU,GAAI;EACxC,QAAQ,IACN,GAAG,OAAO,aAAa,qBAAqB,EAAE;CAEhD;EAEA;CACF;CAEA,MAAM,UAAU,MAAM,aAAa,UAAU;CAC7C,MAAM,YAAY,0BAA0B,OAAO;CAEnD,IAAI,UAAU,WAAW,mBAAmB;EAC1C,QAAQ,IACN,GAAG,OAAO,aAAa,WAAW,EAAE,4DACtC;EAEA;CACF;CAEA,IAAI,UAAU,WAAW,gBAAgB;EACvC,QAAQ,IACN,GAAG,OAAO,aAAa,GAAG,EAAE,2CAA2C,OAAO,aAAa,aAAa,EAAE;;CAG5G;EAEA;CACF;CAEA,MAAM,aAAa,YAAY,UAAU,IAAI;CAC7C,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,+CAA+C;AAClF;;;;;AAMA,eAAe,8BAA8B,UAA4C;CACvF,IAAI,CAAE,MAAM,iBAAiB,GAAI;EAC/B,QAAQ,IACN,GAAG,OAAO,UAAU,GAAG,EAAE,4CACpB,OAAO,aAAa,mBAAmB,EAAE,eAAe,OAAO,aAAa,wBAAwB,EAAE,EAC7G;EACA,QAAQ,WAAW;EAEnB;CACF;CAEA,MAAM,wBAAwB;CAE9B,QAAQ,IACN,qLAEF;AACF;;AAGA,MAAa,mBAAsC;CACjD,aACE;CACF,UAAU,CAAC,OAAO;CAClB,cAAc;EACZ,mBAAmB;EACnB,uBAAuB;CACzB;CACA,aAAa;AACf"}
@@ -103,7 +103,8 @@ async function pointConfigAtLegacyModel() {
103
103
  }
104
104
  async function completeNotificationsInstallation(_options) {
105
105
  const modelPath = srcPath("app/notifications/models/notification/notification.model.ts");
106
- if (await fileExistsAsync(srcPath("app/notifications/notification.model.ts"))) {
106
+ const legacyModelPath = srcPath("app/notifications/notification.model.ts");
107
+ if (await fileExistsAsync(legacyModelPath)) {
107
108
  if (!await fileExistsAsync(modelPath)) await pointConfigAtLegacyModel();
108
109
  console.log(`${colors.yellowBright("src/app/notifications")} already scaffolded (5.29 layout), skipping...`);
109
110
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.feature.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/generations/features/notifications.feature.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { dirname } from \"node:path\";\nimport {\n directoryExistsAsync,\n ensureDirectoryAsync,\n fileExistsAsync,\n getFileAsync,\n putFileAsync,\n recordSkippedFile,\n} from \"../generation-fs\";\nimport type { CommandActionData } from \"../../commands/types\";\nimport { srcPath } from \"../../utils\";\nimport {\n listNotificationsControllerStub,\n listNotificationsSchemaStub,\n markAllNotificationsReadControllerStub,\n markNotificationReadControllerStub,\n markNotificationReadServiceStub,\n notificationControllerSpecStub,\n notificationTestFixtureStub,\n notificationLocalesStub,\n notificationMigrationStub,\n notificationModelStub,\n notificationResourceStub,\n notificationRoutesStub,\n notificationsConfigStub,\n notificationsRequestTypeStub,\n unreadNotificationsCountControllerStub,\n} from \"../stubs\";\nimport { migrationTimestamp } from \"./shared/migration-timestamp\";\nimport { type FeatureDefinition, INSTALLED_WARLOCK_VERSION } from \"./types\";\n\n/**\n * The module's controllers, with the route each one serves. A spec per\n * controller is written next to it when the app has the test feature.\n */\nconst notificationControllers = [\n {\n file: \"list-notifications.controller\",\n stub: listNotificationsControllerStub,\n method: \"GET\",\n path: \"/notifications\",\n },\n {\n file: \"unread-notifications-count.controller\",\n stub: unreadNotificationsCountControllerStub,\n method: \"GET\",\n path: \"/notifications/unread-count\",\n },\n {\n file: \"mark-notification-read.controller\",\n stub: markNotificationReadControllerStub,\n method: \"PATCH\",\n path: \"/notifications/1/read\",\n },\n {\n file: \"mark-all-notifications-read.controller\",\n stub: markAllNotificationsReadControllerStub,\n method: \"PATCH\",\n path: \"/notifications/read-all\",\n },\n] as const;\n\n/** The model's import path in the ejected config, before and since 5.30. */\nconst MODEL_IMPORT = \"app/notifications/models/notification/notification.model\";\nconst LEGACY_MODEL_IMPORT = \"app/notifications/notification.model\";\n\n/**\n * Write one module file unless it already exists. A file the app already has\n * is the app's own code: it is reported and left alone, never overwritten.\n */\nasync function writeModuleFile(relativePath: string, content: string, skipped: string[]) {\n const path = srcPath(\"app/notifications\", relativePath);\n\n if (await fileExistsAsync(path)) {\n skipped.push(relativePath);\n recordSkippedFile(path, \"exists\");\n return;\n }\n\n await ensureDirectoryAsync(dirname(path));\n await putFileAsync(path, content);\n console.log(`${colors.green(\"✓\")} Created src/app/notifications/${relativePath}`);\n}\n\n/**\n * Add the module's `notFound` message to an existing utils/locales.json, or\n * create the file. Existing keys win; a file that is not a JSON object, or\n * that renames its group, is left for the app to update by hand.\n */\nasync function registerNotificationLocales(skipped: string[]) {\n const localesPath = srcPath(\"app/notifications/utils/locales.json\");\n\n if (!(await fileExistsAsync(localesPath))) {\n await writeModuleFile(\"utils/locales.json\", notificationLocalesStub, skipped);\n return;\n }\n\n const defaults = JSON.parse(notificationLocalesStub) as Record<string, unknown>;\n let dictionary: Record<string, unknown>;\n\n try {\n const parsed: unknown = JSON.parse(await getFileAsync(localesPath));\n\n if (parsed === null || Array.isArray(parsed) || typeof parsed !== \"object\") throw new Error();\n\n dictionary = parsed as Record<string, unknown>;\n } catch {\n console.log(\n `${colors.yellowBright(\"notifications\")} locale JSON is invalid; add notFound to src/app/notifications/utils/locales.json manually.`,\n );\n return;\n }\n\n // A root `$group` renames the file's namespace, so the service's\n // t(\"notifications.notFound\") would not find a key merged here.\n if (dictionary.$group !== undefined && dictionary.$group !== \"notifications\") {\n console.log(\n `${colors.yellowBright(\"notifications\")} locale JSON declares a different $group; add notifications.notFound manually.`,\n );\n return;\n }\n\n const missing = Object.keys(defaults).filter((key) => dictionary[key] === undefined);\n\n if (missing.length === 0) return;\n\n for (const key of missing) dictionary[key] = defaults[key];\n\n await putFileAsync(localesPath, `${JSON.stringify(dictionary, null, 2)}\\n`);\n console.log(\n `${colors.green(\"✓\")} Added ${missing.join(\", \")} to src/app/notifications/utils/locales.json`,\n );\n}\n\n/**\n * The config ejected just before this runs imports the 5.30 model path. In an\n * app scaffolded by 5.29 the model is still at the module root, so point the\n * import there instead of at a file that does not exist.\n */\nasync function pointConfigAtLegacyModel() {\n const configPath = srcPath(\"config/notifications.ts\");\n\n if (!(await fileExistsAsync(configPath))) return;\n\n const config = await getFileAsync(configPath);\n\n if (!config.includes(`\"${MODEL_IMPORT}\"`)) return;\n\n await putFileAsync(configPath, config.replace(`\"${MODEL_IMPORT}\"`, `\"${LEGACY_MODEL_IMPORT}\"`));\n console.log(\n `${colors.green(\"✓\")} src/config/notifications.ts imports the existing model at ${LEGACY_MODEL_IMPORT}`,\n );\n}\n\nasync function completeNotificationsInstallation(_options: CommandActionData) {\n const modelPath = srcPath(\"app/notifications/models/notification/notification.model.ts\");\n // Where 5.29 and earlier wrote the model.\n const legacyModelPath = srcPath(\"app/notifications/notification.model.ts\");\n\n // The model file is the sentinel for \"notifications already scaffolded\" —\n // its presence means the migration was created too (timestamped, so we must\n // not re-emit a duplicate on a second run).\n if (await fileExistsAsync(legacyModelPath)) {\n if (!(await fileExistsAsync(modelPath))) await pointConfigAtLegacyModel();\n\n console.log(\n `${colors.yellowBright(\"src/app/notifications\")} already scaffolded (5.29 layout), skipping...`,\n );\n return;\n }\n\n if (await fileExistsAsync(modelPath)) {\n console.log(`${colors.yellowBright(\"src/app/notifications\")} already scaffolded, skipping...`);\n return;\n }\n\n const skipped: string[] = [];\n // An app that already has its own notifications module may keep its model\n // anywhere in it; a second Notification model would collide with it.\n const moduleExists = await directoryExistsAsync(srcPath(\"app/notifications\"));\n\n // 1. Model + migration under models/notification/, like every other module.\n // The migration's MM-DD-YYYY_HH-MM-SS prefix lets cascade infer its\n // createdAt and order it deterministically.\n if (moduleExists) {\n console.log(\n `${colors.yellowBright(\"src/app/notifications\")} already exists: not adding a Notification model or migration. config/notifications.ts must import your model.`,\n );\n } else {\n await writeModuleFile(\n \"models/notification/notification.model.ts\",\n notificationModelStub,\n skipped,\n );\n await writeModuleFile(\n `models/notification/migrations/${migrationTimestamp()}-notification.migration.ts`,\n notificationMigrationStub,\n skipped,\n );\n }\n\n // 2. One responsibility per file: output resource, validated list query,\n // guarded request type, service, translations.\n await writeModuleFile(\"resources/notification.resource.ts\", notificationResourceStub, skipped);\n await writeModuleFile(\n \"schema/list-notifications.schema.ts\",\n listNotificationsSchemaStub,\n skipped,\n );\n await writeModuleFile(\n \"types/notifications-request.type.ts\",\n notificationsRequestTypeStub,\n skipped,\n );\n await writeModuleFile(\n \"services/mark-notification-read.service.ts\",\n markNotificationReadServiceStub,\n skipped,\n );\n await registerNotificationLocales(skipped);\n\n // 3. HTTP surface — list, unread count, mark read, mark all read, one\n // controller per file, gated by authMiddleware in routes.ts.\n const withSpecs = await fileExistsAsync(srcPath(\"test-setup.ts\"));\n if (withSpecs) {\n await writeModuleFile(\"tests/notifications.fixture.ts\", notificationTestFixtureStub, skipped);\n }\n\n for (const controller of notificationControllers) {\n await writeModuleFile(`controllers/${controller.file}.ts`, controller.stub, skipped);\n\n if (withSpecs) {\n await writeModuleFile(\n `controllers/${controller.file}.spec.ts`,\n notificationControllerSpecStub(controller.method, controller.path),\n skipped,\n );\n }\n }\n\n await writeModuleFile(\"routes.ts\", notificationRoutesStub, skipped);\n\n if (skipped.length > 0) {\n console.log(\n `${colors.yellowBright(\"Kept your existing files\")} (not overwritten): ${skipped\n .map((file) => `src/app/notifications/${file}`)\n .join(\", \")}`,\n );\n }\n}\n\nexport const notificationsFeature: FeatureDefinition = {\n description:\n \"Installs @warlock.js/notifications — multi-channel notifications (mail + in-app database). Pulls the mail feature, ejects config/notifications.ts, and scaffolds src/app/notifications: the Notification model + migration, a resource, a validated list query, and the recipient-scoped list / unread-count / mark-read / mark-all-read endpoints (one controller per file, a spec each when tests are set up)\",\n // The ejected config wires a `mail` channel by default (needs nodemailer,\n // via the `mail` feature); the scaffolded routes are gated by\n // `authMiddleware`, so `@warlock.js/auth` is pulled in too.\n requires: [\"mail\"],\n dependencies: {\n \"@warlock.js/notifications\": INSTALLED_WARLOCK_VERSION,\n \"@warlock.js/auth\": INSTALLED_WARLOCK_VERSION,\n },\n ejectConfig: {\n content: notificationsConfigStub,\n name: \"notifications\",\n },\n onExecuting: completeNotificationsInstallation,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"notifications.feature.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/generations/features/notifications.feature.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { dirname } from \"node:path\";\nimport {\n directoryExistsAsync,\n ensureDirectoryAsync,\n fileExistsAsync,\n getFileAsync,\n putFileAsync,\n recordSkippedFile,\n} from \"../generation-fs\";\nimport type { CommandActionData } from \"../../commands/types\";\nimport { srcPath } from \"../../utils\";\nimport {\n listNotificationsControllerStub,\n listNotificationsSchemaStub,\n markAllNotificationsReadControllerStub,\n markNotificationReadControllerStub,\n markNotificationReadServiceStub,\n notificationControllerSpecStub,\n notificationTestFixtureStub,\n notificationLocalesStub,\n notificationMigrationStub,\n notificationModelStub,\n notificationResourceStub,\n notificationRoutesStub,\n notificationsConfigStub,\n notificationsRequestTypeStub,\n unreadNotificationsCountControllerStub,\n} from \"../stubs\";\nimport { migrationTimestamp } from \"./shared/migration-timestamp\";\nimport { type FeatureDefinition, INSTALLED_WARLOCK_VERSION } from \"./types\";\n\n/**\n * The module's controllers, with the route each one serves. A spec per\n * controller is written next to it when the app has the test feature.\n */\nconst notificationControllers = [\n {\n file: \"list-notifications.controller\",\n stub: listNotificationsControllerStub,\n method: \"GET\",\n path: \"/notifications\",\n },\n {\n file: \"unread-notifications-count.controller\",\n stub: unreadNotificationsCountControllerStub,\n method: \"GET\",\n path: \"/notifications/unread-count\",\n },\n {\n file: \"mark-notification-read.controller\",\n stub: markNotificationReadControllerStub,\n method: \"PATCH\",\n path: \"/notifications/1/read\",\n },\n {\n file: \"mark-all-notifications-read.controller\",\n stub: markAllNotificationsReadControllerStub,\n method: \"PATCH\",\n path: \"/notifications/read-all\",\n },\n] as const;\n\n/** The model's import path in the ejected config, before and since 5.30. */\nconst MODEL_IMPORT = \"app/notifications/models/notification/notification.model\";\nconst LEGACY_MODEL_IMPORT = \"app/notifications/notification.model\";\n\n/**\n * Write one module file unless it already exists. A file the app already has\n * is the app's own code: it is reported and left alone, never overwritten.\n */\nasync function writeModuleFile(relativePath: string, content: string, skipped: string[]) {\n const path = srcPath(\"app/notifications\", relativePath);\n\n if (await fileExistsAsync(path)) {\n skipped.push(relativePath);\n recordSkippedFile(path, \"exists\");\n return;\n }\n\n await ensureDirectoryAsync(dirname(path));\n await putFileAsync(path, content);\n console.log(`${colors.green(\"✓\")} Created src/app/notifications/${relativePath}`);\n}\n\n/**\n * Add the module's `notFound` message to an existing utils/locales.json, or\n * create the file. Existing keys win; a file that is not a JSON object, or\n * that renames its group, is left for the app to update by hand.\n */\nasync function registerNotificationLocales(skipped: string[]) {\n const localesPath = srcPath(\"app/notifications/utils/locales.json\");\n\n if (!(await fileExistsAsync(localesPath))) {\n await writeModuleFile(\"utils/locales.json\", notificationLocalesStub, skipped);\n return;\n }\n\n const defaults = JSON.parse(notificationLocalesStub) as Record<string, unknown>;\n let dictionary: Record<string, unknown>;\n\n try {\n const parsed: unknown = JSON.parse(await getFileAsync(localesPath));\n\n if (parsed === null || Array.isArray(parsed) || typeof parsed !== \"object\") throw new Error();\n\n dictionary = parsed as Record<string, unknown>;\n } catch {\n console.log(\n `${colors.yellowBright(\"notifications\")} locale JSON is invalid; add notFound to src/app/notifications/utils/locales.json manually.`,\n );\n return;\n }\n\n // A root `$group` renames the file's namespace, so the service's\n // t(\"notifications.notFound\") would not find a key merged here.\n if (dictionary.$group !== undefined && dictionary.$group !== \"notifications\") {\n console.log(\n `${colors.yellowBright(\"notifications\")} locale JSON declares a different $group; add notifications.notFound manually.`,\n );\n return;\n }\n\n const missing = Object.keys(defaults).filter((key) => dictionary[key] === undefined);\n\n if (missing.length === 0) return;\n\n for (const key of missing) dictionary[key] = defaults[key];\n\n await putFileAsync(localesPath, `${JSON.stringify(dictionary, null, 2)}\\n`);\n console.log(\n `${colors.green(\"✓\")} Added ${missing.join(\", \")} to src/app/notifications/utils/locales.json`,\n );\n}\n\n/**\n * The config ejected just before this runs imports the 5.30 model path. In an\n * app scaffolded by 5.29 the model is still at the module root, so point the\n * import there instead of at a file that does not exist.\n */\nasync function pointConfigAtLegacyModel() {\n const configPath = srcPath(\"config/notifications.ts\");\n\n if (!(await fileExistsAsync(configPath))) return;\n\n const config = await getFileAsync(configPath);\n\n if (!config.includes(`\"${MODEL_IMPORT}\"`)) return;\n\n await putFileAsync(configPath, config.replace(`\"${MODEL_IMPORT}\"`, `\"${LEGACY_MODEL_IMPORT}\"`));\n console.log(\n `${colors.green(\"✓\")} src/config/notifications.ts imports the existing model at ${LEGACY_MODEL_IMPORT}`,\n );\n}\n\nasync function completeNotificationsInstallation(_options: CommandActionData) {\n const modelPath = srcPath(\"app/notifications/models/notification/notification.model.ts\");\n // Where 5.29 and earlier wrote the model.\n const legacyModelPath = srcPath(\"app/notifications/notification.model.ts\");\n\n // The model file is the sentinel for \"notifications already scaffolded\" —\n // its presence means the migration was created too (timestamped, so we must\n // not re-emit a duplicate on a second run).\n if (await fileExistsAsync(legacyModelPath)) {\n if (!(await fileExistsAsync(modelPath))) await pointConfigAtLegacyModel();\n\n console.log(\n `${colors.yellowBright(\"src/app/notifications\")} already scaffolded (5.29 layout), skipping...`,\n );\n return;\n }\n\n if (await fileExistsAsync(modelPath)) {\n console.log(`${colors.yellowBright(\"src/app/notifications\")} already scaffolded, skipping...`);\n return;\n }\n\n const skipped: string[] = [];\n // An app that already has its own notifications module may keep its model\n // anywhere in it; a second Notification model would collide with it.\n const moduleExists = await directoryExistsAsync(srcPath(\"app/notifications\"));\n\n // 1. Model + migration under models/notification/, like every other module.\n // The migration's MM-DD-YYYY_HH-MM-SS prefix lets cascade infer its\n // createdAt and order it deterministically.\n if (moduleExists) {\n console.log(\n `${colors.yellowBright(\"src/app/notifications\")} already exists: not adding a Notification model or migration. config/notifications.ts must import your model.`,\n );\n } else {\n await writeModuleFile(\n \"models/notification/notification.model.ts\",\n notificationModelStub,\n skipped,\n );\n await writeModuleFile(\n `models/notification/migrations/${migrationTimestamp()}-notification.migration.ts`,\n notificationMigrationStub,\n skipped,\n );\n }\n\n // 2. One responsibility per file: output resource, validated list query,\n // guarded request type, service, translations.\n await writeModuleFile(\"resources/notification.resource.ts\", notificationResourceStub, skipped);\n await writeModuleFile(\n \"schema/list-notifications.schema.ts\",\n listNotificationsSchemaStub,\n skipped,\n );\n await writeModuleFile(\n \"types/notifications-request.type.ts\",\n notificationsRequestTypeStub,\n skipped,\n );\n await writeModuleFile(\n \"services/mark-notification-read.service.ts\",\n markNotificationReadServiceStub,\n skipped,\n );\n await registerNotificationLocales(skipped);\n\n // 3. HTTP surface — list, unread count, mark read, mark all read, one\n // controller per file, gated by authMiddleware in routes.ts.\n const withSpecs = await fileExistsAsync(srcPath(\"test-setup.ts\"));\n if (withSpecs) {\n await writeModuleFile(\"tests/notifications.fixture.ts\", notificationTestFixtureStub, skipped);\n }\n\n for (const controller of notificationControllers) {\n await writeModuleFile(`controllers/${controller.file}.ts`, controller.stub, skipped);\n\n if (withSpecs) {\n await writeModuleFile(\n `controllers/${controller.file}.spec.ts`,\n notificationControllerSpecStub(controller.method, controller.path),\n skipped,\n );\n }\n }\n\n await writeModuleFile(\"routes.ts\", notificationRoutesStub, skipped);\n\n if (skipped.length > 0) {\n console.log(\n `${colors.yellowBright(\"Kept your existing files\")} (not overwritten): ${skipped\n .map((file) => `src/app/notifications/${file}`)\n .join(\", \")}`,\n );\n }\n}\n\nexport const notificationsFeature: FeatureDefinition = {\n description:\n \"Installs @warlock.js/notifications — multi-channel notifications (mail + in-app database). Pulls the mail feature, ejects config/notifications.ts, and scaffolds src/app/notifications: the Notification model + migration, a resource, a validated list query, and the recipient-scoped list / unread-count / mark-read / mark-all-read endpoints (one controller per file, a spec each when tests are set up)\",\n // The ejected config wires a `mail` channel by default (needs nodemailer,\n // via the `mail` feature); the scaffolded routes are gated by\n // `authMiddleware`, so `@warlock.js/auth` is pulled in too.\n requires: [\"mail\"],\n dependencies: {\n \"@warlock.js/notifications\": INSTALLED_WARLOCK_VERSION,\n \"@warlock.js/auth\": INSTALLED_WARLOCK_VERSION,\n },\n ejectConfig: {\n content: notificationsConfigStub,\n name: \"notifications\",\n },\n onExecuting: completeNotificationsInstallation,\n};\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
- import ts from "typescript";
1
+ import { isExportAssignment, isIdentifier, isNumericLiteral, isObjectLiteralExpression, isPropertyAssignment, isShorthandPropertyAssignment, isStringLiteral, isVariableStatement, nameNode, parseSourceFile, topLevelDeclarations, valueText } from "../../../tooling/syntax/ast.mjs";
2
+ import { parseSync } from "oxc-parser";
2
3
 
3
4
  //#region ../../packages/core/src/generations/features/shared/merge-web-sitemap-config.ts
4
5
  /**
@@ -35,12 +36,11 @@ import ts from "typescript";
35
36
  * @returns What happened, and the new text when there is any.
36
37
  */
37
38
  function mergeWebSitemapConfig(source) {
38
- const sourceFile = ts.createSourceFile("web.ts", source, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TS);
39
- const objectLiteral = findExportedConfigObjectLiteral(sourceFile);
39
+ const objectLiteral = findExportedConfigObjectLiteral(parseSourceFile("web.ts", source));
40
40
  if (!objectLiteral) return { status: "unrecognised" };
41
41
  if (hasTopLevelSitemapProperty(objectLiteral)) return { status: "already-present" };
42
- const bodyStart = objectLiteral.getStart(sourceFile) + 1;
43
- const closingBraceIndex = objectLiteral.getEnd() - 1;
42
+ const bodyStart = objectLiteral.start + 1;
43
+ const closingBraceIndex = objectLiteral.end - 1;
44
44
  const body = source.slice(bodyStart, closingBraceIndex);
45
45
  const indentMatch = /\n([ \t]*)\S/.exec(body);
46
46
  const indent = indentMatch ? indentMatch[1] : " ";
@@ -55,14 +55,7 @@ function mergeWebSitemapConfig(source) {
55
55
  }
56
56
  /** Whether TEXT fails to parse as TypeScript source. */
57
57
  function hasSyntaxErrors(text) {
58
- const { diagnostics } = ts.transpileModule(text, {
59
- compilerOptions: {
60
- module: ts.ModuleKind.ESNext,
61
- target: ts.ScriptTarget.ESNext
62
- },
63
- reportDiagnostics: true
64
- });
65
- return Boolean(diagnostics && diagnostics.length > 0);
58
+ return parseSync("web.ts", text).errors.length > 0;
66
59
  }
67
60
  /**
68
61
  * Whether the exported config object literal already has a `sitemap`
@@ -71,11 +64,11 @@ function hasSyntaxErrors(text) {
71
64
  * and must not block adding the top-level one.
72
65
  */
73
66
  function hasTopLevelSitemapProperty(objectLiteral) {
74
- return objectLiteral.properties.some((property) => (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property)) && propertyKeyName(property.name) === "sitemap");
67
+ return objectLiteral.properties.some((property) => (isPropertyAssignment(property) || isShorthandPropertyAssignment(property)) && propertyKeyName(nameNode(property)) === "sitemap");
75
68
  }
76
69
  /** The literal text of a property name node, when it is one of the plain shapes we care about. */
77
70
  function propertyKeyName(name) {
78
- if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
71
+ if (isIdentifier(name) || isStringLiteral(name) || isNumericLiteral(name)) return valueText(name);
79
72
  }
80
73
  /**
81
74
  * Find the object literal a source file's default export ultimately points
@@ -83,15 +76,15 @@ function propertyKeyName(name) {
83
76
  * file.
84
77
  */
85
78
  function findExportedConfigObjectLiteral(sourceFile) {
86
- const exportAssignment = sourceFile.statements.find((statement) => ts.isExportAssignment(statement) && !statement.isExportEquals);
79
+ const exportAssignment = sourceFile.body.find((statement) => isExportAssignment(statement));
87
80
  if (!exportAssignment) return void 0;
88
- const { expression } = exportAssignment;
89
- if (ts.isObjectLiteralExpression(expression)) return expression;
90
- if (!ts.isIdentifier(expression)) return void 0;
91
- const identifier = expression.text;
92
- for (const statement of sourceFile.statements) {
93
- if (!ts.isVariableStatement(statement)) continue;
94
- for (const declaration of statement.declarationList.declarations) if (ts.isIdentifier(declaration.name) && declaration.name.text === identifier && declaration.initializer && ts.isObjectLiteralExpression(declaration.initializer)) return declaration.initializer;
81
+ const expression = exportAssignment.declaration;
82
+ if (isObjectLiteralExpression(expression)) return expression;
83
+ if (!isIdentifier(expression)) return void 0;
84
+ const identifier = valueText(expression);
85
+ for (const statement of topLevelDeclarations(sourceFile)) {
86
+ if (!isVariableStatement(statement)) continue;
87
+ for (const declaration of statement.declarations) if (isIdentifier(nameNode(declaration)) && valueText(declaration.id) === identifier && declaration.init && isObjectLiteralExpression(declaration.init)) return declaration.init;
95
88
  }
96
89
  }
97
90
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"merge-web-sitemap-config.mjs","names":[],"sources":["../../../../../../../../../../packages/core/src/generations/features/shared/merge-web-sitemap-config.ts"],"sourcesContent":["import ts from \"typescript\";\n\n/** What {@link mergeWebSitemapConfig} did, or could not do, to the source it was given. */\nexport type WebSitemapMergeResult =\n | { status: \"merged\"; next: string }\n | { status: \"already-present\" }\n | { status: \"unrecognised\" };\n\n/**\n * Merge a disabled `sitemap` section into `src/config/web.ts` SOURCE TEXT.\n *\n * **String surgery, never parse-and-print** — same rationale as\n * `insertConnectorEntry`: `web.ts` is app-owned and may carry any formatting\n * or comments a parse-and-print would discard. The TypeScript AST is used to\n * *find where to cut*, never to regenerate the file — the splice below still\n * copies the original source's bytes verbatim.\n *\n * Recognises the exported config object two ways: an inline `export default\n * {...}`, or `export default <identifier>;` pointing back at a `const\n * <identifier> = {...}` (or `const <identifier>: SomeType = {...}`) declared\n * earlier in the file — the shape this generator itself scaffolds, and the\n * shape every other generated config file in this project uses. Any other\n * shape (a function call, a re-export, no default export at all) returns\n * `\"unrecognised\"` rather than guessing at where to cut — clobbering an\n * app-owned file the merge could not actually understand is worse than\n * refusing.\n *\n * A `sitemap` property already present anywhere in the source (by key, so one\n * a human has since hand-edited is still found) is left unchanged — that is\n * what makes a second `warlock add sitemap` a no-op instead of a duplicate\n * block. Detection walks the AST rather than regex-matching `sitemap\\s*:`, so\n * a comment like `// sitemap: TODO` — text, not a property — does not count.\n *\n * Before returning a merge, the resulting text is re-parsed and checked for\n * syntax errors; a merge that would not itself parse is refused (as\n * `\"unrecognised\"`) instead of written, since a matched-but-corrupt splice is\n * worse than doing nothing.\n *\n * @param source The config file's current text.\n * @returns What happened, and the new text when there is any.\n */\nexport function mergeWebSitemapConfig(source: string): WebSitemapMergeResult {\n const sourceFile = ts.createSourceFile(\n \"web.ts\",\n source,\n ts.ScriptTarget.ESNext,\n /* setParentNodes */ true,\n ts.ScriptKind.TS,\n );\n\n const objectLiteral = findExportedConfigObjectLiteral(sourceFile);\n\n if (!objectLiteral) {\n return { status: \"unrecognised\" };\n }\n\n if (hasTopLevelSitemapProperty(objectLiteral)) {\n return { status: \"already-present\" };\n }\n\n const bodyStart = objectLiteral.getStart(sourceFile) + 1;\n const closingBraceIndex = objectLiteral.getEnd() - 1;\n const body = source.slice(bodyStart, closingBraceIndex);\n\n const indentMatch = /\\n([ \\t]*)\\S/.exec(body);\n const indent = indentMatch ? indentMatch[1] : \" \";\n\n const block =\n `${indent}sitemap: {\\n` +\n `${indent}${indent}enabled: false,\\n` +\n `${indent}${indent}path: \"/sitemap.xml\",\\n` +\n `${indent}${indent}defaults: { changefreq: \"weekly\", priority: 0.5 },\\n` +\n `${indent}},\\n`;\n\n const { index: insertionPoint, needsComma } = lastPropertyEnd(source, closingBraceIndex);\n\n const next =\n `${source.slice(0, insertionPoint)}` +\n `${needsComma ? \",\\n\" : \"\"}` +\n `${block}` +\n `${source.slice(closingBraceIndex)}`;\n\n if (hasSyntaxErrors(next)) {\n return { status: \"unrecognised\" };\n }\n\n return { status: \"merged\", next };\n}\n\n/** Whether TEXT fails to parse as TypeScript source. */\nfunction hasSyntaxErrors(text: string): boolean {\n const { diagnostics } = ts.transpileModule(text, {\n compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ESNext },\n reportDiagnostics: true,\n });\n\n return Boolean(diagnostics && diagnostics.length > 0);\n}\n\n/**\n * Whether the exported config object literal already has a `sitemap`\n * property directly on it — a `sitemap` key nested under some other\n * property (e.g. `seo: { sitemap: true }`) is a different feature's field\n * and must not block adding the top-level one.\n */\nfunction hasTopLevelSitemapProperty(objectLiteral: ts.ObjectLiteralExpression): boolean {\n return objectLiteral.properties.some(\n (property) =>\n (ts.isPropertyAssignment(property) || ts.isShorthandPropertyAssignment(property)) &&\n propertyKeyName(property.name) === \"sitemap\",\n );\n}\n\n/** The literal text of a property name node, when it is one of the plain shapes we care about. */\nfunction propertyKeyName(name: ts.PropertyName): string | undefined {\n if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) {\n return name.text;\n }\n\n return undefined;\n}\n\n/**\n * Find the object literal a source file's default export ultimately points\n * at, whether the export is inline or an identifier declared earlier in the\n * file.\n */\nfunction findExportedConfigObjectLiteral(\n sourceFile: ts.SourceFile,\n): ts.ObjectLiteralExpression | undefined {\n const exportAssignment = sourceFile.statements.find(\n (statement): statement is ts.ExportAssignment =>\n ts.isExportAssignment(statement) && !statement.isExportEquals,\n );\n\n if (!exportAssignment) return undefined;\n\n const { expression } = exportAssignment;\n\n if (ts.isObjectLiteralExpression(expression)) {\n return expression;\n }\n\n if (!ts.isIdentifier(expression)) return undefined;\n\n const identifier = expression.text;\n\n for (const statement of sourceFile.statements) {\n if (!ts.isVariableStatement(statement)) continue;\n\n for (const declaration of statement.declarationList.declarations) {\n if (\n ts.isIdentifier(declaration.name) &&\n declaration.name.text === identifier &&\n declaration.initializer &&\n ts.isObjectLiteralExpression(declaration.initializer)\n ) {\n return declaration.initializer;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Where to insert a new property right before a closing brace, and whether\n * the property immediately before it (if any) needs a trailing comma added —\n * an object literal with two properties and no comma between them does not\n * parse.\n */\nfunction lastPropertyEnd(\n source: string,\n closingBraceIndex: number,\n): { index: number; needsComma: boolean } {\n let cursor = closingBraceIndex - 1;\n\n while (cursor >= 0 && /\\s/.test(source.charAt(cursor))) {\n cursor--;\n }\n\n if (cursor < 0 || source[cursor] === \"{\" || source[cursor] === \",\") {\n return { index: closingBraceIndex, needsComma: false };\n }\n\n return { index: cursor + 1, needsComma: true };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,SAAgB,sBAAsB,QAAuC;CAC3E,MAAM,aAAa,GAAG,iBACpB,UACA,QACA,GAAG,aAAa,QACK,MACrB,GAAG,WAAW,EAChB;CAEA,MAAM,gBAAgB,gCAAgC,UAAU;CAEhE,IAAI,CAAC,eACH,OAAO,EAAE,QAAQ,eAAe;CAGlC,IAAI,2BAA2B,aAAa,GAC1C,OAAO,EAAE,QAAQ,kBAAkB;CAGrC,MAAM,YAAY,cAAc,SAAS,UAAU,IAAI;CACvD,MAAM,oBAAoB,cAAc,OAAO,IAAI;CACnD,MAAM,OAAO,OAAO,MAAM,WAAW,iBAAiB;CAEtD,MAAM,cAAc,eAAe,KAAK,IAAI;CAC5C,MAAM,SAAS,cAAc,YAAY,KAAK;CAE9C,MAAM,QACJ,GAAG,OAAO,cACP,SAAS,OAAO,mBAChB,SAAS,OAAO,yBAChB,SAAS,OAAO,sDAChB,OAAO;CAEZ,MAAM,EAAE,OAAO,gBAAgB,eAAe,gBAAgB,QAAQ,iBAAiB;CAEvF,MAAM,OACJ,GAAG,OAAO,MAAM,GAAG,cAAc,IAC9B,aAAa,QAAQ,KACrB,QACA,OAAO,MAAM,iBAAiB;CAEnC,IAAI,gBAAgB,IAAI,GACtB,OAAO,EAAE,QAAQ,eAAe;CAGlC,OAAO;EAAE,QAAQ;EAAU;CAAK;AAClC;;AAGA,SAAS,gBAAgB,MAAuB;CAC9C,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,MAAM;EAC/C,iBAAiB;GAAE,QAAQ,GAAG,WAAW;GAAQ,QAAQ,GAAG,aAAa;EAAO;EAChF,mBAAmB;CACrB,CAAC;CAED,OAAO,QAAQ,eAAe,YAAY,SAAS,CAAC;AACtD;;;;;;;AAQA,SAAS,2BAA2B,eAAoD;CACtF,OAAO,cAAc,WAAW,MAC7B,cACE,GAAG,qBAAqB,QAAQ,KAAK,GAAG,8BAA8B,QAAQ,MAC/E,gBAAgB,SAAS,IAAI,MAAM,SACvC;AACF;;AAGA,SAAS,gBAAgB,MAA2C;CAClE,IAAI,GAAG,aAAa,IAAI,KAAK,GAAG,gBAAgB,IAAI,KAAK,GAAG,iBAAiB,IAAI,GAC/E,OAAO,KAAK;AAIhB;;;;;;AAOA,SAAS,gCACP,YACwC;CACxC,MAAM,mBAAmB,WAAW,WAAW,MAC5C,cACC,GAAG,mBAAmB,SAAS,KAAK,CAAC,UAAU,cACnD;CAEA,IAAI,CAAC,kBAAkB,OAAO;CAE9B,MAAM,EAAE,eAAe;CAEvB,IAAI,GAAG,0BAA0B,UAAU,GACzC,OAAO;CAGT,IAAI,CAAC,GAAG,aAAa,UAAU,GAAG,OAAO;CAEzC,MAAM,aAAa,WAAW;CAE9B,KAAK,MAAM,aAAa,WAAW,YAAY;EAC7C,IAAI,CAAC,GAAG,oBAAoB,SAAS,GAAG;EAExC,KAAK,MAAM,eAAe,UAAU,gBAAgB,cAClD,IACE,GAAG,aAAa,YAAY,IAAI,KAChC,YAAY,KAAK,SAAS,cAC1B,YAAY,eACZ,GAAG,0BAA0B,YAAY,WAAW,GAEpD,OAAO,YAAY;CAGzB;AAGF;;;;;;;AAQA,SAAS,gBACP,QACA,mBACwC;CACxC,IAAI,SAAS,oBAAoB;CAEjC,OAAO,UAAU,KAAK,KAAK,KAAK,OAAO,OAAO,MAAM,CAAC,GACnD;CAGF,IAAI,SAAS,KAAK,OAAO,YAAY,OAAO,OAAO,YAAY,KAC7D,OAAO;EAAE,OAAO;EAAmB,YAAY;CAAM;CAGvD,OAAO;EAAE,OAAO,SAAS;EAAG,YAAY;CAAK;AAC/C"}
1
+ {"version":3,"file":"merge-web-sitemap-config.mjs","names":["ast.parseSourceFile","ast.isPropertyAssignment","ast.isShorthandPropertyAssignment","ast.nameNode","ast.isIdentifier","ast.isStringLiteral","ast.isNumericLiteral","ast.valueText","ast.isExportAssignment","ast.isObjectLiteralExpression","ast.topLevelDeclarations","ast.isVariableStatement"],"sources":["../../../../../../../../../../packages/core/src/generations/features/shared/merge-web-sitemap-config.ts"],"sourcesContent":["import { parseSync } from \"oxc-parser\";\nimport * as ast from \"../../../tooling/syntax/ast\";\n\n/** What {@link mergeWebSitemapConfig} did, or could not do, to the source it was given. */\nexport type WebSitemapMergeResult =\n | { status: \"merged\"; next: string }\n | { status: \"already-present\" }\n | { status: \"unrecognised\" };\n\n/**\n * Merge a disabled `sitemap` section into `src/config/web.ts` SOURCE TEXT.\n *\n * **String surgery, never parse-and-print** — same rationale as\n * `insertConnectorEntry`: `web.ts` is app-owned and may carry any formatting\n * or comments a parse-and-print would discard. The TypeScript AST is used to\n * *find where to cut*, never to regenerate the file — the splice below still\n * copies the original source's bytes verbatim.\n *\n * Recognises the exported config object two ways: an inline `export default\n * {...}`, or `export default <identifier>;` pointing back at a `const\n * <identifier> = {...}` (or `const <identifier>: SomeType = {...}`) declared\n * earlier in the file — the shape this generator itself scaffolds, and the\n * shape every other generated config file in this project uses. Any other\n * shape (a function call, a re-export, no default export at all) returns\n * `\"unrecognised\"` rather than guessing at where to cut — clobbering an\n * app-owned file the merge could not actually understand is worse than\n * refusing.\n *\n * A `sitemap` property already present anywhere in the source (by key, so one\n * a human has since hand-edited is still found) is left unchanged — that is\n * what makes a second `warlock add sitemap` a no-op instead of a duplicate\n * block. Detection walks the AST rather than regex-matching `sitemap\\s*:`, so\n * a comment like `// sitemap: TODO` — text, not a property — does not count.\n *\n * Before returning a merge, the resulting text is re-parsed and checked for\n * syntax errors; a merge that would not itself parse is refused (as\n * `\"unrecognised\"`) instead of written, since a matched-but-corrupt splice is\n * worse than doing nothing.\n *\n * @param source The config file's current text.\n * @returns What happened, and the new text when there is any.\n */\nexport function mergeWebSitemapConfig(source: string): WebSitemapMergeResult {\n const sourceFile = ast.parseSourceFile(\"web.ts\", source);\n\n const objectLiteral = findExportedConfigObjectLiteral(sourceFile);\n\n if (!objectLiteral) {\n return { status: \"unrecognised\" };\n }\n\n if (hasTopLevelSitemapProperty(objectLiteral)) {\n return { status: \"already-present\" };\n }\n\n const bodyStart = objectLiteral.start + 1;\n const closingBraceIndex = objectLiteral.end - 1;\n const body = source.slice(bodyStart, closingBraceIndex);\n\n const indentMatch = /\\n([ \\t]*)\\S/.exec(body);\n const indent = indentMatch ? indentMatch[1] : \" \";\n\n const block =\n `${indent}sitemap: {\\n` +\n `${indent}${indent}enabled: false,\\n` +\n `${indent}${indent}path: \"/sitemap.xml\",\\n` +\n `${indent}${indent}defaults: { changefreq: \"weekly\", priority: 0.5 },\\n` +\n `${indent}},\\n`;\n\n const { index: insertionPoint, needsComma } = lastPropertyEnd(source, closingBraceIndex);\n\n const next =\n `${source.slice(0, insertionPoint)}` +\n `${needsComma ? \",\\n\" : \"\"}` +\n `${block}` +\n `${source.slice(closingBraceIndex)}`;\n\n if (hasSyntaxErrors(next)) {\n return { status: \"unrecognised\" };\n }\n\n return { status: \"merged\", next };\n}\n\n/** Whether TEXT fails to parse as TypeScript source. */\nfunction hasSyntaxErrors(text: string): boolean {\n return parseSync(\"web.ts\", text).errors.length > 0;\n}\n\n/**\n * Whether the exported config object literal already has a `sitemap`\n * property directly on it — a `sitemap` key nested under some other\n * property (e.g. `seo: { sitemap: true }`) is a different feature's field\n * and must not block adding the top-level one.\n */\nfunction hasTopLevelSitemapProperty(objectLiteral: ast.ObjectExpression): boolean {\n return objectLiteral.properties.some(\n (property) =>\n (ast.isPropertyAssignment(property) || ast.isShorthandPropertyAssignment(property)) &&\n propertyKeyName(ast.nameNode(property)) === \"sitemap\",\n );\n}\n\n/** The literal text of a property name node, when it is one of the plain shapes we care about. */\nfunction propertyKeyName(name: ast.Node): string | undefined {\n if (ast.isIdentifier(name) || ast.isStringLiteral(name) || ast.isNumericLiteral(name)) {\n return ast.valueText(name);\n }\n\n return undefined;\n}\n\n/**\n * Find the object literal a source file's default export ultimately points\n * at, whether the export is inline or an identifier declared earlier in the\n * file.\n */\nfunction findExportedConfigObjectLiteral(\n sourceFile: ast.SourceFile,\n): ast.ObjectExpression | undefined {\n const exportAssignment = sourceFile.body.find(\n (statement): statement is ast.ExportDefaultDeclaration => ast.isExportAssignment(statement),\n );\n\n if (!exportAssignment) return undefined;\n\n const expression = exportAssignment.declaration;\n\n if (ast.isObjectLiteralExpression(expression)) {\n return expression;\n }\n\n if (!ast.isIdentifier(expression)) return undefined;\n\n const identifier = ast.valueText(expression);\n\n for (const statement of ast.topLevelDeclarations(sourceFile)) {\n if (!ast.isVariableStatement(statement)) continue;\n\n for (const declaration of statement.declarations) {\n if (\n ast.isIdentifier(ast.nameNode(declaration)) &&\n ast.valueText(declaration.id) === identifier &&\n declaration.init &&\n ast.isObjectLiteralExpression(declaration.init)\n ) {\n return declaration.init;\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Where to insert a new property right before a closing brace, and whether\n * the property immediately before it (if any) needs a trailing comma added —\n * an object literal with two properties and no comma between them does not\n * parse.\n */\nfunction lastPropertyEnd(\n source: string,\n closingBraceIndex: number,\n): { index: number; needsComma: boolean } {\n let cursor = closingBraceIndex - 1;\n\n while (cursor >= 0 && /\\s/.test(source.charAt(cursor))) {\n cursor--;\n }\n\n if (cursor < 0 || source[cursor] === \"{\" || source[cursor] === \",\") {\n return { index: closingBraceIndex, needsComma: false };\n }\n\n return { index: cursor + 1, needsComma: true };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,sBAAsB,QAAuC;CAG3E,MAAM,gBAAgB,gCAFHA,gBAAoB,UAAU,MAEc,CAAC;CAEhE,IAAI,CAAC,eACH,OAAO,EAAE,QAAQ,eAAe;CAGlC,IAAI,2BAA2B,aAAa,GAC1C,OAAO,EAAE,QAAQ,kBAAkB;CAGrC,MAAM,YAAY,cAAc,QAAQ;CACxC,MAAM,oBAAoB,cAAc,MAAM;CAC9C,MAAM,OAAO,OAAO,MAAM,WAAW,iBAAiB;CAEtD,MAAM,cAAc,eAAe,KAAK,IAAI;CAC5C,MAAM,SAAS,cAAc,YAAY,KAAK;CAE9C,MAAM,QACJ,GAAG,OAAO,cACP,SAAS,OAAO,mBAChB,SAAS,OAAO,yBAChB,SAAS,OAAO,sDAChB,OAAO;CAEZ,MAAM,EAAE,OAAO,gBAAgB,eAAe,gBAAgB,QAAQ,iBAAiB;CAEvF,MAAM,OACJ,GAAG,OAAO,MAAM,GAAG,cAAc,IAC9B,aAAa,QAAQ,KACrB,QACA,OAAO,MAAM,iBAAiB;CAEnC,IAAI,gBAAgB,IAAI,GACtB,OAAO,EAAE,QAAQ,eAAe;CAGlC,OAAO;EAAE,QAAQ;EAAU;CAAK;AAClC;;AAGA,SAAS,gBAAgB,MAAuB;CAC9C,OAAO,UAAU,UAAU,IAAI,CAAC,CAAC,OAAO,SAAS;AACnD;;;;;;;AAQA,SAAS,2BAA2B,eAA8C;CAChF,OAAO,cAAc,WAAW,MAC7B,cACEC,qBAAyB,QAAQ,KAAKC,8BAAkC,QAAQ,MACjF,gBAAgBC,SAAa,QAAQ,CAAC,MAAM,SAChD;AACF;;AAGA,SAAS,gBAAgB,MAAoC;CAC3D,IAAIC,aAAiB,IAAI,KAAKC,gBAAoB,IAAI,KAAKC,iBAAqB,IAAI,GAClF,OAAOC,UAAc,IAAI;AAI7B;;;;;;AAOA,SAAS,gCACP,YACkC;CAClC,MAAM,mBAAmB,WAAW,KAAK,MACtC,cAAyDC,mBAAuB,SAAS,CAC5F;CAEA,IAAI,CAAC,kBAAkB,OAAO;CAE9B,MAAM,aAAa,iBAAiB;CAEpC,IAAIC,0BAA8B,UAAU,GAC1C,OAAO;CAGT,IAAI,CAACL,aAAiB,UAAU,GAAG,OAAO;CAE1C,MAAM,aAAaG,UAAc,UAAU;CAE3C,KAAK,MAAM,aAAaG,qBAAyB,UAAU,GAAG;EAC5D,IAAI,CAACC,oBAAwB,SAAS,GAAG;EAEzC,KAAK,MAAM,eAAe,UAAU,cAClC,IACEP,aAAiBD,SAAa,WAAW,CAAC,KAC1CI,UAAc,YAAY,EAAE,MAAM,cAClC,YAAY,QACZE,0BAA8B,YAAY,IAAI,GAE9C,OAAO,YAAY;CAGzB;AAGF;;;;;;;AAQA,SAAS,gBACP,QACA,mBACwC;CACxC,IAAI,SAAS,oBAAoB;CAEjC,OAAO,UAAU,KAAK,KAAK,KAAK,OAAO,OAAO,MAAM,CAAC,GACnD;CAGF,IAAI,SAAS,KAAK,OAAO,YAAY,OAAO,OAAO,YAAY,KAC7D,OAAO;EAAE,OAAO;EAAmB,YAAY;CAAM;CAGvD,OAAO;EAAE,OAAO,SAAS;EAAG,YAAY;CAAK;AAC/C"}
@@ -81,5 +81,5 @@ function escapeForRegExp(value) {
81
81
  }
82
82
 
83
83
  //#endregion
84
- export { patchTsconfigInclude };
84
+ export { insertIncludeEntry, patchTsconfigInclude };
85
85
  //# sourceMappingURL=patch-tsconfig-include.mjs.map
@@ -154,5 +154,5 @@ async function relocateConflictingHomeRoute() {
154
154
  }
155
155
 
156
156
  //#endregion
157
- export { relocateConflictingHomeRoute };
157
+ export { relocateConflictingHomeRoute, resolveHomeRouteCollision };
158
158
  //# sourceMappingURL=relocate-conflicting-home-route.mjs.map
@@ -49,7 +49,8 @@ async function installSitemapConfig() {
49
49
  console.log(NEXT_STEPS);
50
50
  return;
51
51
  }
52
- const merge = mergeWebSitemapConfig(await getFileAsync(configPath));
52
+ const current = await getFileAsync(configPath);
53
+ const merge = mergeWebSitemapConfig(current);
53
54
  if (merge.status === "already-present") {
54
55
  console.log(`${colors.yellowBright("sitemap")} already configured in src/config/web.ts, skipping...`);
55
56
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"sitemap.feature.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/generations/features/sitemap.feature.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { fileExistsAsync, getFileAsync, putFileAsync } from \"../generation-fs\";\nimport { srcPath } from \"../../utils\";\nimport { mergeWebSitemapConfig } from \"./shared/merge-web-sitemap-config\";\nimport { type FeatureDefinition, INSTALLED_WARLOCK_VERSION } from \"./types\";\n\nconst NEXT_STEPS =\n \"Next: set `app.publicUrl` (src/config/app.ts) or the PUBLIC_APP_URL environment \" +\n \"variable, then flip `sitemap.enabled` to true in src/config/web.ts.\";\n\n/**\n * Ships DISABLED because a sitemap needs this application's public origin and\n * a freshly generated app has no way to know it. Two steps to turn it on:\n *\n * 1. set `app.publicUrl` in src/config/app.ts, or the PUBLIC_APP_URL\n * environment variable;\n * 2. flip `sitemap.enabled` to true here.\n *\n * With it enabled and no origin configured, generation REFUSES rather than\n * serving absolute URLs built from a guessed host — a sitemap pointing at\n * the wrong domain is worse than one that never starts, because nothing\n * downstream reports it.\n */\nconst freshWebConfigStub = `import type { WebSitemapConfig } from \"@warlock.js/web/sitemap\";\n\nconst webConfig: { sitemap: WebSitemapConfig } = {\n sitemap: {\n enabled: false,\n path: \"/sitemap.xml\",\n defaults: { changefreq: \"weekly\", priority: 0.5 },\n },\n};\n\nexport default webConfig;\n`;\n\n/**\n * `warlock add sitemap` writes its policy into the app's \\`src/config/web.ts\\`,\n * under the \\`sitemap\\` key — there is no \\`src/config/sitemap.ts\\` and no\n * standalone connector to register; \\`@warlock.js/web\\` (already installed via\n * the \\`web\\` requirement) reads \\`web.sitemap\\` itself.\n *\n * Creates \\`web.ts\\` when the app does not have one yet; otherwise merges a\n * \\`sitemap\\` section into whatever is already there rather than clobbering it.\n */\nasync function installSitemapConfig(): Promise<void> {\n const configPath = srcPath(\"config/web.ts\");\n\n if (!(await fileExistsAsync(configPath))) {\n await putFileAsync(configPath, freshWebConfigStub);\n console.log(`${colors.green(\"✓\")} Created src/config/web.ts with a disabled sitemap section`);\n console.log(NEXT_STEPS);\n\n return;\n }\n\n const current = await getFileAsync(configPath);\n const merge = mergeWebSitemapConfig(current);\n\n if (merge.status === \"already-present\") {\n console.log(\n `${colors.yellowBright(\"sitemap\")} already configured in src/config/web.ts, skipping...`,\n );\n\n return;\n }\n\n if (merge.status === \"unrecognised\") {\n console.log(\n `${colors.redBright(\"✗\")} Could not safely add a \\`sitemap\\` section to ` +\n `${colors.yellowBright(\"src/config/web.ts\")} — its exported config object was not ` +\n \"recognised, so nothing was written. Add it yourself:\\n\" +\n ' sitemap: { enabled: false, path: \"/sitemap.xml\", defaults: { changefreq: \"weekly\", priority: 0.5 } },',\n );\n\n process.exitCode = 1;\n\n return;\n }\n\n await putFileAsync(configPath, merge.next);\n console.log(`${colors.green(\"✓\")} Added a disabled \\`sitemap\\` section to src/config/web.ts`);\n console.log(NEXT_STEPS);\n}\n\n/** `warlock add sitemap` — runtime sitemap.xml generation, backed by the page registry. */\nexport const sitemapFeature: FeatureDefinition = {\n description:\n \"Installs @warlock.js/sitemap — runtime sitemap.xml generation from the page registry. \" +\n \"Adds a disabled `sitemap` section to src/config/web.ts, creating the file if it doesn't \" +\n \"exist yet. Requires app.publicUrl (or PUBLIC_APP_URL) to be set.\",\n requires: [\"web\"],\n dependencies: {\n \"@warlock.js/sitemap\": INSTALLED_WARLOCK_VERSION,\n },\n onExecuting: installSitemapConfig,\n};\n"],"mappings":";;;;;;;;AAMA,MAAM,aACJ;;;;;;;;;;;;;;AAgBF,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;AAsB3B,eAAe,uBAAsC;CACnD,MAAM,aAAa,QAAQ,eAAe;CAE1C,IAAI,CAAE,MAAM,gBAAgB,UAAU,GAAI;EACxC,MAAM,aAAa,YAAY,kBAAkB;EACjD,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,2DAA2D;EAC5F,QAAQ,IAAI,UAAU;EAEtB;CACF;CAGA,MAAM,QAAQ,sBAAsB,MADd,aAAa,UAAU,CACF;CAE3C,IAAI,MAAM,WAAW,mBAAmB;EACtC,QAAQ,IACN,GAAG,OAAO,aAAa,SAAS,EAAE,sDACpC;EAEA;CACF;CAEA,IAAI,MAAM,WAAW,gBAAgB;EACnC,QAAQ,IACN,GAAG,OAAO,UAAU,GAAG,EAAE,iDACpB,OAAO,aAAa,mBAAmB,EAAE;wGAGhD;EAEA,QAAQ,WAAW;EAEnB;CACF;CAEA,MAAM,aAAa,YAAY,MAAM,IAAI;CACzC,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,2DAA2D;CAC5F,QAAQ,IAAI,UAAU;AACxB;;AAGA,MAAa,iBAAoC;CAC/C,aACE;CAGF,UAAU,CAAC,KAAK;CAChB,cAAc,EACZ,uBAAuB,0BACzB;CACA,aAAa;AACf"}
1
+ {"version":3,"file":"sitemap.feature.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/generations/features/sitemap.feature.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { fileExistsAsync, getFileAsync, putFileAsync } from \"../generation-fs\";\nimport { srcPath } from \"../../utils\";\nimport { mergeWebSitemapConfig } from \"./shared/merge-web-sitemap-config\";\nimport { type FeatureDefinition, INSTALLED_WARLOCK_VERSION } from \"./types\";\n\nconst NEXT_STEPS =\n \"Next: set `app.publicUrl` (src/config/app.ts) or the PUBLIC_APP_URL environment \" +\n \"variable, then flip `sitemap.enabled` to true in src/config/web.ts.\";\n\n/**\n * Ships DISABLED because a sitemap needs this application's public origin and\n * a freshly generated app has no way to know it. Two steps to turn it on:\n *\n * 1. set `app.publicUrl` in src/config/app.ts, or the PUBLIC_APP_URL\n * environment variable;\n * 2. flip `sitemap.enabled` to true here.\n *\n * With it enabled and no origin configured, generation REFUSES rather than\n * serving absolute URLs built from a guessed host — a sitemap pointing at\n * the wrong domain is worse than one that never starts, because nothing\n * downstream reports it.\n */\nconst freshWebConfigStub = `import type { WebSitemapConfig } from \"@warlock.js/web/sitemap\";\n\nconst webConfig: { sitemap: WebSitemapConfig } = {\n sitemap: {\n enabled: false,\n path: \"/sitemap.xml\",\n defaults: { changefreq: \"weekly\", priority: 0.5 },\n },\n};\n\nexport default webConfig;\n`;\n\n/**\n * `warlock add sitemap` writes its policy into the app's \\`src/config/web.ts\\`,\n * under the \\`sitemap\\` key — there is no \\`src/config/sitemap.ts\\` and no\n * standalone connector to register; \\`@warlock.js/web\\` (already installed via\n * the \\`web\\` requirement) reads \\`web.sitemap\\` itself.\n *\n * Creates \\`web.ts\\` when the app does not have one yet; otherwise merges a\n * \\`sitemap\\` section into whatever is already there rather than clobbering it.\n */\nasync function installSitemapConfig(): Promise<void> {\n const configPath = srcPath(\"config/web.ts\");\n\n if (!(await fileExistsAsync(configPath))) {\n await putFileAsync(configPath, freshWebConfigStub);\n console.log(`${colors.green(\"✓\")} Created src/config/web.ts with a disabled sitemap section`);\n console.log(NEXT_STEPS);\n\n return;\n }\n\n const current = await getFileAsync(configPath);\n const merge = mergeWebSitemapConfig(current);\n\n if (merge.status === \"already-present\") {\n console.log(\n `${colors.yellowBright(\"sitemap\")} already configured in src/config/web.ts, skipping...`,\n );\n\n return;\n }\n\n if (merge.status === \"unrecognised\") {\n console.log(\n `${colors.redBright(\"✗\")} Could not safely add a \\`sitemap\\` section to ` +\n `${colors.yellowBright(\"src/config/web.ts\")} — its exported config object was not ` +\n \"recognised, so nothing was written. Add it yourself:\\n\" +\n ' sitemap: { enabled: false, path: \"/sitemap.xml\", defaults: { changefreq: \"weekly\", priority: 0.5 } },',\n );\n\n process.exitCode = 1;\n\n return;\n }\n\n await putFileAsync(configPath, merge.next);\n console.log(`${colors.green(\"✓\")} Added a disabled \\`sitemap\\` section to src/config/web.ts`);\n console.log(NEXT_STEPS);\n}\n\n/** `warlock add sitemap` — runtime sitemap.xml generation, backed by the page registry. */\nexport const sitemapFeature: FeatureDefinition = {\n description:\n \"Installs @warlock.js/sitemap — runtime sitemap.xml generation from the page registry. \" +\n \"Adds a disabled `sitemap` section to src/config/web.ts, creating the file if it doesn't \" +\n \"exist yet. Requires app.publicUrl (or PUBLIC_APP_URL) to be set.\",\n requires: [\"web\"],\n dependencies: {\n \"@warlock.js/sitemap\": INSTALLED_WARLOCK_VERSION,\n },\n onExecuting: installSitemapConfig,\n};\n"],"mappings":";;;;;;;;AAMA,MAAM,aACJ;;;;;;;;;;;;;;AAgBF,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;AAsB3B,eAAe,uBAAsC;CACnD,MAAM,aAAa,QAAQ,eAAe;CAE1C,IAAI,CAAE,MAAM,gBAAgB,UAAU,GAAI;EACxC,MAAM,aAAa,YAAY,kBAAkB;EACjD,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,2DAA2D;EAC5F,QAAQ,IAAI,UAAU;EAEtB;CACF;CAEA,MAAM,UAAU,MAAM,aAAa,UAAU;CAC7C,MAAM,QAAQ,sBAAsB,OAAO;CAE3C,IAAI,MAAM,WAAW,mBAAmB;EACtC,QAAQ,IACN,GAAG,OAAO,aAAa,SAAS,EAAE,sDACpC;EAEA;CACF;CAEA,IAAI,MAAM,WAAW,gBAAgB;EACnC,QAAQ,IACN,GAAG,OAAO,UAAU,GAAG,EAAE,iDACpB,OAAO,aAAa,mBAAmB,EAAE;wGAGhD;EAEA,QAAQ,WAAW;EAEnB;CACF;CAEA,MAAM,aAAa,YAAY,MAAM,IAAI;CACzC,QAAQ,IAAI,GAAG,OAAO,MAAM,GAAG,EAAE,2DAA2D;CAC5F,QAAQ,IAAI,UAAU;AACxB;;AAGA,MAAa,iBAAoC;CAC/C,aACE;CAGF,UAAU,CAAC,KAAK;CAChB,cAAc,EACZ,uBAAuB,0BACzB;CACA,aAAa;AACf"}
@@ -69,5 +69,5 @@ async function ensureDirectoryAsync$1(directory) {
69
69
  }
70
70
 
71
71
  //#endregion
72
- export { directoryExistsAsync$1 as directoryExistsAsync, ensureDirectoryAsync$1 as ensureDirectoryAsync, fileExistsAsync$1 as fileExistsAsync, getFileAsync$1 as getFileAsync, getJsonFileAsync$1 as getJsonFileAsync, putFileAsync$1 as putFileAsync, putJsonFileAsync$1 as putJsonFileAsync };
72
+ export { directoryExistsAsync$1 as directoryExistsAsync, ensureDirectoryAsync$1 as ensureDirectoryAsync, fileExistsAsync$1 as fileExistsAsync, getFileAsync$1 as getFileAsync, getJsonFileAsync$1 as getJsonFileAsync, putFileAsync$1 as putFileAsync, putJsonFileAsync$1 as putJsonFileAsync, recordSkippedFile };
73
73
  //# sourceMappingURL=generation-fs.mjs.map
@@ -181,5 +181,5 @@ const generationOutputOptions = [{
181
181
  }];
182
182
 
183
183
  //#endregion
184
- export { currentGenerationRun, generationOutputOptions, hasPendingContentUnder, isGenerationDryRun, pendingGeneratedContent, recordGeneratedFile, recordSkippedFile, runGenerationCommand, setGenerationDetail, setPendingGeneratedContent, toReportPath };
184
+ export { beginGenerationRun, currentGenerationRun, endGenerationRun, generationOutputOptions, hasPendingContentUnder, isGenerationDryRun, pendingGeneratedContent, recordGeneratedFile, recordSkippedFile, runGenerationCommand, setGenerationDetail, setPendingGeneratedContent, toReportPath };
185
185
  //# sourceMappingURL=generation-run.mjs.map