@expressots/cli 3.0.0 ā 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.
- package/README.md +41 -95
- package/bin/cicd/cli.d.ts +6 -0
- package/bin/cicd/cli.js +126 -0
- package/bin/cicd/form.d.ts +29 -0
- package/bin/cicd/form.js +345 -0
- package/bin/cicd/generators/azure-devops.d.ts +2 -0
- package/bin/cicd/generators/azure-devops.js +370 -0
- package/bin/cicd/generators/bitbucket.d.ts +2 -0
- package/bin/cicd/generators/bitbucket.js +217 -0
- package/bin/cicd/generators/circleci.d.ts +2 -0
- package/bin/cicd/generators/circleci.js +274 -0
- package/bin/cicd/generators/github-actions.d.ts +14 -0
- package/bin/cicd/generators/github-actions.js +426 -0
- package/bin/cicd/generators/gitlab-ci.d.ts +2 -0
- package/bin/cicd/generators/gitlab-ci.js +237 -0
- package/bin/cicd/generators/index.d.ts +6 -0
- package/bin/cicd/generators/index.js +15 -0
- package/bin/cicd/generators/jenkins.d.ts +2 -0
- package/bin/cicd/generators/jenkins.js +248 -0
- package/bin/cicd/generators/template-loader.d.ts +17 -0
- package/bin/cicd/generators/template-loader.js +128 -0
- package/bin/cicd/index.d.ts +1 -0
- package/bin/cicd/index.js +5 -0
- package/bin/cli.d.ts +1 -1
- package/bin/cli.js +18 -3
- package/bin/commands/project.commands.d.ts +19 -6
- package/bin/commands/project.commands.js +390 -61
- package/bin/config/index.d.ts +5 -0
- package/bin/config/index.js +10 -0
- package/bin/config/manager.d.ts +98 -0
- package/bin/config/manager.js +222 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.d.ts +46 -0
- package/bin/containerize/analyzers/bootstrap-analyzer.js +187 -0
- package/bin/containerize/analyzers/project-analyzer.d.ts +20 -0
- package/bin/containerize/analyzers/project-analyzer.js +150 -0
- package/bin/containerize/cli.d.ts +4 -0
- package/bin/containerize/cli.js +113 -0
- package/bin/containerize/form.d.ts +15 -0
- package/bin/containerize/form.js +154 -0
- package/bin/containerize/generators/ci-generator.d.ts +31 -0
- package/bin/containerize/generators/ci-generator.js +936 -0
- package/bin/containerize/generators/docker-compose-generator.d.ts +8 -0
- package/bin/containerize/generators/docker-compose-generator.js +186 -0
- package/bin/containerize/generators/dockerfile-generator.d.ts +8 -0
- package/bin/containerize/generators/dockerfile-generator.js +635 -0
- package/bin/containerize/generators/kubernetes-generator.d.ts +8 -0
- package/bin/containerize/generators/kubernetes-generator.js +133 -0
- package/bin/containerize/generators/template-loader.d.ts +36 -0
- package/bin/containerize/generators/template-loader.js +129 -0
- package/bin/containerize/index.d.ts +4 -0
- package/bin/containerize/index.js +13 -0
- package/bin/containerize/presets/preset-registry.d.ts +20 -0
- package/bin/containerize/presets/preset-registry.js +102 -0
- package/bin/costs/cli.d.ts +5 -0
- package/bin/costs/cli.js +183 -0
- package/bin/costs/form.d.ts +44 -0
- package/bin/costs/form.js +412 -0
- package/bin/costs/index.d.ts +4 -0
- package/bin/costs/index.js +25 -0
- package/bin/costs/pricing-manager.d.ts +84 -0
- package/bin/costs/pricing-manager.js +342 -0
- package/bin/costs/providers/index.d.ts +32 -0
- package/bin/costs/providers/index.js +153 -0
- package/bin/costs/sources/api-source.d.ts +10 -0
- package/bin/costs/sources/api-source.js +32 -0
- package/bin/costs/sources/index.d.ts +6 -0
- package/bin/costs/sources/index.js +15 -0
- package/bin/costs/sources/local-json-source.d.ts +23 -0
- package/bin/costs/sources/local-json-source.js +59 -0
- package/bin/costs/sources/remote-json-source.d.ts +11 -0
- package/bin/costs/sources/remote-json-source.js +53 -0
- package/bin/costs/types.d.ts +53 -0
- package/bin/costs/types.js +5 -0
- package/bin/dev/cli.d.ts +4 -0
- package/bin/dev/cli.js +134 -0
- package/bin/dev/form.d.ts +36 -0
- package/bin/dev/form.js +254 -0
- package/bin/dev/index.d.ts +1 -0
- package/bin/dev/index.js +5 -0
- package/bin/generate/cli.js +29 -2
- package/bin/generate/form.d.ts +5 -1
- package/bin/generate/form.js +3 -3
- package/bin/generate/templates/nonopinionated/config.tpl +12 -0
- package/bin/generate/templates/nonopinionated/event.tpl +10 -0
- package/bin/generate/templates/nonopinionated/guard.tpl +18 -0
- package/bin/generate/templates/nonopinionated/handler.tpl +12 -0
- package/bin/generate/templates/nonopinionated/interceptor.tpl +27 -0
- package/bin/generate/templates/opinionated/config.tpl +47 -0
- package/bin/generate/templates/opinionated/entity.tpl +1 -8
- package/bin/generate/templates/opinionated/event.tpl +15 -0
- package/bin/generate/templates/opinionated/guard.tpl +41 -0
- package/bin/generate/templates/opinionated/handler.tpl +23 -0
- package/bin/generate/templates/opinionated/interceptor.tpl +50 -0
- package/bin/generate/utils/command-utils.d.ts +7 -3
- package/bin/generate/utils/command-utils.js +95 -31
- package/bin/generate/utils/nonopininated-cmd.d.ts +10 -1
- package/bin/generate/utils/nonopininated-cmd.js +100 -1
- package/bin/generate/utils/opinionated-cmd.d.ts +10 -1
- package/bin/generate/utils/opinionated-cmd.js +112 -7
- package/bin/generate/utils/string-utils.d.ts +6 -0
- package/bin/generate/utils/string-utils.js +13 -1
- package/bin/help/form.js +11 -3
- package/bin/migrate/analyzers/platform-detector.d.ts +14 -0
- package/bin/migrate/analyzers/platform-detector.js +116 -0
- package/bin/migrate/cli.d.ts +6 -0
- package/bin/migrate/cli.js +96 -0
- package/bin/migrate/form.d.ts +25 -0
- package/bin/migrate/form.js +347 -0
- package/bin/migrate/generators/compose-to-k8s.d.ts +2 -0
- package/bin/migrate/generators/compose-to-k8s.js +324 -0
- package/bin/migrate/generators/compose-to-railway.d.ts +2 -0
- package/bin/migrate/generators/compose-to-railway.js +138 -0
- package/bin/migrate/generators/compose-to-render.d.ts +2 -0
- package/bin/migrate/generators/compose-to-render.js +148 -0
- package/bin/migrate/generators/generic-migration.d.ts +9 -0
- package/bin/migrate/generators/generic-migration.js +221 -0
- package/bin/migrate/generators/heroku-to-fly.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-fly.js +291 -0
- package/bin/migrate/generators/heroku-to-railway.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-railway.js +283 -0
- package/bin/migrate/generators/heroku-to-render.d.ts +2 -0
- package/bin/migrate/generators/heroku-to-render.js +148 -0
- package/bin/migrate/generators/index.d.ts +7 -0
- package/bin/migrate/generators/index.js +17 -0
- package/bin/migrate/generators/template-loader.d.ts +21 -0
- package/bin/migrate/generators/template-loader.js +59 -0
- package/bin/migrate/index.d.ts +1 -0
- package/bin/migrate/index.js +5 -0
- package/bin/new/cli.js +21 -6
- package/bin/new/form.d.ts +25 -4
- package/bin/new/form.js +285 -70
- package/bin/profile/analyzers/dockerfile-analyzer.d.ts +27 -0
- package/bin/profile/analyzers/dockerfile-analyzer.js +122 -0
- package/bin/profile/analyzers/image-analyzer.d.ts +19 -0
- package/bin/profile/analyzers/image-analyzer.js +85 -0
- package/bin/profile/cli.d.ts +4 -0
- package/bin/profile/cli.js +92 -0
- package/bin/profile/form.d.ts +56 -0
- package/bin/profile/form.js +400 -0
- package/bin/profile/index.d.ts +1 -0
- package/bin/profile/index.js +5 -0
- package/bin/profile/optimizers/index.d.ts +19 -0
- package/bin/profile/optimizers/index.js +137 -0
- package/bin/providers/add/form.d.ts +1 -1
- package/bin/providers/add/form.js +27 -6
- package/bin/providers/create/form.js +2 -1
- package/bin/scripts/form.js +27 -5
- package/bin/studio/cli.d.ts +15 -0
- package/bin/studio/cli.js +166 -0
- package/bin/studio/index.d.ts +5 -0
- package/bin/studio/index.js +9 -0
- package/bin/templates/cache.d.ts +54 -0
- package/bin/templates/cache.js +180 -0
- package/bin/templates/cli.d.ts +8 -0
- package/bin/templates/cli.js +292 -0
- package/bin/templates/fetcher.d.ts +49 -0
- package/bin/templates/fetcher.js +208 -0
- package/bin/templates/index.d.ts +11 -0
- package/bin/templates/index.js +37 -0
- package/bin/templates/manager.d.ts +116 -0
- package/bin/templates/manager.js +323 -0
- package/bin/templates/renderer.d.ts +49 -0
- package/bin/templates/renderer.js +204 -0
- package/bin/templates/types.d.ts +51 -0
- package/bin/templates/types.js +5 -0
- package/bin/utils/add-module-to-container.d.ts +2 -2
- package/bin/utils/add-module-to-container.js +15 -5
- package/bin/utils/cli-ui.d.ts +30 -3
- package/bin/utils/cli-ui.js +95 -13
- package/bin/utils/index.d.ts +4 -0
- package/bin/utils/index.js +4 -0
- package/bin/utils/input-validation.d.ts +50 -0
- package/bin/utils/input-validation.js +143 -0
- package/bin/utils/package-manager-commands.d.ts +24 -0
- package/bin/utils/package-manager-commands.js +50 -0
- package/bin/utils/safe-spawn.d.ts +35 -0
- package/bin/utils/safe-spawn.js +51 -0
- package/bin/utils/update-tsconfig-paths.d.ts +35 -0
- package/bin/utils/update-tsconfig-paths.js +286 -0
- package/package.json +154 -154
|
@@ -0,0 +1,291 @@
|
|
|
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.generateHerokuToFly = 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 generateHerokuToFly(outputDir, options) {
|
|
12
|
+
console.log(chalk_1.default.yellow(" Generating Heroku ā Fly.io migration..."));
|
|
13
|
+
const vars = (0, template_loader_1.buildMigrationVars)(options);
|
|
14
|
+
// Generate fly.toml
|
|
15
|
+
const flyConfig = `# Fly.io Configuration
|
|
16
|
+
# Generated by ExpressoTS CLI
|
|
17
|
+
|
|
18
|
+
app = "expressots-app"
|
|
19
|
+
primary_region = "iad"
|
|
20
|
+
kill_signal = "SIGINT"
|
|
21
|
+
kill_timeout = "5s"
|
|
22
|
+
|
|
23
|
+
[experimental]
|
|
24
|
+
auto_rollback = true
|
|
25
|
+
|
|
26
|
+
[build]
|
|
27
|
+
# Uses Dockerfile by default
|
|
28
|
+
# Or use Nixpacks:
|
|
29
|
+
# builder = "nixpacks"
|
|
30
|
+
|
|
31
|
+
[env]
|
|
32
|
+
NODE_ENV = "production"
|
|
33
|
+
PORT = "3000"
|
|
34
|
+
|
|
35
|
+
[http_service]
|
|
36
|
+
internal_port = 3000
|
|
37
|
+
force_https = true
|
|
38
|
+
auto_stop_machines = true
|
|
39
|
+
auto_start_machines = true
|
|
40
|
+
min_machines_running = 0
|
|
41
|
+
processes = ["app"]
|
|
42
|
+
|
|
43
|
+
[[services]]
|
|
44
|
+
protocol = "tcp"
|
|
45
|
+
internal_port = 3000
|
|
46
|
+
processes = ["app"]
|
|
47
|
+
|
|
48
|
+
[[services.ports]]
|
|
49
|
+
port = 80
|
|
50
|
+
handlers = ["http"]
|
|
51
|
+
force_https = true
|
|
52
|
+
|
|
53
|
+
[[services.ports]]
|
|
54
|
+
port = 443
|
|
55
|
+
handlers = ["tls", "http"]
|
|
56
|
+
|
|
57
|
+
[services.concurrency]
|
|
58
|
+
type = "connections"
|
|
59
|
+
hard_limit = 25
|
|
60
|
+
soft_limit = 20
|
|
61
|
+
|
|
62
|
+
[[services.tcp_checks]]
|
|
63
|
+
interval = "15s"
|
|
64
|
+
timeout = "2s"
|
|
65
|
+
grace_period = "1s"
|
|
66
|
+
|
|
67
|
+
[[services.http_checks]]
|
|
68
|
+
interval = "10s"
|
|
69
|
+
timeout = "2s"
|
|
70
|
+
grace_period = "5s"
|
|
71
|
+
method = "GET"
|
|
72
|
+
path = "/health"
|
|
73
|
+
protocol = "http"
|
|
74
|
+
`;
|
|
75
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "fly.toml"), flyConfig, "utf-8");
|
|
76
|
+
console.log(chalk_1.default.green(" ā Created fly.toml"));
|
|
77
|
+
// Generate migration checklist
|
|
78
|
+
const checklist = generateFlyChecklist();
|
|
79
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "MIGRATION_CHECKLIST.md"), checklist, "utf-8");
|
|
80
|
+
console.log(chalk_1.default.green(" ā Created MIGRATION_CHECKLIST.md"));
|
|
81
|
+
// Generate migration scripts (cross-platform)
|
|
82
|
+
const nodeScript = generateFlyMigrationScriptNode();
|
|
83
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "migrate.js"), nodeScript, "utf-8");
|
|
84
|
+
console.log(chalk_1.default.green(" ā Created migrate.js (cross-platform)"));
|
|
85
|
+
// Also generate bash script for Unix users
|
|
86
|
+
const bashScript = generateFlyMigrationScriptBash();
|
|
87
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "migrate.sh"), bashScript, "utf-8");
|
|
88
|
+
console.log(chalk_1.default.green(" ā Created migrate.sh (Unix/Mac)"));
|
|
89
|
+
}
|
|
90
|
+
exports.generateHerokuToFly = generateHerokuToFly;
|
|
91
|
+
function generateFlyChecklist() {
|
|
92
|
+
return `# Migration Checklist: Heroku ā Fly.io
|
|
93
|
+
|
|
94
|
+
## Pre-Migration
|
|
95
|
+
|
|
96
|
+
Install Fly CLI:
|
|
97
|
+
- **Windows**: \`powershell -Command "iwr https://fly.io/install.ps1 -useb | iex"\`
|
|
98
|
+
- **Mac/Linux**: \`curl -L https://fly.io/install.sh | sh\`
|
|
99
|
+
|
|
100
|
+
- [ ] Create account: \`fly auth signup\` or \`fly auth login\`
|
|
101
|
+
- [ ] Export Heroku config: \`heroku config --app your-app\`
|
|
102
|
+
|
|
103
|
+
## Automated Migration Script
|
|
104
|
+
|
|
105
|
+
\`\`\`bash
|
|
106
|
+
# Set your app name
|
|
107
|
+
export HEROKU_APP_NAME=your-app # Mac/Linux
|
|
108
|
+
set HEROKU_APP_NAME=your-app # Windows CMD
|
|
109
|
+
$env:HEROKU_APP_NAME="your-app" # Windows PowerShell
|
|
110
|
+
|
|
111
|
+
# Run migration
|
|
112
|
+
node migrate.js
|
|
113
|
+
\`\`\`
|
|
114
|
+
|
|
115
|
+
## Fly.io Setup
|
|
116
|
+
|
|
117
|
+
- [ ] Copy \`fly.toml\` to project root
|
|
118
|
+
- [ ] Create app: \`fly apps create expressots-app\`
|
|
119
|
+
- [ ] Set secrets: \`fly secrets set KEY=value\`
|
|
120
|
+
|
|
121
|
+
## Database (if using PostgreSQL)
|
|
122
|
+
|
|
123
|
+
- [ ] Create Fly Postgres: \`fly postgres create\`
|
|
124
|
+
- [ ] Attach to app: \`fly postgres attach --app expressots-app\`
|
|
125
|
+
- [ ] Export Heroku data and import to Fly Postgres
|
|
126
|
+
|
|
127
|
+
## Deployment
|
|
128
|
+
|
|
129
|
+
- [ ] Deploy: \`fly deploy\`
|
|
130
|
+
- [ ] Check status: \`fly status\`
|
|
131
|
+
- [ ] View logs: \`fly logs\`
|
|
132
|
+
|
|
133
|
+
## Custom Domain
|
|
134
|
+
|
|
135
|
+
- [ ] Add certificate: \`fly certs add your-domain.com\`
|
|
136
|
+
- [ ] Update DNS to point to Fly
|
|
137
|
+
|
|
138
|
+
## Scaling
|
|
139
|
+
|
|
140
|
+
- [ ] Adjust scaling: \`fly scale count 2\`
|
|
141
|
+
- [ ] Set memory: \`fly scale memory 512\`
|
|
142
|
+
|
|
143
|
+
## Post-Migration
|
|
144
|
+
|
|
145
|
+
- [ ] Verify endpoints
|
|
146
|
+
- [ ] Monitor metrics: \`fly dashboard\`
|
|
147
|
+
- [ ] Disable Heroku after verification
|
|
148
|
+
`;
|
|
149
|
+
}
|
|
150
|
+
function generateFlyMigrationScriptNode() {
|
|
151
|
+
return `#!/usr/bin/env node
|
|
152
|
+
/**
|
|
153
|
+
* Migration Script: Heroku ā Fly.io
|
|
154
|
+
* Generated by ExpressoTS CLI
|
|
155
|
+
* Cross-platform (Windows, macOS, Linux)
|
|
156
|
+
*/
|
|
157
|
+
|
|
158
|
+
const { execSync } = require('child_process');
|
|
159
|
+
const fs = require('fs');
|
|
160
|
+
|
|
161
|
+
const HEROKU_APP = process.env.HEROKU_APP_NAME || 'your-app';
|
|
162
|
+
const FLY_APP = process.env.FLY_APP_NAME || 'expressots-app';
|
|
163
|
+
|
|
164
|
+
function run(cmd, options = {}) {
|
|
165
|
+
console.log(\` Running: \${cmd}\`);
|
|
166
|
+
try {
|
|
167
|
+
return execSync(cmd, { encoding: 'utf-8', stdio: 'inherit', ...options });
|
|
168
|
+
} catch (error) {
|
|
169
|
+
if (!options.ignoreError) {
|
|
170
|
+
console.error(\` Error: \${error.message}\`);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function checkCommand(cmd) {
|
|
177
|
+
try {
|
|
178
|
+
execSync(\`\${cmd} version\`, { stdio: 'pipe' });
|
|
179
|
+
return true;
|
|
180
|
+
} catch {
|
|
181
|
+
try {
|
|
182
|
+
execSync(\`\${cmd} --version\`, { stdio: 'pipe' });
|
|
183
|
+
return true;
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function main() {
|
|
191
|
+
console.log('\\nšŖ° Starting Heroku ā Fly.io Migration\\n');
|
|
192
|
+
|
|
193
|
+
// Check prerequisites
|
|
194
|
+
if (!checkCommand('fly') && !checkCommand('flyctl')) {
|
|
195
|
+
console.error('ā Fly CLI required.');
|
|
196
|
+
console.error(' Windows: powershell -Command "iwr https://fly.io/install.ps1 -useb | iex"');
|
|
197
|
+
console.error(' Mac/Linux: curl -L https://fly.io/install.sh | sh');
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const flyCmd = checkCommand('flyctl') ? 'flyctl' : 'fly';
|
|
202
|
+
|
|
203
|
+
// Export Heroku config (if available)
|
|
204
|
+
if (checkCommand('heroku')) {
|
|
205
|
+
console.log('š¦ Exporting Heroku configuration...');
|
|
206
|
+
try {
|
|
207
|
+
const config = execSync(\`heroku config --app \${HEROKU_APP} --shell\`, { encoding: 'utf-8' });
|
|
208
|
+
fs.writeFileSync('.env.heroku', config);
|
|
209
|
+
console.log(' ā Exported to .env.heroku');
|
|
210
|
+
} catch {
|
|
211
|
+
console.log(' ā Could not export. Set HEROKU_APP_NAME env var.');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Create Fly app
|
|
216
|
+
console.log('\\nšŖ° Creating Fly app...');
|
|
217
|
+
run(\`\${flyCmd} apps create \${FLY_APP}\`, { ignoreError: true });
|
|
218
|
+
|
|
219
|
+
// Import secrets
|
|
220
|
+
if (fs.existsSync('.env.heroku')) {
|
|
221
|
+
console.log('\\nš Setting secrets...');
|
|
222
|
+
const envContent = fs.readFileSync('.env.heroku', 'utf-8');
|
|
223
|
+
const lines = envContent.split('\\n');
|
|
224
|
+
|
|
225
|
+
for (const line of lines) {
|
|
226
|
+
const match = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
|
|
227
|
+
if (match) {
|
|
228
|
+
const [, key, value] = match;
|
|
229
|
+
console.log(\` Setting \${key}...\`);
|
|
230
|
+
run(\`\${flyCmd} secrets set "\${key}=\${value}" --app \${FLY_APP}\`, { ignoreError: true });
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Deploy
|
|
236
|
+
console.log('\\nš Deploying to Fly.io...');
|
|
237
|
+
run(\`\${flyCmd} deploy\`);
|
|
238
|
+
|
|
239
|
+
console.log('\\nā
Migration complete!');
|
|
240
|
+
console.log(\` Dashboard: \${flyCmd} dashboard\`);
|
|
241
|
+
console.log(\` Logs: \${flyCmd} logs\\n\`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
main().catch(console.error);
|
|
245
|
+
`;
|
|
246
|
+
}
|
|
247
|
+
function generateFlyMigrationScriptBash() {
|
|
248
|
+
return `#!/bin/bash
|
|
249
|
+
# Migration Script: Heroku ā Fly.io
|
|
250
|
+
# Generated by ExpressoTS CLI
|
|
251
|
+
# For Unix/macOS - Windows users: use migrate.js instead
|
|
252
|
+
|
|
253
|
+
set -e
|
|
254
|
+
|
|
255
|
+
echo "šŖ° Starting Heroku ā Fly.io Migration"
|
|
256
|
+
|
|
257
|
+
# Check prerequisites
|
|
258
|
+
command -v fly >/dev/null 2>&1 || command -v flyctl >/dev/null 2>&1 || {
|
|
259
|
+
echo "Fly CLI required. Install: curl -L https://fly.io/install.sh | sh"
|
|
260
|
+
exit 1
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
FLY_CMD="fly"
|
|
264
|
+
command -v flyctl >/dev/null 2>&1 && FLY_CMD="flyctl"
|
|
265
|
+
|
|
266
|
+
# Export Heroku config
|
|
267
|
+
echo "š¦ Exporting Heroku configuration..."
|
|
268
|
+
heroku config --app \${HEROKU_APP_NAME:-your-app} --shell > .env.heroku
|
|
269
|
+
|
|
270
|
+
# Create Fly app
|
|
271
|
+
echo "šŖ° Creating Fly app..."
|
|
272
|
+
$FLY_CMD apps create \${FLY_APP_NAME:-expressots-app} || echo "App may already exist"
|
|
273
|
+
|
|
274
|
+
# Set secrets from Heroku config
|
|
275
|
+
echo "š Setting secrets..."
|
|
276
|
+
while IFS='=' read -r key value; do
|
|
277
|
+
if [[ ! -z "$key" && ! "$key" =~ ^# ]]; then
|
|
278
|
+
echo " Setting $key..."
|
|
279
|
+
$FLY_CMD secrets set "$key=$value" --app \${FLY_APP_NAME:-expressots-app}
|
|
280
|
+
fi
|
|
281
|
+
done < .env.heroku
|
|
282
|
+
|
|
283
|
+
# Deploy
|
|
284
|
+
echo "š Deploying to Fly.io..."
|
|
285
|
+
$FLY_CMD deploy
|
|
286
|
+
|
|
287
|
+
echo "ā
Migration complete!"
|
|
288
|
+
echo " Dashboard: $FLY_CMD dashboard"
|
|
289
|
+
echo " Logs: $FLY_CMD logs"
|
|
290
|
+
`;
|
|
291
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
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.generateHerokuToRailway = 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 generateHerokuToRailway(outputDir, options) {
|
|
12
|
+
console.log(chalk_1.default.yellow(" Generating Heroku ā Railway migration..."));
|
|
13
|
+
const vars = (0, template_loader_1.buildMigrationVars)(options);
|
|
14
|
+
// Generate railway.json
|
|
15
|
+
const railwayConfig = {
|
|
16
|
+
$schema: "https://railway.app/railway.schema.json",
|
|
17
|
+
build: {
|
|
18
|
+
builder: "NIXPACKS",
|
|
19
|
+
},
|
|
20
|
+
deploy: {
|
|
21
|
+
startCommand: "npm start",
|
|
22
|
+
healthcheckPath: "/health",
|
|
23
|
+
healthcheckTimeout: 300,
|
|
24
|
+
restartPolicyType: "ON_FAILURE",
|
|
25
|
+
restartPolicyMaxRetries: 10,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "railway.json"), JSON.stringify(railwayConfig, null, 2), "utf-8");
|
|
29
|
+
console.log(chalk_1.default.green(" ā Created railway.json"));
|
|
30
|
+
// Generate environment variable mapping
|
|
31
|
+
if (options.includeSecrets) {
|
|
32
|
+
const envMapping = generateEnvMapping();
|
|
33
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "env-mapping.md"), envMapping, "utf-8");
|
|
34
|
+
console.log(chalk_1.default.green(" ā Created env-mapping.md"));
|
|
35
|
+
}
|
|
36
|
+
// Generate migration checklist (try remote template first)
|
|
37
|
+
const checklistResult = await (0, template_loader_1.loadMigrationTemplate)("heroku", "railway", "checklist", vars, () => generateChecklist(options));
|
|
38
|
+
(0, template_loader_1.logTemplateSource)("MIGRATION_CHECKLIST.md", checklistResult.source);
|
|
39
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "MIGRATION_CHECKLIST.md"), checklistResult.content, "utf-8");
|
|
40
|
+
console.log(chalk_1.default.green(" ā Created MIGRATION_CHECKLIST.md"));
|
|
41
|
+
// Generate migration scripts (cross-platform)
|
|
42
|
+
const nodeScript = generateMigrationScriptNode();
|
|
43
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "migrate.js"), nodeScript, "utf-8");
|
|
44
|
+
console.log(chalk_1.default.green(" ā Created migrate.js (cross-platform)"));
|
|
45
|
+
// Also generate bash script for Unix users
|
|
46
|
+
const bashScript = generateMigrationScriptBash();
|
|
47
|
+
fs_1.default.writeFileSync(path_1.default.join(outputDir, "migrate.sh"), bashScript, "utf-8");
|
|
48
|
+
console.log(chalk_1.default.green(" ā Created migrate.sh (Unix/Mac)"));
|
|
49
|
+
}
|
|
50
|
+
exports.generateHerokuToRailway = generateHerokuToRailway;
|
|
51
|
+
function generateEnvMapping() {
|
|
52
|
+
return `# Environment Variable Mapping: Heroku ā Railway
|
|
53
|
+
|
|
54
|
+
## Common Variable Translations
|
|
55
|
+
|
|
56
|
+
| Heroku Variable | Railway Variable | Notes |
|
|
57
|
+
|-----------------|------------------|-------|
|
|
58
|
+
| \`DATABASE_URL\` | \`DATABASE_URL\` | Same format, Railway provides PostgreSQL |
|
|
59
|
+
| \`REDIS_URL\` | \`REDIS_URL\` | Same format |
|
|
60
|
+
| \`PORT\` | \`PORT\` | Railway sets this automatically |
|
|
61
|
+
| \`NODE_ENV\` | \`NODE_ENV\` | Set to \`production\` |
|
|
62
|
+
| \`HEROKU_APP_NAME\` | \`RAILWAY_SERVICE_NAME\` | Service name |
|
|
63
|
+
|
|
64
|
+
## Database Migration
|
|
65
|
+
|
|
66
|
+
If using Heroku Postgres:
|
|
67
|
+
1. Export data: \`heroku pg:backups:capture --app your-app\`
|
|
68
|
+
2. Download: \`heroku pg:backups:download --app your-app\`
|
|
69
|
+
3. Import to Railway PostgreSQL instance
|
|
70
|
+
|
|
71
|
+
## Steps to Set Environment Variables
|
|
72
|
+
|
|
73
|
+
\`\`\`bash
|
|
74
|
+
# List Heroku config vars
|
|
75
|
+
heroku config --app your-app
|
|
76
|
+
|
|
77
|
+
# Set Railway variables via CLI
|
|
78
|
+
railway variables set KEY=value
|
|
79
|
+
|
|
80
|
+
# Or use Railway dashboard
|
|
81
|
+
# https://railway.app/project/[project-id]/settings
|
|
82
|
+
\`\`\`
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
function generateChecklist(options) {
|
|
86
|
+
return `# Migration Checklist: Heroku ā Railway
|
|
87
|
+
|
|
88
|
+
## Pre-Migration
|
|
89
|
+
|
|
90
|
+
- [ ] Export Heroku environment variables: \`heroku config --app your-app > .env.heroku\`
|
|
91
|
+
- [ ] Backup database if applicable
|
|
92
|
+
- [ ] Document current Heroku add-ons
|
|
93
|
+
- [ ] Note current dyno configuration
|
|
94
|
+
|
|
95
|
+
## Automated Migration Script
|
|
96
|
+
|
|
97
|
+
Run the cross-platform migration script:
|
|
98
|
+
\`\`\`bash
|
|
99
|
+
# Set your app name
|
|
100
|
+
export HEROKU_APP_NAME=your-app # Mac/Linux
|
|
101
|
+
set HEROKU_APP_NAME=your-app # Windows CMD
|
|
102
|
+
$env:HEROKU_APP_NAME="your-app" # Windows PowerShell
|
|
103
|
+
|
|
104
|
+
# Run migration
|
|
105
|
+
node migrate.js
|
|
106
|
+
\`\`\`
|
|
107
|
+
|
|
108
|
+
## Railway Setup (Manual)
|
|
109
|
+
|
|
110
|
+
- [ ] Create Railway account at https://railway.app
|
|
111
|
+
- [ ] Install Railway CLI: \`npm install -g @railway/cli\`
|
|
112
|
+
- [ ] Login: \`railway login\`
|
|
113
|
+
- [ ] Create new project: \`railway init\`
|
|
114
|
+
|
|
115
|
+
## Configuration
|
|
116
|
+
|
|
117
|
+
- [ ] Copy \`railway.json\` to your project root
|
|
118
|
+
- [ ] Set environment variables in Railway dashboard
|
|
119
|
+
- [ ] Configure custom domain (if needed)
|
|
120
|
+
|
|
121
|
+
## Database Migration
|
|
122
|
+
|
|
123
|
+
- [ ] Provision PostgreSQL on Railway
|
|
124
|
+
- [ ] Export Heroku database
|
|
125
|
+
- [ ] Import to Railway PostgreSQL
|
|
126
|
+
- [ ] Update \`DATABASE_URL\`
|
|
127
|
+
|
|
128
|
+
## Deployment
|
|
129
|
+
|
|
130
|
+
- [ ] Deploy: \`railway up\`
|
|
131
|
+
- [ ] Verify deployment in Railway dashboard
|
|
132
|
+
- [ ] Test application endpoints
|
|
133
|
+
- [ ] Monitor logs: \`railway logs\`
|
|
134
|
+
|
|
135
|
+
## DNS & Domain
|
|
136
|
+
|
|
137
|
+
- [ ] Add custom domain in Railway
|
|
138
|
+
- [ ] Update DNS records
|
|
139
|
+
- [ ] Verify SSL certificate
|
|
140
|
+
|
|
141
|
+
## Post-Migration
|
|
142
|
+
|
|
143
|
+
- [ ] Monitor for 24-48 hours
|
|
144
|
+
- [ ] Disable Heroku app
|
|
145
|
+
- [ ] Delete Heroku resources after verification
|
|
146
|
+
|
|
147
|
+
## Rollback Plan
|
|
148
|
+
|
|
149
|
+
If issues occur:
|
|
150
|
+
1. Re-enable Heroku app
|
|
151
|
+
2. Point DNS back to Heroku
|
|
152
|
+
3. Investigate and fix Railway deployment
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
function generateMigrationScriptNode() {
|
|
156
|
+
return `#!/usr/bin/env node
|
|
157
|
+
/**
|
|
158
|
+
* Migration Script: Heroku ā Railway
|
|
159
|
+
* Generated by ExpressoTS CLI
|
|
160
|
+
* Cross-platform (Windows, macOS, Linux)
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
const { execSync, spawnSync } = require('child_process');
|
|
164
|
+
const fs = require('fs');
|
|
165
|
+
const path = require('path');
|
|
166
|
+
|
|
167
|
+
const HEROKU_APP = process.env.HEROKU_APP_NAME || 'your-app';
|
|
168
|
+
|
|
169
|
+
function run(cmd, options = {}) {
|
|
170
|
+
console.log(\` Running: \${cmd}\`);
|
|
171
|
+
try {
|
|
172
|
+
return execSync(cmd, { encoding: 'utf-8', stdio: 'inherit', ...options });
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (!options.ignoreError) {
|
|
175
|
+
console.error(\` Error: \${error.message}\`);
|
|
176
|
+
process.exit(1);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function checkCommand(cmd) {
|
|
182
|
+
try {
|
|
183
|
+
execSync(\`\${cmd} --version\`, { stdio: 'pipe' });
|
|
184
|
+
return true;
|
|
185
|
+
} catch {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function main() {
|
|
191
|
+
console.log('\\nš Starting Heroku ā Railway Migration\\n');
|
|
192
|
+
|
|
193
|
+
// Check prerequisites
|
|
194
|
+
if (!checkCommand('railway')) {
|
|
195
|
+
console.error('ā Railway CLI required. Install: npm i -g @railway/cli');
|
|
196
|
+
process.exit(1);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Export Heroku config (if heroku CLI available)
|
|
200
|
+
if (checkCommand('heroku')) {
|
|
201
|
+
console.log('š¦ Exporting Heroku configuration...');
|
|
202
|
+
try {
|
|
203
|
+
const config = execSync(\`heroku config --app \${HEROKU_APP} --shell\`, { encoding: 'utf-8' });
|
|
204
|
+
fs.writeFileSync('.env.heroku', config);
|
|
205
|
+
console.log(' ā Exported to .env.heroku');
|
|
206
|
+
} catch {
|
|
207
|
+
console.log(' ā Could not export Heroku config. Set HEROKU_APP_NAME env var.');
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
console.log('ā Heroku CLI not found. Skipping config export.');
|
|
211
|
+
console.log(' Manually export your environment variables.');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Initialize Railway project
|
|
215
|
+
console.log('\\nš Initializing Railway project...');
|
|
216
|
+
run('railway init', { ignoreError: true });
|
|
217
|
+
|
|
218
|
+
// Import environment variables
|
|
219
|
+
if (fs.existsSync('.env.heroku')) {
|
|
220
|
+
console.log('\\nš Setting up environment variables...');
|
|
221
|
+
const envContent = fs.readFileSync('.env.heroku', 'utf-8');
|
|
222
|
+
const lines = envContent.split('\\n');
|
|
223
|
+
|
|
224
|
+
for (const line of lines) {
|
|
225
|
+
const match = line.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);
|
|
226
|
+
if (match) {
|
|
227
|
+
const [, key, value] = match;
|
|
228
|
+
console.log(\` Setting \${key}...\`);
|
|
229
|
+
run(\`railway variables set "\${key}=\${value}"\`, { ignoreError: true });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Deploy
|
|
235
|
+
console.log('\\nš Deploying to Railway...');
|
|
236
|
+
run('railway up');
|
|
237
|
+
|
|
238
|
+
console.log('\\nā
Migration complete!');
|
|
239
|
+
console.log(' Check your deployment at: https://railway.app/dashboard\\n');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
main().catch(console.error);
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
function generateMigrationScriptBash() {
|
|
246
|
+
return `#!/bin/bash
|
|
247
|
+
# Migration Script: Heroku ā Railway
|
|
248
|
+
# Generated by ExpressoTS CLI
|
|
249
|
+
# For Unix/macOS - Windows users: use migrate.js instead
|
|
250
|
+
|
|
251
|
+
set -e
|
|
252
|
+
|
|
253
|
+
echo "š Starting Heroku ā Railway Migration"
|
|
254
|
+
|
|
255
|
+
# Check prerequisites
|
|
256
|
+
command -v railway >/dev/null 2>&1 || { echo "Railway CLI required. Install: npm i -g @railway/cli"; exit 1; }
|
|
257
|
+
command -v heroku >/dev/null 2>&1 || { echo "Heroku CLI required."; exit 1; }
|
|
258
|
+
|
|
259
|
+
# Export Heroku config
|
|
260
|
+
echo "š¦ Exporting Heroku configuration..."
|
|
261
|
+
heroku config --app \${HEROKU_APP_NAME:-your-app} --shell > .env.heroku
|
|
262
|
+
|
|
263
|
+
# Initialize Railway project
|
|
264
|
+
echo "š Initializing Railway project..."
|
|
265
|
+
railway init
|
|
266
|
+
|
|
267
|
+
# Copy environment variables
|
|
268
|
+
echo "š Setting up environment variables..."
|
|
269
|
+
while IFS='=' read -r key value; do
|
|
270
|
+
if [[ ! -z "$key" && ! "$key" =~ ^# ]]; then
|
|
271
|
+
echo " Setting $key..."
|
|
272
|
+
railway variables set "$key=$value"
|
|
273
|
+
fi
|
|
274
|
+
done < .env.heroku
|
|
275
|
+
|
|
276
|
+
# Deploy
|
|
277
|
+
echo "š Deploying to Railway..."
|
|
278
|
+
railway up
|
|
279
|
+
|
|
280
|
+
echo "ā
Migration complete!"
|
|
281
|
+
echo " Check your deployment at: https://railway.app/dashboard"
|
|
282
|
+
`;
|
|
283
|
+
}
|