nestjs-ddd-cli 3.2.1 → 3.3.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 (214) hide show
  1. package/README.md +118 -9
  2. package/ddd.schema.json +11 -1
  3. package/dist/commands/doctor-enhanced.d.ts +1 -0
  4. package/dist/commands/doctor-enhanced.js +94 -79
  5. package/dist/commands/doctor-enhanced.js.map +1 -1
  6. package/dist/commands/doctor.d.ts +9 -0
  7. package/dist/commands/doctor.js +68 -21
  8. package/dist/commands/doctor.js.map +1 -1
  9. package/dist/commands/generate-all.js +238 -176
  10. package/dist/commands/generate-all.js.map +1 -1
  11. package/dist/commands/generate-controller.d.ts +1 -0
  12. package/dist/commands/generate-controller.js +71 -0
  13. package/dist/commands/generate-controller.js.map +1 -0
  14. package/dist/commands/generate-domain-service.d.ts +1 -1
  15. package/dist/commands/generate-domain-service.js +6 -4
  16. package/dist/commands/generate-domain-service.js.map +1 -1
  17. package/dist/commands/generate-dto.d.ts +4 -0
  18. package/dist/commands/generate-dto.js +162 -0
  19. package/dist/commands/generate-dto.js.map +1 -0
  20. package/dist/commands/generate-entity.js +44 -35
  21. package/dist/commands/generate-entity.js.map +1 -1
  22. package/dist/commands/generate-event.js +10 -4
  23. package/dist/commands/generate-event.js.map +1 -1
  24. package/dist/commands/generate-migration-deployment.d.ts +15 -0
  25. package/dist/commands/generate-migration-deployment.js +326 -0
  26. package/dist/commands/generate-migration-deployment.js.map +1 -0
  27. package/dist/commands/generate-migration-deployment.spec.d.ts +1 -0
  28. package/dist/commands/generate-migration-deployment.spec.js +337 -0
  29. package/dist/commands/generate-migration-deployment.spec.js.map +1 -0
  30. package/dist/commands/generate-module.js +41 -31
  31. package/dist/commands/generate-module.js.map +1 -1
  32. package/dist/commands/generate-query.js +23 -4
  33. package/dist/commands/generate-query.js.map +1 -1
  34. package/dist/commands/generate-repository.d.ts +1 -1
  35. package/dist/commands/generate-repository.js +17 -34
  36. package/dist/commands/generate-repository.js.map +1 -1
  37. package/dist/commands/generate-service.js +19 -4
  38. package/dist/commands/generate-service.js.map +1 -1
  39. package/dist/commands/generate-usecase.js +12 -31
  40. package/dist/commands/generate-usecase.js.map +1 -1
  41. package/dist/commands/generate-value-object.js +3 -14
  42. package/dist/commands/generate-value-object.js.map +1 -1
  43. package/dist/commands/init-project.d.ts +3 -0
  44. package/dist/commands/init-project.js +19 -9
  45. package/dist/commands/init-project.js.map +1 -1
  46. package/dist/commands/interactive-scaffold.js +10 -0
  47. package/dist/commands/interactive-scaffold.js.map +1 -1
  48. package/dist/commands/migration.d.ts +3 -0
  49. package/dist/commands/migration.js +83 -48
  50. package/dist/commands/migration.js.map +1 -1
  51. package/dist/commands/recipe.d.ts +2 -0
  52. package/dist/commands/recipe.js +282 -91
  53. package/dist/commands/recipe.js.map +1 -1
  54. package/dist/commands/recipes/banklink-connector-contract.recipe.d.ts +1 -0
  55. package/dist/commands/recipes/banklink-connector-contract.recipe.js +161 -0
  56. package/dist/commands/recipes/banklink-connector-contract.recipe.js.map +1 -0
  57. package/dist/commands/recipes/bounded-json-http.recipe.d.ts +2 -0
  58. package/dist/commands/recipes/bounded-json-http.recipe.js +53 -0
  59. package/dist/commands/recipes/bounded-json-http.recipe.js.map +1 -0
  60. package/dist/commands/recipes/business-reference-identifiers.recipe.d.ts +1 -0
  61. package/dist/commands/recipes/business-reference-identifiers.recipe.js +223 -0
  62. package/dist/commands/recipes/business-reference-identifiers.recipe.js.map +1 -0
  63. package/dist/commands/recipes/event-backbone.recipe.d.ts +1 -0
  64. package/dist/commands/recipes/event-backbone.recipe.js +1118 -0
  65. package/dist/commands/recipes/event-backbone.recipe.js.map +1 -0
  66. package/dist/commands/recipes/external-projection-worker.recipe.d.ts +6 -0
  67. package/dist/commands/recipes/external-projection-worker.recipe.js +211 -0
  68. package/dist/commands/recipes/external-projection-worker.recipe.js.map +1 -0
  69. package/dist/commands/recipes/index.d.ts +12 -0
  70. package/dist/commands/recipes/index.js +12 -0
  71. package/dist/commands/recipes/index.js.map +1 -1
  72. package/dist/commands/recipes/jest-cjs-compat.recipe.d.ts +3 -0
  73. package/dist/commands/recipes/jest-cjs-compat.recipe.js +130 -0
  74. package/dist/commands/recipes/jest-cjs-compat.recipe.js.map +1 -0
  75. package/dist/commands/recipes/joi-env.recipe.d.ts +1 -0
  76. package/dist/commands/recipes/joi-env.recipe.js +301 -0
  77. package/dist/commands/recipes/joi-env.recipe.js.map +1 -0
  78. package/dist/commands/recipes/kafka-consumer.recipe.d.ts +1 -0
  79. package/dist/commands/recipes/kafka-consumer.recipe.js +65 -0
  80. package/dist/commands/recipes/kafka-consumer.recipe.js.map +1 -0
  81. package/dist/commands/recipes/oauth2-client-credentials.recipe.d.ts +1 -0
  82. package/dist/commands/recipes/oauth2-client-credentials.recipe.js +60 -0
  83. package/dist/commands/recipes/oauth2-client-credentials.recipe.js.map +1 -0
  84. package/dist/commands/recipes/oauth2-token-introspection.recipe.d.ts +1 -0
  85. package/dist/commands/recipes/oauth2-token-introspection.recipe.js +67 -0
  86. package/dist/commands/recipes/oauth2-token-introspection.recipe.js.map +1 -0
  87. package/dist/commands/recipes/oidc-bff-session.recipe.d.ts +1 -0
  88. package/dist/commands/recipes/oidc-bff-session.recipe.js +57 -0
  89. package/dist/commands/recipes/oidc-bff-session.recipe.js.map +1 -0
  90. package/dist/commands/recipes/oidc-dashboard.recipe.d.ts +1 -0
  91. package/dist/commands/recipes/oidc-dashboard.recipe.js +463 -0
  92. package/dist/commands/recipes/oidc-dashboard.recipe.js.map +1 -0
  93. package/dist/commands/recipes/oidc-resource-server.recipe.d.ts +1 -0
  94. package/dist/commands/recipes/oidc-resource-server.recipe.js +85 -0
  95. package/dist/commands/recipes/oidc-resource-server.recipe.js.map +1 -0
  96. package/dist/commands/recipes/platform-context.recipe.d.ts +1 -0
  97. package/dist/commands/recipes/platform-context.recipe.js +229 -0
  98. package/dist/commands/recipes/platform-context.recipe.js.map +1 -0
  99. package/dist/commands/recipes/platform-parc-authorization.recipe.d.ts +1 -0
  100. package/dist/commands/recipes/platform-parc-authorization.recipe.js +339 -0
  101. package/dist/commands/recipes/platform-parc-authorization.recipe.js.map +1 -0
  102. package/dist/commands/recipes/platform-parc-bound-authorization.recipe.d.ts +1 -0
  103. package/dist/commands/recipes/platform-parc-bound-authorization.recipe.js +56 -0
  104. package/dist/commands/recipes/platform-parc-bound-authorization.recipe.js.map +1 -0
  105. package/dist/commands/recipes/platform-service-access-request-context.recipe.d.ts +1 -0
  106. package/dist/commands/recipes/platform-service-access-request-context.recipe.js +103 -0
  107. package/dist/commands/recipes/platform-service-access-request-context.recipe.js.map +1 -0
  108. package/dist/commands/recipes/platform-service-runtime.recipe.d.ts +1 -0
  109. package/dist/commands/recipes/platform-service-runtime.recipe.js +415 -0
  110. package/dist/commands/recipes/platform-service-runtime.recipe.js.map +1 -0
  111. package/dist/index.js +82 -11
  112. package/dist/index.js.map +1 -1
  113. package/dist/templates/ai-context/CLAUDE.md.hbs +54 -3
  114. package/dist/templates/ai-context/conventions.md.hbs +20 -8
  115. package/dist/templates/command/create-command.hbs +8 -3
  116. package/dist/templates/command/delete-command.hbs +1 -1
  117. package/dist/templates/command/update-command.hbs +1 -1
  118. package/dist/templates/controller/application-controller.hbs +7 -0
  119. package/dist/templates/controller/controller.hbs +6 -0
  120. package/dist/templates/dto/create-dto.hbs +17 -5
  121. package/dist/templates/dto/filter-dto.hbs +1 -1
  122. package/dist/templates/dto/response-dto.hbs +1 -1
  123. package/dist/templates/entity/entity.hbs +4 -0
  124. package/dist/templates/mapper/mapper.hbs +6 -2
  125. package/dist/templates/orm-entity/orm-entity.hbs +9 -1
  126. package/dist/templates/prisma/prisma-mapper.hbs +6 -0
  127. package/dist/templates/prisma/prisma-repository.hbs +57 -5
  128. package/dist/templates/prisma/prisma-schema.hbs +2 -0
  129. package/dist/templates/query/get-all.query.hbs +10 -2
  130. package/dist/templates/recipes/bounded-json-http/README.md.hbs +36 -0
  131. package/dist/templates/recipes/external-projection-worker/README.md.hbs +157 -0
  132. package/dist/templates/recipes/external-projection-worker/canonical-json.ts.hbs +123 -0
  133. package/dist/templates/recipes/external-projection-worker/enqueuer.ts.hbs +167 -0
  134. package/dist/templates/recipes/external-projection-worker/index.ts.hbs +6 -0
  135. package/dist/templates/recipes/external-projection-worker/migration.ts.hbs +88 -0
  136. package/dist/templates/recipes/external-projection-worker/module.ts.hbs +36 -0
  137. package/dist/templates/recipes/external-projection-worker/store.ts.hbs +354 -0
  138. package/dist/templates/recipes/external-projection-worker/types.ts.hbs +134 -0
  139. package/dist/templates/recipes/external-projection-worker/worker.ts.hbs +296 -0
  140. package/dist/templates/recipes/kafka-consumer/README.md.hbs +50 -0
  141. package/dist/templates/recipes/kafka-consumer/kafka-consumer.ts.hbs +135 -0
  142. package/dist/templates/recipes/kafka-consumer/migration.ts.hbs +17 -0
  143. package/dist/templates/recipes/oauth2-client-credentials/README.md.hbs +40 -0
  144. package/dist/templates/recipes/oauth2-client-credentials/client.spec.ts.hbs +234 -0
  145. package/dist/templates/recipes/oauth2-client-credentials/client.ts.hbs +210 -0
  146. package/dist/templates/recipes/oauth2-client-credentials/index.ts.hbs +2 -0
  147. package/dist/templates/recipes/oauth2-client-credentials/module.ts.hbs +58 -0
  148. package/dist/templates/recipes/oauth2-token-introspection/README.md.hbs +158 -0
  149. package/dist/templates/recipes/oauth2-token-introspection/client.spec.ts.hbs +350 -0
  150. package/dist/templates/recipes/oauth2-token-introspection/client.ts.hbs +241 -0
  151. package/dist/templates/recipes/oauth2-token-introspection/http-client.spec.ts.hbs +411 -0
  152. package/dist/templates/recipes/oauth2-token-introspection/http-client.ts.hbs +343 -0
  153. package/dist/templates/recipes/oauth2-token-introspection/index.ts.hbs +3 -0
  154. package/dist/templates/recipes/oauth2-token-introspection/module.ts.hbs +58 -0
  155. package/dist/templates/recipes/oidc-bff-session/README.md.hbs +96 -0
  156. package/dist/templates/recipes/oidc-bff-session/client.test.ts.hbs +663 -0
  157. package/dist/templates/recipes/oidc-bff-session/client.ts.hbs +635 -0
  158. package/dist/templates/recipes/oidc-bff-session/index.ts.hbs +3 -0
  159. package/dist/templates/recipes/oidc-bff-session/store.integration.test.ts.hbs +480 -0
  160. package/dist/templates/recipes/oidc-bff-session/store.test.ts.hbs +87 -0
  161. package/dist/templates/recipes/oidc-bff-session/store.ts.hbs +549 -0
  162. package/dist/templates/recipes/oidc-bff-session/valkey.test.ts.hbs +158 -0
  163. package/dist/templates/recipes/oidc-bff-session/valkey.ts.hbs +148 -0
  164. package/dist/templates/recipes/oidc-resource-server/README.md.hbs +74 -0
  165. package/dist/templates/recipes/oidc-resource-server/index.ts.hbs +2 -0
  166. package/dist/templates/recipes/oidc-resource-server/module.ts.hbs +51 -0
  167. package/dist/templates/recipes/oidc-resource-server/verifier.spec.ts.hbs +186 -0
  168. package/dist/templates/recipes/oidc-resource-server/verifier.ts.hbs +440 -0
  169. package/dist/templates/recipes/platform-parc-bound-authorization/README.md.hbs +92 -0
  170. package/dist/templates/recipes/platform-parc-bound-authorization/client.ts.hbs +142 -0
  171. package/dist/templates/recipes/platform-service-access-request-context/docs.md.hbs +61 -0
  172. package/dist/templates/recipes/platform-service-access-request-context/env.example.hbs +7 -0
  173. package/dist/templates/recipes/platform-service-access-request-context/index.ts.hbs +7 -0
  174. package/dist/templates/recipes/platform-service-access-request-context/request-context-headers.ts.hbs +61 -0
  175. package/dist/templates/recipes/platform-service-access-request-context/request-context-introspection.parser.ts.hbs +132 -0
  176. package/dist/templates/recipes/platform-service-access-request-context/request-context-introspection.types.ts.hbs +40 -0
  177. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.client.ts.hbs +45 -0
  178. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.config.ts.hbs +142 -0
  179. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.guard.ts.hbs +77 -0
  180. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.module.ts.hbs +17 -0
  181. package/dist/templates/repository/repository.hbs +43 -5
  182. package/dist/templates/resolver/graphql-input.hbs +23 -6
  183. package/dist/templates/resolver/resolver.hbs +4 -0
  184. package/dist/templates/service/domain-service.hbs +2 -2
  185. package/dist/templates/test/controller.spec.hbs +5 -1
  186. package/dist/templates/test/prisma-repository.spec.hbs +192 -0
  187. package/dist/templates/test/repository.spec.hbs +41 -2
  188. package/dist/templates/test/usecase.spec.hbs +24 -5
  189. package/dist/templates/usecase/application-usecase.hbs +17 -0
  190. package/dist/templates/usecase/create-usecase.hbs +34 -3
  191. package/dist/templates/usecase/update-usecase.hbs +15 -1
  192. package/dist/utils/config.utils.d.ts +2 -0
  193. package/dist/utils/config.utils.js +14 -2
  194. package/dist/utils/config.utils.js.map +1 -1
  195. package/dist/utils/dependency.utils.d.ts +18 -2
  196. package/dist/utils/dependency.utils.js +144 -15
  197. package/dist/utils/dependency.utils.js.map +1 -1
  198. package/dist/utils/field.utils.d.ts +6 -0
  199. package/dist/utils/field.utils.js +78 -24
  200. package/dist/utils/field.utils.js.map +1 -1
  201. package/dist/utils/field.utils.spec.d.ts +1 -0
  202. package/dist/utils/field.utils.spec.js +38 -0
  203. package/dist/utils/field.utils.spec.js.map +1 -0
  204. package/dist/utils/file.utils.d.ts +39 -3
  205. package/dist/utils/file.utils.js +150 -13
  206. package/dist/utils/file.utils.js.map +1 -1
  207. package/dist/utils/naming.utils.js +5 -4
  208. package/dist/utils/naming.utils.js.map +1 -1
  209. package/dist/utils/static-recipe.utils.d.ts +4 -0
  210. package/dist/utils/static-recipe.utils.js +148 -0
  211. package/dist/utils/static-recipe.utils.js.map +1 -0
  212. package/dist/utils/template-engine.utils.js +83 -68
  213. package/dist/utils/template-engine.utils.js.map +1 -1
  214. package/package.json +20 -11
