@warlock.js/core 5.19.1 → 5.21.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 (378) hide show
  1. package/CHANGELOG.md +1136 -1073
  2. package/esm/benchmark/benchmark.mjs +34 -25
  3. package/esm/benchmark/benchmark.mjs.map +1 -1
  4. package/esm/benchmark/profiler.d.mts.map +1 -1
  5. package/esm/benchmark/profiler.mjs +8 -3
  6. package/esm/benchmark/profiler.mjs.map +1 -1
  7. package/esm/bootstrap.d.mts.map +1 -1
  8. package/esm/bootstrap.mjs +3 -0
  9. package/esm/bootstrap.mjs.map +1 -1
  10. package/esm/cache/database-cache-driver.d.mts +2 -2
  11. package/esm/cache/database-cache-driver.d.mts.map +1 -1
  12. package/esm/cache/database-cache-driver.mjs +3 -2
  13. package/esm/cache/database-cache-driver.mjs.map +1 -1
  14. package/esm/cli/cli-commands.manager.mjs +16 -14
  15. package/esm/cli/cli-commands.manager.mjs.map +1 -1
  16. package/esm/cli/commands/add.command.mjs +1 -1
  17. package/esm/cli/commands/add.command.mjs.map +1 -1
  18. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +3 -2
  19. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
  20. package/esm/cli/commands/generate/generate.command.mjs +20 -0
  21. package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
  22. package/esm/cli/commands/generate/generators/column-dsl-parser.mjs +4 -2
  23. package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
  24. package/esm/cli/commands/generate/generators/controller.generator.mjs +1 -1
  25. package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
  26. package/esm/cli/commands/generate/generators/migration.generator.mjs +22 -6
  27. package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
  28. package/esm/cli/commands/generate/generators/model.generator.mjs +22 -7
  29. package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
  30. package/esm/cli/commands/generate/generators/module.generator.mjs +8 -6
  31. package/esm/cli/commands/generate/generators/module.generator.mjs.map +1 -1
  32. package/esm/cli/commands/generate/generators/repository.generator.mjs +1 -1
  33. package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
  34. package/esm/cli/commands/generate/generators/resource.generator.mjs +1 -1
  35. package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
  36. package/esm/cli/commands/generate/generators/service.generator.mjs +1 -1
  37. package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
  38. package/esm/cli/commands/generate/templates/stubs.mjs +7 -7
  39. package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
  40. package/esm/cli/commands/generate/utils/writer.mjs +25 -1
  41. package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
  42. package/esm/cli/commands/routes/routes-command.action.mjs +5 -1
  43. package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -1
  44. package/esm/cli/commands/routes/with-console-on-stderr.mjs +24 -0
  45. package/esm/cli/commands/routes/with-console-on-stderr.mjs.map +1 -0
  46. package/esm/cli/commands/routes.command.mjs +3 -4
  47. package/esm/cli/commands/routes.command.mjs.map +1 -1
  48. package/esm/cli/commands/start-production.command.mjs +5 -5
  49. package/esm/cli/commands/start-production.command.mjs.map +1 -1
  50. package/esm/cli/commands/storage-put.action.mjs +2 -1
  51. package/esm/cli/commands/storage-put.action.mjs.map +1 -1
  52. package/esm/cli/commands/update.command.mjs +1 -0
  53. package/esm/cli/commands/update.command.mjs.map +1 -1
  54. package/esm/cli/parse-cli-args.mjs +13 -1
  55. package/esm/cli/parse-cli-args.mjs.map +1 -1
  56. package/esm/commands/cli-command.d.mts.map +1 -1
  57. package/esm/commands/cli-command.mjs +4 -2
  58. package/esm/commands/cli-command.mjs.map +1 -1
  59. package/esm/commands/index.mjs +3 -0
  60. package/esm/config/config-key-from-path.mjs +20 -0
  61. package/esm/config/config-key-from-path.mjs.map +1 -0
  62. package/esm/config/config-loader.d.mts.map +1 -1
  63. package/esm/config/config-loader.mjs +2 -3
  64. package/esm/config/config-loader.mjs.map +1 -1
  65. package/esm/connectors/cache-connector.d.mts.map +1 -1
  66. package/esm/connectors/cache-connector.mjs +5 -0
  67. package/esm/connectors/cache-connector.mjs.map +1 -1
  68. package/esm/connectors/connectors-manager.d.mts +4 -0
  69. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  70. package/esm/connectors/connectors-manager.mjs +30 -2
  71. package/esm/connectors/connectors-manager.mjs.map +1 -1
  72. package/esm/connectors/single-server-warnings.mjs +33 -0
  73. package/esm/connectors/single-server-warnings.mjs.map +1 -0
  74. package/esm/connectors/socket-connector.d.mts +29 -0
  75. package/esm/connectors/socket-connector.d.mts.map +1 -1
  76. package/esm/connectors/socket-connector.mjs +77 -9
  77. package/esm/connectors/socket-connector.mjs.map +1 -1
  78. package/esm/connectors/storage.connector.d.mts.map +1 -1
  79. package/esm/connectors/storage.connector.mjs +6 -0
  80. package/esm/connectors/storage.connector.mjs.map +1 -1
  81. package/esm/connectors/types.d.mts +4 -2
  82. package/esm/connectors/types.d.mts.map +1 -1
  83. package/esm/connectors/types.mjs.map +1 -1
  84. package/esm/database/models/database-log/database-log.d.mts +47 -24
  85. package/esm/database/models/database-log/database-log.d.mts.map +1 -1
  86. package/esm/database/models/database-log/database-log.mjs +36 -4
  87. package/esm/database/models/database-log/database-log.mjs.map +1 -1
  88. package/esm/database/seed-command-action.mjs +10 -2
  89. package/esm/database/seed-command-action.mjs.map +1 -1
  90. package/esm/dev-server/development-server.mjs +15 -4
  91. package/esm/dev-server/development-server.mjs.map +1 -1
  92. package/esm/dev-server/file-event-handler.mjs +26 -6
  93. package/esm/dev-server/file-event-handler.mjs.map +1 -1
  94. package/esm/dev-server/file-manager.d.mts.map +1 -1
  95. package/esm/dev-server/file-manager.mjs +2 -2
  96. package/esm/dev-server/file-manager.mjs.map +1 -1
  97. package/esm/dev-server/files-orchestrator.mjs +3 -1
  98. package/esm/dev-server/files-orchestrator.mjs.map +1 -1
  99. package/esm/dev-server/files-watcher.mjs +64 -5
  100. package/esm/dev-server/files-watcher.mjs.map +1 -1
  101. package/esm/dev-server/health-checker/files-healthcare.manager.mjs +31 -9
  102. package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
  103. package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +11 -7
  104. package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +1 -1
  105. package/esm/dev-server/loader/load-hook.mjs +1 -1
  106. package/esm/dev-server/loader/register-loader.mjs +1 -1
  107. package/esm/dev-server/manifest-manager.d.mts.map +1 -1
  108. package/esm/dev-server/manifest-manager.mjs +12 -6
  109. package/esm/dev-server/manifest-manager.mjs.map +1 -1
  110. package/esm/dev-server/parse-imports.mjs +9 -0
  111. package/esm/dev-server/parse-imports.mjs.map +1 -1
  112. package/esm/dev-server/register-dev-shortcuts.mjs +2 -1
  113. package/esm/dev-server/register-dev-shortcuts.mjs.map +1 -1
  114. package/esm/dev-server/route-types-publisher.mjs +60 -0
  115. package/esm/dev-server/route-types-publisher.mjs.map +1 -0
  116. package/esm/dev-server/shortcuts.mjs +2 -2
  117. package/esm/dev-server/shortcuts.mjs.map +1 -1
  118. package/esm/dev-server/special-file-patterns.mjs +18 -0
  119. package/esm/dev-server/special-file-patterns.mjs.map +1 -0
  120. package/esm/dev-server/special-files-collector.d.mts.map +1 -1
  121. package/esm/dev-server/special-files-collector.mjs +2 -5
  122. package/esm/dev-server/special-files-collector.mjs.map +1 -1
  123. package/esm/dev-server/start-development-server.mjs +1 -2
  124. package/esm/dev-server/start-development-server.mjs.map +1 -1
  125. package/esm/dev-server/supervisor.mjs +23 -3
  126. package/esm/dev-server/supervisor.mjs.map +1 -1
  127. package/esm/dev-server/tsconfig-manager.mjs +22 -12
  128. package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
  129. package/esm/dev-server/type-generator.mjs +10 -9
  130. package/esm/dev-server/type-generator.mjs.map +1 -1
  131. package/esm/encryption/encrypt.d.mts.map +1 -1
  132. package/esm/encryption/encrypt.mjs +16 -5
  133. package/esm/encryption/encrypt.mjs.map +1 -1
  134. package/esm/encryption/hash.d.mts.map +1 -1
  135. package/esm/encryption/hash.mjs +2 -0
  136. package/esm/encryption/hash.mjs.map +1 -1
  137. package/esm/encryption/password.d.mts.map +1 -1
  138. package/esm/encryption/password.mjs +3 -1
  139. package/esm/encryption/password.mjs.map +1 -1
  140. package/esm/generations/features/index.mjs +1 -1
  141. package/esm/generations/features/mysql.feature.mjs +9 -2
  142. package/esm/generations/features/mysql.feature.mjs.map +1 -1
  143. package/esm/generations/features/test.feature.mjs +2 -1
  144. package/esm/generations/features/test.feature.mjs.map +1 -1
  145. package/esm/generations/features/web.feature.mjs +4 -2
  146. package/esm/generations/features/web.feature.mjs.map +1 -1
  147. package/esm/http/build-rate-limit-options.d.mts +37 -0
  148. package/esm/http/build-rate-limit-options.d.mts.map +1 -0
  149. package/esm/http/build-rate-limit-options.mjs +37 -0
  150. package/esm/http/build-rate-limit-options.mjs.map +1 -0
  151. package/esm/http/csrf-origin-policy.d.mts.map +1 -1
  152. package/esm/http/csrf-origin-policy.mjs +5 -2
  153. package/esm/http/csrf-origin-policy.mjs.map +1 -1
  154. package/esm/http/flush-pending-cookies.mjs +52 -0
  155. package/esm/http/flush-pending-cookies.mjs.map +1 -0
  156. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  157. package/esm/http/middleware/cache-response-middleware.mjs +4 -2
  158. package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
  159. package/esm/http/middleware/idempotency.middleware.d.mts +5 -0
  160. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  161. package/esm/http/middleware/idempotency.middleware.mjs +35 -3
  162. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  163. package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
  164. package/esm/http/middleware/inject-request-context.mjs +14 -3
  165. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  166. package/esm/http/middleware/rate-limit.middleware.d.mts +4 -3
  167. package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
  168. package/esm/http/middleware/rate-limit.middleware.mjs +4 -3
  169. package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
  170. package/esm/http/middleware/utils/cidr-match.d.mts +1 -1
  171. package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
  172. package/esm/http/middleware/utils/cidr-match.mjs +11 -2
  173. package/esm/http/middleware/utils/cidr-match.mjs.map +1 -1
  174. package/esm/http/middleware/utils/idempotency-key.mjs +1 -1
  175. package/esm/http/middleware/utils/idempotency-key.mjs.map +1 -1
  176. package/esm/http/plugins.d.mts.map +1 -1
  177. package/esm/http/plugins.mjs +13 -5
  178. package/esm/http/plugins.mjs.map +1 -1
  179. package/esm/http/request.d.mts +12 -1
  180. package/esm/http/request.d.mts.map +1 -1
  181. package/esm/http/request.mjs +35 -7
  182. package/esm/http/request.mjs.map +1 -1
  183. package/esm/http/response.d.mts +16 -0
  184. package/esm/http/response.d.mts.map +1 -1
  185. package/esm/http/response.mjs +75 -37
  186. package/esm/http/response.mjs.map +1 -1
  187. package/esm/http/types.d.mts +26 -14
  188. package/esm/http/types.d.mts.map +1 -1
  189. package/esm/http/uploads/uploaded-file.controller.mjs +1 -1
  190. package/esm/http/uploads-config.mjs +2 -1
  191. package/esm/http/uploads-config.mjs.map +1 -1
  192. package/esm/http/uploads-types.d.mts +3 -3
  193. package/esm/image/image.d.mts +1 -1
  194. package/esm/image/image.d.mts.map +1 -1
  195. package/esm/image/image.mjs +25 -15
  196. package/esm/image/image.mjs.map +1 -1
  197. package/esm/index.d.mts +6 -4
  198. package/esm/index.mjs +7 -4
  199. package/esm/logger/logger.mjs +6 -1
  200. package/esm/logger/logger.mjs.map +1 -1
  201. package/esm/mail/config.d.mts.map +1 -1
  202. package/esm/mail/config.mjs +31 -21
  203. package/esm/mail/config.mjs.map +1 -1
  204. package/esm/mail/react-mail.mjs +6 -3
  205. package/esm/mail/react-mail.mjs.map +1 -1
  206. package/esm/mail/send-mail.d.mts.map +1 -1
  207. package/esm/mail/send-mail.mjs +40 -19
  208. package/esm/mail/send-mail.mjs.map +1 -1
  209. package/esm/production/assert-generated-imports.mjs +1 -0
  210. package/esm/production/assert-generated-imports.mjs.map +1 -1
  211. package/esm/production/build-contributions.mjs +3 -0
  212. package/esm/production/build-contributions.mjs.map +1 -1
  213. package/esm/production/esbuild-plugins.mjs +3 -2
  214. package/esm/production/esbuild-plugins.mjs.map +1 -1
  215. package/esm/production/production-builder.mjs +49 -37
  216. package/esm/production/production-builder.mjs.map +1 -1
  217. package/esm/production/production-supervisor.mjs +12 -5
  218. package/esm/production/production-supervisor.mjs.map +1 -1
  219. package/esm/production/route-registration-child.d.mts +1 -0
  220. package/esm/production/route-registration-child.mjs +65 -0
  221. package/esm/production/route-registration-child.mjs.map +1 -0
  222. package/esm/production/route-registration-snapshot.mjs +166 -0
  223. package/esm/production/route-registration-snapshot.mjs.map +1 -0
  224. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +3 -1
  225. package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
  226. package/esm/repositories/adapters/cascade/cascade-adapter.mjs +22 -12
  227. package/esm/repositories/adapters/cascade/cascade-adapter.mjs.map +1 -1
  228. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +3 -3
  229. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
  230. package/esm/repositories/adapters/cascade/filter-applicator.mjs +88 -61
  231. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  232. package/esm/repositories/adapters/cascade/index.d.mts +1 -1
  233. package/esm/repositories/adapters/cascade/index.mjs +1 -1
  234. package/esm/repositories/contracts/query-builder.contract.d.mts +3 -3
  235. package/esm/repositories/contracts/types.d.mts +5 -0
  236. package/esm/repositories/contracts/types.d.mts.map +1 -1
  237. package/esm/repositories/index.d.mts +1 -1
  238. package/esm/repositories/index.mjs +1 -1
  239. package/esm/repositories/repository.manager.d.mts +65 -3
  240. package/esm/repositories/repository.manager.d.mts.map +1 -1
  241. package/esm/repositories/repository.manager.mjs +146 -57
  242. package/esm/repositories/repository.manager.mjs.map +1 -1
  243. package/esm/resource/resource-field-builder.d.mts.map +1 -1
  244. package/esm/resource/resource-field-builder.mjs +1 -0
  245. package/esm/resource/resource-field-builder.mjs.map +1 -1
  246. package/esm/resource/resource.d.mts +10 -3
  247. package/esm/resource/resource.d.mts.map +1 -1
  248. package/esm/resource/resource.mjs +19 -5
  249. package/esm/resource/resource.mjs.map +1 -1
  250. package/esm/restful/restful.d.mts +12 -5
  251. package/esm/restful/restful.d.mts.map +1 -1
  252. package/esm/restful/restful.mjs +47 -16
  253. package/esm/restful/restful.mjs.map +1 -1
  254. package/esm/router/build-route-rate-limit.mjs +22 -0
  255. package/esm/router/build-route-rate-limit.mjs.map +1 -0
  256. package/esm/router/dev-dispatch.mjs +60 -0
  257. package/esm/router/dev-dispatch.mjs.map +1 -0
  258. package/esm/router/route-builder.mjs +4 -1
  259. package/esm/router/route-builder.mjs.map +1 -1
  260. package/esm/router/route-registry.d.mts.map +1 -1
  261. package/esm/router/route-registry.mjs +2 -2
  262. package/esm/router/route-registry.mjs.map +1 -1
  263. package/esm/router/router.d.mts +1 -1
  264. package/esm/router/router.d.mts.map +1 -1
  265. package/esm/router/router.mjs +57 -39
  266. package/esm/router/router.mjs.map +1 -1
  267. package/esm/socket/index.d.mts +1 -1
  268. package/esm/socket/types.d.mts +25 -3
  269. package/esm/socket/types.d.mts.map +1 -1
  270. package/esm/storage/drivers/cloud-driver.d.mts +26 -0
  271. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  272. package/esm/storage/drivers/cloud-driver.mjs +100 -16
  273. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  274. package/esm/storage/drivers/do-spaces-driver.d.mts +7 -0
  275. package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
  276. package/esm/storage/drivers/do-spaces-driver.mjs +9 -2
  277. package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
  278. package/esm/storage/drivers/local-driver.d.mts +16 -5
  279. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  280. package/esm/storage/drivers/local-driver.mjs +71 -28
  281. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  282. package/esm/storage/index.d.mts +3 -1
  283. package/esm/storage/index.mjs +4 -2
  284. package/esm/storage/scoped-storage.d.mts +27 -1
  285. package/esm/storage/scoped-storage.d.mts.map +1 -1
  286. package/esm/storage/scoped-storage.mjs +40 -8
  287. package/esm/storage/scoped-storage.mjs.map +1 -1
  288. package/esm/storage/storage.d.mts +11 -5
  289. package/esm/storage/storage.d.mts.map +1 -1
  290. package/esm/storage/storage.mjs +39 -16
  291. package/esm/storage/storage.mjs.map +1 -1
  292. package/esm/storage/types.d.mts +43 -4
  293. package/esm/storage/types.d.mts.map +1 -1
  294. package/esm/storage/utils/classify-ip-address.d.mts +13 -0
  295. package/esm/storage/utils/classify-ip-address.d.mts.map +1 -0
  296. package/esm/storage/utils/classify-ip-address.mjs +98 -0
  297. package/esm/storage/utils/classify-ip-address.mjs.map +1 -0
  298. package/esm/storage/utils/safe-fetch.d.mts +3 -12
  299. package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
  300. package/esm/storage/utils/safe-fetch.mjs +3 -48
  301. package/esm/storage/utils/safe-fetch.mjs.map +1 -1
  302. package/esm/storage/utils/storage-capability-error.d.mts +25 -0
  303. package/esm/storage/utils/storage-capability-error.d.mts.map +1 -0
  304. package/esm/storage/utils/storage-capability-error.mjs +26 -0
  305. package/esm/storage/utils/storage-capability-error.mjs.map +1 -0
  306. package/esm/updater/update-warlock-packages.mjs +11 -1
  307. package/esm/updater/update-warlock-packages.mjs.map +1 -1
  308. package/esm/use-cases/use-case-broadcast.mjs +7 -1
  309. package/esm/use-cases/use-case-broadcast.mjs.map +1 -1
  310. package/esm/use-cases/use-cases-registry.mjs +21 -2
  311. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  312. package/esm/utils/database-log.mjs +0 -3
  313. package/esm/utils/database-log.mjs.map +1 -1
  314. package/esm/utils/queue.d.mts +6 -4
  315. package/esm/utils/queue.d.mts.map +1 -1
  316. package/esm/utils/queue.mjs +20 -9
  317. package/esm/utils/queue.mjs.map +1 -1
  318. package/esm/validation/database/exists-except-current-id.mjs +6 -2
  319. package/esm/validation/database/exists-except-current-id.mjs.map +1 -1
  320. package/esm/validation/database/unique-except-current-id.mjs +6 -2
  321. package/esm/validation/database/unique-except-current-id.mjs.map +1 -1
  322. package/esm/validation/init.mjs +6 -2
  323. package/esm/validation/init.mjs.map +1 -1
  324. package/esm/validation/validateAll.mjs +3 -2
  325. package/esm/validation/validateAll.mjs.map +1 -1
  326. package/esm/warlock-config/types.d.mts +14 -1
  327. package/esm/warlock-config/types.d.mts.map +1 -1
  328. package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
  329. package/esm/warlock-config/warlock-config.manager.mjs +3 -1
  330. package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
  331. package/esm/warlock-config/warn-deprecated-config.mjs +25 -0
  332. package/esm/warlock-config/warn-deprecated-config.mjs.map +1 -0
  333. package/llms-full.txt +71 -42
  334. package/llms.txt +41 -41
  335. package/package.json +21 -15
  336. package/skills/add-connector/SKILL.md +5 -1
  337. package/skills/benchmark-code/SKILL.md +1 -1
  338. package/skills/build-restful/SKILL.md +1 -1
  339. package/skills/build-url/SKILL.md +1 -1
  340. package/skills/configure-app/SKILL.md +7 -1
  341. package/skills/create-controller/SKILL.md +1 -1
  342. package/skills/create-module/SKILL.md +1 -1
  343. package/skills/define-resource/SKILL.md +1 -1
  344. package/skills/encrypt-data/SKILL.md +1 -1
  345. package/skills/hash-password/SKILL.md +1 -1
  346. package/skills/health-checks/SKILL.md +1 -1
  347. package/skills/index.md +30 -0
  348. package/skills/lower-stage3-decorators/SKILL.md +1 -1
  349. package/skills/process-image/SKILL.md +1 -1
  350. package/skills/register-route/SKILL.md +1 -1
  351. package/skills/request-memo/SKILL.md +1 -1
  352. package/skills/request-tracing/SKILL.md +1 -1
  353. package/skills/resolve-path/SKILL.md +1 -1
  354. package/skills/retry-operation/SKILL.md +1 -1
  355. package/skills/run-app/SKILL.md +1 -1
  356. package/skills/send-mail/SKILL.md +1 -1
  357. package/skills/send-response/SKILL.md +1 -1
  358. package/skills/store-file/SKILL.md +11 -1
  359. package/skills/test-http/SKILL.md +1 -1
  360. package/skills/test-service/SKILL.md +1 -1
  361. package/skills/update-packages/SKILL.md +1 -1
  362. package/skills/upload-file/SKILL.md +1 -1
  363. package/skills/use-app-context/SKILL.md +1 -1
  364. package/skills/use-localization/SKILL.md +1 -1
  365. package/skills/use-middleware/SKILL.md +7 -2
  366. package/skills/use-model-transformers/SKILL.md +1 -1
  367. package/skills/use-repository/SKILL.md +1 -1
  368. package/skills/use-request-locals/SKILL.md +1 -1
  369. package/skills/validate-input/SKILL.md +1 -1
  370. package/skills/warlock-conventions/SKILL.md +1 -1
  371. package/skills/warlock-doctor/SKILL.md +1 -1
  372. package/skills/warlock-routes/SKILL.md +1 -1
  373. package/skills/wire-socket/SKILL.md +5 -1
  374. package/skills/write-cli-command/SKILL.md +1 -1
  375. package/skills/write-middleware/SKILL.md +1 -1
  376. package/skills/write-seeder/SKILL.md +1 -1
  377. package/skills/write-use-case/SKILL.md +1 -1
  378. package/esm/_virtual/_rolldown/runtime.mjs +0 -7
