zudojs-cli 2.0.0 → 2.1.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 (249) hide show
  1. package/README.md +69 -9
  2. package/dist/src/adapters/frontend/angular.adapter.d.ts +0 -1
  3. package/dist/src/adapters/frontend/angular.adapter.js +14 -97
  4. package/dist/src/adapters/frontend/astro.adapter.d.ts +0 -1
  5. package/dist/src/adapters/frontend/astro.adapter.js +4 -64
  6. package/dist/src/adapters/frontend/fallback/fallback.helper.d.ts +41 -0
  7. package/dist/src/adapters/frontend/fallback/fallback.helper.js +57 -0
  8. package/dist/src/adapters/frontend/fallback/framework/angular/angular.fallback.d.ts +18 -0
  9. package/dist/src/adapters/frontend/fallback/framework/angular/angular.fallback.js +107 -0
  10. package/dist/src/adapters/frontend/fallback/framework/angular/angularWorkspace.fallback.d.ts +23 -0
  11. package/dist/src/adapters/frontend/fallback/framework/angular/angularWorkspace.fallback.js +125 -0
  12. package/dist/src/adapters/frontend/fallback/framework/angular/index.d.ts +8 -0
  13. package/dist/src/adapters/frontend/fallback/framework/angular/index.js +8 -0
  14. package/dist/src/adapters/frontend/fallback/framework/astro.fallback.d.ts +14 -0
  15. package/dist/src/adapters/frontend/fallback/framework/astro.fallback.js +76 -0
  16. package/dist/src/adapters/frontend/fallback/framework/index.d.ts +13 -0
  17. package/dist/src/adapters/frontend/fallback/framework/index.js +13 -0
  18. package/dist/src/adapters/frontend/fallback/framework/next.fallback.d.ts +13 -0
  19. package/dist/src/adapters/frontend/fallback/framework/next.fallback.js +105 -0
  20. package/dist/src/adapters/frontend/fallback/framework/nuxt.fallback.d.ts +14 -0
  21. package/dist/src/adapters/frontend/fallback/framework/nuxt.fallback.js +56 -0
  22. package/dist/src/adapters/frontend/fallback/framework/sveltekit.fallback.d.ts +15 -0
  23. package/dist/src/adapters/frontend/fallback/framework/sveltekit.fallback.js +94 -0
  24. package/dist/src/adapters/frontend/fallback/index.d.ts +12 -0
  25. package/dist/src/adapters/frontend/fallback/index.js +12 -0
  26. package/dist/src/adapters/frontend/fallback/vite/index.d.ts +11 -0
  27. package/dist/src/adapters/frontend/fallback/vite/index.js +11 -0
  28. package/dist/src/adapters/frontend/fallback/vite/react.fallback.d.ts +13 -0
  29. package/dist/src/adapters/frontend/fallback/vite/react.fallback.js +77 -0
  30. package/dist/src/adapters/frontend/fallback/vite/svelte.fallback.d.ts +14 -0
  31. package/dist/src/adapters/frontend/fallback/vite/svelte.fallback.js +95 -0
  32. package/dist/src/adapters/frontend/fallback/vite/vanilla.fallback.d.ts +13 -0
  33. package/dist/src/adapters/frontend/fallback/vite/vanilla.fallback.js +71 -0
  34. package/dist/src/adapters/frontend/fallback/vite/vue.fallback.d.ts +14 -0
  35. package/dist/src/adapters/frontend/fallback/vite/vue.fallback.js +78 -0
  36. package/dist/src/adapters/frontend/next.adapter.d.ts +0 -1
  37. package/dist/src/adapters/frontend/next.adapter.js +16 -95
  38. package/dist/src/adapters/frontend/nuxt.adapter.d.ts +1 -2
  39. package/dist/src/adapters/frontend/nuxt.adapter.js +32 -43
  40. package/dist/src/adapters/frontend/react-native.adapter.js +1 -1
  41. package/dist/src/adapters/frontend/react.adapter.d.ts +0 -1
  42. package/dist/src/adapters/frontend/react.adapter.js +7 -89
  43. package/dist/src/adapters/frontend/svelte.adapter.d.ts +0 -1
  44. package/dist/src/adapters/frontend/svelte.adapter.js +4 -86
  45. package/dist/src/adapters/frontend/sveltekit.adapter.d.ts +0 -1
  46. package/dist/src/adapters/frontend/sveltekit.adapter.js +4 -57
  47. package/dist/src/adapters/frontend/vanilla.adapter.d.ts +0 -1
  48. package/dist/src/adapters/frontend/vanilla.adapter.js +4 -47
  49. package/dist/src/adapters/frontend/vue.adapter.d.ts +0 -1
  50. package/dist/src/adapters/frontend/vue.adapter.js +4 -76
  51. package/dist/src/bin/bin.menu.d.ts +22 -0
  52. package/dist/src/bin/bin.menu.js +40 -0
  53. package/dist/src/bin/bin.runner.d.ts +38 -0
  54. package/dist/src/bin/bin.runner.js +51 -0
  55. package/dist/src/bin/index.d.ts +9 -0
  56. package/dist/src/bin/index.js +9 -0
  57. package/dist/src/bin/zudojs.js +15 -4
  58. package/dist/src/cliApplication/cliApplication.core.d.ts +4 -2
  59. package/dist/src/cliApplication/cliApplication.core.js +48 -36
  60. package/dist/src/cliApplication/cliApplication.logger.d.ts +5 -0
  61. package/dist/src/cliApplication/cliApplication.logger.js +5 -3
  62. package/dist/src/cliApplication/invocation/index.d.ts +12 -0
  63. package/dist/src/cliApplication/invocation/index.js +12 -0
  64. package/dist/src/cliApplication/invocation/invocation.hint.d.ts +30 -0
  65. package/dist/src/cliApplication/invocation/invocation.hint.js +74 -0
  66. package/dist/src/cliApplication/invocation/invocation.locate.d.ts +34 -0
  67. package/dist/src/cliApplication/invocation/invocation.locate.js +53 -0
  68. package/dist/src/cliApplication/invocation/invocation.name.d.ts +37 -0
  69. package/dist/src/cliApplication/invocation/invocation.name.js +69 -0
  70. package/dist/src/cliApplication/invocation/invocation.sanitize.d.ts +19 -0
  71. package/dist/src/cliApplication/invocation/invocation.sanitize.js +32 -0
  72. package/dist/src/cliParser/cliParser.core.js +3 -1
  73. package/dist/src/cliParser/cliParser.helper.d.ts +7 -0
  74. package/dist/src/cliParser/cliParser.helper.js +19 -2
  75. package/dist/src/cliParser/cliParser.longOption.js +2 -2
  76. package/dist/src/commands/add.command.d.ts +7 -3
  77. package/dist/src/commands/add.command.js +96 -57
  78. package/dist/src/commands/create.command.js +29 -42
  79. package/dist/src/commands/doctor.command.d.ts +2 -1
  80. package/dist/src/commands/doctor.command.js +52 -4
  81. package/dist/src/commands/generate.command.js +31 -16
  82. package/dist/src/commands/info.command.js +11 -1
  83. package/dist/src/constants/index.d.ts +21 -3
  84. package/dist/src/constants/index.js +40 -5
  85. package/dist/src/constants/zudojsVersions.generated.d.ts +9 -0
  86. package/dist/src/constants/zudojsVersions.generated.js +48 -0
  87. package/dist/src/constants/zudojsVersions.helper.d.ts +21 -0
  88. package/dist/src/constants/zudojsVersions.helper.js +29 -0
  89. package/dist/src/generators/frontend/frontendGenerator.core.js +9 -10
  90. package/dist/src/generators/frontend/frontendPipeline.d.ts +6 -1
  91. package/dist/src/generators/frontend/frontendPipeline.js +9 -1
  92. package/dist/src/generators/fullstack/fullstackComposer.core.js +7 -1
  93. package/dist/src/generators/index.d.ts +1 -2
  94. package/dist/src/generators/index.js +1 -2
  95. package/dist/src/generators/infrastructure/infrastructure.generator.js +13 -5
  96. package/dist/src/generators/integration/integrationGenerator.core.d.ts +2 -0
  97. package/dist/src/generators/integration/integrationGenerator.core.js +31 -2
  98. package/dist/src/generators/module/module.generator.js +36 -4
  99. package/dist/src/generators/resource/index.d.ts +8 -0
  100. package/dist/src/generators/resource/index.js +8 -0
  101. package/dist/src/generators/resource/resource.generator.d.ts +27 -0
  102. package/dist/src/generators/resource/resource.generator.js +87 -0
  103. package/dist/src/generators/resource/resource.layout.d.ts +26 -0
  104. package/dist/src/generators/resource/resource.layout.js +46 -0
  105. package/dist/src/generators/resource/resource.plan.d.ts +27 -0
  106. package/dist/src/generators/resource/resource.plan.js +46 -0
  107. package/dist/src/generators/resource/resource.run.d.ts +25 -0
  108. package/dist/src/generators/resource/resource.run.js +52 -0
  109. package/dist/src/prompts/cancel.prompt.d.ts +5 -1
  110. package/dist/src/prompts/cancel.prompt.js +4 -0
  111. package/dist/src/prompts/menu/index.d.ts +13 -0
  112. package/dist/src/prompts/menu/index.js +13 -0
  113. package/dist/src/prompts/menu/menu.adapter.d.ts +16 -0
  114. package/dist/src/prompts/menu/menu.adapter.js +56 -0
  115. package/dist/src/prompts/menu/menu.constant.d.ts +20 -0
  116. package/dist/src/prompts/menu/menu.constant.js +29 -0
  117. package/dist/src/prompts/menu/menu.flow.d.ts +18 -0
  118. package/dist/src/prompts/menu/menu.flow.js +82 -0
  119. package/dist/src/prompts/menu/menu.select.d.ts +26 -0
  120. package/dist/src/prompts/menu/menu.select.js +118 -0
  121. package/dist/src/prompts/menu/menu.type.d.ts +66 -0
  122. package/dist/src/prompts/menu/menu.type.js +8 -0
  123. package/dist/src/recipes/apply/index.d.ts +9 -0
  124. package/dist/src/recipes/apply/index.js +9 -0
  125. package/dist/src/recipes/apply/recipeApply.app.d.ts +20 -0
  126. package/dist/src/recipes/apply/recipeApply.app.js +79 -0
  127. package/dist/src/recipes/apply/recipeApply.context.d.ts +14 -0
  128. package/dist/src/recipes/apply/recipeApply.context.js +76 -0
  129. package/dist/src/recipes/apply/recipeApply.files.d.ts +39 -0
  130. package/dist/src/recipes/apply/recipeApply.files.js +84 -0
  131. package/dist/src/recipes/apply/recipeApply.project.d.ts +11 -0
  132. package/dist/src/recipes/apply/recipeApply.project.js +50 -0
  133. package/dist/src/recipes/apply/recipeApply.report.d.ts +20 -0
  134. package/dist/src/recipes/apply/recipeApply.report.js +51 -0
  135. package/dist/src/recipes/catalog/database/database.files.d.ts +15 -0
  136. package/dist/src/recipes/catalog/database/database.files.js +98 -0
  137. package/dist/src/recipes/catalog/database/database.recipe.d.ts +9 -0
  138. package/dist/src/recipes/catalog/database/database.recipe.js +50 -0
  139. package/dist/src/recipes/catalog/database/index.d.ts +6 -0
  140. package/dist/src/recipes/catalog/database/index.js +6 -0
  141. package/dist/src/recipes/catalog/email.recipe.d.ts +9 -0
  142. package/dist/src/recipes/catalog/email.recipe.js +122 -0
  143. package/dist/src/recipes/catalog/index.d.ts +11 -0
  144. package/dist/src/recipes/catalog/index.js +11 -0
  145. package/dist/src/recipes/catalog/openapi.recipe.d.ts +8 -0
  146. package/dist/src/recipes/catalog/openapi.recipe.js +25 -0
  147. package/dist/src/recipes/catalog/platform/cache.recipe.d.ts +7 -0
  148. package/dist/src/recipes/catalog/platform/cache.recipe.js +55 -0
  149. package/dist/src/recipes/catalog/platform/index.d.ts +9 -0
  150. package/dist/src/recipes/catalog/platform/index.js +9 -0
  151. package/dist/src/recipes/catalog/platform/messaging.recipe.d.ts +7 -0
  152. package/dist/src/recipes/catalog/platform/messaging.recipe.js +46 -0
  153. package/dist/src/recipes/catalog/platform/observability.recipe.d.ts +8 -0
  154. package/dist/src/recipes/catalog/platform/observability.recipe.js +49 -0
  155. package/dist/src/recipes/catalog/platform/queue.recipe.d.ts +7 -0
  156. package/dist/src/recipes/catalog/platform/queue.recipe.js +61 -0
  157. package/dist/src/recipes/catalog/platform/scheduler.recipe.d.ts +7 -0
  158. package/dist/src/recipes/catalog/platform/scheduler.recipe.js +56 -0
  159. package/dist/src/recipes/catalog/redis.recipe.d.ts +8 -0
  160. package/dist/src/recipes/catalog/redis.recipe.js +79 -0
  161. package/dist/src/recipes/catalog/storage.recipe.d.ts +7 -0
  162. package/dist/src/recipes/catalog/storage.recipe.js +49 -0
  163. package/dist/src/recipes/catalog/websockets.recipe.d.ts +10 -0
  164. package/dist/src/recipes/catalog/websockets.recipe.js +84 -0
  165. package/dist/src/recipes/docker/docker.compose.d.ts +19 -0
  166. package/dist/src/recipes/docker/docker.compose.js +90 -0
  167. package/dist/src/recipes/docker/docker.recipe.d.ts +10 -0
  168. package/dist/src/recipes/docker/docker.recipe.js +51 -0
  169. package/dist/src/recipes/docker/docker.refresh.d.ts +13 -0
  170. package/dist/src/recipes/docker/docker.refresh.js +37 -0
  171. package/dist/src/recipes/docker/index.d.ts +7 -0
  172. package/dist/src/recipes/docker/index.js +7 -0
  173. package/dist/src/recipes/index.d.ts +8 -0
  174. package/dist/src/recipes/index.js +8 -0
  175. package/dist/src/recipes/recipe.registry.d.ts +17 -0
  176. package/dist/src/recipes/recipe.registry.js +46 -0
  177. package/dist/src/recipes/recipe.type.d.ts +93 -0
  178. package/dist/src/recipes/recipe.type.js +12 -0
  179. package/dist/src/resolvers/dependency/dependencyVersions.constant.d.ts +100 -5
  180. package/dist/src/resolvers/dependency/dependencyVersions.constant.js +103 -34
  181. package/dist/src/resolvers/dependency/index.d.ts +1 -1
  182. package/dist/src/resolvers/dependency/index.js +1 -1
  183. package/dist/src/resolvers/project.resolver.d.ts +14 -1
  184. package/dist/src/resolvers/project.resolver.js +11 -3
  185. package/dist/src/scaffolders/scaffolder.helper.js +12 -1
  186. package/dist/src/templates/backendApp/backendApp.core.d.ts +45 -0
  187. package/dist/src/templates/backendApp/backendApp.core.js +66 -0
  188. package/dist/src/templates/backendApp/backendApp.modules.d.ts +26 -0
  189. package/dist/src/templates/backendApp/backendApp.modules.js +25 -0
  190. package/dist/src/templates/backendApp/backendApp.project.d.ts +26 -0
  191. package/dist/src/templates/backendApp/backendApp.project.js +87 -0
  192. package/dist/src/templates/backendApp/index.d.ts +8 -0
  193. package/dist/src/templates/backendApp/index.js +8 -0
  194. package/dist/src/templates/backendApp/parts/config.template.d.ts +28 -0
  195. package/dist/src/templates/backendApp/parts/config.template.js +118 -0
  196. package/dist/src/templates/backendApp/parts/httpUtils.template.d.ts +10 -0
  197. package/dist/src/templates/backendApp/parts/httpUtils.template.js +103 -0
  198. package/dist/src/templates/backendApp/parts/index.d.ts +9 -0
  199. package/dist/src/templates/backendApp/parts/index.js +9 -0
  200. package/dist/src/templates/backendApp/parts/integrations.template.d.ts +16 -0
  201. package/dist/src/templates/backendApp/parts/integrations.template.js +115 -0
  202. package/dist/src/templates/backendApp/parts/wiring.template.d.ts +26 -0
  203. package/dist/src/templates/backendApp/parts/wiring.template.js +111 -0
  204. package/dist/src/templates/microservice/microservice.template.d.ts +4 -1
  205. package/dist/src/templates/microservice/microservice.template.js +74 -90
  206. package/dist/src/templates/modular-monolith/modularMonolith.template.js +25 -77
  207. package/dist/src/templates/monolith/monolith.template.d.ts +11 -26
  208. package/dist/src/templates/monolith/monolith.template.js +49 -146
  209. package/dist/src/templates/resource/index.d.ts +9 -0
  210. package/dist/src/templates/resource/index.js +9 -0
  211. package/dist/src/templates/resource/layers/index.d.ts +9 -0
  212. package/dist/src/templates/resource/layers/index.js +9 -0
  213. package/dist/src/templates/resource/layers/resourceData.template.d.ts +9 -0
  214. package/dist/src/templates/resource/layers/resourceData.template.js +108 -0
  215. package/dist/src/templates/resource/layers/resourcePrisma.template.d.ts +15 -0
  216. package/dist/src/templates/resource/layers/resourcePrisma.template.js +89 -0
  217. package/dist/src/templates/resource/layers/resourceRoutes.template.d.ts +13 -0
  218. package/dist/src/templates/resource/layers/resourceRoutes.template.js +128 -0
  219. package/dist/src/templates/resource/layers/resourceService.template.d.ts +13 -0
  220. package/dist/src/templates/resource/layers/resourceService.template.js +95 -0
  221. package/dist/src/templates/resource/resource.files.d.ts +33 -0
  222. package/dist/src/templates/resource/resource.files.js +99 -0
  223. package/dist/src/templates/resource/resource.names.d.ts +38 -0
  224. package/dist/src/templates/resource/resource.names.js +60 -0
  225. package/dist/src/templates/resource/resource.type.d.ts +19 -0
  226. package/dist/src/templates/resource/resource.type.js +15 -0
  227. package/dist/src/templates/shared/appRuntime.template.js +28 -11
  228. package/dist/src/templates/shared/capability.template.d.ts +13 -4
  229. package/dist/src/templates/shared/capability.template.js +21 -5
  230. package/dist/src/templates/shared/dockerfile.template.d.ts +12 -4
  231. package/dist/src/templates/shared/dockerfile.template.js +68 -29
  232. package/dist/src/templates/shared/pnpm.template.d.ts +8 -2
  233. package/dist/src/templates/shared/pnpm.template.js +9 -1
  234. package/dist/src/templates/shared/server.template.d.ts +23 -22
  235. package/dist/src/templates/shared/server.template.js +79 -53
  236. package/dist/src/types/scaffold.type.d.ts +6 -0
  237. package/dist/src/types/scaffold.type.js +2 -1
  238. package/dist/src/utils/utils.name.js +6 -0
  239. package/dist/src/utils/utils.writeGuard.d.ts +5 -0
  240. package/dist/src/utils/utils.writeGuard.js +23 -0
  241. package/dist/src/wiring/index.d.ts +10 -0
  242. package/dist/src/wiring/index.js +10 -0
  243. package/dist/src/wiring/wiring.dependencies.d.ts +29 -0
  244. package/dist/src/wiring/wiring.dependencies.js +83 -0
  245. package/dist/src/wiring/wiring.edits.d.ts +51 -0
  246. package/dist/src/wiring/wiring.edits.js +90 -0
  247. package/dist/src/wiring/wiring.markers.d.ts +53 -0
  248. package/dist/src/wiring/wiring.markers.js +87 -0
  249. package/package.json +20 -15