@@ -0,0 +1,15 @@
1
+ export interface MigrationDeploymentOptions {
2
+ path?: string;
3
+ appName?: string;
4
+ image?: string;
5
+ databaseSecret?: string;
6
+ databaseUrlKey?: string;
7
+ configMap?: string;
8
+ databaseSslKey?: string;
9
+ databaseSslCaSecret?: string;
10
+ databaseSslCaKey?: string;
11
+ databaseSslInsecureSkipVerify?: boolean;
12
+ imagePullSecret?: string;
13
+ dryRun?: boolean;
14
+ }
15
+ export declare function generateMigrationDeployment(options: MigrationDeploymentOptions): Promise<void>;
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.generateMigrationDeployment = generateMigrationDeployment;
40
+ const fs = __importStar(require("fs-extra"));
41
+ const path = __importStar(require("node:path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const file_utils_1 = require("../utils/file.utils");
44
+ const migration_1 = require("./migration");
45
+ const config_utils_1 = require("../utils/config.utils");
46
+ const DNS_LABEL = /^[a-z0-9](?:[-a-z0-9]*[a-z0-9])?$/;
47
+ const SECRET_KEY = /^[A-Za-z_][A-Za-z0-9_.-]*$/;
48
+ const IMMUTABLE_IMAGE = /^[A-Za-z0-9][A-Za-z0-9._/:-]*@sha256:[a-f0-9]{64}$/;
49
+ async function generateMigrationDeployment(options) {
50
+ const resolved = await resolveOptions(options);
51
+ const runnerPath = path.join(resolved.basePath, 'src', 'migration-runner.ts');
52
+ const jobPath = path.join(resolved.basePath, 'k8s', 'migration-job.yaml');
53
+ await assertSafeOutput(runnerPath, resolved.dryRun);
54
+ await assertSafeOutput(jobPath, resolved.dryRun);
55
+ if (!resolved.dryRun) {
56
+ await (0, file_utils_1.ensureDir)(path.dirname(runnerPath));
57
+ await (0, file_utils_1.ensureDir)(path.dirname(jobPath));
58
+ }
59
+ await (0, file_utils_1.writeGeneratedFile)(runnerPath, renderMigrationRunner(resolved.migrationRuntimeDirectory), resolved.dryRun);
60
+ await (0, file_utils_1.writeGeneratedFile)(jobPath, renderMigrationJob(resolved), resolved.dryRun);
61
+ const verb = resolved.dryRun ? 'Would generate' : 'Generated';
62
+ console.log(chalk_1.default.green(` ✓ ${verb} src/migration-runner.ts`));
63
+ console.log(chalk_1.default.green(` ✓ ${verb} k8s/migration-job.yaml`));
64
+ }
65
+ async function resolveOptions(options) {
66
+ const basePath = path.resolve(options.path ?? process.cwd());
67
+ const packageJsonPath = path.join(basePath, 'package.json');
68
+ const packageJson = (await fs.readJson(packageJsonPath));
69
+ const appName = options.appName ?? (typeof packageJson.name === 'string' ? packageJson.name : undefined);
70
+ if (!appName || !isDnsLabel(appName)) {
71
+ throw new Error('Migration deployment requires a DNS-label-safe --app-name');
72
+ }
73
+ if (!options.image || !IMMUTABLE_IMAGE.test(options.image)) {
74
+ throw new Error('Migration deployment --image must be pinned by sha256 digest');
75
+ }
76
+ const databaseSecret = options.databaseSecret ?? `${appName}-secrets`;
77
+ validateDnsLabel(databaseSecret, '--database-secret');
78
+ const databaseUrlKey = options.databaseUrlKey ?? 'DATABASE_URL';
79
+ validateSecretKey(databaseUrlKey, '--database-url-key');
80
+ const databaseSslKey = options.databaseSslKey ?? 'DATABASE_SSL';
81
+ validateSecretKey(databaseSslKey, '--database-ssl-key');
82
+ if (options.configMap) {
83
+ validateDnsLabel(options.configMap, '--config-map');
84
+ }
85
+ if (options.imagePullSecret) {
86
+ validateDnsLabel(options.imagePullSecret, '--image-pull-secret');
87
+ }
88
+ const databaseSslCaSecret = options.databaseSslCaSecret;
89
+ const databaseSslCaKey = options.databaseSslCaKey ?? 'DATABASE_SSL_CA';
90
+ if (databaseSslCaSecret) {
91
+ validateDnsLabel(databaseSslCaSecret, '--database-ssl-ca-secret');
92
+ validateSecretKey(databaseSslCaKey, '--database-ssl-ca-key');
93
+ }
94
+ else if (options.databaseSslCaKey) {
95
+ throw new Error('--database-ssl-ca-key requires --database-ssl-ca-secret');
96
+ }
97
+ const databaseSslInsecureSkipVerify = options.databaseSslInsecureSkipVerify ?? false;
98
+ if (databaseSslCaSecret && databaseSslInsecureSkipVerify) {
99
+ throw new Error('--database-ssl-ca-secret cannot be combined with --database-ssl-insecure-skip-verify');
100
+ }
101
+ if ((databaseSslCaSecret || databaseSslInsecureSkipVerify) && !options.configMap) {
102
+ throw new Error('--config-map is required when configuring a database CA or insecure TLS opt-in');
103
+ }
104
+ const config = await (0, config_utils_1.loadConfig)(basePath);
105
+ const configuredMigrationPath = config.paths?.migrations;
106
+ if (typeof configuredMigrationPath !== 'string' ||
107
+ configuredMigrationPath.trim().length === 0 ||
108
+ /[\0*?{}[\]]/.test(configuredMigrationPath)) {
109
+ throw new Error('.dddrc.json paths.migrations must be a non-empty directory path');
110
+ }
111
+ const migrationSourceDirectory = (0, migration_1.resolveMigrationOutputPath)(basePath, configuredMigrationPath, 'src/migrations');
112
+ const migrationRuntimeDirectory = resolveCompiledMigrationRuntimeDirectory(basePath, migrationSourceDirectory);
113
+ return {
114
+ basePath,
115
+ appName,
116
+ image: options.image,
117
+ databaseSecret,
118
+ databaseUrlKey,
119
+ configMap: options.configMap,
120
+ databaseSslKey,
121
+ databaseSslCaSecret,
122
+ databaseSslCaKey,
123
+ databaseSslInsecureSkipVerify,
124
+ imagePullSecret: options.imagePullSecret,
125
+ migrationRuntimeDirectory,
126
+ dryRun: options.dryRun ?? false,
127
+ };
128
+ }
129
+ function resolveCompiledMigrationRuntimeDirectory(basePath, migrationSourceDirectory) {
130
+ const sourceRoot = findOwningSourceRoot(migrationSourceDirectory);
131
+ if (!sourceRoot) {
132
+ throw new Error('.dddrc.json paths.migrations must be inside a source directory named "src"');
133
+ }
134
+ const compiledMigrationDirectory = path.join(path.dirname(sourceRoot), 'dist', path.relative(sourceRoot, migrationSourceDirectory));
135
+ const compiledRunnerDirectory = path.join(basePath, 'dist');
136
+ const relativeRuntimeDirectory = path.relative(compiledRunnerDirectory, compiledMigrationDirectory);
137
+ return (relativeRuntimeDirectory || '.').split(path.sep).join('/');
138
+ }
139
+ function findOwningSourceRoot(migrationSourceDirectory) {
140
+ let current = path.resolve(migrationSourceDirectory);
141
+ while (true) {
142
+ if (path.basename(current) === 'src') {
143
+ return current;
144
+ }
145
+ const parent = path.dirname(current);
146
+ if (parent === current) {
147
+ return undefined;
148
+ }
149
+ current = parent;
150
+ }
151
+ }
152
+ function isDnsLabel(value) {
153
+ return value.length <= 63 && DNS_LABEL.test(value);
154
+ }
155
+ function validateDnsLabel(value, optionName) {
156
+ if (!isDnsLabel(value)) {
157
+ throw new Error(`${optionName} must be a valid Kubernetes DNS label`);
158
+ }
159
+ }
160
+ function validateSecretKey(value, optionName) {
161
+ if (value.length > 253 || !SECRET_KEY.test(value)) {
162
+ throw new Error(`${optionName} must be a valid Kubernetes Secret or ConfigMap key`);
163
+ }
164
+ }
165
+ async function assertSafeOutput(filePath, dryRun) {
166
+ if (!dryRun && (await (0, file_utils_1.fileExists)(filePath))) {
167
+ throw new Error(`Refusing to overwrite existing migration deployment file: ${filePath}`);
168
+ }
169
+ }
170
+ function renderMigrationRunner(migrationRuntimeDirectory) {
171
+ const serializedRuntimeDirectory = JSON.stringify(migrationRuntimeDirectory);
172
+ return `import 'reflect-metadata';
173
+ import * as path from 'node:path';
174
+ import { DataSource, DataSourceOptions } from 'typeorm';
175
+
176
+ export type MigrationEnvironment = Readonly<Record<string, string | undefined>>;
177
+
178
+ export function createMigrationDataSourceOptions(
179
+ environment: MigrationEnvironment = process.env,
180
+ ): DataSourceOptions {
181
+ const databaseUrl = environment.DATABASE_URL?.trim();
182
+ if (!databaseUrl) {
183
+ throw new Error('DATABASE_URL is required to run migrations');
184
+ }
185
+
186
+ const sslEnabled = parseBoolean(environment.DATABASE_SSL ?? 'false', 'DATABASE_SSL');
187
+ const insecureSkipVerify = parseBoolean(
188
+ environment.DATABASE_SSL_INSECURE_SKIP_VERIFY ?? 'false',
189
+ 'DATABASE_SSL_INSECURE_SKIP_VERIFY',
190
+ );
191
+ const certificateAuthority = environment.DATABASE_SSL_CA?.trim();
192
+
193
+ if (!sslEnabled && (insecureSkipVerify || certificateAuthority)) {
194
+ throw new Error(
195
+ 'DATABASE_SSL must be true when DATABASE_SSL_INSECURE_SKIP_VERIFY or DATABASE_SSL_CA is set',
196
+ );
197
+ }
198
+ if (insecureSkipVerify && certificateAuthority) {
199
+ throw new Error(
200
+ 'DATABASE_SSL_CA cannot be combined with DATABASE_SSL_INSECURE_SKIP_VERIFY=true',
201
+ );
202
+ }
203
+
204
+ const ssl = sslEnabled
205
+ ? {
206
+ rejectUnauthorized: !insecureSkipVerify,
207
+ ...(certificateAuthority ? { ca: certificateAuthority } : {}),
208
+ }
209
+ : false;
210
+
211
+ return {
212
+ type: 'postgres',
213
+ url: databaseUrl,
214
+ ssl,
215
+ synchronize: false,
216
+ migrationsRun: false,
217
+ migrationsTableName: 'migrations',
218
+ migrations: [path.resolve(__dirname, ${serializedRuntimeDirectory}, '*.js')],
219
+ };
220
+ }
221
+
222
+ export async function runMigrations(dataSource: DataSource): Promise<void> {
223
+ await dataSource.initialize();
224
+ try {
225
+ await dataSource.runMigrations({ transaction: 'all' });
226
+ } finally {
227
+ if (dataSource.isInitialized) {
228
+ await dataSource.destroy();
229
+ }
230
+ }
231
+ }
232
+
233
+ function parseBoolean(value: string, name: string): boolean {
234
+ const normalized = value.trim().toLowerCase();
235
+ if (normalized === 'true') return true;
236
+ if (normalized === 'false') return false;
237
+ throw new Error(\`${'${name}'} must be true or false\`);
238
+ }
239
+
240
+ async function main(): Promise<void> {
241
+ const dataSource = new DataSource(createMigrationDataSourceOptions());
242
+ try {
243
+ await runMigrations(dataSource);
244
+ } catch (error: unknown) {
245
+ const message = error instanceof Error ? error.message : 'Unknown migration failure';
246
+ console.error(\`Migration failed: ${'${message}'}\`);
247
+ process.exitCode = 1;
248
+ }
249
+ }
250
+
251
+ if (require.main === module) {
252
+ void main(); // NOSONAR -- CommonJS executable entrypoints cannot use top-level await.
253
+ }
254
+ `;
255
+ }
256
+ function renderMigrationJob(options) {
257
+ const pullSecret = options.imagePullSecret
258
+ ? ` imagePullSecrets:\n - name: ${options.imagePullSecret}\n`
259
+ : '';
260
+ const sslSource = options.configMap
261
+ ? ` - name: DATABASE_SSL\n valueFrom:\n configMapKeyRef:\n name: ${options.configMap}\n key: ${options.databaseSslKey}\n`
262
+ : ` - name: DATABASE_SSL\n value: 'false'\n`;
263
+ const caSource = options.databaseSslCaSecret
264
+ ? ` - name: DATABASE_SSL_CA\n valueFrom:\n secretKeyRef:\n name: ${options.databaseSslCaSecret}\n key: ${options.databaseSslCaKey}\n`
265
+ : '';
266
+ return `apiVersion: batch/v1
267
+ kind: Job
268
+ metadata:
269
+ name: ${options.appName}-migrate
270
+ labels:
271
+ app: ${options.appName}
272
+ app.kubernetes.io/component: database-migration
273
+ annotations:
274
+ argocd.argoproj.io/hook: PreSync
275
+ argocd.argoproj.io/hook-delete-policy: BeforeHookCreation,HookSucceeded
276
+ spec:
277
+ backoffLimit: 2
278
+ activeDeadlineSeconds: 600
279
+ ttlSecondsAfterFinished: 3600
280
+ template:
281
+ metadata:
282
+ labels:
283
+ app: ${options.appName}
284
+ app.kubernetes.io/component: database-migration
285
+ spec:
286
+ automountServiceAccountToken: false
287
+ restartPolicy: Never
288
+ ${pullSecret} securityContext:
289
+ runAsNonRoot: true
290
+ runAsUser: 1001
291
+ runAsGroup: 1001
292
+ seccompProfile:
293
+ type: RuntimeDefault
294
+ containers:
295
+ - name: migrate
296
+ image: ${options.image}
297
+ imagePullPolicy: IfNotPresent
298
+ command:
299
+ - node
300
+ - dist/migration-runner.js
301
+ env:
302
+ - name: DATABASE_URL
303
+ valueFrom:
304
+ secretKeyRef:
305
+ name: ${options.databaseSecret}
306
+ key: ${options.databaseUrlKey}
307
+ ${sslSource} - name: DATABASE_SSL_INSECURE_SKIP_VERIFY
308
+ value: '${options.databaseSslInsecureSkipVerify ? 'true' : 'false'}'
309
+ ${caSource} securityContext:
310
+ allowPrivilegeEscalation: false
311
+ readOnlyRootFilesystem: true
312
+ capabilities:
313
+ drop:
314
+ - ALL
315
+ resources:
316
+ requests:
317
+ cpu: 10m
318
+ memory: 64Mi
319
+ ephemeral-storage: 16Mi
320
+ limits:
321
+ cpu: 250m
322
+ memory: 256Mi
323
+ ephemeral-storage: 128Mi
324
+ `;
325
+ }
326
+ //# sourceMappingURL=generate-migration-deployment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-migration-deployment.js","sourceRoot":"","sources":["../../src/commands/generate-migration-deployment.ts"],"names":[],"mappings":"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"}