@@ -1 +1 @@
1
- {"version":3,"file":"optional-peers.check.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/doctor/checks/optional-peers.check.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { config } from \"../../../../config/config-getter\";\nimport type { CheckStatus, DoctorCheck } from \"../check.types\";\n\n/**\n * A package this project's own configuration requires, and what asked for it.\n */\ntype RequiredPeer = {\n /** The npm package name to probe via `require.resolve`. */\n package: string;\n\n /** The config that asked for it, quoted back to the user verbatim. */\n because: string;\n};\n\n/**\n * Resolve from the project's working directory, not from core's own\n * `node_modules`, so the probe reflects what the *consuming app* has installed.\n */\nconst projectRequire = createRequire(`${process.cwd()}/package.json`);\n\n/**\n * Whether a package can be resolved from the project. A failed resolve (the\n * normal \"not installed\" case) is swallowed and reported as missing.\n */\nfunction isInstalled(packageName: string): boolean {\n try {\n projectRequire.resolve(packageName);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * A non-empty string, or `undefined`. Config values arrive from `env(...)` and\n * an unset variable yields `undefined` — but a `.env` line with nothing after\n * the `=` yields `\"\"`, which is \"not configured\" just as much.\n */\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\n/**\n * The database driver's package. `driver` is a closed union in cascade\n * (`mongodb | postgres | mysql`), so an unrecognised value means the config is\n * wrong in a way this check is not the right one to report.\n */\nfunction databasePeer(): RequiredPeer | undefined {\n const driver = text(config.get(\"database.driver\"));\n\n const packageName =\n driver === \"mongodb\"\n ? \"mongodb\"\n : driver === \"postgres\"\n ? \"pg\"\n : driver === \"mysql\"\n ? \"mysql2\"\n : undefined;\n\n return packageName\n ? { package: packageName, because: `database.driver = \"${driver}\"` }\n : undefined;\n}\n\n/**\n * The selected cache driver. Only the DEFAULT matters: `cache.drivers` is a\n * menu the scaffold fills in for every driver the framework ships, and warning\n * about a menu entry nobody selected is the false positive this whole check was\n * rewritten to remove.\n */\nfunction cachePeer(): RequiredPeer | undefined {\n const selected = text(config.get(\"cache.default\"));\n\n if (!selected || !/redis/i.test(selected)) return undefined;\n\n return { package: \"redis\", because: `cache.default = \"${selected}\"` };\n}\n\n/**\n * The selected storage driver, read through its canonical `driver` field\n * (`local` / `s3` / `r2` / `spaces`) rather than the key the app happened to\n * name it, so a driver called \"cdn\" is still recognised as S3.\n */\nfunction storagePeer(): RequiredPeer | undefined {\n const selected = text(config.get(\"storage.default\"));\n\n if (!selected) return undefined;\n\n const driver = text(config.get(`storage.drivers.${selected}.driver`));\n\n if (!driver || driver === \"local\") return undefined;\n\n return {\n package: \"@aws-sdk/client-s3\",\n because: `storage.default = \"${selected}\" (driver \"${driver}\")`,\n };\n}\n\n/**\n * The mail transport. A `mail` config with no host and no driver is the\n * scaffold's placeholder — every field is an unset env var — so it asks for\n * nothing and this stays quiet.\n */\nfunction mailPeer(): RequiredPeer | undefined {\n const driver = text(config.get(\"mail.driver\"));\n\n if (driver === \"ses\") {\n return { package: \"@aws-sdk/client-sesv2\", because: `mail.driver = \"ses\"` };\n }\n\n const host = text(config.get(\"mail.host\"));\n\n if (!host) return undefined;\n\n return { package: \"nodemailer\", because: `mail.host = \"${host}\"` };\n}\n\n/**\n * Realtime sockets. The connector no-ops without a `socket` config, so the\n * presence of that config is exactly the request for the peer.\n */\nfunction socketPeer(): RequiredPeer | undefined {\n if (!config.get(\"socket\")) return undefined;\n\n return { package: \"socket.io\", because: \"a socket config is present\" };\n}\n\n/**\n * Every peer THIS project's configuration asks for.\n */\nfunction requiredPeers(): RequiredPeer[] {\n return [databasePeer(), cachePeer(), storagePeer(), mailPeer(), socketPeer()].filter(\n (peer): peer is RequiredPeer => Boolean(peer),\n );\n}\n\n/**\n * Checks that every optional peer the project's own configuration selects is\n * actually installed.\n *\n * NEEDS NO BOOTED APP — it reads config and resolves module paths. It runs after\n * the boot pass only because config is loaded by then.\n *\n * WHAT THIS REPLACED, AND WHY: the previous version probed nine packages and\n * warned about every one that was absent. Every one of them is an OPTIONAL\n * peer — a fresh app installs none of them by design — so the check warned, at\n * length, about the framework's own default state. \"No MySQL driver installed\"\n * is not a diagnosis for someone who never wanted MySQL; it is noise that\n * teaches the reader to skim past the line where a real finding will one day\n * appear.\n *\n * Inverted, it becomes a genuine one: a project whose config selects a driver\n * whose package is missing is broken — it will throw the first time that\n * feature is used — so a missing peer here is a `fail`, not a warning.\n */\nexport const optionalPeersCheck: DoctorCheck = {\n name: \"optional-peers\",\n run: () => {\n const required = requiredPeers();\n\n if (required.length === 0) {\n return undefined;\n }\n\n const missing = required.filter((peer) => !isInstalled(peer.package));\n\n const status: CheckStatus = missing.length > 0 ? \"fail\" : \"ok\";\n\n if (missing.length > 0) {\n return {\n name: \"optional-peers\",\n status,\n detail:\n `${missing.length} configured feature(s) have no driver installed:\\n` +\n missing.map((peer) => ` - ${peer.package} — required by ${peer.because}`).join(\"\\n\"),\n };\n }\n\n return {\n name: \"optional-peers\",\n status,\n detail: `every configured driver is installed (${required\n .map((peer) => peer.package)\n .join(\", \")})`,\n };\n },\n};\n"],"mappings":";;;;;;;;AAmBA,MAAM,iBAAiB,cAAc,GAAG,QAAQ,IAAI,EAAE,cAAc;;;;;AAMpE,SAAS,YAAY,aAA8B;CACjD,IAAI;EACF,eAAe,QAAQ,WAAW;EAClC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,SAAS,KAAK,OAAoC;CAChD,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;;;;;;AAOA,SAAS,eAAyC;CAChD,MAAM,SAAS,KAAK,OAAO,IAAI,iBAAiB,CAAC;CAEjD,MAAM,cACJ,WAAW,YACP,YACA,WAAW,aACT,OACA,WAAW,UACT,WACA;CAEV,OAAO,cACH;EAAE,SAAS;EAAa,SAAS,sBAAsB,OAAO;CAAG,IACjE;AACN;;;;;;;AAQA,SAAS,YAAsC;CAC7C,MAAM,WAAW,KAAK,OAAO,IAAI,eAAe,CAAC;CAEjD,IAAI,CAAC,YAAY,CAAC,SAAS,KAAK,QAAQ,GAAG,OAAO;CAElD,OAAO;EAAE,SAAS;EAAS,SAAS,oBAAoB,SAAS;CAAG;AACtE;;;;;;AAOA,SAAS,cAAwC;CAC/C,MAAM,WAAW,KAAK,OAAO,IAAI,iBAAiB,CAAC;CAEnD,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,SAAS,KAAK,OAAO,IAAI,mBAAmB,SAAS,QAAQ,CAAC;CAEpE,IAAI,CAAC,UAAU,WAAW,SAAS,OAAO;CAE1C,OAAO;EACL,SAAS;EACT,SAAS,sBAAsB,SAAS,aAAa,OAAO;CAC9D;AACF;;;;;;AAOA,SAAS,WAAqC;CAG5C,IAFe,KAAK,OAAO,IAAI,aAAa,CAEnC,MAAM,OACb,OAAO;EAAE,SAAS;EAAyB,SAAS;CAAsB;CAG5E,MAAM,OAAO,KAAK,OAAO,IAAI,WAAW,CAAC;CAEzC,IAAI,CAAC,MAAM,OAAO;CAElB,OAAO;EAAE,SAAS;EAAc,SAAS,gBAAgB,KAAK;CAAG;AACnE;;;;;AAMA,SAAS,aAAuC;CAC9C,IAAI,CAAC,OAAO,IAAI,QAAQ,GAAG,OAAO;CAElC,OAAO;EAAE,SAAS;EAAa,SAAS;CAA6B;AACvE;;;;AAKA,SAAS,gBAAgC;CACvC,OAAO;EAAC,aAAa;EAAG,UAAU;EAAG,YAAY;EAAG,SAAS;EAAG,WAAW;CAAC,CAAC,CAAC,QAC3E,SAA+B,QAAQ,IAAI,CAC9C;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,qBAAkC;CAC7C,MAAM;CACN,WAAW;EACT,MAAM,WAAW,cAAc;EAE/B,IAAI,SAAS,WAAW,GACtB;EAGF,MAAM,UAAU,SAAS,QAAQ,SAAS,CAAC,YAAY,KAAK,OAAO,CAAC;EAEpE,MAAM,SAAsB,QAAQ,SAAS,IAAI,SAAS;EAE1D,IAAI,QAAQ,SAAS,GACnB,OAAO;GACL,MAAM;GACN;GACA,QACE,GAAG,QAAQ,OAAO,sDAClB,QAAQ,KAAK,SAAS,OAAO,KAAK,QAAQ,iBAAiB,KAAK,SAAS,CAAC,CAAC,KAAK,IAAI;EACxF;EAGF,OAAO;GACL,MAAM;GACN;GACA,QAAQ,yCAAyC,SAC9C,KAAK,SAAS,KAAK,OAAO,CAAC,CAC3B,KAAK,IAAI,EAAE;EAChB;CACF;AACF"}
1
+ {"version":3,"file":"optional-peers.check.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/doctor/checks/optional-peers.check.ts"],"sourcesContent":["import { createRequire } from \"node:module\";\nimport { config } from \"../../../../config/config-getter\";\nimport type { CheckStatus, DoctorCheck } from \"../check.types\";\n\n/**\n * A package this project's own configuration requires, and what asked for it.\n */\ntype RequiredPeer = {\n /** The npm package name to probe via `require.resolve`. */\n package: string;\n\n /** The config that asked for it, quoted back to the user verbatim. */\n because: string;\n};\n\n/**\n * Resolve from the project's working directory, not from core's own\n * `node_modules`, so the probe reflects what the *consuming app* has installed.\n */\nconst projectRequire = createRequire(`${process.cwd()}/package.json`);\n\n/**\n * Whether a package can be resolved from the project. A failed resolve (the\n * normal \"not installed\" case) is swallowed and reported as missing.\n */\nfunction isInstalled(packageName: string): boolean {\n try {\n projectRequire.resolve(packageName);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * A non-empty string, or `undefined`. Config values arrive from `env(...)` and\n * an unset variable yields `undefined` — but a `.env` line with nothing after\n * the `=` yields `\"\"`, which is \"not configured\" just as much.\n */\nfunction text(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : undefined;\n}\n\n/**\n * The database driver's package. `driver` is a closed union in cascade\n * (`mongodb | postgres | mysql`) and mysql is not implemented by cascade, so it\n * has no peer to report; an unrecognised value means the config is\n * wrong in a way this check is not the right one to report.\n */\nfunction databasePeer(): RequiredPeer | undefined {\n const driver = text(config.get(\"database.driver\"));\n\n const packageName =\n driver === \"mongodb\"\n ? \"mongodb\"\n : driver === \"postgres\"\n ? \"pg\"\n : undefined;\n\n return packageName\n ? { package: packageName, because: `database.driver = \"${driver}\"` }\n : undefined;\n}\n\n/**\n * The selected cache driver. Only the DEFAULT matters: `cache.drivers` is a\n * menu the scaffold fills in for every driver the framework ships, and warning\n * about a menu entry nobody selected is the false positive this whole check was\n * rewritten to remove.\n */\nfunction cachePeer(): RequiredPeer | undefined {\n const selected = text(config.get(\"cache.default\"));\n\n if (!selected || !/redis/i.test(selected)) return undefined;\n\n return { package: \"redis\", because: `cache.default = \"${selected}\"` };\n}\n\n/**\n * The selected storage driver, read through its canonical `driver` field\n * (`local` / `s3` / `r2` / `spaces`) rather than the key the app happened to\n * name it, so a driver called \"cdn\" is still recognised as S3.\n */\nfunction storagePeer(): RequiredPeer | undefined {\n const selected = text(config.get(\"storage.default\"));\n\n if (!selected) return undefined;\n\n const driver = text(config.get(`storage.drivers.${selected}.driver`));\n\n if (!driver || driver === \"local\") return undefined;\n\n return {\n package: \"@aws-sdk/client-s3\",\n because: `storage.default = \"${selected}\" (driver \"${driver}\")`,\n };\n}\n\n/**\n * The mail transport. A `mail` config with no host and no driver is the\n * scaffold's placeholder — every field is an unset env var — so it asks for\n * nothing and this stays quiet.\n */\nfunction mailPeer(): RequiredPeer | undefined {\n const driver = text(config.get(\"mail.driver\"));\n\n if (driver === \"ses\") {\n return { package: \"@aws-sdk/client-sesv2\", because: `mail.driver = \"ses\"` };\n }\n\n const host = text(config.get(\"mail.host\"));\n\n if (!host) return undefined;\n\n return { package: \"nodemailer\", because: `mail.host = \"${host}\"` };\n}\n\n/**\n * Realtime sockets. The connector no-ops without a `socket` config, so the\n * presence of that config is exactly the request for the peer.\n */\nfunction socketPeer(): RequiredPeer | undefined {\n if (!config.get(\"socket\")) return undefined;\n\n return { package: \"socket.io\", because: \"a socket config is present\" };\n}\n\n/**\n * Every peer THIS project's configuration asks for.\n */\nfunction requiredPeers(): RequiredPeer[] {\n return [databasePeer(), cachePeer(), storagePeer(), mailPeer(), socketPeer()].filter(\n (peer): peer is RequiredPeer => Boolean(peer),\n );\n}\n\n/**\n * Checks that every optional peer the project's own configuration selects is\n * actually installed.\n *\n * NEEDS NO BOOTED APP — it reads config and resolves module paths. It runs after\n * the boot pass only because config is loaded by then.\n *\n * WHAT THIS REPLACED, AND WHY: the previous version probed nine packages and\n * warned about every one that was absent. Every one of them is an OPTIONAL\n * peer — a fresh app installs none of them by design — so the check warned, at\n * length, about the framework's own default state. \"No MySQL driver installed\"\n * is not a diagnosis for someone who never wanted MySQL; it is noise that\n * teaches the reader to skim past the line where a real finding will one day\n * appear.\n *\n * Inverted, it becomes a genuine one: a project whose config selects a driver\n * whose package is missing is broken — it will throw the first time that\n * feature is used — so a missing peer here is a `fail`, not a warning.\n */\nexport const optionalPeersCheck: DoctorCheck = {\n name: \"optional-peers\",\n run: () => {\n const required = requiredPeers();\n\n if (required.length === 0) {\n return undefined;\n }\n\n const missing = required.filter((peer) => !isInstalled(peer.package));\n\n const status: CheckStatus = missing.length > 0 ? \"fail\" : \"ok\";\n\n if (missing.length > 0) {\n return {\n name: \"optional-peers\",\n status,\n detail:\n `${missing.length} configured feature(s) have no driver installed:\\n` +\n missing.map((peer) => ` - ${peer.package} — required by ${peer.because}`).join(\"\\n\"),\n };\n }\n\n return {\n name: \"optional-peers\",\n status,\n detail: `every configured driver is installed (${required\n .map((peer) => peer.package)\n .join(\", \")})`,\n };\n },\n};\n"],"mappings":";;;;;;;;AAmBA,MAAM,iBAAiB,cAAc,GAAG,QAAQ,IAAI,EAAE,cAAc;;;;;AAMpE,SAAS,YAAY,aAA8B;CACjD,IAAI;EACF,eAAe,QAAQ,WAAW;EAClC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;;;;;AAOA,SAAS,KAAK,OAAoC;CAChD,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,CAAC,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;;;;;;;AAQA,SAAS,eAAyC;CAChD,MAAM,SAAS,KAAK,OAAO,IAAI,iBAAiB,CAAC;CAEjD,MAAM,cACJ,WAAW,YACP,YACA,WAAW,aACT,OACA;CAER,OAAO,cACH;EAAE,SAAS;EAAa,SAAS,sBAAsB,OAAO;CAAG,IACjE;AACN;;;;;;;AAQA,SAAS,YAAsC;CAC7C,MAAM,WAAW,KAAK,OAAO,IAAI,eAAe,CAAC;CAEjD,IAAI,CAAC,YAAY,CAAC,SAAS,KAAK,QAAQ,GAAG,OAAO;CAElD,OAAO;EAAE,SAAS;EAAS,SAAS,oBAAoB,SAAS;CAAG;AACtE;;;;;;AAOA,SAAS,cAAwC;CAC/C,MAAM,WAAW,KAAK,OAAO,IAAI,iBAAiB,CAAC;CAEnD,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,SAAS,KAAK,OAAO,IAAI,mBAAmB,SAAS,QAAQ,CAAC;CAEpE,IAAI,CAAC,UAAU,WAAW,SAAS,OAAO;CAE1C,OAAO;EACL,SAAS;EACT,SAAS,sBAAsB,SAAS,aAAa,OAAO;CAC9D;AACF;;;;;;AAOA,SAAS,WAAqC;CAG5C,IAFe,KAAK,OAAO,IAAI,aAAa,CAEnC,MAAM,OACb,OAAO;EAAE,SAAS;EAAyB,SAAS;CAAsB;CAG5E,MAAM,OAAO,KAAK,OAAO,IAAI,WAAW,CAAC;CAEzC,IAAI,CAAC,MAAM,OAAO;CAElB,OAAO;EAAE,SAAS;EAAc,SAAS,gBAAgB,KAAK;CAAG;AACnE;;;;;AAMA,SAAS,aAAuC;CAC9C,IAAI,CAAC,OAAO,IAAI,QAAQ,GAAG,OAAO;CAElC,OAAO;EAAE,SAAS;EAAa,SAAS;CAA6B;AACvE;;;;AAKA,SAAS,gBAAgC;CACvC,OAAO;EAAC,aAAa;EAAG,UAAU;EAAG,YAAY;EAAG,SAAS;EAAG,WAAW;CAAC,CAAC,CAAC,QAC3E,SAA+B,QAAQ,IAAI,CAC9C;AACF;;;;;;;;;;;;;;;;;;;;AAqBA,MAAa,qBAAkC;CAC7C,MAAM;CACN,WAAW;EACT,MAAM,WAAW,cAAc;EAE/B,IAAI,SAAS,WAAW,GACtB;EAGF,MAAM,UAAU,SAAS,QAAQ,SAAS,CAAC,YAAY,KAAK,OAAO,CAAC;EAEpE,MAAM,SAAsB,QAAQ,SAAS,IAAI,SAAS;EAE1D,IAAI,QAAQ,SAAS,GACnB,OAAO;GACL,MAAM;GACN;GACA,QACE,GAAG,QAAQ,OAAO,sDAClB,QAAQ,KAAK,SAAS,OAAO,KAAK,QAAQ,iBAAiB,KAAK,SAAS,CAAC,CAAC,KAAK,IAAI;EACxF;EAGF,OAAO;GACL,MAAM;GACN;GACA,QAAQ,yCAAyC,SAC9C,KAAK,SAAS,KAAK,OAAO,CAAC,CAC3B,KAAK,IAAI,EAAE;EAChB;CACF;AACF"}
@@ -74,6 +74,11 @@ const generateModuleCommand = command({
74
74
  description: "Overwrite existing files",
75
75
  type: "boolean"
76
76
  },
77
+ {
78
+ text: "--overwrite",
79
+ description: "With --force, also replace existing files that differ from the generated output (default: skip and list them)",
80
+ type: "boolean"
81
+ },
77
82
  {
78
83
  text: "--dry-run",
79
84
  description: "Preview the files that would be generated without writing anything",
@@ -139,6 +144,11 @@ const generateModelCommand = command({
139
144
  description: "Overwrite existing files",
140
145
  type: "boolean"
141
146
  },
147
+ {
148
+ text: "--overwrite",
149
+ description: "With --force, also replace existing files that differ from the generated output (default: skip and list them)",
150
+ type: "boolean"
151
+ },
142
152
  {
143
153
  text: "--dry-run",
144
154
  description: "Preview the files that would be generated without writing anything",
@@ -148,6 +158,11 @@ const generateModelCommand = command({
148
158
  text: "--timestamps [bool]",
149
159
  description: "Include timestamps in migration (default: true)",
150
160
  type: "boolean"
161
+ },
162
+ {
163
+ text: "--no-timestamps",
164
+ description: "Disable timestamps (same as --timestamps false)",
165
+ type: "boolean"
151
166
  }
152
167
  ]
153
168
  });
@@ -213,6 +228,11 @@ const generateMigrationCommand = command({
213
228
  text: "--timestamps [bool]",
214
229
  description: "Include timestamps (default: true)",
215
230
  type: "boolean"
231
+ },
232
+ {
233
+ text: "--no-timestamps",
234
+ description: "Disable timestamps (same as --timestamps false)",
235
+ type: "boolean"
216
236
  }
217
237
  ]
218
238
  });
