@expressots/cli 3.0.0-beta.4 → 4.0.0-preview.2

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 (180) hide show
  1. package/README.md +41 -95
  2. package/bin/cicd/cli.d.ts +6 -0
  3. package/bin/cicd/cli.js +126 -0
  4. package/bin/cicd/form.d.ts +29 -0
  5. package/bin/cicd/form.js +345 -0
  6. package/bin/cicd/generators/azure-devops.d.ts +2 -0
  7. package/bin/cicd/generators/azure-devops.js +370 -0
  8. package/bin/cicd/generators/bitbucket.d.ts +2 -0
  9. package/bin/cicd/generators/bitbucket.js +217 -0
  10. package/bin/cicd/generators/circleci.d.ts +2 -0
  11. package/bin/cicd/generators/circleci.js +274 -0
  12. package/bin/cicd/generators/github-actions.d.ts +14 -0
  13. package/bin/cicd/generators/github-actions.js +426 -0
  14. package/bin/cicd/generators/gitlab-ci.d.ts +2 -0
  15. package/bin/cicd/generators/gitlab-ci.js +237 -0
  16. package/bin/cicd/generators/index.d.ts +6 -0
  17. package/bin/cicd/generators/index.js +15 -0
  18. package/bin/cicd/generators/jenkins.d.ts +2 -0
  19. package/bin/cicd/generators/jenkins.js +248 -0
  20. package/bin/cicd/generators/template-loader.d.ts +17 -0
  21. package/bin/cicd/generators/template-loader.js +128 -0
  22. package/bin/cicd/index.d.ts +1 -0
  23. package/bin/cicd/index.js +5 -0
  24. package/bin/cli.d.ts +1 -1
  25. package/bin/cli.js +18 -3
  26. package/bin/commands/project.commands.d.ts +19 -6
  27. package/bin/commands/project.commands.js +390 -61
  28. package/bin/config/index.d.ts +5 -0
  29. package/bin/config/index.js +10 -0
  30. package/bin/config/manager.d.ts +98 -0
  31. package/bin/config/manager.js +222 -0
  32. package/bin/containerize/analyzers/bootstrap-analyzer.d.ts +46 -0
  33. package/bin/containerize/analyzers/bootstrap-analyzer.js +187 -0
  34. package/bin/containerize/analyzers/project-analyzer.d.ts +20 -0
  35. package/bin/containerize/analyzers/project-analyzer.js +150 -0
  36. package/bin/containerize/cli.d.ts +4 -0
  37. package/bin/containerize/cli.js +113 -0
  38. package/bin/containerize/form.d.ts +15 -0
  39. package/bin/containerize/form.js +154 -0
  40. package/bin/containerize/generators/ci-generator.d.ts +31 -0
  41. package/bin/containerize/generators/ci-generator.js +936 -0
  42. package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
  43. package/bin/containerize/generators/docker-compose-generator.js +186 -0
  44. package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
  45. package/bin/containerize/generators/dockerfile-generator.js +635 -0
  46. package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
  47. package/bin/containerize/generators/kubernetes-generator.js +133 -0
  48. package/bin/containerize/generators/template-loader.d.ts +36 -0
  49. package/bin/containerize/generators/template-loader.js +129 -0
  50. package/bin/containerize/index.d.ts +4 -0
  51. package/bin/containerize/index.js +13 -0
  52. package/bin/containerize/presets/preset-registry.d.ts +20 -0
  53. package/bin/containerize/presets/preset-registry.js +102 -0
  54. package/bin/costs/cli.d.ts +5 -0
  55. package/bin/costs/cli.js +183 -0
  56. package/bin/costs/form.d.ts +44 -0
  57. package/bin/costs/form.js +412 -0
  58. package/bin/costs/index.d.ts +4 -0
  59. package/bin/costs/index.js +25 -0
  60. package/bin/costs/pricing-manager.d.ts +84 -0
  61. package/bin/costs/pricing-manager.js +342 -0
  62. package/bin/costs/providers/index.d.ts +32 -0
  63. package/bin/costs/providers/index.js +153 -0
  64. package/bin/costs/sources/api-source.d.ts +10 -0
  65. package/bin/costs/sources/api-source.js +32 -0
  66. package/bin/costs/sources/index.d.ts +6 -0
  67. package/bin/costs/sources/index.js +15 -0
  68. package/bin/costs/sources/local-json-source.d.ts +23 -0
  69. package/bin/costs/sources/local-json-source.js +59 -0
  70. package/bin/costs/sources/remote-json-source.d.ts +11 -0
  71. package/bin/costs/sources/remote-json-source.js +53 -0
  72. package/bin/costs/types.d.ts +53 -0
  73. package/bin/costs/types.js +5 -0
  74. package/bin/dev/cli.d.ts +4 -0
  75. package/bin/dev/cli.js +134 -0
  76. package/bin/dev/form.d.ts +36 -0
  77. package/bin/dev/form.js +254 -0
  78. package/bin/dev/index.d.ts +1 -0
  79. package/bin/dev/index.js +5 -0
  80. package/bin/generate/cli.js +29 -2
  81. package/bin/generate/form.d.ts +5 -1
  82. package/bin/generate/form.js +3 -3
  83. package/bin/generate/templates/nonopinionated/config.tpl +12 -0
  84. package/bin/generate/templates/nonopinionated/event.tpl +10 -0
  85. package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
  86. package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
  87. package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
  88. package/bin/generate/templates/opinionated/config.tpl +47 -0
  89. package/bin/generate/templates/opinionated/entity.tpl +1 -8
  90. package/bin/generate/templates/opinionated/event.tpl +15 -0
  91. package/bin/generate/templates/opinionated/guard.tpl +41 -0
  92. package/bin/generate/templates/opinionated/handler.tpl +23 -0
  93. package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
  94. package/bin/generate/utils/command-utils.d.ts +7 -3
  95. package/bin/generate/utils/command-utils.js +95 -31
  96. package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
  97. package/bin/generate/utils/nonopininated-cmd.js +100 -1
  98. package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
  99. package/bin/generate/utils/opinionated-cmd.js +112 -7
  100. package/bin/generate/utils/string-utils.d.ts +6 -0
  101. package/bin/generate/utils/string-utils.js +13 -1
  102. package/bin/help/form.js +11 -3
  103. package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
  104. package/bin/migrate/analyzers/platform-detector.js +116 -0
  105. package/bin/migrate/cli.d.ts +6 -0
  106. package/bin/migrate/cli.js +96 -0
  107. package/bin/migrate/form.d.ts +25 -0
  108. package/bin/migrate/form.js +347 -0
  109. package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
  110. package/bin/migrate/generators/compose-to-k8s.js +324 -0
  111. package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
  112. package/bin/migrate/generators/compose-to-railway.js +138 -0
  113. package/bin/migrate/generators/compose-to-render.d.ts +2 -0
  114. package/bin/migrate/generators/compose-to-render.js +148 -0
  115. package/bin/migrate/generators/generic-migration.d.ts +9 -0
  116. package/bin/migrate/generators/generic-migration.js +221 -0
  117. package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
  118. package/bin/migrate/generators/heroku-to-fly.js +291 -0
  119. package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
  120. package/bin/migrate/generators/heroku-to-railway.js +283 -0
  121. package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
  122. package/bin/migrate/generators/heroku-to-render.js +148 -0
  123. package/bin/migrate/generators/index.d.ts +7 -0
  124. package/bin/migrate/generators/index.js +17 -0
  125. package/bin/migrate/generators/template-loader.d.ts +21 -0
  126. package/bin/migrate/generators/template-loader.js +59 -0
  127. package/bin/migrate/index.d.ts +1 -0
  128. package/bin/migrate/index.js +5 -0
  129. package/bin/new/cli.js +21 -6
  130. package/bin/new/form.d.ts +25 -4
  131. package/bin/new/form.js +285 -70
  132. package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
  133. package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
  134. package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
  135. package/bin/profile/analyzers/image-analyzer.js +85 -0
  136. package/bin/profile/cli.d.ts +4 -0
  137. package/bin/profile/cli.js +92 -0
  138. package/bin/profile/form.d.ts +56 -0
  139. package/bin/profile/form.js +400 -0
  140. package/bin/profile/index.d.ts +1 -0
  141. package/bin/profile/index.js +5 -0
  142. package/bin/profile/optimizers/index.d.ts +19 -0
  143. package/bin/profile/optimizers/index.js +137 -0
  144. package/bin/providers/add/form.d.ts +1 -1
  145. package/bin/providers/add/form.js +27 -6
  146. package/bin/providers/create/form.js +2 -1
  147. package/bin/scripts/form.js +27 -5
  148. package/bin/studio/cli.d.ts +15 -0
  149. package/bin/studio/cli.js +166 -0
  150. package/bin/studio/index.d.ts +5 -0
  151. package/bin/studio/index.js +9 -0
  152. package/bin/templates/cache.d.ts +54 -0
  153. package/bin/templates/cache.js +180 -0
  154. package/bin/templates/cli.d.ts +8 -0
  155. package/bin/templates/cli.js +292 -0
  156. package/bin/templates/fetcher.d.ts +49 -0
  157. package/bin/templates/fetcher.js +208 -0
  158. package/bin/templates/index.d.ts +11 -0
  159. package/bin/templates/index.js +37 -0
  160. package/bin/templates/manager.d.ts +116 -0
  161. package/bin/templates/manager.js +323 -0
  162. package/bin/templates/renderer.d.ts +49 -0
  163. package/bin/templates/renderer.js +204 -0
  164. package/bin/templates/types.d.ts +51 -0
  165. package/bin/templates/types.js +5 -0
  166. package/bin/utils/add-module-to-container.d.ts +2 -2
  167. package/bin/utils/add-module-to-container.js +15 -5
  168. package/bin/utils/cli-ui.d.ts +30 -3
  169. package/bin/utils/cli-ui.js +95 -13
  170. package/bin/utils/index.d.ts +4 -0
  171. package/bin/utils/index.js +4 -0
  172. package/bin/utils/input-validation.d.ts +50 -0
  173. package/bin/utils/input-validation.js +143 -0
  174. package/bin/utils/package-manager-commands.d.ts +24 -0
  175. package/bin/utils/package-manager-commands.js +50 -0
  176. package/bin/utils/safe-spawn.d.ts +35 -0
  177. package/bin/utils/safe-spawn.js +51 -0
  178. package/bin/utils/update-tsconfig-paths.d.ts +35 -0
  179. package/bin/utils/update-tsconfig-paths.js +286 -0
  180. package/package.json +154 -154
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.analyzeMigration = exports.listMigrations = exports.generateMigration = exports.initMigration = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const platform_detector_1 = require("./analyzers/platform-detector");
12
+ const generators_1 = require("./generators");
13
+ const SUPPORTED_MIGRATIONS = [
14
+ {
15
+ from: "heroku",
16
+ to: "railway",
17
+ description: "Heroku to Railway",
18
+ complexity: "low",
19
+ },
20
+ {
21
+ from: "heroku",
22
+ to: "render",
23
+ description: "Heroku to Render",
24
+ complexity: "low",
25
+ },
26
+ {
27
+ from: "heroku",
28
+ to: "fly",
29
+ description: "Heroku to Fly.io",
30
+ complexity: "medium",
31
+ },
32
+ {
33
+ from: "heroku",
34
+ to: "kubernetes",
35
+ description: "Heroku to Kubernetes",
36
+ complexity: "high",
37
+ },
38
+ {
39
+ from: "docker-compose",
40
+ to: "kubernetes",
41
+ description: "Docker Compose to Kubernetes",
42
+ complexity: "medium",
43
+ },
44
+ {
45
+ from: "docker-compose",
46
+ to: "railway",
47
+ description: "Docker Compose to Railway",
48
+ complexity: "low",
49
+ },
50
+ {
51
+ from: "docker-compose",
52
+ to: "render",
53
+ description: "Docker Compose to Render",
54
+ complexity: "low",
55
+ },
56
+ {
57
+ from: "docker-compose",
58
+ to: "fly",
59
+ description: "Docker Compose to Fly.io",
60
+ complexity: "medium",
61
+ },
62
+ {
63
+ from: "vercel",
64
+ to: "railway",
65
+ description: "Vercel to Railway",
66
+ complexity: "low",
67
+ },
68
+ {
69
+ from: "vercel",
70
+ to: "render",
71
+ description: "Vercel to Render",
72
+ complexity: "low",
73
+ },
74
+ {
75
+ from: "aws-ecs",
76
+ to: "gcp-cloudrun",
77
+ description: "AWS ECS to GCP Cloud Run",
78
+ complexity: "high",
79
+ },
80
+ {
81
+ from: "aws-ecs",
82
+ to: "kubernetes",
83
+ description: "AWS ECS to Kubernetes",
84
+ complexity: "medium",
85
+ },
86
+ {
87
+ from: "gcp-cloudrun",
88
+ to: "aws-ecs",
89
+ description: "GCP Cloud Run to AWS ECS",
90
+ complexity: "high",
91
+ },
92
+ ];
93
+ /**
94
+ * Interactive migration setup wizard
95
+ */
96
+ async function initMigration(options) {
97
+ console.log(chalk_1.default.cyan("\n🚀 ExpressoTS Migration Wizard\n"));
98
+ // Detect current platform
99
+ const detected = await (0, platform_detector_1.detectCurrentPlatform)();
100
+ if (detected) {
101
+ console.log(chalk_1.default.green(`✓ Detected current platform: ${detected}`));
102
+ }
103
+ // Interactive prompts
104
+ const answers = await inquirer_1.default.prompt([
105
+ {
106
+ type: "list",
107
+ name: "from",
108
+ message: "Select source platform:",
109
+ choices: [
110
+ { name: "Heroku", value: "heroku" },
111
+ { name: "Docker Compose", value: "docker-compose" },
112
+ { name: "Vercel", value: "vercel" },
113
+ { name: "AWS ECS", value: "aws-ecs" },
114
+ { name: "GCP Cloud Run", value: "gcp-cloudrun" },
115
+ { name: "Azure Container Apps", value: "azure-container" },
116
+ ],
117
+ default: detected || "heroku",
118
+ },
119
+ {
120
+ type: "list",
121
+ name: "to",
122
+ message: "Select target platform:",
123
+ choices: (prev) => {
124
+ const migrations = SUPPORTED_MIGRATIONS.filter((m) => m.from === prev.from);
125
+ if (migrations.length === 0) {
126
+ // Show all targets if no specific migrations defined
127
+ return [
128
+ { name: "Railway", value: "railway" },
129
+ { name: "Render", value: "render" },
130
+ { name: "Fly.io", value: "fly" },
131
+ { name: "Kubernetes", value: "kubernetes" },
132
+ { name: "AWS ECS", value: "aws-ecs" },
133
+ { name: "GCP Cloud Run", value: "gcp-cloudrun" },
134
+ ];
135
+ }
136
+ return migrations.map((m) => ({
137
+ name: `${m.to.charAt(0).toUpperCase() + m.to.slice(1)} (${m.complexity} complexity)`,
138
+ value: m.to,
139
+ }));
140
+ },
141
+ },
142
+ {
143
+ type: "confirm",
144
+ name: "includeSecrets",
145
+ message: "Include environment variable migration?",
146
+ default: true,
147
+ },
148
+ {
149
+ type: "confirm",
150
+ name: "includeData",
151
+ message: "Include data migration scripts?",
152
+ default: false,
153
+ },
154
+ {
155
+ type: "input",
156
+ name: "outputDir",
157
+ message: "Output directory for migration files:",
158
+ default: "./migration",
159
+ },
160
+ ]);
161
+ const migrationOptions = {
162
+ ...options,
163
+ from: answers.from,
164
+ to: answers.to,
165
+ includeSecrets: answers.includeSecrets,
166
+ includeData: answers.includeData,
167
+ outputDir: answers.outputDir,
168
+ };
169
+ await generateMigration(migrationOptions);
170
+ }
171
+ exports.initMigration = initMigration;
172
+ /**
173
+ * Generate migration scripts
174
+ */
175
+ async function generateMigration(options) {
176
+ if (!options.from || !options.to) {
177
+ console.log(chalk_1.default.red("Error: Please specify both --from and --to platforms."));
178
+ console.log(chalk_1.default.gray("Use 'expressots migrate list' to see available migrations."));
179
+ return;
180
+ }
181
+ console.log(chalk_1.default.cyan(`\n📦 Generating migration: ${options.from} → ${options.to}\n`));
182
+ // Create output directory
183
+ const outputDir = path_1.default.resolve(options.outputDir);
184
+ if (!options.dryRun) {
185
+ fs_1.default.mkdirSync(outputDir, { recursive: true });
186
+ }
187
+ // Find migration path
188
+ const migration = SUPPORTED_MIGRATIONS.find((m) => m.from === options.from && m.to === options.to);
189
+ if (options.dryRun) {
190
+ console.log(chalk_1.default.yellow("🔍 Dry run mode - showing migration steps:\n"));
191
+ printMigrationSteps(options, migration);
192
+ return;
193
+ }
194
+ // Generate migration files based on source/target
195
+ try {
196
+ await generateMigrationFiles(options, outputDir, migration);
197
+ console.log(chalk_1.default.green(`\n✅ Migration files generated in ${outputDir}\n`));
198
+ printNextSteps(options);
199
+ }
200
+ catch (error) {
201
+ console.log(chalk_1.default.red(`Error generating migration: ${error}`));
202
+ }
203
+ }
204
+ exports.generateMigration = generateMigration;
205
+ /**
206
+ * List available migrations
207
+ */
208
+ async function listMigrations() {
209
+ console.log(chalk_1.default.cyan("\n📋 Available Migration Paths\n"));
210
+ // Group by source
211
+ const bySource = SUPPORTED_MIGRATIONS.reduce((acc, m) => {
212
+ if (!acc[m.from])
213
+ acc[m.from] = [];
214
+ acc[m.from].push(m);
215
+ return acc;
216
+ }, {});
217
+ for (const [source, migrations] of Object.entries(bySource)) {
218
+ console.log(chalk_1.default.bold(`\nFrom ${source}:`));
219
+ for (const m of migrations) {
220
+ const complexityColor = m.complexity === "low"
221
+ ? chalk_1.default.green
222
+ : m.complexity === "medium"
223
+ ? chalk_1.default.yellow
224
+ : chalk_1.default.red;
225
+ console.log(` → ${m.to.padEnd(20)} ${complexityColor(`[${m.complexity}]`)}`);
226
+ }
227
+ }
228
+ console.log(chalk_1.default.gray("\n\nUsage: expressots migrate generate --from <source> --to <target>"));
229
+ console.log(chalk_1.default.gray(" expressots migrate init (interactive wizard)\n"));
230
+ }
231
+ exports.listMigrations = listMigrations;
232
+ /**
233
+ * Analyze migration complexity
234
+ */
235
+ async function analyzeMigration(options) {
236
+ console.log(chalk_1.default.cyan("\n🔍 Migration Analysis\n"));
237
+ const detected = await (0, platform_detector_1.detectCurrentPlatform)();
238
+ const cwd = process.cwd();
239
+ console.log(chalk_1.default.bold("Current Setup:"));
240
+ console.log(` Platform: ${detected || "Unknown"}`);
241
+ // Analyze project files
242
+ const hasDockerfile = fs_1.default.existsSync(path_1.default.join(cwd, "Dockerfile"));
243
+ const hasDockerCompose = fs_1.default.existsSync(path_1.default.join(cwd, "docker-compose.yml"));
244
+ const hasK8s = fs_1.default.existsSync(path_1.default.join(cwd, "k8s"));
245
+ const hasProcfile = fs_1.default.existsSync(path_1.default.join(cwd, "Procfile"));
246
+ const hasVercelConfig = fs_1.default.existsSync(path_1.default.join(cwd, "vercel.json"));
247
+ const hasRailwayConfig = fs_1.default.existsSync(path_1.default.join(cwd, "railway.json"));
248
+ console.log(` Dockerfile: ${hasDockerfile ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
249
+ console.log(` Docker Compose: ${hasDockerCompose ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
250
+ console.log(` Kubernetes: ${hasK8s ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
251
+ console.log(` Procfile (Heroku): ${hasProcfile ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
252
+ console.log(` Vercel Config: ${hasVercelConfig ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
253
+ console.log(` Railway Config: ${hasRailwayConfig ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
254
+ // Check for environment variables
255
+ const hasEnvFile = fs_1.default.existsSync(path_1.default.join(cwd, ".env"));
256
+ const hasEnvExample = fs_1.default.existsSync(path_1.default.join(cwd, ".env.example"));
257
+ console.log(chalk_1.default.bold("\nEnvironment:"));
258
+ console.log(` .env file: ${hasEnvFile ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
259
+ console.log(` .env.example: ${hasEnvExample ? chalk_1.default.green("✓") : chalk_1.default.gray("✗")}`);
260
+ // Analyze package.json for dependencies
261
+ const packageJsonPath = path_1.default.join(cwd, "package.json");
262
+ if (fs_1.default.existsSync(packageJsonPath)) {
263
+ const pkg = JSON.parse(fs_1.default.readFileSync(packageJsonPath, "utf-8"));
264
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
265
+ console.log(chalk_1.default.bold("\nDependencies:"));
266
+ if (deps.pg || deps.postgres)
267
+ console.log(" Database: PostgreSQL");
268
+ if (deps.mysql || deps.mysql2)
269
+ console.log(" Database: MySQL");
270
+ if (deps.mongodb)
271
+ console.log(" Database: MongoDB");
272
+ if (deps.redis || deps.ioredis)
273
+ console.log(" Cache: Redis");
274
+ }
275
+ if (options.to) {
276
+ const migration = SUPPORTED_MIGRATIONS.find((m) => m.from === (detected || options.from) && m.to === options.to);
277
+ if (migration) {
278
+ console.log(chalk_1.default.bold(`\nMigration to ${options.to}:`));
279
+ console.log(` Complexity: ${migration.complexity}`);
280
+ console.log(` Description: ${migration.description}`);
281
+ }
282
+ }
283
+ console.log();
284
+ }
285
+ exports.analyzeMigration = analyzeMigration;
286
+ /**
287
+ * Generate migration files based on source/target
288
+ */
289
+ async function generateMigrationFiles(options, outputDir, migration) {
290
+ const { from, to } = options;
291
+ // Generate based on migration path
292
+ if (from === "heroku" && to === "railway") {
293
+ await (0, generators_1.generateHerokuToRailway)(outputDir, options);
294
+ }
295
+ else if (from === "heroku" && to === "render") {
296
+ await (0, generators_1.generateHerokuToRender)(outputDir, options);
297
+ }
298
+ else if (from === "heroku" && to === "fly") {
299
+ await (0, generators_1.generateHerokuToFly)(outputDir, options);
300
+ }
301
+ else if (from === "docker-compose" && to === "kubernetes") {
302
+ await (0, generators_1.generateComposeToK8s)(outputDir, options);
303
+ }
304
+ else if (from === "docker-compose" && to === "railway") {
305
+ await (0, generators_1.generateComposeToRailway)(outputDir, options);
306
+ }
307
+ else if (from === "docker-compose" && to === "render") {
308
+ await (0, generators_1.generateComposeToRender)(outputDir, options);
309
+ }
310
+ else {
311
+ // Generic migration
312
+ await (0, generators_1.generateGenericMigration)(outputDir, options, migration);
313
+ }
314
+ }
315
+ /**
316
+ * Print migration steps for dry run
317
+ */
318
+ function printMigrationSteps(options, migration) {
319
+ console.log(chalk_1.default.bold(`Migration: ${options.from} → ${options.to}`));
320
+ console.log(`Complexity: ${migration?.complexity || "unknown"}`);
321
+ console.log();
322
+ console.log(chalk_1.default.bold("Steps:"));
323
+ console.log(" 1. Generate target platform configuration");
324
+ console.log(" 2. Create environment variable mapping");
325
+ if (options.includeSecrets) {
326
+ console.log(" 3. Generate secrets migration script");
327
+ }
328
+ if (options.includeData) {
329
+ console.log(" 4. Generate data migration scripts");
330
+ }
331
+ console.log(" 5. Create migration checklist (README.md)");
332
+ console.log();
333
+ }
334
+ /**
335
+ * Print next steps after migration
336
+ */
337
+ function printNextSteps(options) {
338
+ console.log(chalk_1.default.bold("📖 Next Steps:"));
339
+ console.log(` 1. Review the migration files in ${options.outputDir}`);
340
+ console.log(" 2. Check the MIGRATION_CHECKLIST.md for step-by-step instructions");
341
+ console.log(" 3. Set up environment variables on the target platform");
342
+ if (options.includeData) {
343
+ console.log(" 4. Review and run data migration scripts carefully");
344
+ }
345
+ console.log(" 5. Test the deployment in a staging environment first");
346
+ console.log();
347
+ }
@@ -0,0 +1,2 @@
1
+ import type { MigrationOptions } from "../form";
2
+ export declare function generateComposeToK8s(outputDir: string, options: MigrationOptions): Promise<void>;
@@ -0,0 +1,324 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateComposeToK8s = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const template_loader_1 = require("./template-loader");
11
+ async function generateComposeToK8s(outputDir, options) {
12
+ console.log(chalk_1.default.yellow(" Generating Docker Compose → Kubernetes migration..."));
13
+ const vars = (0, template_loader_1.buildMigrationVars)(options);
14
+ const k8sDir = path_1.default.join(outputDir, "k8s");
15
+ fs_1.default.mkdirSync(k8sDir, { recursive: true });
16
+ // Generate deployment.yaml
17
+ const deployment = generateDeployment();
18
+ fs_1.default.writeFileSync(path_1.default.join(k8sDir, "deployment.yaml"), deployment, "utf-8");
19
+ console.log(chalk_1.default.green(" ✓ Created k8s/deployment.yaml"));
20
+ // Generate service.yaml
21
+ const service = generateService();
22
+ fs_1.default.writeFileSync(path_1.default.join(k8sDir, "service.yaml"), service, "utf-8");
23
+ console.log(chalk_1.default.green(" ✓ Created k8s/service.yaml"));
24
+ // Generate configmap.yaml
25
+ const configMap = generateConfigMap();
26
+ fs_1.default.writeFileSync(path_1.default.join(k8sDir, "configmap.yaml"), configMap, "utf-8");
27
+ console.log(chalk_1.default.green(" ✓ Created k8s/configmap.yaml"));
28
+ // Generate secrets.yaml template
29
+ const secrets = generateSecrets();
30
+ fs_1.default.writeFileSync(path_1.default.join(k8sDir, "secrets.yaml"), secrets, "utf-8");
31
+ console.log(chalk_1.default.green(" ✓ Created k8s/secrets.yaml"));
32
+ // Generate ingress.yaml
33
+ const ingress = generateIngress();
34
+ fs_1.default.writeFileSync(path_1.default.join(k8sDir, "ingress.yaml"), ingress, "utf-8");
35
+ console.log(chalk_1.default.green(" ✓ Created k8s/ingress.yaml"));
36
+ // Generate kustomization.yaml
37
+ const kustomization = generateKustomization();
38
+ fs_1.default.writeFileSync(path_1.default.join(k8sDir, "kustomization.yaml"), kustomization, "utf-8");
39
+ console.log(chalk_1.default.green(" ✓ Created k8s/kustomization.yaml"));
40
+ // Generate migration checklist
41
+ const checklist = generateK8sChecklist();
42
+ fs_1.default.writeFileSync(path_1.default.join(outputDir, "MIGRATION_CHECKLIST.md"), checklist, "utf-8");
43
+ console.log(chalk_1.default.green(" ✓ Created MIGRATION_CHECKLIST.md"));
44
+ // Generate kompose command reference
45
+ const komposeRef = generateKomposeReference();
46
+ fs_1.default.writeFileSync(path_1.default.join(outputDir, "kompose-reference.md"), komposeRef, "utf-8");
47
+ console.log(chalk_1.default.green(" ✓ Created kompose-reference.md"));
48
+ }
49
+ exports.generateComposeToK8s = generateComposeToK8s;
50
+ function generateDeployment() {
51
+ return `# Kubernetes Deployment
52
+ # Generated by ExpressoTS CLI
53
+ # Migrated from Docker Compose
54
+
55
+ apiVersion: apps/v1
56
+ kind: Deployment
57
+ metadata:
58
+ name: expressots-app
59
+ labels:
60
+ app: expressots-app
61
+ spec:
62
+ replicas: 2
63
+ selector:
64
+ matchLabels:
65
+ app: expressots-app
66
+ template:
67
+ metadata:
68
+ labels:
69
+ app: expressots-app
70
+ spec:
71
+ containers:
72
+ - name: app
73
+ image: your-registry/expressots-app:latest
74
+ ports:
75
+ - containerPort: 3000
76
+ envFrom:
77
+ - configMapRef:
78
+ name: expressots-config
79
+ - secretRef:
80
+ name: expressots-secrets
81
+ resources:
82
+ requests:
83
+ memory: "128Mi"
84
+ cpu: "100m"
85
+ limits:
86
+ memory: "512Mi"
87
+ cpu: "500m"
88
+ livenessProbe:
89
+ httpGet:
90
+ path: /health
91
+ port: 3000
92
+ initialDelaySeconds: 30
93
+ periodSeconds: 10
94
+ readinessProbe:
95
+ httpGet:
96
+ path: /health
97
+ port: 3000
98
+ initialDelaySeconds: 5
99
+ periodSeconds: 5
100
+ imagePullSecrets:
101
+ - name: registry-credentials
102
+ `;
103
+ }
104
+ function generateService() {
105
+ return `# Kubernetes Service
106
+ # Generated by ExpressoTS CLI
107
+
108
+ apiVersion: v1
109
+ kind: Service
110
+ metadata:
111
+ name: expressots-app-service
112
+ labels:
113
+ app: expressots-app
114
+ spec:
115
+ type: ClusterIP
116
+ ports:
117
+ - port: 80
118
+ targetPort: 3000
119
+ protocol: TCP
120
+ name: http
121
+ selector:
122
+ app: expressots-app
123
+ `;
124
+ }
125
+ function generateConfigMap() {
126
+ return `# Kubernetes ConfigMap
127
+ # Generated by ExpressoTS CLI
128
+ # Non-sensitive configuration values
129
+
130
+ apiVersion: v1
131
+ kind: ConfigMap
132
+ metadata:
133
+ name: expressots-config
134
+ data:
135
+ NODE_ENV: "production"
136
+ PORT: "3000"
137
+ # Add your non-sensitive config values here
138
+ `;
139
+ }
140
+ function generateSecrets() {
141
+ return `# Kubernetes Secrets
142
+ # Generated by ExpressoTS CLI
143
+ # ⚠️ DO NOT commit this file with real values!
144
+ # Use: kubectl create secret generic expressots-secrets --from-env-file=.env
145
+
146
+ apiVersion: v1
147
+ kind: Secret
148
+ metadata:
149
+ name: expressots-secrets
150
+ type: Opaque
151
+ stringData:
152
+ DATABASE_URL: "postgresql://user:pass@host:5432/db"
153
+ API_KEY: "your-api-key"
154
+ # Add your sensitive values here
155
+ # In production, use sealed-secrets or external-secrets
156
+ `;
157
+ }
158
+ function generateIngress() {
159
+ return `# Kubernetes Ingress
160
+ # Generated by ExpressoTS CLI
161
+
162
+ apiVersion: networking.k8s.io/v1
163
+ kind: Ingress
164
+ metadata:
165
+ name: expressots-ingress
166
+ annotations:
167
+ kubernetes.io/ingress.class: nginx
168
+ cert-manager.io/cluster-issuer: letsencrypt-prod
169
+ spec:
170
+ tls:
171
+ - hosts:
172
+ - your-domain.com
173
+ secretName: expressots-tls
174
+ rules:
175
+ - host: your-domain.com
176
+ http:
177
+ paths:
178
+ - path: /
179
+ pathType: Prefix
180
+ backend:
181
+ service:
182
+ name: expressots-app-service
183
+ port:
184
+ number: 80
185
+ `;
186
+ }
187
+ function generateKustomization() {
188
+ return `# Kustomization
189
+ # Generated by ExpressoTS CLI
190
+
191
+ apiVersion: kustomize.config.k8s.io/v1beta1
192
+ kind: Kustomization
193
+
194
+ resources:
195
+ - deployment.yaml
196
+ - service.yaml
197
+ - configmap.yaml
198
+ - secrets.yaml
199
+ - ingress.yaml
200
+
201
+ commonLabels:
202
+ app.kubernetes.io/name: expressots-app
203
+ app.kubernetes.io/managed-by: kustomize
204
+ `;
205
+ }
206
+ function generateK8sChecklist() {
207
+ return `# Migration Checklist: Docker Compose → Kubernetes
208
+
209
+ ## Pre-Migration
210
+
211
+ - [ ] Ensure kubectl is installed and configured
212
+ - [ ] Have access to a Kubernetes cluster
213
+ - [ ] Push Docker image to container registry
214
+
215
+ ## Automatic Conversion (Optional)
216
+
217
+ Use Kompose for automatic conversion:
218
+ \`\`\`bash
219
+ kompose convert -f docker-compose.yml -o k8s/
220
+ \`\`\`
221
+
222
+ ## Manual Migration Steps
223
+
224
+ 1. **Deployment**
225
+ - [ ] Update image name in deployment.yaml
226
+ - [ ] Adjust replica count
227
+ - [ ] Configure resource limits
228
+
229
+ 2. **Configuration**
230
+ - [ ] Add non-sensitive values to configmap.yaml
231
+ - [ ] Add sensitive values to secrets.yaml
232
+ - [ ] Never commit secrets with real values!
233
+
234
+ 3. **Networking**
235
+ - [ ] Configure Service (ClusterIP, LoadBalancer, NodePort)
236
+ - [ ] Set up Ingress for external access
237
+ - [ ] Configure TLS/SSL certificates
238
+
239
+ 4. **Storage (if needed)**
240
+ - [ ] Create PersistentVolumeClaims for data
241
+ - [ ] Mount volumes in deployment
242
+
243
+ ## Deployment
244
+
245
+ \`\`\`bash
246
+ # Apply all resources
247
+ kubectl apply -k k8s/
248
+
249
+ # Or apply individually
250
+ kubectl apply -f k8s/configmap.yaml
251
+ kubectl apply -f k8s/secrets.yaml
252
+ kubectl apply -f k8s/deployment.yaml
253
+ kubectl apply -f k8s/service.yaml
254
+ kubectl apply -f k8s/ingress.yaml
255
+ \`\`\`
256
+
257
+ ## Verification
258
+
259
+ \`\`\`bash
260
+ kubectl get pods
261
+ kubectl get services
262
+ kubectl get ingress
263
+ kubectl logs -f deployment/expressots-app
264
+ \`\`\`
265
+
266
+ ## Database Migration
267
+
268
+ If migrating database:
269
+ - [ ] Create PersistentVolumeClaim for database
270
+ - [ ] Deploy database as StatefulSet
271
+ - [ ] Or use managed database service (RDS, Cloud SQL)
272
+ `;
273
+ }
274
+ function generateKomposeReference() {
275
+ return `# Kompose Reference
276
+
277
+ Kompose is a tool to convert Docker Compose files to Kubernetes resources.
278
+
279
+ ## Installation
280
+
281
+ \`\`\`bash
282
+ # macOS
283
+ brew install kompose
284
+
285
+ # Linux
286
+ curl -L https://github.com/kubernetes/kompose/releases/download/v1.31.2/kompose-linux-amd64 -o kompose
287
+ chmod +x kompose
288
+ sudo mv kompose /usr/local/bin/
289
+
290
+ # Windows
291
+ choco install kubernetes-kompose
292
+ \`\`\`
293
+
294
+ ## Basic Conversion
295
+
296
+ \`\`\`bash
297
+ # Convert docker-compose.yml
298
+ kompose convert
299
+
300
+ # Output to specific directory
301
+ kompose convert -o k8s/
302
+
303
+ # Generate Helm chart
304
+ kompose convert -c
305
+ \`\`\`
306
+
307
+ ## Supported Features
308
+
309
+ | Docker Compose | Kubernetes |
310
+ |---------------|------------|
311
+ | services | Deployment + Service |
312
+ | volumes | PersistentVolumeClaim |
313
+ | environment | ConfigMap/Secret |
314
+ | ports | Service ports |
315
+ | depends_on | (manual ordering) |
316
+ | networks | (default pod networking) |
317
+
318
+ ## Limitations
319
+
320
+ - \`build\` context is not supported (pre-build images)
321
+ - \`links\` deprecated, use service DNS
322
+ - Some volume types not supported
323
+ `;
324
+ }
@@ -0,0 +1,2 @@
1
+ import type { MigrationOptions } from "../form";
2
+ export declare function generateComposeToRailway(outputDir: string, options: MigrationOptions): Promise<void>;