@@ -0,0 +1,90 @@
1
+ /**
2
+ * zudojs-cli — `compose.yaml` for `zudojs add docker`.
3
+ *
4
+ * One service per backend app plus one per enabled integration that needs
5
+ * a server: `postgres` (database), `redis` and `mailpit` (email, SMTP on
6
+ * 1025, web UI on 8025). Backing services publish on 127.0.0.1 only, and
7
+ * the Postgres password is read from `.env` (POSTGRES_PASSWORD): compose
8
+ * refuses to start without it, so no credential is written into the file.
9
+ */
10
+ /**
11
+ * Whether compose runs a `postgres` service. The `database` capability is
12
+ * recorded for MySQL and SQLite projects too, which used to get a Postgres
13
+ * container and a DATABASE_URL overriding their own.
14
+ */
15
+ export function usesPostgres(context) {
16
+ return context.features.has("database") && context.database === "postgresql";
17
+ }
18
+ const POSTGRES_URL = (db) => `postgresql://postgres:\${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}@postgres:5432/${db}`;
19
+ function appService(context, app) {
20
+ const env = [
21
+ ` NODE_ENV: production`,
22
+ ` HOST: 0.0.0.0`,
23
+ ` PORT: "${app.port}"`,
24
+ ...(usesPostgres(context) ? [` DATABASE_URL: ${POSTGRES_URL(context.projectSlug)}`] : []),
25
+ ...(context.features.has("redis") ? [` REDIS_URL: redis://redis:6379`] : []),
26
+ ...(context.features.has("email") ? [` SMTP_HOST: mailpit`, ` SMTP_PORT: "1025"`] : []),
27
+ ];
28
+ const dependsOn = [
29
+ ...(usesPostgres(context) ? ["postgres"] : []),
30
+ ...(context.features.has("redis") ? ["redis"] : []),
31
+ ];
32
+ const dockerfile = app.dir === "" ? "Dockerfile" : `${app.dir}/Dockerfile`;
33
+ return ` ${app.name}:
34
+ build:
35
+ context: .
36
+ dockerfile: ${dockerfile}
37
+ ports:
38
+ - "${app.port}:${app.port}"
39
+ env_file:
40
+ - path: ${app.dir === "" ? "" : `${app.dir}/`}.env
41
+ required: false
42
+ environment:
43
+ ${env.join("\n")}
44
+ ${dependsOn.length === 0 ? "" : ` depends_on:\n${dependsOn.map((name) => ` ${name}:\n condition: service_healthy`).join("\n")}\n`}`;
45
+ }
46
+ const BACKING_SERVICES = {
47
+ database: (db) => ` postgres:
48
+ image: postgres:17-alpine
49
+ environment:
50
+ POSTGRES_USER: postgres
51
+ POSTGRES_PASSWORD: \${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
52
+ POSTGRES_DB: ${db}
53
+ ports:
54
+ - "127.0.0.1:5432:5432"
55
+ volumes:
56
+ - postgres-data:/var/lib/postgresql/data
57
+ healthcheck:
58
+ test: ["CMD-SHELL", "pg_isready -U postgres -d ${db}"]
59
+ interval: 5s
60
+ timeout: 3s
61
+ retries: 20
62
+ `,
63
+ redis: () => ` redis:
64
+ image: redis:8-alpine
65
+ ports:
66
+ - "127.0.0.1:6379:6379"
67
+ healthcheck:
68
+ test: ["CMD", "redis-cli", "ping"]
69
+ interval: 5s
70
+ timeout: 3s
71
+ retries: 20
72
+ `,
73
+ email: () => ` mailpit:
74
+ image: axllent/mailpit:v1.27
75
+ ports:
76
+ - "127.0.0.1:1025:1025"
77
+ - "127.0.0.1:8025:8025"
78
+ `,
79
+ };
80
+ /** Renders `compose.yaml`. */
81
+ export function renderComposeFile(context) {
82
+ const backing = Object.entries(BACKING_SERVICES)
83
+ .filter(([feature]) => (feature === "database" ? usesPostgres(context) : context.features.has(feature)))
84
+ .map(([, render]) => render(context.projectSlug));
85
+ const volumes = usesPostgres(context) ? "\nvolumes:\n postgres-data:\n" : "";
86
+ return `# docker compose up --build
87
+ services:
88
+ ${[...context.apps.map((app) => appService(context, app)), ...backing].join("\n")}${volumes}`;
89
+ }
90
+ //# sourceMappingURL=docker.compose.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * zudojs-cli — `zudojs add docker`: a multi-stage, non-root Node 24
3
+ * Dockerfile per backend app, `.dockerignore`, and `compose.yaml` with a
4
+ * service per app and per enabled integration (postgres, redis, mailpit).
5
+ * Existing files are kept: a project that already has a compose file
6
+ * (microservice projects are created with docker-compose.yml) keeps it.
7
+ */
8
+ import type { ProjectRecipe } from "../recipe.type.js";
9
+ export declare const dockerRecipe: ProjectRecipe;
10
+ //# sourceMappingURL=docker.recipe.d.ts.map
@@ -0,0 +1,51 @@
1
+ /**
2
+ * zudojs-cli — `zudojs add docker`: a multi-stage, non-root Node 24
3
+ * Dockerfile per backend app, `.dockerignore`, and `compose.yaml` with a
4
+ * service per app and per enabled integration (postgres, redis, mailpit).
5
+ * Existing files are kept: a project that already has a compose file
6
+ * (microservice projects are created with docker-compose.yml) keeps it.
7
+ */
8
+ import { existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { renderAppPackageDockerfile } from "../../templates/shared/dockerfile.template.js";
11
+ import { renderComposeFile, usesPostgres } from "./docker.compose.js";
12
+ const DOCKERIGNORE = `node_modules
13
+ **/node_modules
14
+ dist
15
+ **/dist
16
+ .git
17
+ .env
18
+ **/.env
19
+ *.log
20
+ .data
21
+ **/src/generated
22
+ `;
23
+ export const dockerRecipe = {
24
+ scope: "project",
25
+ feature: "docker",
26
+ summary: "Dockerfile (multi-stage, non-root, Node 24), .dockerignore and compose.yaml",
27
+ files: (context) => {
28
+ const files = { ".dockerignore": DOCKERIGNORE };
29
+ for (const app of context.apps) {
30
+ files[app.dir === "" ? "Dockerfile" : `${app.dir}/Dockerfile`] = renderAppPackageDockerfile({
31
+ appPath: app.dir === "" ? "." : app.dir,
32
+ port: app.port,
33
+ packageManager: context.packageManager,
34
+ prisma: app.prisma,
35
+ });
36
+ }
37
+ const hasCompose = ["compose.yaml", "compose.yml", "docker-compose.yml", "docker-compose.yaml"]
38
+ .some((name) => existsSync(join(context.root, name)));
39
+ if (!hasCompose)
40
+ files["compose.yaml"] = renderComposeFile(context);
41
+ return files;
42
+ },
43
+ // Empty, never a placeholder: compose refuses to start until it is set,
44
+ // so a copied .env.example cannot ship a guessable password. Hex keeps it
45
+ // valid inside DATABASE_URL.
46
+ env: (context) => usesPostgres(context)
47
+ ? [{ name: "POSTGRES_PASSWORD", value: "", comment: "Password for the compose.yaml postgres service; generate with: openssl rand -hex 32" }]
48
+ : [],
49
+ nextSteps: () => ["cp .env.example .env, then: docker compose up --build"],
50
+ };
51
+ //# sourceMappingURL=docker.recipe.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * zudojs-cli — Keeping CLI-written Dockerfiles in step with the app.
3
+ *
4
+ * A Dockerfile the CLI wrote for an app without Prisma cannot build it once
5
+ * `zudojs add database` has run (the schema is needed before `prisma
6
+ * generate`). A Dockerfile is rewritten only when it is byte-for-byte what
7
+ * the CLI rendered for the other Prisma setting, so a hand-edited file is
8
+ * never touched.
9
+ */
10
+ import type { ProjectRecipeContext } from "../recipe.type.js";
11
+ /** Rewrites unedited CLI Dockerfiles whose Prisma setting is stale; returns their paths. */
12
+ export declare function refreshGeneratedDockerfiles(context: ProjectRecipeContext): Promise<readonly string[]>;
13
+ //# sourceMappingURL=docker.refresh.d.ts.map
@@ -0,0 +1,37 @@
1
+ /**
2
+ * zudojs-cli — Keeping CLI-written Dockerfiles in step with the app.
3
+ *
4
+ * A Dockerfile the CLI wrote for an app without Prisma cannot build it once
5
+ * `zudojs add database` has run (the schema is needed before `prisma
6
+ * generate`). A Dockerfile is rewritten only when it is byte-for-byte what
7
+ * the CLI rendered for the other Prisma setting, so a hand-edited file is
8
+ * never touched.
9
+ */
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { renderAppPackageDockerfile } from "../../templates/shared/dockerfile.template.js";
13
+ import { writeFile } from "../../utils/utils.fileSystem.js";
14
+ /** Rewrites unedited CLI Dockerfiles whose Prisma setting is stale; returns their paths. */
15
+ export async function refreshGeneratedDockerfiles(context) {
16
+ const refreshed = [];
17
+ for (const app of context.apps) {
18
+ const path = app.dir === "" ? "Dockerfile" : `${app.dir}/Dockerfile`;
19
+ const fullPath = join(context.root, path);
20
+ if (!existsSync(fullPath))
21
+ continue;
22
+ const render = (prisma) => renderAppPackageDockerfile({
23
+ appPath: app.dir === "" ? "." : app.dir,
24
+ port: app.port,
25
+ packageManager: context.packageManager,
26
+ prisma,
27
+ });
28
+ const current = readFileSync(fullPath, "utf-8");
29
+ const wanted = render(app.prisma);
30
+ if (current !== wanted && current === render(!app.prisma)) {
31
+ await writeFile(context.root, path, wanted);
32
+ refreshed.push(path);
33
+ }
34
+ }
35
+ return refreshed;
36
+ }
37
+ //# sourceMappingURL=docker.refresh.js.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * zudojs-cli — The docker project recipe.
3
+ */
4
+ export { dockerRecipe } from "./docker.recipe.js";
5
+ export { renderComposeFile } from "./docker.compose.js";
6
+ export { refreshGeneratedDockerfiles } from "./docker.refresh.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * zudojs-cli — The docker project recipe.
3
+ */
4
+ export { dockerRecipe } from "./docker.recipe.js";
5
+ export { renderComposeFile } from "./docker.compose.js";
6
+ export { refreshGeneratedDockerfiles } from "./docker.refresh.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * zudojs-cli — Feature recipes for `zudojs add`.
3
+ */
4
+ export * from "./recipe.type.js";
5
+ export * from "./recipe.registry.js";
6
+ export { refreshGeneratedDockerfiles } from "./docker/index.js";
7
+ export * from "./apply/index.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * zudojs-cli — Feature recipes for `zudojs add`.
3
+ */
4
+ export * from "./recipe.type.js";
5
+ export * from "./recipe.registry.js";
6
+ export { refreshGeneratedDockerfiles } from "./docker/index.js";
7
+ export * from "./apply/index.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * zudojs-cli — The recipe behind every feature `zudojs add` accepts.
3
+ *
4
+ * Kept in step with `FEATURE_PACKAGES` by `tests/addRecipes.test.ts`: a
5
+ * feature name without a recipe would install a package and write nothing,
6
+ * which is exactly what `add` used to do.
7
+ */
8
+ import type { FeatureRecipe } from "./recipe.type.js";
9
+ /** Every recipe, keyed by feature. */
10
+ export declare const FEATURE_RECIPES: Readonly<Record<string, FeatureRecipe>>;
11
+ /**
12
+ * Resolves a feature name (or alias) to its recipe.
13
+ *
14
+ * @throws {CLIValidationError} For refused or unknown names.
15
+ */
16
+ export declare function resolveFeatureRecipe(name: string): FeatureRecipe;
17
+ //# sourceMappingURL=recipe.registry.d.ts.map
@@ -0,0 +1,46 @@
1
+ /**
2
+ * zudojs-cli — The recipe behind every feature `zudojs add` accepts.
3
+ *
4
+ * Kept in step with `FEATURE_PACKAGES` by `tests/addRecipes.test.ts`: a
5
+ * feature name without a recipe would install a package and write nothing,
6
+ * which is exactly what `add` used to do.
7
+ */
8
+ import { FEATURE_ALIASES, FEATURE_PACKAGES, FEATURE_REFUSALS, } from "../constants/index.js";
9
+ import { CLIValidationError } from "../errors/index.js";
10
+ import { cacheRecipe, databaseRecipe, emailRecipe, messagingRecipe, observabilityRecipe, openapiRecipe, queueRecipe, redisRecipe, schedulerRecipe, storageRecipe, websocketsRecipe, } from "./catalog/index.js";
11
+ import { dockerRecipe } from "./docker/index.js";
12
+ /** Every recipe, keyed by feature. */
13
+ export const FEATURE_RECIPES = Object.freeze({
14
+ database: databaseRecipe,
15
+ redis: redisRecipe,
16
+ websockets: websocketsRecipe,
17
+ email: emailRecipe,
18
+ docker: dockerRecipe,
19
+ queue: queueRecipe,
20
+ messaging: messagingRecipe,
21
+ openapi: openapiRecipe,
22
+ observability: observabilityRecipe,
23
+ cache: cacheRecipe,
24
+ storage: storageRecipe,
25
+ scheduler: schedulerRecipe,
26
+ });
27
+ /**
28
+ * Resolves a feature name (or alias) to its recipe.
29
+ *
30
+ * @throws {CLIValidationError} For refused or unknown names.
31
+ */
32
+ export function resolveFeatureRecipe(name) {
33
+ const available = Object.keys(FEATURE_PACKAGES).join(", ");
34
+ const feature = Object.hasOwn(FEATURE_ALIASES, name) ? (FEATURE_ALIASES[name] ?? name) : name;
35
+ if (Object.hasOwn(FEATURE_REFUSALS, feature)) {
36
+ throw new CLIValidationError(`"${name}" cannot be added: ${FEATURE_REFUSALS[feature]}`);
37
+ }
38
+ // Own keys only: `constructor` or `__proto__` must not resolve to
39
+ // Object.prototype members.
40
+ const recipe = Object.hasOwn(FEATURE_RECIPES, feature) ? FEATURE_RECIPES[feature] : undefined;
41
+ if (recipe === undefined) {
42
+ throw new CLIValidationError(`Unknown feature: "${name}". Available: ${available}`);
43
+ }
44
+ return recipe;
45
+ }
46
+ //# sourceMappingURL=recipe.registry.js.map
@@ -0,0 +1,93 @@
1
+ /**
2
+ * zudojs-cli — Feature recipes: what `zudojs add <feature>` writes.
3
+ *
4
+ * `add` used to install a package and write no code. Every feature it
5
+ * accepts now has a recipe: an app recipe adds an integration
6
+ * (`src/integrations/<name>.ts`, registered between the markers of
7
+ * `src/integrations/index.ts` and started/stopped with the runtime), its
8
+ * config section, its `.env.example` variables and its dependencies; a
9
+ * project recipe (docker) writes files at the project root.
10
+ */
11
+ import type { EnvVariable } from "../templates/backendApp/index.js";
12
+ import type { MarkerName } from "../wiring/index.js";
13
+ /** What a recipe knows about the app it is applied to. */
14
+ export interface RecipeContext {
15
+ /** Project name slug (database name, service names). */
16
+ readonly projectSlug: string;
17
+ /** App name: `app` for a single-app project, `gateway`, a service name. */
18
+ readonly appName: string;
19
+ /** Database engine recorded in the manifest (`postgresql`, ...). */
20
+ readonly database: string;
21
+ /** App root relative to the project root (`""`, `apps/gateway`). */
22
+ readonly appRoot: string;
23
+ }
24
+ /** A line inserted between the markers of `src/server.ts`. */
25
+ export interface ServerLine {
26
+ readonly marker: MarkerName;
27
+ readonly line: string;
28
+ }
29
+ /** A recipe applied to each backend app. */
30
+ export interface AppRecipe {
31
+ readonly scope: "app";
32
+ readonly feature: string;
33
+ /** One line for `zudojs add --help` style listings and the success message. */
34
+ readonly summary: string;
35
+ /** Throws a CLIValidationError when the app cannot take the feature. */
36
+ readonly validate?: (context: RecipeContext) => void;
37
+ readonly dependencies: Readonly<Record<string, string>>;
38
+ readonly devDependencies?: Readonly<Record<string, string>>;
39
+ /** Scripts added when missing; `replace` rewrites an existing value. */
40
+ readonly scripts?: Readonly<Record<string, string>>;
41
+ readonly replaceScripts?: Readonly<Record<string, {
42
+ from: string;
43
+ to: string;
44
+ }>>;
45
+ readonly env?: (context: RecipeContext) => readonly EnvVariable[];
46
+ /** Single-line entry for the config markers, e.g. `redis: Object.freeze({...}),`. */
47
+ readonly configSection?: string;
48
+ /** `src/integrations/<file>` exporting `<exportName>: Integration`. */
49
+ readonly integration?: {
50
+ readonly file: string;
51
+ readonly exportName: string;
52
+ readonly source: (context: RecipeContext) => string;
53
+ };
54
+ /** Extra files, relative to the app root, written only when missing. */
55
+ readonly files?: (context: RecipeContext) => Readonly<Record<string, string>>;
56
+ readonly serverLines?: (context: RecipeContext) => readonly ServerLine[];
57
+ /** Lines for the project's .gitignore. */
58
+ readonly gitignore?: (context: RecipeContext) => readonly string[];
59
+ /** Packages allowed to run install scripts (pnpm allowBuilds). */
60
+ readonly allowBuilds?: readonly string[];
61
+ /** What to do next, printed after the recipe is applied. */
62
+ readonly nextSteps?: (context: RecipeContext) => readonly string[];
63
+ }
64
+ /** Everything a project recipe needs to know. */
65
+ export interface ProjectRecipeContext {
66
+ readonly root: string;
67
+ readonly projectSlug: string;
68
+ readonly architecture: string;
69
+ readonly packageManager: string;
70
+ readonly database: string;
71
+ /** Features already enabled anywhere in the project (plus this one). */
72
+ readonly features: ReadonlySet<string>;
73
+ /** Backend apps: root-relative directory, name and port. */
74
+ readonly apps: readonly {
75
+ readonly dir: string;
76
+ readonly name: string;
77
+ readonly port: number;
78
+ readonly prisma: boolean;
79
+ }[];
80
+ }
81
+ /** A recipe applied once, at the project root. */
82
+ export interface ProjectRecipe {
83
+ readonly scope: "project";
84
+ readonly feature: string;
85
+ readonly summary: string;
86
+ /** Files to write (relative to the root); existing files are kept. */
87
+ readonly files: (context: ProjectRecipeContext) => Readonly<Record<string, string>>;
88
+ readonly env?: (context: ProjectRecipeContext) => readonly EnvVariable[];
89
+ readonly nextSteps?: (context: ProjectRecipeContext) => readonly string[];
90
+ }
91
+ /** Any recipe. */
92
+ export type FeatureRecipe = AppRecipe | ProjectRecipe;
93
+ //# sourceMappingURL=recipe.type.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * zudojs-cli — Feature recipes: what `zudojs add <feature>` writes.
3
+ *
4
+ * `add` used to install a package and write no code. Every feature it
5
+ * accepts now has a recipe: an app recipe adds an integration
6
+ * (`src/integrations/<name>.ts`, registered between the markers of
7
+ * `src/integrations/index.ts` and started/stopped with the runtime), its
8
+ * config section, its `.env.example` variables and its dependencies; a
9
+ * project recipe (docker) writes files at the project root.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=recipe.type.js.map
@@ -1,12 +1,107 @@
1
1
  /**
2
- * Default version ranges for frontend dependencies the adapters request
3
- * without a version.
2
+ * Version ranges for every third-party package a generated project depends
3
+ * on: the ranges adapters request without a version, the framework
4
+ * toolchains the built-in fallback templates write, and the backend
5
+ * templates' dev tooling.
4
6
  *
5
7
  * Unpinned requirements used to be written as `"latest"`, so the same
6
- * scaffold produced a different dependency set every day. Every name a
7
- * built-in adapter requests unpinned has a caret range here (checked by
8
+ * scaffold produced a different dependency set every day, and the fallback
9
+ * templates carried their own literals that went stale independently (Vite
10
+ * 6, Next 15, Nuxt 3, Angular 19 and TypeScript 5 long after newer majors
11
+ * shipped). Every range now lives here. Every name a built-in adapter
12
+ * requests unpinned must have an entry (checked by
8
13
  * `tests/cli.round10.*.test.ts`). Ranges were taken from the npm registry on
9
- * 2026-09-19.
14
+ * 2026-09-23; pre-releases (for example Prisma 8 RCs or `@nuxt/devtools`
15
+ * betas tagged `latest`) are never used.
16
+ */
17
+ export declare const DEPENDENCY_VERSION_RANGES: Readonly<{
18
+ readonly "@angular/build": "^22.1.8";
19
+ readonly "@angular/cli": "^22.1.8";
20
+ readonly "@angular/common": "^22.1.7";
21
+ readonly "@angular/compiler": "^22.1.7";
22
+ readonly "@angular/compiler-cli": "^22.1.7";
23
+ readonly "@angular/core": "^22.1.7";
24
+ readonly "@angular/forms": "^22.1.7";
25
+ readonly "@angular/platform-browser": "^22.1.7";
26
+ readonly "@angular/router": "^22.1.7";
27
+ readonly "@astrojs/check": "^0.9.10";
28
+ readonly "@ngrx/store": "^22.0.1";
29
+ readonly "@prisma/adapter-pg": "^7.10.0";
30
+ readonly "@prisma/client": "^7.10.0";
31
+ readonly "@sveltejs/adapter-auto": "^7.0.1";
32
+ readonly "@sveltejs/kit": "^2.70.3";
33
+ readonly "@sveltejs/vite-plugin-svelte": "^7.3.1";
34
+ readonly "@testing-library/dom": "^10.4.2";
35
+ readonly "@testing-library/jest-dom": "^7.0.1";
36
+ readonly "@testing-library/react": "^16.3.3";
37
+ readonly "@testing-library/react-native": "^14.0.1";
38
+ readonly "@testing-library/svelte": "^5.4.2";
39
+ readonly "@testing-library/user-event": "^14.6.7";
40
+ readonly "@tsconfig/svelte": "^5.0.8";
41
+ readonly "@types/node": "^26.6.2";
42
+ readonly "@types/react": "^19.3.0";
43
+ readonly "@types/react-dom": "^19.3.0";
44
+ readonly "@types/ws": "^8.18.1";
45
+ readonly "@vitejs/plugin-react": "^6.1.1";
46
+ readonly "@vitejs/plugin-vue": "^6.0.9";
47
+ readonly "@vue/test-utils": "^2.5.1";
48
+ readonly "@vue/tsconfig": "^0.9.1";
49
+ readonly astro: "^7.3.4";
50
+ readonly eslint: "^10.11.0";
51
+ readonly "eslint-plugin-react-hooks": "^7.1.1";
52
+ readonly "eslint-plugin-react-refresh": "^0.5.7";
53
+ readonly "eslint-plugin-svelte": "^3.23.0";
54
+ readonly "eslint-plugin-vue": "^10.11.0";
55
+ readonly jest: "^30.5.2";
56
+ readonly jsdom: "^30.1.1";
57
+ readonly next: "^16.3.6";
58
+ readonly nodemailer: "^10.0.10";
59
+ readonly nuxt: "^4.5.2";
60
+ readonly pinia: "^4.0.3";
61
+ readonly prettier: "^3.9.9";
62
+ readonly prisma: "^7.10.0";
63
+ readonly "prettier-plugin-svelte": "^4.1.1";
64
+ readonly react: "^19.3.0";
65
+ readonly "react-dom": "^19.3.0";
66
+ readonly redis: "^6.2.1";
67
+ readonly rxjs: "~7.8.2";
68
+ readonly svelte: "^5.57.1";
69
+ readonly "svelte-check": "^4.7.6";
70
+ readonly tslib: "^2.8.1";
71
+ readonly tsx: "^4.23.15";
72
+ readonly "typescript-eslint": "^8.70.1";
73
+ readonly vite: "^8.3.0";
74
+ readonly vitest: "^5.0.1";
75
+ readonly vue: "^3.5.43";
76
+ readonly "vue-router": "^5.3.1";
77
+ readonly "vue-tsc": "^3.3.11";
78
+ readonly ws: "^8.21.3";
79
+ readonly zustand: "^5.0.15";
80
+ }>;
81
+ /**
82
+ * TypeScript ranges, split by where the compiler runs.
83
+ *
84
+ * Backend templates only run `tsc` and `tsx`, so they get TypeScript 7.
85
+ * Frontend toolchains call the TypeScript 6 JavaScript API and declare it
86
+ * as a peer: `@angular/compiler-cli` and `@angular/build` need
87
+ * `>=6.0 <6.1`, `typescript-eslint` needs `<6.1.0`, and `@sveltejs/kit`,
88
+ * `svelte-check` and `@astrojs/check` need `^5 || ^6`. The frontend range is
89
+ * therefore a tilde range on 6.0 — do not raise it to 7 until those peer
90
+ * ranges admit it.
91
+ */
92
+ export declare const TYPESCRIPT_VERSION_RANGES: Readonly<{
93
+ readonly backend: "^7.0.2";
94
+ readonly frontend: "~6.0.3";
95
+ }>;
96
+ /**
97
+ * Vitest range for Angular projects. `@angular/build:unit-test` declares
98
+ * `vitest` `^4.0.8` as a peer, so Angular cannot take the Vitest 5 range the
99
+ * other frameworks use.
100
+ */
101
+ export declare const ANGULAR_VITEST_VERSION_RANGE = "^4.1.11";
102
+ /**
103
+ * Default ranges the dependency resolver applies to requirements that carry
104
+ * no version of their own.
10
105
  */
11
106
  export declare const DEFAULT_DEPENDENCY_VERSIONS: ReadonlyMap<string, string>;
12
107
  //# sourceMappingURL=dependencyVersions.constant.d.ts.map