@@ -1 +1 @@
1
- {"version":3,"file":"generate.command.mjs","names":[],"sources":["../../../../../../../../../core/src/cli/commands/generate/generate.command.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\r\nimport { command } from \"../../../commands/cli-command\";\r\nimport type { CommandActionData } from \"../../../commands/types\";\r\nimport { generateController } from \"./generators/controller.generator\";\r\nimport { generateMigration } from \"./generators/migration.generator\";\r\nimport { generateModel } from \"./generators/model.generator\";\r\nimport { generateModule } from \"./generators/module.generator\";\r\nimport { generateRepository } from \"./generators/repository.generator\";\r\nimport { generateResource } from \"./generators/resource.generator\";\r\nimport { generateService } from \"./generators/service.generator\";\r\n\r\nconst generators: Record<string, (data: CommandActionData) => Promise<void>> = {\r\n module: generateModule,\r\n controller: generateController,\r\n service: generateService,\r\n model: generateModel,\r\n migration: generateMigration,\r\n repository: generateRepository,\r\n resource: generateResource,\r\n};\r\n\r\nasync function generateCommandAction(data: CommandActionData) {\r\n const commandName = data.args[0];\r\n\r\n if (!commandName) {\r\n console.log(colors.red(\"Error: Generator name is required\"));\r\n console.log(colors.yellow(\"\\nAvailable generators:\"));\r\n Object.keys(generators).forEach((cmd) => {\r\n console.log(colors.cyan(` - ${cmd}`));\r\n });\r\n console.log(colors.yellow(\"\\nUsage: warlock generate <generator> <name> [options]\"));\r\n process.exit(1);\r\n }\r\n\r\n const generator = generators[commandName];\r\n\r\n if (!generator) {\r\n console.log(colors.red(`Error: Unknown generator \"${commandName}\"`));\r\n console.log(colors.yellow(\"\\nAvailable generators:\"));\r\n Object.keys(generators).forEach((cmd) => {\r\n console.log(colors.cyan(` - ${cmd}`));\r\n });\r\n process.exit(1);\r\n }\r\n\r\n // Remove the command name from args for the generator\r\n const generatorData: CommandActionData = {\r\n ...data,\r\n args: data.args.slice(1),\r\n };\r\n\r\n await generator(generatorData);\r\n}\r\n\r\n// Master generate command\r\nexport const generateCommand = command({\r\n name: \"generate <generator> [args...]\",\r\n alias: \"g\", // Allows 'warlock g module ...'\r\n description: \"Scaffold a new component\",\r\n action: generateCommandAction,\r\n options: [\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\n// Individual commands\r\nexport const generateModuleCommand = command({\r\n name: \"generate.module <name>\",\r\n alias: \"gen.m\",\r\n description: \"Generate a new module\",\r\n action: generateModule,\r\n options: [\r\n {\r\n text: \"--minimal, -m\",\r\n description:\r\n \"Generate a minimal skeleton (routes, main, locales, empty subfolders) instead of the full CRUD scaffold\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\nexport const generateControllerCommand = command({\r\n name: \"generate.controller <module>/<name>\",\r\n alias: \"gen.c\",\r\n description: \"Generate a new controller\",\r\n action: generateController,\r\n options: [\r\n {\r\n text: \"--with-validation, -v\",\r\n description: \"Generate a validation schema and bind it to the controller\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\nexport const generateServiceCommand = command({\r\n name: \"generate.service <module>/<name>\",\r\n alias: \"gen.s\",\r\n description: \"Generate a new service\",\r\n action: generateService,\r\n options: [\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\nexport const generateModelCommand = command({\r\n name: \"generate.model <module>/<name>\",\r\n alias: \"gen.md\",\r\n description: \"Generate a new model with migration\",\r\n action: generateModel,\r\n options: [\r\n {\r\n text: \"--with-resource, -rs\",\r\n description: \"Generate resource\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--table <name>\",\r\n description: \"Specify table name\",\r\n },\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--timestamps [bool]\",\r\n description: \"Include timestamps in migration (default: true)\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\nexport const generateRepositoryCommand = command({\r\n name: \"generate.repository <module>/<name>\",\r\n alias: \"gen.r\",\r\n description: \"Generate a new repository\",\r\n action: generateRepository,\r\n options: [\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\nexport const generateResourceCommand = command({\r\n name: \"generate.resource <module>/<name>\",\r\n alias: \"gen.rs\",\r\n description: \"Generate a new resource\",\r\n action: generateResource,\r\n options: [\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n\r\nexport const generateMigrationCommand = command({\r\n name: \"generate.migration <model-path>\",\r\n alias: \"gen.mig\",\r\n description: \"Generate a new migration for a model\",\r\n action: generateMigration,\r\n options: [\r\n {\r\n text: \"--force, -f\",\r\n description: \"Overwrite existing files\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--dry-run\",\r\n description: \"Preview the files that would be generated without writing anything\",\r\n type: \"boolean\",\r\n },\r\n {\r\n text: \"--add <columns>\",\r\n description: \"Columns to add (DSL: name:type:modifier,...)\",\r\n },\r\n {\r\n text: \"--drop <columns>\",\r\n description: \"Columns to drop (comma-separated names)\",\r\n },\r\n {\r\n text: \"--rename <columns>\",\r\n description: \"Columns to rename (DSL: old:new,...)\",\r\n },\r\n {\r\n text: \"--timestamps [bool]\",\r\n description: \"Include timestamps (default: true)\",\r\n type: \"boolean\",\r\n },\r\n ],\r\n});\r\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,aAAyE;CAC7E,QAAQ;CACR,YAAY;CACZ,SAAS;CACT,OAAO;CACP,WAAW;CACX,YAAY;CACZ,UAAU;AACZ;AAEA,eAAe,sBAAsB,MAAyB;CAC5D,MAAM,cAAc,KAAK,KAAK;CAE9B,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,OAAO,IAAI,mCAAmC,CAAC;EAC3D,QAAQ,IAAI,OAAO,OAAO,yBAAyB,CAAC;EACpD,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,QAAQ;GACvC,QAAQ,IAAI,OAAO,KAAK,OAAO,KAAK,CAAC;EACvC,CAAC;EACD,QAAQ,IAAI,OAAO,OAAO,wDAAwD,CAAC;EACnF,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,YAAY,WAAW;CAE7B,IAAI,CAAC,WAAW;EACd,QAAQ,IAAI,OAAO,IAAI,6BAA6B,YAAY,EAAE,CAAC;EACnE,QAAQ,IAAI,OAAO,OAAO,yBAAyB,CAAC;EACpD,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,QAAQ;GACvC,QAAQ,IAAI,OAAO,KAAK,OAAO,KAAK,CAAC;EACvC,CAAC;EACD,QAAQ,KAAK,CAAC;CAChB;CAQA,MAAM,UAAU;EAJd,GAAG;EACH,MAAM,KAAK,KAAK,MAAM,CAAC;CAGG,CAAC;AAC/B;AAGA,MAAa,kBAAkB,QAAQ;CACrC,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAGD,MAAa,wBAAwB,QAAQ;CAC3C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aACE;GACF,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC;AAED,MAAa,4BAA4B,QAAQ;CAC/C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC;AAED,MAAa,yBAAyB,QAAQ;CAC5C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAED,MAAa,uBAAuB,QAAQ;CAC1C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC;AAED,MAAa,4BAA4B,QAAQ;CAC/C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAED,MAAa,0BAA0B,QAAQ;CAC7C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAED,MAAa,2BAA2B,QAAQ;CAC9C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC"}
1
+ {"version":3,"file":"generate.command.mjs","names":[],"sources":["../../../../../../../../../core/src/cli/commands/generate/generate.command.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { command } from \"../../../commands/cli-command\";\nimport type { CommandActionData } from \"../../../commands/types\";\nimport { generateController } from \"./generators/controller.generator\";\nimport { generateMigration } from \"./generators/migration.generator\";\nimport { generateModel } from \"./generators/model.generator\";\nimport { generateModule } from \"./generators/module.generator\";\nimport { generateRepository } from \"./generators/repository.generator\";\nimport { generateResource } from \"./generators/resource.generator\";\nimport { generateService } from \"./generators/service.generator\";\n\nconst generators: Record<string, (data: CommandActionData) => Promise<void>> = {\n module: generateModule,\n controller: generateController,\n service: generateService,\n model: generateModel,\n migration: generateMigration,\n repository: generateRepository,\n resource: generateResource,\n};\n\nasync function generateCommandAction(data: CommandActionData) {\n const commandName = data.args[0];\n\n if (!commandName) {\n console.log(colors.red(\"Error: Generator name is required\"));\n console.log(colors.yellow(\"\\nAvailable generators:\"));\n Object.keys(generators).forEach((cmd) => {\n console.log(colors.cyan(` - ${cmd}`));\n });\n console.log(colors.yellow(\"\\nUsage: warlock generate <generator> <name> [options]\"));\n process.exit(1);\n }\n\n const generator = generators[commandName];\n\n if (!generator) {\n console.log(colors.red(`Error: Unknown generator \"${commandName}\"`));\n console.log(colors.yellow(\"\\nAvailable generators:\"));\n Object.keys(generators).forEach((cmd) => {\n console.log(colors.cyan(` - ${cmd}`));\n });\n process.exit(1);\n }\n\n // Remove the command name from args for the generator\n const generatorData: CommandActionData = {\n ...data,\n args: data.args.slice(1),\n };\n\n await generator(generatorData);\n}\n\n// Master generate command\nexport const generateCommand = command({\n name: \"generate <generator> [args...]\",\n alias: \"g\", // Allows 'warlock g module ...'\n description: \"Scaffold a new component\",\n action: generateCommandAction,\n options: [\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n ],\n});\n\n// Individual commands\nexport const generateModuleCommand = command({\n name: \"generate.module <name>\",\n alias: \"gen.m\",\n description: \"Generate a new module\",\n action: generateModule,\n options: [\n {\n text: \"--minimal, -m\",\n description:\n \"Generate a minimal skeleton (routes, main, locales, empty subfolders) instead of the full CRUD scaffold\",\n type: \"boolean\",\n },\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--overwrite\",\n description:\n \"With --force, also replace existing files that differ from the generated output (default: skip and list them)\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n ],\n});\n\nexport const generateControllerCommand = command({\n name: \"generate.controller <module>/<name>\",\n alias: \"gen.c\",\n description: \"Generate a new controller\",\n action: generateController,\n options: [\n {\n text: \"--with-validation, -v\",\n description: \"Generate a validation schema and bind it to the controller\",\n type: \"boolean\",\n },\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n ],\n});\n\nexport const generateServiceCommand = command({\n name: \"generate.service <module>/<name>\",\n alias: \"gen.s\",\n description: \"Generate a new service\",\n action: generateService,\n options: [\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n ],\n});\n\nexport const generateModelCommand = command({\n name: \"generate.model <module>/<name>\",\n alias: \"gen.md\",\n description: \"Generate a new model with migration\",\n action: generateModel,\n options: [\n {\n text: \"--with-resource, -rs\",\n description: \"Generate resource\",\n type: \"boolean\",\n },\n {\n text: \"--table <name>\",\n description: \"Specify table name\",\n },\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--overwrite\",\n description:\n \"With --force, also replace existing files that differ from the generated output (default: skip and list them)\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n {\n text: \"--timestamps [bool]\",\n description: \"Include timestamps in migration (default: true)\",\n type: \"boolean\",\n },\n {\n text: \"--no-timestamps\",\n description: \"Disable timestamps (same as --timestamps false)\",\n type: \"boolean\",\n },\n ],\n});\n\nexport const generateRepositoryCommand = command({\n name: \"generate.repository <module>/<name>\",\n alias: \"gen.r\",\n description: \"Generate a new repository\",\n action: generateRepository,\n options: [\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n ],\n});\n\nexport const generateResourceCommand = command({\n name: \"generate.resource <module>/<name>\",\n alias: \"gen.rs\",\n description: \"Generate a new resource\",\n action: generateResource,\n options: [\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n ],\n});\n\nexport const generateMigrationCommand = command({\n name: \"generate.migration <model-path>\",\n alias: \"gen.mig\",\n description: \"Generate a new migration for a model\",\n action: generateMigration,\n options: [\n {\n text: \"--force, -f\",\n description: \"Overwrite existing files\",\n type: \"boolean\",\n },\n {\n text: \"--dry-run\",\n description: \"Preview the files that would be generated without writing anything\",\n type: \"boolean\",\n },\n {\n text: \"--add <columns>\",\n description: \"Columns to add (DSL: name:type:modifier,...)\",\n },\n {\n text: \"--drop <columns>\",\n description: \"Columns to drop (comma-separated names)\",\n },\n {\n text: \"--rename <columns>\",\n description: \"Columns to rename (DSL: old:new,...)\",\n },\n {\n text: \"--timestamps [bool]\",\n description: \"Include timestamps (default: true)\",\n type: \"boolean\",\n },\n {\n text: \"--no-timestamps\",\n description: \"Disable timestamps (same as --timestamps false)\",\n type: \"boolean\",\n },\n ],\n});\n"],"mappings":";;;;;;;;;;;AAWA,MAAM,aAAyE;CAC7E,QAAQ;CACR,YAAY;CACZ,SAAS;CACT,OAAO;CACP,WAAW;CACX,YAAY;CACZ,UAAU;AACZ;AAEA,eAAe,sBAAsB,MAAyB;CAC5D,MAAM,cAAc,KAAK,KAAK;CAE9B,IAAI,CAAC,aAAa;EAChB,QAAQ,IAAI,OAAO,IAAI,mCAAmC,CAAC;EAC3D,QAAQ,IAAI,OAAO,OAAO,yBAAyB,CAAC;EACpD,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,QAAQ;GACvC,QAAQ,IAAI,OAAO,KAAK,OAAO,KAAK,CAAC;EACvC,CAAC;EACD,QAAQ,IAAI,OAAO,OAAO,wDAAwD,CAAC;EACnF,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,YAAY,WAAW;CAE7B,IAAI,CAAC,WAAW;EACd,QAAQ,IAAI,OAAO,IAAI,6BAA6B,YAAY,EAAE,CAAC;EACnE,QAAQ,IAAI,OAAO,OAAO,yBAAyB,CAAC;EACpD,OAAO,KAAK,UAAU,CAAC,CAAC,SAAS,QAAQ;GACvC,QAAQ,IAAI,OAAO,KAAK,OAAO,KAAK,CAAC;EACvC,CAAC;EACD,QAAQ,KAAK,CAAC;CAChB;CAQA,MAAM,UAAU;EAJd,GAAG;EACH,MAAM,KAAK,KAAK,MAAM,CAAC;CAGG,CAAC;AAC/B;AAGA,MAAa,kBAAkB,QAAQ;CACrC,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAGD,MAAa,wBAAwB,QAAQ;CAC3C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aACE;GACF,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aACE;GACF,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC;AAED,MAAa,4BAA4B,QAAQ;CAC/C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC;AAED,MAAa,yBAAyB,QAAQ;CAC5C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAED,MAAa,uBAAuB,QAAQ;CAC1C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aACE;GACF,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC;AAED,MAAa,4BAA4B,QAAQ;CAC/C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAED,MAAa,0BAA0B,QAAQ;CAC7C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS,CACP;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,GACA;EACE,MAAM;EACN,aAAa;EACb,MAAM;CACR,CACF;AACF,CAAC;AAED,MAAa,2BAA2B,QAAQ;CAC9C,MAAM;CACN,OAAO;CACP,aAAa;CACb,QAAQ;CACR,SAAS;EACP;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;EACf;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;EACA;GACE,MAAM;GACN,aAAa;GACb,MAAM;EACR;CACF;AACF,CAAC"}
@@ -15,6 +15,7 @@ const typeMapping = {
15
15
  object: "objectCol",
16
16
  decimal: "decimal",
17
17
  float: "float",
18
+ number: "float",
18
19
  enum: "enumCol",
19
20
  set: "setCol",
20
21
  blob: "blobCol",
@@ -28,9 +29,10 @@ function parseColumnDsl(input) {
28
29
  if (!input) return [];
29
30
  return input.split(",").map((c) => c.trim()).filter(Boolean).map((colStr) => {
30
31
  const parts = colStr.split(":").map((p) => p.trim());
31
- const name = parts[0];
32
+ const name = parts[0] ?? "";
32
33
  const rawType = parts[1] || "string";
33
- const helper = typeMapping[rawType] || rawType;
34
+ const helper = typeMapping[rawType];
35
+ if (!helper) throw new Error(`Unknown column type "${rawType}" for "${name}". Valid types: ${Object.keys(typeMapping).join(", ")}`);
34
36
  const modifiers = [];
35
37
  for (let i = 2; i < parts.length; i++) {
36
38
  let modifier = parts[i];
@@ -1 +1 @@
1
- {"version":3,"file":"column-dsl-parser.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/column-dsl-parser.ts"],"sourcesContent":["export type ParsedColumn = {\n name: string;\n helper: string; // e.g. \"text\", \"boolCol\", \"decimal\"\n modifiers: string[]; // e.g. [\".nullable()\", \".unsigned()\"]\n};\n\nconst typeMapping: Record<string, string> = {\n text: \"text\",\n string: \"string\",\n integer: \"integer\",\n int: \"integer\",\n bigInteger: \"bigInteger\",\n bigInt: \"bigInteger\",\n boolean: \"boolCol\",\n bool: \"boolCol\",\n uuid: \"uuid\",\n timestamp: \"timestamp\",\n date: \"date\",\n json: \"json\",\n object: \"objectCol\",\n decimal: \"decimal\",\n float: \"float\",\n enum: \"enumCol\",\n set: \"setCol\",\n blob: \"blobCol\",\n binary: \"blobCol\",\n};\n\n/**\n * Parses a subset DSL for column schemas:\n * \"phone:text:nullable,price:decimal:notNullable:unsigned\"\n */\nexport function parseColumnDsl(input: string): ParsedColumn[] {\n if (!input) return [];\n\n const columns = input\n .split(\",\")\n .map((c) => c.trim())\n .filter(Boolean);\n\n return columns.map((colStr) => {\n const parts = colStr.split(\":\").map((p) => p.trim());\n const name = parts[0];\n const rawType = parts[1] || \"string\";\n const helper = typeMapping[rawType] || rawType; // fallback to raw string if not mapped\n\n const modifiers: string[] = [];\n for (let i = 2; i < parts.length; i++) {\n let modifier = parts[i];\n // Basic modifiers that translates to builder calls\n modifiers.push(`.${modifier}()`);\n }\n\n return {\n name,\n helper,\n modifiers,\n };\n });\n}\n"],"mappings":";AAMA,MAAM,cAAsC;CAC1C,MAAM;CACN,QAAQ;CACR,SAAS;CACT,KAAK;CACL,YAAY;CACZ,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;CACN,WAAW;CACX,MAAM;CACN,MAAM;CACN,QAAQ;CACR,SAAS;CACT,OAAO;CACP,MAAM;CACN,KAAK;CACL,MAAM;CACN,QAAQ;AACV;;;;;AAMA,SAAgB,eAAe,OAA+B;CAC5D,IAAI,CAAC,OAAO,OAAO,CAAC;CAOpB,OALgB,MACb,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,OAAO,OAEG,CAAC,CAAC,KAAK,WAAW;EAC7B,MAAM,QAAQ,OAAO,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;EACnD,MAAM,OAAO,MAAM;EACnB,MAAM,UAAU,MAAM,MAAM;EAC5B,MAAM,SAAS,YAAY,YAAY;EAEvC,MAAM,YAAsB,CAAC;EAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACrC,IAAI,WAAW,MAAM;GAErB,UAAU,KAAK,IAAI,SAAS,GAAG;EACjC;EAEA,OAAO;GACL;GACA;GACA;EACF;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"column-dsl-parser.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/column-dsl-parser.ts"],"sourcesContent":["export type ParsedColumn = {\n name: string;\n helper: string; // e.g. \"text\", \"boolCol\", \"decimal\"\n modifiers: string[]; // e.g. [\".nullable()\", \".unsigned()\"]\n};\n\nconst typeMapping: Record<string, string> = {\n text: \"text\",\n string: \"string\",\n integer: \"integer\",\n int: \"integer\",\n bigInteger: \"bigInteger\",\n bigInt: \"bigInteger\",\n boolean: \"boolCol\",\n bool: \"boolCol\",\n uuid: \"uuid\",\n timestamp: \"timestamp\",\n date: \"date\",\n json: \"json\",\n object: \"objectCol\",\n decimal: \"decimal\",\n float: \"float\",\n number: \"float\",\n enum: \"enumCol\",\n set: \"setCol\",\n blob: \"blobCol\",\n binary: \"blobCol\",\n};\n\n/**\n * Parses a subset DSL for column schemas:\n * \"phone:text:nullable,price:decimal:notNullable:unsigned\"\n */\nexport function parseColumnDsl(input: string): ParsedColumn[] {\n if (!input) return [];\n\n const columns = input\n .split(\",\")\n .map((c) => c.trim())\n .filter(Boolean);\n\n return columns.map((colStr) => {\n const parts = colStr.split(\":\").map((p) => p.trim());\n const name = parts[0] ?? \"\"; // colStr is non-empty, so split always yields a first part\n const rawType = parts[1] || \"string\";\n const helper = typeMapping[rawType];\n\n if (!helper) {\n throw new Error(\n `Unknown column type \"${rawType}\" for \"${name}\". Valid types: ${Object.keys(typeMapping).join(\", \")}`,\n );\n }\n\n const modifiers: string[] = [];\n for (let i = 2; i < parts.length; i++) {\n let modifier = parts[i];\n // Basic modifiers that translates to builder calls\n modifiers.push(`.${modifier}()`);\n }\n\n return {\n name,\n helper,\n modifiers,\n };\n });\n}\n"],"mappings":";AAMA,MAAM,cAAsC;CAC1C,MAAM;CACN,QAAQ;CACR,SAAS;CACT,KAAK;CACL,YAAY;CACZ,QAAQ;CACR,SAAS;CACT,MAAM;CACN,MAAM;CACN,WAAW;CACX,MAAM;CACN,MAAM;CACN,QAAQ;CACR,SAAS;CACT,OAAO;CACP,QAAQ;CACR,MAAM;CACN,KAAK;CACL,MAAM;CACN,QAAQ;AACV;;;;;AAMA,SAAgB,eAAe,OAA+B;CAC5D,IAAI,CAAC,OAAO,OAAO,CAAC;CAOpB,OALgB,MACb,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,OAAO,OAEG,CAAC,CAAC,KAAK,WAAW;EAC7B,MAAM,QAAQ,OAAO,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;EACnD,MAAM,OAAO,MAAM,MAAM;EACzB,MAAM,UAAU,MAAM,MAAM;EAC5B,MAAM,SAAS,YAAY;EAE3B,IAAI,CAAC,QACH,MAAM,IAAI,MACR,wBAAwB,QAAQ,SAAS,KAAK,kBAAkB,OAAO,KAAK,WAAW,CAAC,CAAC,KAAK,IAAI,GACpG;EAGF,MAAM,YAAsB,CAAC;EAC7B,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;GACrC,IAAI,WAAW,MAAM;GAErB,UAAU,KAAK,IAAI,SAAS,GAAG;EACjC;EAEA,OAAO;GACL;GACA;GACA;EACF;CACF,CAAC;AACH"}
@@ -40,7 +40,7 @@ async function generateController(data) {
40
40
  await ensureComponentDirectory(module, "schema");
41
41
  await putFileAsync(resolveComponentPath(module, "schema", `${name.kebab}.schema`), schemaStub(name));
42
42
  }
43
- console.log(colors.cyan(`\n✨ Controller "${name.camel}" generated successfully!`));
43
+ console.log(colors.cyan(`\nController "${name.camel}" generated successfully!`));
44
44
  }
45
45
 
46
46
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"controller.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/controller.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { controllerStub, schemaStub } from \"../templates/stubs\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\n\nexport async function generateController(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Controller name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.controller users/create-user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const withValidation = data.options.withValidation || data.options.v;\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if controller already exists\n const controllerPath = resolveComponentPath(module, \"controllers\", `${name.kebab}.controller`);\n if ((await componentExists(module, \"controllers\", `${name.kebab}.controller`)) && !force) {\n console.log(colors.red(`Error: Controller \"${name.kebab}.controller.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"controllers\");\n\n // Generate controller\n const controllerContent = controllerStub(name, { withValidation: !!withValidation });\n await putFileAsync(controllerPath, controllerContent);\n\n // Generate the validation schema alongside the controller if requested.\n // The controller imports the schema's exported type + value directly —\n // there is no separate `requests/` alias file.\n if (withValidation) {\n await ensureComponentDirectory(module, \"schema\");\n\n const schemaPath = resolveComponentPath(module, \"schema\", `${name.kebab}.schema`);\n const schemaContent = schemaStub(name);\n\n await putFileAsync(schemaPath, schemaContent);\n }\n\n console.log(colors.cyan(`\\n✨ Controller \"${name.camel}\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,wDAAwD,CAAC;EACnF,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,iBAAiB,KAAK,QAAQ,kBAAkB,KAAK,QAAQ;CACnE,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,MAAM,iBAAiB,qBAAqB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY;CAC7F,IAAK,MAAM,gBAAgB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACxF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,aAAa;CAIpD,MAAM,aAAa,gBADO,eAAe,MAAM,EAAE,gBAAgB,CAAC,CAAC,eAAe,CAC/B,CAAC;CAKpD,IAAI,gBAAgB;EAClB,MAAM,yBAAyB,QAAQ,QAAQ;EAK/C,MAAM,aAHa,qBAAqB,QAAQ,UAAU,GAAG,KAAK,MAAM,QAG5C,GAFN,WAAW,IAEU,CAAC;CAC9C;CAEA,QAAQ,IAAI,OAAO,KAAK,qBAAqB,KAAK,MAAM,0BAA0B,CAAC;AACrF"}
1
+ {"version":3,"file":"controller.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/controller.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { controllerStub, schemaStub } from \"../templates/stubs\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\n\nexport async function generateController(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Controller name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.controller users/create-user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.controller <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const withValidation = data.options.withValidation || data.options.v;\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if controller already exists\n const controllerPath = resolveComponentPath(module, \"controllers\", `${name.kebab}.controller`);\n if ((await componentExists(module, \"controllers\", `${name.kebab}.controller`)) && !force) {\n console.log(colors.red(`Error: Controller \"${name.kebab}.controller.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"controllers\");\n\n // Generate controller\n const controllerContent = controllerStub(name, { withValidation: !!withValidation });\n await putFileAsync(controllerPath, controllerContent);\n\n // Generate the validation schema alongside the controller if requested.\n // The controller imports the schema's exported type + value directly —\n // there is no separate `requests/` alias file.\n if (withValidation) {\n await ensureComponentDirectory(module, \"schema\");\n\n const schemaPath = resolveComponentPath(module, \"schema\", `${name.kebab}.schema`);\n const schemaContent = schemaStub(name);\n\n await putFileAsync(schemaPath, schemaContent);\n }\n\n console.log(colors.cyan(`\\nController \"${name.camel}\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,wDAAwD,CAAC;EACnF,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,iBAAiB,KAAK,QAAQ,kBAAkB,KAAK,QAAQ;CACnE,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,MAAM,iBAAiB,qBAAqB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY;CAC7F,IAAK,MAAM,gBAAgB,QAAQ,eAAe,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACxF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,aAAa;CAIpD,MAAM,aAAa,gBADO,eAAe,MAAM,EAAE,gBAAgB,CAAC,CAAC,eAAe,CAC/B,CAAC;CAKpD,IAAI,gBAAgB;EAClB,MAAM,yBAAyB,QAAQ,QAAQ;EAK/C,MAAM,aAHa,qBAAqB,QAAQ,UAAU,GAAG,KAAK,MAAM,QAG5C,GAFN,WAAW,IAEU,CAAC;CAC9C;CAEA,QAAQ,IAAI,OAAO,KAAK,iBAAiB,KAAK,MAAM,0BAA0B,CAAC;AACjF"}
@@ -1,11 +1,13 @@
1
1
  import { appPath } from "../../../../utils/paths.mjs";
2
2
  import "../../../../utils/index.mjs";
3
+ import { migrationTimestamp } from "../../../../generations/features/shared/migration-timestamp.mjs";
3
4
  import { migrationAlterStub, migrationStub } from "../templates/stubs.mjs";
4
5
  import { parseName } from "../utils/name-parser.mjs";
5
6
  import { ensureDirectoryAsync, putFileAsync, setDryRun } from "../utils/writer.mjs";
6
7
  import { parseColumnDsl } from "./column-dsl-parser.mjs";
7
8
  import path from "node:path";
8
9
  import { colors } from "@mongez/copper";
10
+ import { existsSync, readdirSync } from "node:fs";
9
11
 
10
12
  //#region ../core/src/cli/commands/generate/generators/migration.generator.ts
11
13
  /**
@@ -16,14 +18,17 @@ import { colors } from "@mongez/copper";
16
18
  */
17
19
  async function createMigrationFile(moduleName, entityName, options = {}) {
18
20
  const entity = parseName(entityName);
19
- const now = /* @__PURE__ */ new Date();
20
- const migrationFileName = `${`${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}-${now.getFullYear()}_${String(now.getHours()).padStart(2, "0")}-${String(now.getMinutes()).padStart(2, "0")}-${String(now.getSeconds()).padStart(2, "0")}`}-${entity.kebab}.migration.ts`;
21
+ const timestamp = migrationTimestamp();
22
+ const isCreate = !(options.add || options.drop || options.rename);
23
+ const existingDir = path.join(appPath(), moduleName, "models", entity.kebab, "migrations");
24
+ if (isCreate && existsSync(existingDir) && readdirSync(existingDir).some((file) => file.endsWith(".migration.ts"))) return;
25
+ const migrationFileName = `${timestamp}-${entity.kebab}.migration.ts`;
21
26
  const migrationsPath = path.join(appPath(), moduleName, "models", entity.kebab, "migrations");
22
27
  await ensureDirectoryAsync(migrationsPath);
23
28
  const addParams = options.add;
24
29
  const dropParams = options.drop;
25
30
  const renameParams = options.rename;
26
- const timestamps = options.timestamps !== "false" && options.timestamps !== false;
31
+ const timestamps = options.timestamps !== "false" && options.timestamps !== false && !options.noTimestamps;
27
32
  let migrationContent = "";
28
33
  if (addParams || dropParams || renameParams) {
29
34
  const parsedAdd = parseColumnDsl(addParams || "");
@@ -63,17 +68,28 @@ async function generateMigration(data) {
63
68
  console.log(colors.red("Error: Model path is required"));
64
69
  console.log(colors.gray("Usage: warlock gen.migration <model-path>"));
65
70
  console.log(colors.gray("Example: warlock gen.migration products/product"));
66
- return;
71
+ process.exit(1);
67
72
  }
68
73
  const [moduleName, entityName] = modelPath.split("/");
69
74
  if (!moduleName || !entityName) {
70
75
  console.log(colors.red("Error: Invalid model path format. Expected: <module>/<entity>"));
71
76
  console.log(colors.gray("Example: warlock gen.migration products/product"));
72
- return;
77
+ process.exit(1);
78
+ }
79
+ const entity = parseName(entityName);
80
+ const modelFilePath = path.join(appPath(), moduleName, "models", entity.kebab, `${entity.kebab}.model.ts`);
81
+ if (!existsSync(modelFilePath)) {
82
+ console.log(colors.red(`Error: Model not found at ${path.relative(appPath(), modelFilePath)}`));
83
+ console.log(colors.gray("Generate the model first: warlock gen.model " + modelPath));
84
+ process.exit(1);
73
85
  }
74
86
  setDryRun(Boolean(data.options.dryRun));
75
87
  const migrationFilePath = await createMigrationFile(moduleName, entityName, data.options);
76
- console.log(colors.cyan(`\n✨ Migration file created at: ${path.relative(appPath(), migrationFilePath)}`));
88
+ if (!migrationFilePath) {
89
+ console.log(colors.yellow("Skipped: this model already has a create migration. Use --add/--drop/--rename for changes."));
90
+ return;
91
+ }
92
+ console.log(colors.cyan(`\n✨ Migration file created at: ${path.relative(appPath(), migrationFilePath)}`));
77
93
  }
78
94
 
79
95
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"migration.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/migration.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport path from \"node:path\";\nimport { appPath } from \"../../../../utils\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { migrationAlterStub, migrationStub } from \"../templates/stubs\";\nimport { parseColumnDsl } from \"./column-dsl-parser\";\nimport { parseName } from \"../utils/name-parser\";\nimport { ensureDirectoryAsync, putFileAsync, setDryRun } from \"../utils/writer\";\n\n/**\n * Generate a migration file for a model\n */\n/**\n * Create a migration file for a model\n */\nexport async function createMigrationFile(\n moduleName: string,\n entityName: string,\n options: any = {},\n) {\n const entity = parseName(entityName);\n\n // Generate timestamp: MM-DD-YYYY_HH-MM-SS\n const now = new Date();\n const timestamp = `${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}-${now.getFullYear()}_${String(now.getHours()).padStart(2, \"0\")}-${String(now.getMinutes()).padStart(2, \"0\")}-${String(now.getSeconds()).padStart(2, \"0\")}`;\n\n const migrationFileName = `${timestamp}-${entity.kebab}.migration.ts`;\n const migrationsPath = path.join(appPath(), moduleName, \"models\", entity.kebab, \"migrations\");\n\n // Ensure migrations directory exists\n await ensureDirectoryAsync(migrationsPath);\n\n const addParams = options.add as string;\n const dropParams = options.drop as string;\n const renameParams = options.rename as string;\n const timestamps = options.timestamps !== \"false\" && options.timestamps !== false;\n\n let migrationContent = \"\";\n\n if (addParams || dropParams || renameParams) {\n // Generate alter stub\n const parsedAdd = parseColumnDsl(addParams || \"\");\n const helpersSet = new Set<string>();\n\n const addLines = parsedAdd.map((col) => {\n helpersSet.add(col.helper);\n return ` ${col.name}: ${col.helper}()${col.modifiers.join(\"\")},`;\n });\n\n let formattedDrop: string | undefined = undefined;\n if (dropParams) {\n formattedDrop = JSON.stringify(dropParams.split(\",\").map((s) => s.trim()));\n }\n\n let formattedRename: string | undefined = undefined;\n if (renameParams) {\n const obj: Record<string, string> = {};\n renameParams\n .split(\",\")\n .map((s) => s.trim())\n .forEach((p) => {\n const [oldN, newN] = p.split(\":\").map((s) => s.trim());\n if (oldN && newN) obj[oldN] = newN;\n });\n formattedRename = JSON.stringify(obj, null, 2).replace(/\\n/g, \"\\n \");\n }\n\n migrationContent = migrationAlterStub(entity, {\n add: addLines.length > 0 ? addLines.join(\"\\n\") : undefined,\n drop: formattedDrop,\n rename: formattedRename,\n imports: Array.from(helpersSet),\n });\n } else {\n // Generate create stub\n migrationContent = migrationStub(entity, {\n timestamps,\n });\n }\n\n // Create migration file\n const migrationFilePath = path.join(migrationsPath, migrationFileName);\n await putFileAsync(migrationFilePath, migrationContent);\n\n return migrationFilePath;\n}\n\n/**\n * Generate a migration file for a model\n */\nexport async function generateMigration(data: CommandActionData) {\n const modelPath = data.args[0] as string;\n\n if (!modelPath) {\n console.log(colors.red(\"Error: Model path is required\"));\n console.log(colors.gray(\"Usage: warlock gen.migration <model-path>\"));\n console.log(colors.gray(\"Example: warlock gen.migration products/product\"));\n return;\n }\n\n // Parse model path (e.g., \"products/product\")\n const [moduleName, entityName] = modelPath.split(\"/\");\n\n if (!moduleName || !entityName) {\n console.log(colors.red(\"Error: Invalid model path format. Expected: <module>/<entity>\"));\n console.log(colors.gray(\"Example: warlock gen.migration products/product\"));\n return;\n }\n\n setDryRun(Boolean(data.options.dryRun));\n\n const migrationFilePath = await createMigrationFile(moduleName, entityName, data.options);\n\n console.log(\n colors.cyan(`\\n✨ Migration file created at: ${path.relative(appPath(), migrationFilePath)}`),\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,eAAsB,oBACpB,YACA,YACA,UAAe,CAAC,GAChB;CACA,MAAM,SAAS,UAAU,UAAU;CAGnC,MAAM,sBAAM,IAAI,KAAK;CAGrB,MAAM,oBAAoB,GAAG,GAFR,OAAO,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,IAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,IAAI,YAAY,EAAE,GAAG,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAE,GAAG,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,IAE5N,GAAG,OAAO,MAAM;CACvD,MAAM,iBAAiB,KAAK,KAAK,QAAQ,GAAG,YAAY,UAAU,OAAO,OAAO,YAAY;CAG5F,MAAM,qBAAqB,cAAc;CAEzC,MAAM,YAAY,QAAQ;CAC1B,MAAM,aAAa,QAAQ;CAC3B,MAAM,eAAe,QAAQ;CAC7B,MAAM,aAAa,QAAQ,eAAe,WAAW,QAAQ,eAAe;CAE5E,IAAI,mBAAmB;CAEvB,IAAI,aAAa,cAAc,cAAc;EAE3C,MAAM,YAAY,eAAe,aAAa,EAAE;EAChD,MAAM,6BAAa,IAAI,IAAY;EAEnC,MAAM,WAAW,UAAU,KAAK,QAAQ;GACtC,WAAW,IAAI,IAAI,MAAM;GACzB,OAAO,OAAO,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI,UAAU,KAAK,EAAE,EAAE;EACnE,CAAC;EAED,IAAI,gBAAoC;EACxC,IAAI,YACF,gBAAgB,KAAK,UAAU,WAAW,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC;EAG3E,IAAI,kBAAsC;EAC1C,IAAI,cAAc;GAChB,MAAM,MAA8B,CAAC;GACrC,aACG,MAAM,GAAG,CAAC,CACV,KAAK,MAAM,EAAE,KAAK,CAAC,CAAC,CACpB,SAAS,MAAM;IACd,MAAM,CAAC,MAAM,QAAQ,EAAE,MAAM,GAAG,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK,CAAC;IACrD,IAAI,QAAQ,MAAM,IAAI,QAAQ;GAChC,CAAC;GACH,kBAAkB,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,OAAO,MAAM;EACtE;EAEA,mBAAmB,mBAAmB,QAAQ;GAC5C,KAAK,SAAS,SAAS,IAAI,SAAS,KAAK,IAAI,IAAI;GACjD,MAAM;GACN,QAAQ;GACR,SAAS,MAAM,KAAK,UAAU;EAChC,CAAC;CACH,OAEE,mBAAmB,cAAc,QAAQ,EACvC,WACF,CAAC;CAIH,MAAM,oBAAoB,KAAK,KAAK,gBAAgB,iBAAiB;CACrE,MAAM,aAAa,mBAAmB,gBAAgB;CAEtD,OAAO;AACT;;;;AAKA,eAAsB,kBAAkB,MAAyB;CAC/D,MAAM,YAAY,KAAK,KAAK;CAE5B,IAAI,CAAC,WAAW;EACd,QAAQ,IAAI,OAAO,IAAI,+BAA+B,CAAC;EACvD,QAAQ,IAAI,OAAO,KAAK,2CAA2C,CAAC;EACpE,QAAQ,IAAI,OAAO,KAAK,iDAAiD,CAAC;EAC1E;CACF;CAGA,MAAM,CAAC,YAAY,cAAc,UAAU,MAAM,GAAG;CAEpD,IAAI,CAAC,cAAc,CAAC,YAAY;EAC9B,QAAQ,IAAI,OAAO,IAAI,+DAA+D,CAAC;EACvF,QAAQ,IAAI,OAAO,KAAK,iDAAiD,CAAC;EAC1E;CACF;CAEA,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAEtC,MAAM,oBAAoB,MAAM,oBAAoB,YAAY,YAAY,KAAK,OAAO;CAExF,QAAQ,IACN,OAAO,KAAK,oCAAoC,KAAK,SAAS,QAAQ,GAAG,iBAAiB,GAAG,CAC/F;AACF"}
1
+ {"version":3,"file":"migration.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/migration.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { existsSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { appPath } from \"../../../../utils\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { migrationAlterStub, migrationStub } from \"../templates/stubs\";\nimport { migrationTimestamp } from \"../../../../generations/features/shared/migration-timestamp\";\nimport { parseColumnDsl } from \"./column-dsl-parser\";\nimport { parseName } from \"../utils/name-parser\";\nimport { ensureDirectoryAsync, putFileAsync, setDryRun } from \"../utils/writer\";\n\n/**\n * Generate a migration file for a model\n */\n/**\n * Create a migration file for a model\n */\nexport async function createMigrationFile(\n moduleName: string,\n entityName: string,\n options: any = {},\n) {\n const entity = parseName(entityName);\n\n // Generate timestamp: MM-DD-YYYY_HH-MM-SS\n const timestamp = migrationTimestamp();\n\n // \"Create missing, skip existing\": never write a second CREATE-table migration\n // for an entity that already has one (it would fail with \"table already exists\").\n const isCreate = !(options.add || options.drop || options.rename);\n const existingDir = path.join(appPath(), moduleName, \"models\", entity.kebab, \"migrations\");\n\n if (isCreate && existsSync(existingDir) && readdirSync(existingDir).some((file) => file.endsWith(\".migration.ts\"))) {\n return undefined;\n }\n\n const migrationFileName = `${timestamp}-${entity.kebab}.migration.ts`;\n const migrationsPath = path.join(appPath(), moduleName, \"models\", entity.kebab, \"migrations\");\n\n // Ensure migrations directory exists\n await ensureDirectoryAsync(migrationsPath);\n\n const addParams = options.add as string;\n const dropParams = options.drop as string;\n const renameParams = options.rename as string;\n const timestamps =\n options.timestamps !== \"false\" && options.timestamps !== false && !options.noTimestamps;\n\n let migrationContent = \"\";\n\n if (addParams || dropParams || renameParams) {\n // Generate alter stub\n const parsedAdd = parseColumnDsl(addParams || \"\");\n const helpersSet = new Set<string>();\n\n const addLines = parsedAdd.map((col) => {\n helpersSet.add(col.helper);\n return ` ${col.name}: ${col.helper}()${col.modifiers.join(\"\")},`;\n });\n\n let formattedDrop: string | undefined = undefined;\n if (dropParams) {\n formattedDrop = JSON.stringify(dropParams.split(\",\").map((s) => s.trim()));\n }\n\n let formattedRename: string | undefined = undefined;\n if (renameParams) {\n const obj: Record<string, string> = {};\n renameParams\n .split(\",\")\n .map((s) => s.trim())\n .forEach((p) => {\n const [oldN, newN] = p.split(\":\").map((s) => s.trim());\n if (oldN && newN) obj[oldN] = newN;\n });\n formattedRename = JSON.stringify(obj, null, 2).replace(/\\n/g, \"\\n \");\n }\n\n migrationContent = migrationAlterStub(entity, {\n add: addLines.length > 0 ? addLines.join(\"\\n\") : undefined,\n drop: formattedDrop,\n rename: formattedRename,\n imports: Array.from(helpersSet),\n });\n } else {\n // Generate create stub\n migrationContent = migrationStub(entity, {\n timestamps,\n });\n }\n\n // Create migration file\n const migrationFilePath = path.join(migrationsPath, migrationFileName);\n await putFileAsync(migrationFilePath, migrationContent);\n\n return migrationFilePath;\n}\n\n/**\n * Generate a migration file for a model\n */\nexport async function generateMigration(data: CommandActionData) {\n const modelPath = data.args[0] as string;\n\n if (!modelPath) {\n console.log(colors.red(\"Error: Model path is required\"));\n console.log(colors.gray(\"Usage: warlock gen.migration <model-path>\"));\n console.log(colors.gray(\"Example: warlock gen.migration products/product\"));\n process.exit(1);\n }\n\n // Parse model path (e.g., \"products/product\")\n const [moduleName, entityName] = modelPath.split(\"/\");\n\n if (!moduleName || !entityName) {\n console.log(colors.red(\"Error: Invalid model path format. Expected: <module>/<entity>\"));\n console.log(colors.gray(\"Example: warlock gen.migration products/product\"));\n process.exit(1);\n }\n\n const entity = parseName(entityName);\n const modelFilePath = path.join(\n appPath(),\n moduleName,\n \"models\",\n entity.kebab,\n `${entity.kebab}.model.ts`,\n );\n\n if (!existsSync(modelFilePath)) {\n console.log(\n colors.red(`Error: Model not found at ${path.relative(appPath(), modelFilePath)}`),\n );\n console.log(colors.gray(\"Generate the model first: warlock gen.model \" + modelPath));\n process.exit(1);\n }\n\n setDryRun(Boolean(data.options.dryRun));\n\n const migrationFilePath = await createMigrationFile(moduleName, entityName, data.options);\n\n if (!migrationFilePath) {\n console.log(\n colors.yellow(\n \"Skipped: this model already has a create migration. Use --add/--drop/--rename for changes.\",\n ),\n );\n return;\n }\n\n console.log(\n colors.cyan(`\\n✨ Migration file created at: ${path.relative(appPath(), migrationFilePath)}`),\n );\n}\n"],"mappings":"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"}
@@ -1,9 +1,11 @@
1
- import { migrationStub, modelStub } from "../templates/stubs.mjs";
1
+ import { migrationTimestamp } from "../../../../generations/features/shared/migration-timestamp.mjs";
2
+ import { migrationStub, modelStub, resourceStub } from "../templates/stubs.mjs";
2
3
  import { parseModulePath, singularName } from "../utils/name-parser.mjs";
3
- import { ensureDirectoryAsync, putFileAsync, setDryRun } from "../utils/writer.mjs";
4
- import { componentExists, moduleExists, resolveModulePath } from "../utils/path-resolver.mjs";
4
+ import { ensureDirectoryAsync, putFileAsync, reportSkippedFiles, setDryRun, setSkipExisting } from "../utils/writer.mjs";
5
+ import { componentExists, ensureComponentDirectory, moduleExists, resolveComponentPath, resolveModulePath } from "../utils/path-resolver.mjs";
5
6
  import path from "node:path";
6
7
  import { colors } from "@mongez/copper";
8
+ import { existsSync, readdirSync } from "node:fs";
7
9
 
8
10
  //#region ../core/src/cli/commands/generate/generators/model.generator.ts
9
11
  async function generateModel(data) {
@@ -28,6 +30,7 @@ async function generateModel(data) {
28
30
  const name = singularName(componentName);
29
31
  const force = data.options.force || data.options.f;
30
32
  setDryRun(Boolean(data.options.dryRun));
33
+ setSkipExisting(!data.options.overwrite);
31
34
  const withResource = data.options.withResource || data.options.rs;
32
35
  const tableName = data.options.table || name.plural.snake;
33
36
  const modelDir = path.join(resolveModulePath(module), "models", name.kebab);
@@ -43,15 +46,27 @@ async function generateModel(data) {
43
46
  tableName,
44
47
  withResource: !!withResource
45
48
  }));
49
+ if (withResource) {
50
+ const resourceFile = `${name.singular.kebab}.resource`;
51
+ if (force || !await componentExists(module, "resources", resourceFile)) {
52
+ await ensureComponentDirectory(module, "resources");
53
+ await putFileAsync(resolveComponentPath(module, "resources", resourceFile), resourceStub(name));
54
+ }
55
+ }
46
56
  const indexContent = `export * from "./${name.kebab}.model";
47
57
  `;
48
58
  await putFileAsync(path.join(modelDir, "index.ts"), indexContent);
49
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, "_").split(".")[0];
50
- await putFileAsync(path.join(modelDir, "migrations", `${timestamp}_${name.kebab}.migration.ts`), migrationStub(name, { timestamps: data.options.timestamps !== "false" && data.options.timestamps !== false }));
51
- console.log(colors.cyan(`\n✨ Model "${name.pascal}" generated successfully!`));
59
+ const migrationsDir = path.join(modelDir, "migrations");
60
+ const hasMigration = existsSync(migrationsDir) && readdirSync(migrationsDir).some((file) => file.endsWith(".migration.ts"));
61
+ const timestamp = migrationTimestamp();
62
+ const migrationPath = path.join(modelDir, "migrations", `${timestamp}-${name.kebab}.migration.ts`);
63
+ const migrationContent = migrationStub(name, { timestamps: data.options.timestamps !== "false" && data.options.timestamps !== false && !data.options.noTimestamps });
64
+ if (!hasMigration) await putFileAsync(migrationPath, migrationContent);
65
+ reportSkippedFiles();
66
+ console.log(colors.cyan(`\n✨ Model "${name.pascal}" generated successfully!`));
52
67
  console.log(colors.gray(`\nNext steps:`));
53
68
  console.log(colors.gray(` 1. Update model schema in ${name.kebab}.model.ts`));
54
- console.log(colors.gray(` 2. Update migration in migrations/${timestamp}_${name.kebab}.migration.ts`));
69
+ console.log(colors.gray(hasMigration ? ` 2. Existing migration kept; add changes with: warlock gen.migration ${module}/${name.kebab} --add ...` : ` 2. Update migration in migrations/${timestamp}-${name.kebab}.migration.ts`));
55
70
  console.log(colors.gray(` 3. Run migration: warlock migrate`));
56
71
  }
57
72
 
@@ -1 +1 @@
1
- {"version":3,"file":"model.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/model.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport path from \"node:path\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { migrationStub, modelStub } from \"../templates/stubs\";\nimport { parseModulePath, singularName } from \"../utils/name-parser\";\nimport { componentExists, moduleExists, resolveModulePath } from \"../utils/path-resolver\";\nimport { ensureDirectoryAsync, putFileAsync, setDryRun } from \"../utils/writer\";\n\nexport async function generateModel(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Model name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.model users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = singularName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n const withResource = data.options.withResource || data.options.rs;\n const tableName = (data.options.table as string) || name.plural.snake;\n\n // Check if model already exists\n const modelDir = path.join(resolveModulePath(module), \"models\", name.kebab);\n const modelPath = path.join(modelDir, `${name.kebab}.model.ts`);\n\n if ((await componentExists(module, `models/${name.kebab}`, `${name.kebab}.model`)) && !force) {\n console.log(colors.red(`Error: Model \"${name.kebab}\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureDirectoryAsync(modelDir);\n await ensureDirectoryAsync(path.join(modelDir, \"migrations\"));\n\n // Generate model\n const modelContent = modelStub(name, { tableName, withResource: !!withResource });\n await putFileAsync(modelPath, modelContent);\n\n // Generate index.ts\n const indexContent = `export * from \"./${name.kebab}.model\";\n`;\n await putFileAsync(path.join(modelDir, \"index.ts\"), indexContent);\n\n // Generate migration\n const timestamp = new Date().toISOString().replace(/[-:T]/g, \"_\").split(\".\")[0];\n const migrationPath = path.join(\n modelDir,\n \"migrations\",\n `${timestamp}_${name.kebab}.migration.ts`,\n );\n\n const migrationContent = migrationStub(name, {\n timestamps: data.options.timestamps !== \"false\" && data.options.timestamps !== false,\n });\n\n await putFileAsync(migrationPath, migrationContent);\n\n console.log(colors.cyan(`\\n✨ Model \"${name.pascal}\" generated successfully!`));\n console.log(colors.gray(`\\nNext steps:`));\n console.log(colors.gray(` 1. Update model schema in ${name.kebab}.model.ts`));\n console.log(\n colors.gray(` 2. Update migration in migrations/${timestamp}_${name.kebab}.migration.ts`),\n );\n console.log(colors.gray(` 3. Run migration: warlock migrate`));\n}\n"],"mappings":";;;;;;;;AAQA,eAAsB,cAAc,MAAwC;CAC1E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,+BAA+B,CAAC;EACvD,QAAQ,IAAI,OAAO,OAAO,+CAA+C,CAAC;EAC1E,QAAQ,IAAI,OAAO,OAAO,4CAA4C,CAAC;EACvE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,+CAA+C,CAAC;EAC1E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,aAAa,aAAa;CACvC,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CACtC,MAAM,eAAe,KAAK,QAAQ,gBAAgB,KAAK,QAAQ;CAC/D,MAAM,YAAa,KAAK,QAAQ,SAAoB,KAAK,OAAO;CAGhE,MAAM,WAAW,KAAK,KAAK,kBAAkB,MAAM,GAAG,UAAU,KAAK,KAAK;CAC1E,MAAM,YAAY,KAAK,KAAK,UAAU,GAAG,KAAK,MAAM,UAAU;CAE9D,IAAK,MAAM,gBAAgB,QAAQ,UAAU,KAAK,SAAS,GAAG,KAAK,MAAM,OAAO,KAAM,CAAC,OAAO;EAC5F,QAAQ,IAAI,OAAO,IAAI,iBAAiB,KAAK,MAAM,iBAAiB,CAAC;EACrE,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,qBAAqB,QAAQ;CACnC,MAAM,qBAAqB,KAAK,KAAK,UAAU,YAAY,CAAC;CAI5D,MAAM,aAAa,WADE,UAAU,MAAM;EAAE;EAAW,cAAc,CAAC,CAAC;CAAa,CACtC,CAAC;CAG1C,MAAM,eAAe,oBAAoB,KAAK,MAAM;;CAEpD,MAAM,aAAa,KAAK,KAAK,UAAU,UAAU,GAAG,YAAY;CAGhE,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,UAAU,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;CAW7E,MAAM,aAVgB,KAAK,KACzB,UACA,cACA,GAAG,UAAU,GAAG,KAAK,MAAM,cAOE,GAJN,cAAc,MAAM,EAC3C,YAAY,KAAK,QAAQ,eAAe,WAAW,KAAK,QAAQ,eAAe,MACjF,CAEiD,CAAC;CAElD,QAAQ,IAAI,OAAO,KAAK,gBAAgB,KAAK,OAAO,0BAA0B,CAAC;CAC/E,QAAQ,IAAI,OAAO,KAAK,eAAe,CAAC;CACxC,QAAQ,IAAI,OAAO,KAAK,+BAA+B,KAAK,MAAM,UAAU,CAAC;CAC7E,QAAQ,IACN,OAAO,KAAK,uCAAuC,UAAU,GAAG,KAAK,MAAM,cAAc,CAC3F;CACA,QAAQ,IAAI,OAAO,KAAK,qCAAqC,CAAC;AAChE"}
1
+ {"version":3,"file":"model.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/model.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport { existsSync, readdirSync } from \"node:fs\";\nimport path from \"node:path\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { migrationTimestamp } from \"../../../../generations/features/shared/migration-timestamp\";\nimport { migrationStub, modelStub, resourceStub } from \"../templates/stubs\";\nimport { parseModulePath, singularName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n resolveModulePath,\n} from \"../utils/path-resolver\";\nimport {\n ensureDirectoryAsync,\n putFileAsync,\n reportSkippedFiles,\n setDryRun,\n setSkipExisting,\n} from \"../utils/writer\";\n\nexport async function generateModel(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Model name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.model users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.model <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = singularName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n // --force only creates what is missing; replacing edited files needs --overwrite too\n setSkipExisting(!data.options.overwrite);\n const withResource = data.options.withResource || data.options.rs;\n const tableName = (data.options.table as string) || name.plural.snake;\n\n // Check if model already exists\n const modelDir = path.join(resolveModulePath(module), \"models\", name.kebab);\n const modelPath = path.join(modelDir, `${name.kebab}.model.ts`);\n\n if ((await componentExists(module, `models/${name.kebab}`, `${name.kebab}.model`)) && !force) {\n console.log(colors.red(`Error: Model \"${name.kebab}\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureDirectoryAsync(modelDir);\n await ensureDirectoryAsync(path.join(modelDir, \"migrations\"));\n\n // Generate model\n const modelContent = modelStub(name, { tableName, withResource: !!withResource });\n await putFileAsync(modelPath, modelContent);\n\n // The model imports ../../resources/<name>.resource, so that file must exist\n if (withResource) {\n const resourceFile = `${name.singular.kebab}.resource`;\n\n if (force || !(await componentExists(module, \"resources\", resourceFile))) {\n await ensureComponentDirectory(module, \"resources\");\n await putFileAsync(\n resolveComponentPath(module, \"resources\", resourceFile),\n resourceStub(name),\n );\n }\n }\n\n // Generate index.ts\n const indexContent = `export * from \"./${name.kebab}.model\";\n`;\n await putFileAsync(path.join(modelDir, \"index.ts\"), indexContent);\n\n // Generate migration (skip when one already exists, e.g. on --force)\n const migrationsDir = path.join(modelDir, \"migrations\");\n const hasMigration =\n existsSync(migrationsDir) &&\n readdirSync(migrationsDir).some((file) => file.endsWith(\".migration.ts\"));\n const timestamp = migrationTimestamp();\n const migrationPath = path.join(\n modelDir,\n \"migrations\",\n `${timestamp}-${name.kebab}.migration.ts`,\n );\n\n const migrationContent = migrationStub(name, {\n timestamps:\n data.options.timestamps !== \"false\" &&\n data.options.timestamps !== false &&\n !data.options.noTimestamps,\n });\n\n if (!hasMigration) {\n await putFileAsync(migrationPath, migrationContent);\n }\n\n reportSkippedFiles();\n\n console.log(colors.cyan(`\\n✨ Model \"${name.pascal}\" generated successfully!`));\n console.log(colors.gray(`\\nNext steps:`));\n console.log(colors.gray(` 1. Update model schema in ${name.kebab}.model.ts`));\n console.log(\n colors.gray(\n hasMigration\n ? ` 2. Existing migration kept; add changes with: warlock gen.migration ${module}/${name.kebab} --add ...`\n : ` 2. Update migration in migrations/${timestamp}-${name.kebab}.migration.ts`,\n ),\n );\n console.log(colors.gray(` 3. Run migration: warlock migrate`));\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { appPath } from "../../../../utils/paths.mjs";
2
2
  import "../../../../utils/index.mjs";
3
3
  import { crudCreateControllerStub, crudCreateSchemaStub, crudCreateServiceStub, crudDeleteControllerStub, crudDeleteServiceStub, crudGetServiceStub, crudListControllerStub, crudListServiceStub, crudModelStub, crudRepositoryStub, crudResourceStub, crudRoutesStub, crudSeedStub, crudShowControllerStub, crudUpdateControllerStub, crudUpdateSchemaStub, crudUpdateServiceStub } from "../templates/stubs.mjs";
4
4
  import { pluralName, singularName } from "../utils/name-parser.mjs";
5
- import { ensureDirectoryAsync, putFileAsync, setDryRun } from "../utils/writer.mjs";
5
+ import { ensureDirectoryAsync, putFileAsync, reportSkippedFiles, setDryRun, setSkipExisting } from "../utils/writer.mjs";
6
6
  import { moduleExists } from "../utils/path-resolver.mjs";
7
7
  import { createMigrationFile } from "./migration.generator.mjs";
8
8
  import path from "node:path";
@@ -21,6 +21,7 @@ async function generateModule(data) {
21
21
  const name = pluralName(moduleName);
22
22
  const force = data.options.force || data.options.f;
23
23
  setDryRun(Boolean(data.options.dryRun));
24
+ setSkipExisting(!data.options.overwrite);
24
25
  const withCrud = !(data.options.minimal || data.options.m);
25
26
  if (await moduleExists(name.kebab) && !force) {
26
27
  console.log(colors.red(`Error: Module "${name.kebab}" already exists`));
@@ -58,7 +59,7 @@ groupedTranslations("${name.camel}", {
58
59
  // Example:
59
60
  // welcome: {
60
61
  // en: "Welcome",
61
- // ar: "مرحبا",
62
+ // ar: "مرحبا",
62
63
  // },
63
64
  });
64
65
  `;
@@ -87,18 +88,19 @@ groupedTranslations("${name.camel}", {
87
88
  await putFileAsync(path.join(modulePath, "seeds", `${name.kebab}.seed.ts`), crudSeedStub(name));
88
89
  await createMigrationFile(name.kebab, entity.kebab);
89
90
  }
90
- console.log(colors.cyan(`\n✨ Module "${name.kebab}" generated successfully!`));
91
+ reportSkippedFiles();
92
+ console.log(colors.cyan(`\n✨ Module "${name.kebab}" generated successfully!`));
91
93
  if (withCrud) {
92
- console.log(colors.gray(`\n📦 CRUD scaffold created with:`));
94
+ console.log(colors.gray(`\n📦 CRUD scaffold created with:`));
93
95
  console.log(colors.gray(` - List, Get, Create, Update & Delete controllers`));
94
96
  console.log(colors.gray(` - Repository`));
95
97
  console.log(colors.gray(` - Validation schemas in schema/`));
96
98
  console.log(colors.gray(` - Model with resource`));
97
99
  console.log(colors.gray(` - Routes configured`));
98
100
  console.log(colors.gray(`\nNext steps:`));
99
- console.log(colors.gray(` 1. Update model schema in models/${name.kebab}/${name.kebab}.model.ts`));
101
+ const entity = singularName(moduleName);
102
+ console.log(colors.gray(` 1. Update model schema in models/${entity.kebab}/${entity.kebab}.model.ts`));
100
103
  console.log(colors.gray(` 2. Update schema rules in schema/*.schema.ts`));
101
- console.log(colors.gray(` 3. Create migration: warlock generate.model ${name.kebab}/${name.kebab}`));
102
104
  } else {
103
105
  console.log(colors.gray(`\nNext steps:`));
104
106
  console.log(colors.gray(` 1. Define routes in ${name.kebab}/routes.ts`));
@@ -1 +1 @@
1
- {"version":3,"file":"module.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/module.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport path from \"node:path\";\nimport { appPath } from \"../../../../utils\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport {\n crudCreateControllerStub,\n crudCreateSchemaStub,\n crudCreateServiceStub,\n crudDeleteControllerStub,\n crudDeleteServiceStub,\n crudGetServiceStub,\n crudListControllerStub,\n crudListServiceStub,\n crudModelStub,\n crudRepositoryStub,\n crudResourceStub,\n crudRoutesStub,\n crudSeedStub,\n crudShowControllerStub,\n crudUpdateControllerStub,\n crudUpdateSchemaStub,\n crudUpdateServiceStub,\n} from \"../templates/stubs\";\nimport { pluralName, singularName } from \"../utils/name-parser\";\nimport { moduleExists } from \"../utils/path-resolver\";\nimport { ensureDirectoryAsync, putFileAsync, setDryRun } from \"../utils/writer\";\nimport { createMigrationFile } from \"./migration.generator\";\n\nexport async function generateModule(data: CommandActionData): Promise<void> {\n const moduleName = data.args[0];\n\n if (!moduleName) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.module <name> [options]\"));\n console.log(colors.yellow(\"Example: warlock generate.module products\"));\n console.log(colors.yellow(\" warlock generate.module products --minimal\"));\n process.exit(1);\n }\n\n const name = pluralName(moduleName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Full CRUD is the default; --minimal (-m) opts down to a bare skeleton.\n const minimal = data.options.minimal || data.options.m;\n const withCrud = !minimal;\n\n // Check if module already exists\n if ((await moduleExists(name.kebab)) && !force) {\n console.log(colors.red(`Error: Module \"${name.kebab}\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n const modulePath = appPath(name.kebab);\n\n // Create module directory structure\n const directories = [\n \"controllers\",\n \"services\",\n \"models\",\n \"repositories\",\n \"schema\",\n \"resources\",\n \"events\",\n \"types\",\n \"utils\",\n ];\n\n for (const dir of directories) {\n await ensureDirectoryAsync(path.join(modulePath, dir));\n }\n\n // Create main.ts\n const mainContent = `// You may use this file as a custom entry point to be executed when the app starts.\n// it runs only once, and you don't need to import the routes.ts file, it will be imported automatically.\n// Use it to regsiter or boot up any custom logic for this module.\n`;\n await putFileAsync(path.join(modulePath, \"main.ts\"), mainContent);\n\n // Create routes.ts\n const routesContent = withCrud\n ? crudRoutesStub(name)\n : `import { router } from \"@warlock.js/core\";\nimport { guarded } from \"app/shared/utils/router\";\n\n// Define your routes here\n// Example:\n// router.get(\"/${name.kebab}\", listController);\n`;\n await putFileAsync(path.join(modulePath, \"routes.ts\"), routesContent);\n\n // Create utils/locales.ts\n const localesContent = `import { groupedTranslations } from \"@warlock.js/core\";\n\ngroupedTranslations(\"${name.camel}\", {\n // Add your translations here\n // Example:\n // welcome: {\n // en: \"Welcome\",\n // ar: \"مرحبا\",\n // },\n});\n`;\n await putFileAsync(path.join(modulePath, \"utils\", \"locales.ts\"), localesContent);\n\n // Full CRUD scaffold (the default) unless --minimal was passed\n if (withCrud) {\n const entity = singularName(moduleName);\n\n // Create controllers\n await putFileAsync(\n path.join(modulePath, \"controllers\", `create-${entity.kebab}.controller.ts`),\n crudCreateControllerStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `update-${entity.kebab}.controller.ts`),\n crudUpdateControllerStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `list-${name.kebab}.controller.ts`),\n crudListControllerStub(name),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `get-${entity.kebab}.controller.ts`),\n crudShowControllerStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `delete-${entity.kebab}.controller.ts`),\n crudDeleteControllerStub(entity),\n );\n\n // Create schema files — each exports both the schema value and its\n // inferred type; controllers import them directly (no requests/ alias).\n await putFileAsync(\n path.join(modulePath, \"schema\", `create-${entity.kebab}.schema.ts`),\n crudCreateSchemaStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"schema\", `update-${entity.kebab}.schema.ts`),\n crudUpdateSchemaStub(entity),\n );\n\n // Create model\n await ensureDirectoryAsync(path.join(modulePath, \"models\", entity.kebab));\n await putFileAsync(\n path.join(modulePath, \"models\", entity.kebab, `${entity.kebab}.model.ts`),\n crudModelStub(entity),\n );\n\n // Create model index\n await putFileAsync(\n path.join(modulePath, \"models\", entity.kebab, \"index.ts\"),\n `export * from \"./${entity.kebab}.model\";\\n`,\n );\n\n // Create migrations folder\n await ensureDirectoryAsync(path.join(modulePath, \"models\", entity.kebab, \"migrations\"));\n\n // Create resource\n await putFileAsync(\n path.join(modulePath, \"resources\", `${entity.kebab}.resource.ts`),\n crudResourceStub(name),\n );\n\n // Create repository\n await putFileAsync(\n path.join(modulePath, \"repositories\", `${name.kebab}.repository.ts`),\n crudRepositoryStub(name),\n );\n\n // Create services\n await putFileAsync(\n path.join(modulePath, \"services\", `create-${entity.kebab}.service.ts`),\n crudCreateServiceStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `update-${entity.kebab}.service.ts`),\n crudUpdateServiceStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `list-${name.kebab}.service.ts`),\n crudListServiceStub(name),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `get-${entity.kebab}.service.ts`),\n crudGetServiceStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `delete-${entity.kebab}.service.ts`),\n crudDeleteServiceStub(entity),\n );\n\n // Create seeds\n await ensureDirectoryAsync(path.join(modulePath, \"seeds\"));\n await putFileAsync(path.join(modulePath, \"seeds\", `${name.kebab}.seed.ts`), crudSeedStub(name));\n\n // Create migration\n await createMigrationFile(name.kebab, entity.kebab);\n }\n\n console.log(colors.cyan(`\\n✨ Module \"${name.kebab}\" generated successfully!`));\n\n if (withCrud) {\n console.log(colors.gray(`\\n📦 CRUD scaffold created with:`));\n console.log(colors.gray(` - List, Get, Create, Update & Delete controllers`));\n console.log(colors.gray(` - Repository`));\n console.log(colors.gray(` - Validation schemas in schema/`));\n console.log(colors.gray(` - Model with resource`));\n console.log(colors.gray(` - Routes configured`));\n console.log(colors.gray(`\\nNext steps:`));\n console.log(\n colors.gray(` 1. Update model schema in models/${name.kebab}/${name.kebab}.model.ts`),\n );\n console.log(colors.gray(` 2. Update schema rules in schema/*.schema.ts`));\n console.log(\n colors.gray(` 3. Create migration: warlock generate.model ${name.kebab}/${name.kebab}`),\n );\n } else {\n console.log(colors.gray(`\\nNext steps:`));\n console.log(colors.gray(` 1. Define routes in ${name.kebab}/routes.ts`));\n console.log(\n colors.gray(` 2. Create controllers: warlock generate.controller ${name.kebab}/<name>`),\n );\n console.log(colors.gray(` 3. Create models: warlock generate.model ${name.kebab}/<name>`));\n console.log(colors.gray(`\\nTip: omit --minimal to generate a full CRUD scaffold`));\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"module.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/module.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport path from \"node:path\";\nimport { appPath } from \"../../../../utils\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport {\n crudCreateControllerStub,\n crudCreateSchemaStub,\n crudCreateServiceStub,\n crudDeleteControllerStub,\n crudDeleteServiceStub,\n crudGetServiceStub,\n crudListControllerStub,\n crudListServiceStub,\n crudModelStub,\n crudRepositoryStub,\n crudResourceStub,\n crudRoutesStub,\n crudSeedStub,\n crudShowControllerStub,\n crudUpdateControllerStub,\n crudUpdateSchemaStub,\n crudUpdateServiceStub,\n} from \"../templates/stubs\";\nimport { pluralName, singularName } from \"../utils/name-parser\";\nimport { moduleExists } from \"../utils/path-resolver\";\nimport {\n ensureDirectoryAsync,\n putFileAsync,\n reportSkippedFiles,\n setDryRun,\n setSkipExisting,\n} from \"../utils/writer\";\nimport { createMigrationFile } from \"./migration.generator\";\n\nexport async function generateModule(data: CommandActionData): Promise<void> {\n const moduleName = data.args[0];\n\n if (!moduleName) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.module <name> [options]\"));\n console.log(colors.yellow(\"Example: warlock generate.module products\"));\n console.log(colors.yellow(\" warlock generate.module products --minimal\"));\n process.exit(1);\n }\n\n const name = pluralName(moduleName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n // --force only creates what is missing; replacing edited files needs --overwrite too\n setSkipExisting(!data.options.overwrite);\n\n // Full CRUD is the default; --minimal (-m) opts down to a bare skeleton.\n const minimal = data.options.minimal || data.options.m;\n const withCrud = !minimal;\n\n // Check if module already exists\n if ((await moduleExists(name.kebab)) && !force) {\n console.log(colors.red(`Error: Module \"${name.kebab}\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n const modulePath = appPath(name.kebab);\n\n // Create module directory structure\n const directories = [\n \"controllers\",\n \"services\",\n \"models\",\n \"repositories\",\n \"schema\",\n \"resources\",\n \"events\",\n \"types\",\n \"utils\",\n ];\n\n for (const dir of directories) {\n await ensureDirectoryAsync(path.join(modulePath, dir));\n }\n\n // Create main.ts\n const mainContent = `// You may use this file as a custom entry point to be executed when the app starts.\n// it runs only once, and you don't need to import the routes.ts file, it will be imported automatically.\n// Use it to regsiter or boot up any custom logic for this module.\n`;\n await putFileAsync(path.join(modulePath, \"main.ts\"), mainContent);\n\n // Create routes.ts\n const routesContent = withCrud\n ? crudRoutesStub(name)\n : `import { router } from \"@warlock.js/core\";\nimport { guarded } from \"app/shared/utils/router\";\n\n// Define your routes here\n// Example:\n// router.get(\"/${name.kebab}\", listController);\n`;\n await putFileAsync(path.join(modulePath, \"routes.ts\"), routesContent);\n\n // Create utils/locales.ts\n const localesContent = `import { groupedTranslations } from \"@warlock.js/core\";\n\ngroupedTranslations(\"${name.camel}\", {\n // Add your translations here\n // Example:\n // welcome: {\n // en: \"Welcome\",\n // ar: \"مرحبا\",\n // },\n});\n`;\n await putFileAsync(path.join(modulePath, \"utils\", \"locales.ts\"), localesContent);\n\n // Full CRUD scaffold (the default) unless --minimal was passed\n if (withCrud) {\n const entity = singularName(moduleName);\n\n // Create controllers\n await putFileAsync(\n path.join(modulePath, \"controllers\", `create-${entity.kebab}.controller.ts`),\n crudCreateControllerStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `update-${entity.kebab}.controller.ts`),\n crudUpdateControllerStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `list-${name.kebab}.controller.ts`),\n crudListControllerStub(name),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `get-${entity.kebab}.controller.ts`),\n crudShowControllerStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"controllers\", `delete-${entity.kebab}.controller.ts`),\n crudDeleteControllerStub(entity),\n );\n\n // Create schema files — each exports both the schema value and its\n // inferred type; controllers import them directly (no requests/ alias).\n await putFileAsync(\n path.join(modulePath, \"schema\", `create-${entity.kebab}.schema.ts`),\n crudCreateSchemaStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"schema\", `update-${entity.kebab}.schema.ts`),\n crudUpdateSchemaStub(entity),\n );\n\n // Create model\n await ensureDirectoryAsync(path.join(modulePath, \"models\", entity.kebab));\n await putFileAsync(\n path.join(modulePath, \"models\", entity.kebab, `${entity.kebab}.model.ts`),\n crudModelStub(entity),\n );\n\n // Create model index\n await putFileAsync(\n path.join(modulePath, \"models\", entity.kebab, \"index.ts\"),\n `export * from \"./${entity.kebab}.model\";\\n`,\n );\n\n // Create migrations folder\n await ensureDirectoryAsync(path.join(modulePath, \"models\", entity.kebab, \"migrations\"));\n\n // Create resource\n await putFileAsync(\n path.join(modulePath, \"resources\", `${entity.kebab}.resource.ts`),\n crudResourceStub(name),\n );\n\n // Create repository\n await putFileAsync(\n path.join(modulePath, \"repositories\", `${name.kebab}.repository.ts`),\n crudRepositoryStub(name),\n );\n\n // Create services\n await putFileAsync(\n path.join(modulePath, \"services\", `create-${entity.kebab}.service.ts`),\n crudCreateServiceStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `update-${entity.kebab}.service.ts`),\n crudUpdateServiceStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `list-${name.kebab}.service.ts`),\n crudListServiceStub(name),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `get-${entity.kebab}.service.ts`),\n crudGetServiceStub(entity),\n );\n\n await putFileAsync(\n path.join(modulePath, \"services\", `delete-${entity.kebab}.service.ts`),\n crudDeleteServiceStub(entity),\n );\n\n // Create seeds\n await ensureDirectoryAsync(path.join(modulePath, \"seeds\"));\n await putFileAsync(path.join(modulePath, \"seeds\", `${name.kebab}.seed.ts`), crudSeedStub(name));\n\n // Create migration\n await createMigrationFile(name.kebab, entity.kebab);\n }\n\n reportSkippedFiles();\n\n console.log(colors.cyan(`\\n✨ Module \"${name.kebab}\" generated successfully!`));\n\n if (withCrud) {\n console.log(colors.gray(`\\n📦 CRUD scaffold created with:`));\n console.log(colors.gray(` - List, Get, Create, Update & Delete controllers`));\n console.log(colors.gray(` - Repository`));\n console.log(colors.gray(` - Validation schemas in schema/`));\n console.log(colors.gray(` - Model with resource`));\n console.log(colors.gray(` - Routes configured`));\n console.log(colors.gray(`\\nNext steps:`));\n const entity = singularName(moduleName);\n console.log(\n colors.gray(\n ` 1. Update model schema in models/${entity.kebab}/${entity.kebab}.model.ts`,\n ),\n );\n console.log(colors.gray(` 2. Update schema rules in schema/*.schema.ts`));\n } else {\n console.log(colors.gray(`\\nNext steps:`));\n console.log(colors.gray(` 1. Define routes in ${name.kebab}/routes.ts`));\n console.log(\n colors.gray(` 2. Create controllers: warlock generate.controller ${name.kebab}/<name>`),\n );\n console.log(colors.gray(` 3. Create models: warlock generate.model ${name.kebab}/<name>`));\n console.log(colors.gray(`\\nTip: omit --minimal to generate a full CRUD scaffold`));\n }\n}\n"],"mappings":"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"}
@@ -34,7 +34,7 @@ async function generateRepository(data) {
34
34
  }
35
35
  await ensureComponentDirectory(module, "repositories");
36
36
  await putFileAsync(resolveComponentPath(module, "repositories", `${name.kebab}.repository`), repositoryStub(name));
37
- console.log(colors.cyan(`\n✨ Repository "${name.pascal}Repository" generated successfully!`));
37
+ console.log(colors.cyan(`\nRepository "${name.pascal}Repository" generated successfully!`));
38
38
  }
39
39
 
40
40
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"repository.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/repository.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { repositoryStub } from \"../templates/stubs\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\n\nexport async function generateRepository(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Repository name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.repository users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if repository already exists\n if ((await componentExists(module, \"repositories\", `${name.kebab}.repository`)) && !force) {\n console.log(colors.red(`Error: Repository \"${name.kebab}.repository.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"repositories\");\n\n // Generate repository\n const repositoryPath = resolveComponentPath(module, \"repositories\", `${name.kebab}.repository`);\n const repositoryContent = repositoryStub(name);\n\n await putFileAsync(repositoryPath, repositoryContent);\n\n console.log(colors.cyan(`\\n✨ Repository \"${name.pascal}Repository\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,iDAAiD,CAAC;EAC5E,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,IAAK,MAAM,gBAAgB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACzF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,cAAc;CAMrD,MAAM,aAHiB,qBAAqB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAGlD,GAFN,eAAe,IAEU,CAAC;CAEpD,QAAQ,IAAI,OAAO,KAAK,qBAAqB,KAAK,OAAO,oCAAoC,CAAC;AAChG"}
1
+ {"version":3,"file":"repository.generator.mjs","names":[],"sources":["../../../../../../../../../../core/src/cli/commands/generate/generators/repository.generator.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\nimport type { CommandActionData } from \"../../../../commands/types\";\nimport { repositoryStub } from \"../templates/stubs\";\nimport { putFileAsync, setDryRun } from \"../utils/writer\";\nimport { parseModulePath, parseName } from \"../utils/name-parser\";\nimport {\n componentExists,\n ensureComponentDirectory,\n moduleExists,\n resolveComponentPath,\n} from \"../utils/path-resolver\";\n\nexport async function generateRepository(data: CommandActionData): Promise<void> {\n const input = data.args[0];\n\n if (!input) {\n console.log(colors.red(\"Error: Repository name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n console.log(colors.yellow(\"Example: warlock generate.repository users/user\"));\n process.exit(1);\n }\n\n const { module, name: componentName } = parseModulePath(input);\n\n if (!module) {\n console.log(colors.red(\"Error: Module name is required\"));\n console.log(colors.yellow(\"Usage: warlock generate.repository <module>/<name>\"));\n process.exit(1);\n }\n\n // Check if module exists\n if (!(await moduleExists(module))) {\n console.log(colors.red(`Error: Module \"${module}\" does not exist`));\n console.log(colors.yellow(`Run: warlock generate.module ${module}`));\n process.exit(1);\n }\n\n const name = parseName(componentName);\n const force = data.options.force || data.options.f;\n setDryRun(Boolean(data.options.dryRun));\n\n // Check if repository already exists\n if ((await componentExists(module, \"repositories\", `${name.kebab}.repository`)) && !force) {\n console.log(colors.red(`Error: Repository \"${name.kebab}.repository.ts\" already exists`));\n console.log(colors.yellow(\"Use --force to overwrite\"));\n process.exit(1);\n }\n\n // Ensure directories exist\n await ensureComponentDirectory(module, \"repositories\");\n\n // Generate repository\n const repositoryPath = resolveComponentPath(module, \"repositories\", `${name.kebab}.repository`);\n const repositoryContent = repositoryStub(name);\n\n await putFileAsync(repositoryPath, repositoryContent);\n\n console.log(colors.cyan(`\\nRepository \"${name.pascal}Repository\" generated successfully!`));\n}\n"],"mappings":";;;;;;;AAYA,eAAsB,mBAAmB,MAAwC;CAC/E,MAAM,QAAQ,KAAK,KAAK;CAExB,IAAI,CAAC,OAAO;EACV,QAAQ,IAAI,OAAO,IAAI,oCAAoC,CAAC;EAC5D,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,IAAI,OAAO,OAAO,iDAAiD,CAAC;EAC5E,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,EAAE,QAAQ,MAAM,kBAAkB,gBAAgB,KAAK;CAE7D,IAAI,CAAC,QAAQ;EACX,QAAQ,IAAI,OAAO,IAAI,gCAAgC,CAAC;EACxD,QAAQ,IAAI,OAAO,OAAO,oDAAoD,CAAC;EAC/E,QAAQ,KAAK,CAAC;CAChB;CAGA,IAAI,CAAE,MAAM,aAAa,MAAM,GAAI;EACjC,QAAQ,IAAI,OAAO,IAAI,kBAAkB,OAAO,iBAAiB,CAAC;EAClE,QAAQ,IAAI,OAAO,OAAO,gCAAgC,QAAQ,CAAC;EACnE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,OAAO,UAAU,aAAa;CACpC,MAAM,QAAQ,KAAK,QAAQ,SAAS,KAAK,QAAQ;CACjD,UAAU,QAAQ,KAAK,QAAQ,MAAM,CAAC;CAGtC,IAAK,MAAM,gBAAgB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAAY,KAAM,CAAC,OAAO;EACzF,QAAQ,IAAI,OAAO,IAAI,sBAAsB,KAAK,MAAM,+BAA+B,CAAC;EACxF,QAAQ,IAAI,OAAO,OAAO,0BAA0B,CAAC;EACrD,QAAQ,KAAK,CAAC;CAChB;CAGA,MAAM,yBAAyB,QAAQ,cAAc;CAMrD,MAAM,aAHiB,qBAAqB,QAAQ,gBAAgB,GAAG,KAAK,MAAM,YAGlD,GAFN,eAAe,IAEU,CAAC;CAEpD,QAAQ,IAAI,OAAO,KAAK,iBAAiB,KAAK,OAAO,oCAAoC,CAAC;AAC5F"}
@@ -34,7 +34,7 @@ async function generateResource(data) {
34
34
  }
35
35
  await ensureComponentDirectory(module, "resources");
36
36
  await putFileAsync(resolveComponentPath(module, "resources", `${name.kebab}.resource`), resourceStub(name));
37
- console.log(colors.cyan(`\n✨ Resource "${name.pascal}Resource" generated successfully!`));
37
+ console.log(colors.cyan(`\nResource "${name.pascal}Resource" generated successfully!`));
38
38
  }
39
39
 
40
40
  //#endregion