ugly-app 0.1.2 → 0.1.4

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 (46) hide show
  1. package/dist/cli/deploy.d.ts +3 -0
  2. package/dist/cli/deploy.d.ts.map +1 -0
  3. package/dist/cli/deploy.js +427 -0
  4. package/dist/cli/deploy.js.map +1 -0
  5. package/dist/cli/deployGenerators.d.ts +7 -0
  6. package/dist/cli/deployGenerators.d.ts.map +1 -0
  7. package/dist/cli/deployGenerators.js +80 -0
  8. package/dist/cli/deployGenerators.js.map +1 -0
  9. package/dist/cli/deployGenerators.test.d.ts +2 -0
  10. package/dist/cli/deployGenerators.test.d.ts.map +1 -0
  11. package/dist/cli/deployGenerators.test.js +65 -0
  12. package/dist/cli/deployGenerators.test.js.map +1 -0
  13. package/dist/cli/deployPlatform.d.ts +20 -0
  14. package/dist/cli/deployPlatform.d.ts.map +1 -0
  15. package/dist/cli/deployPlatform.js +61 -0
  16. package/dist/cli/deployPlatform.js.map +1 -0
  17. package/dist/cli/deployPlatform.test.d.ts +2 -0
  18. package/dist/cli/deployPlatform.test.d.ts.map +1 -0
  19. package/dist/cli/deployPlatform.test.js +47 -0
  20. package/dist/cli/deployPlatform.test.js.map +1 -0
  21. package/dist/cli/dev.d.ts.map +1 -1
  22. package/dist/cli/dev.js +56 -16
  23. package/dist/cli/dev.js.map +1 -1
  24. package/dist/cli/index.js +36 -10
  25. package/dist/cli/index.js.map +1 -1
  26. package/dist/cli/scaffold.d.ts.map +1 -1
  27. package/dist/cli/scaffold.js +35 -3
  28. package/dist/cli/scaffold.js.map +1 -1
  29. package/dist/cli/uglyappConfig.d.ts +1 -0
  30. package/dist/cli/uglyappConfig.d.ts.map +1 -1
  31. package/dist/cli/uglyappConfig.js +9 -1
  32. package/dist/cli/uglyappConfig.js.map +1 -1
  33. package/dist/cli/uglyappConfig.test.d.ts +2 -0
  34. package/dist/cli/uglyappConfig.test.d.ts.map +1 -0
  35. package/dist/cli/uglyappConfig.test.js +31 -0
  36. package/dist/cli/uglyappConfig.test.js.map +1 -0
  37. package/dist/cli/vultrClient.d.ts +41 -0
  38. package/dist/cli/vultrClient.d.ts.map +1 -0
  39. package/dist/cli/vultrClient.js +64 -0
  40. package/dist/cli/vultrClient.js.map +1 -0
  41. package/dist/cli/vultrClient.test.d.ts +2 -0
  42. package/dist/cli/vultrClient.test.d.ts.map +1 -0
  43. package/dist/cli/vultrClient.test.js +52 -0
  44. package/dist/cli/vultrClient.test.js.map +1 -0
  45. package/package.json +1 -1
  46. package/templates/package.json +3 -3
@@ -0,0 +1,3 @@
1
+ export declare function runDeploySingle(): Promise<void>;
2
+ export declare function runDeployMulti(): Promise<void>;
3
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/cli/deploy.ts"],"names":[],"mappings":"AAscA,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAoCrD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAmFpD"}
@@ -0,0 +1,427 @@
1
+ import { execSync, spawnSync } from 'child_process';
2
+ import fs from 'fs';
3
+ import net from 'net';
4
+ import os from 'os';
5
+ import path from 'path';
6
+ import readline from 'readline';
7
+ import { generateCaddyfile, generateDefaultDockerfile, generateDockerComposeYml, generateEnvServer, } from './deployGenerators.js';
8
+ import { getPlatformOrThrow } from './deployPlatform.js';
9
+ import { createVultrClient } from './vultrClient.js';
10
+ import { readUglyAppConfig } from './uglyappConfig.js';
11
+ // ─── Constants ────────────────────────────────────────────────────────────────
12
+ const UBUNTU_22_OS_ID = 1743; // Ubuntu 22.04 LTS x64 on Vultr
13
+ const DEFAULT_PLAN = 'vc2-1c-1gb';
14
+ const DEFAULT_REGION = 'ewr';
15
+ const VULTR_KEY_PATH = path.join(os.homedir(), '.config', 'ugly-app', 'vultr.json');
16
+ const STARTUP_SCRIPT = `#!/bin/bash
17
+ set -e
18
+ apt-get update -y
19
+ apt-get install -y ca-certificates curl gnupg rsync
20
+ install -m 0755 -d /etc/apt/keyrings
21
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
22
+ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" > /etc/apt/sources.list.d/docker.list
23
+ apt-get update -y
24
+ apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
25
+ systemctl enable docker
26
+ systemctl start docker
27
+ curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
28
+ apt-get install -y nodejs
29
+ mkdir -p /srv/app
30
+ `;
31
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
32
+ function prompt(question, defaultValue = '') {
33
+ return new Promise((resolve) => {
34
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
35
+ const display = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
36
+ rl.question(display, (answer) => {
37
+ rl.close();
38
+ resolve(answer.trim() || defaultValue);
39
+ });
40
+ });
41
+ }
42
+ async function loadOrPromptVultrKey() {
43
+ if (fs.existsSync(VULTR_KEY_PATH)) {
44
+ const raw = JSON.parse(fs.readFileSync(VULTR_KEY_PATH, 'utf-8'));
45
+ if (raw.apiKey)
46
+ return raw.apiKey;
47
+ }
48
+ console.log(' No Vultr API key found. Get one at https://my.vultr.com/settings/#settingsapi');
49
+ const apiKey = await prompt(' Vultr API key');
50
+ if (!apiKey)
51
+ throw new Error('API key is required.');
52
+ fs.mkdirSync(path.dirname(VULTR_KEY_PATH), { recursive: true });
53
+ fs.writeFileSync(VULTR_KEY_PATH, JSON.stringify({ apiKey }, null, 2) + '\n', 'utf-8');
54
+ return apiKey;
55
+ }
56
+ function detectSshKey() {
57
+ const candidates = [
58
+ { pub: path.join(os.homedir(), '.ssh', 'id_ed25519.pub'), priv: path.join(os.homedir(), '.ssh', 'id_ed25519') },
59
+ { pub: path.join(os.homedir(), '.ssh', 'id_rsa.pub'), priv: path.join(os.homedir(), '.ssh', 'id_rsa') },
60
+ ];
61
+ for (const { pub, priv } of candidates) {
62
+ if (fs.existsSync(pub) && fs.existsSync(priv)) {
63
+ return { publicKeyPath: pub, privateKeyPath: priv, publicKey: fs.readFileSync(pub, 'utf-8').trim() };
64
+ }
65
+ }
66
+ throw new Error('No SSH public key found. Run: ssh-keygen -t ed25519');
67
+ }
68
+ async function ensureVultrSshKey(client, publicKey) {
69
+ const keyName = `${os.hostname()}-${os.userInfo().username}`;
70
+ const existing = await client.listSshKeys();
71
+ const found = existing.find((k) => k.name === keyName);
72
+ if (found)
73
+ return found.id;
74
+ const created = await client.createSshKey(keyName, publicKey);
75
+ return created.id;
76
+ }
77
+ function buildSshArgs(ip, privateKeyPath, platform) {
78
+ const keyPath = platform.toLocalPath(privateKeyPath);
79
+ return [
80
+ ...platform.sshArgs,
81
+ '-i', keyPath,
82
+ '-o', 'StrictHostKeyChecking=no',
83
+ '-o', 'UserKnownHostsFile=/dev/null',
84
+ `root@${ip}`,
85
+ ];
86
+ }
87
+ function runSsh(ip, privateKeyPath, platform, command) {
88
+ const args = [...buildSshArgs(ip, privateKeyPath, platform), command];
89
+ const result = spawnSync(platform.sshBin, args, { stdio: 'inherit' });
90
+ if (result.status !== 0)
91
+ throw new Error(`SSH command failed: ${command}`);
92
+ }
93
+ function runRsync(localPaths, ip, privateKeyPath, platform, extraArgs = []) {
94
+ const keyPath = platform.toLocalPath(privateKeyPath);
95
+ const sshCmd = [
96
+ platform.sshBin,
97
+ ...platform.sshArgs,
98
+ '-i', keyPath,
99
+ '-o', 'StrictHostKeyChecking=no',
100
+ '-o', 'UserKnownHostsFile=/dev/null',
101
+ ].join(' ');
102
+ const remoteDest = `root@${ip}:/srv/app/`;
103
+ const args = [
104
+ ...platform.rsyncArgs,
105
+ '-az',
106
+ '--delete',
107
+ '-e', sshCmd,
108
+ ...extraArgs,
109
+ ...localPaths.map((p) => platform.toLocalPath(p)),
110
+ remoteDest,
111
+ ];
112
+ const result = spawnSync(platform.rsyncBin, args, { stdio: 'inherit' });
113
+ if (result.status !== 0)
114
+ throw new Error('rsync failed');
115
+ }
116
+ async function pollSshReady(ip, timeoutMs = 3 * 60 * 1000) {
117
+ const deadline = Date.now() + timeoutMs;
118
+ while (Date.now() < deadline) {
119
+ const ready = await new Promise((resolve) => {
120
+ const sock = new net.Socket();
121
+ sock.setTimeout(3000);
122
+ sock.connect(22, ip, () => { sock.destroy(); resolve(true); });
123
+ sock.on('error', () => resolve(false));
124
+ sock.on('timeout', () => { sock.destroy(); resolve(false); });
125
+ });
126
+ if (ready)
127
+ return;
128
+ await new Promise((r) => setTimeout(r, 5000));
129
+ }
130
+ throw new Error(`SSH not ready on ${ip} after 3 minutes.`);
131
+ }
132
+ async function pollInstanceReady(client, id, timeoutMs = 10 * 60 * 1000) {
133
+ const deadline = Date.now() + timeoutMs;
134
+ while (Date.now() < deadline) {
135
+ const instance = await client.getInstance(id);
136
+ if (instance.status === 'active' && instance.main_ip && instance.main_ip !== '0.0.0.0') {
137
+ return instance.main_ip;
138
+ }
139
+ await new Promise((r) => setTimeout(r, 10000));
140
+ }
141
+ throw new Error(`Instance ${id} not active after 10 minutes.`);
142
+ }
143
+ // ─── Generated file helpers ───────────────────────────────────────────────────
144
+ function prepareGeneratedFiles(opts) {
145
+ const { cwd, domain, tmpDir } = opts;
146
+ // docker-compose.prod.yml
147
+ const dockerComposePath = path.join(tmpDir, 'docker-compose.prod.yml');
148
+ fs.writeFileSync(dockerComposePath, generateDockerComposeYml({ domain }), 'utf-8');
149
+ // .env.server — rewrite connection strings
150
+ const envPath = path.join(cwd, '.env');
151
+ const envContent = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf-8') : '';
152
+ const envServerPath = path.join(tmpDir, '.env.server');
153
+ fs.writeFileSync(envServerPath, generateEnvServer(envContent), 'utf-8');
154
+ // Caddyfile (only if domain set)
155
+ let caddyfilePath = null;
156
+ if (domain) {
157
+ // Guard: reject empty-string domain
158
+ if (!domain.trim())
159
+ throw new Error('domain in .uglyapp must not be empty.');
160
+ caddyfilePath = path.join(tmpDir, 'Caddyfile');
161
+ fs.writeFileSync(caddyfilePath, generateCaddyfile(domain), 'utf-8');
162
+ }
163
+ // Dockerfile — use existing or generate default
164
+ const existingDockerfile = path.join(cwd, 'Dockerfile');
165
+ const dockerfilePath = fs.existsSync(existingDockerfile)
166
+ ? existingDockerfile
167
+ : (() => {
168
+ const p = path.join(tmpDir, 'Dockerfile');
169
+ fs.writeFileSync(p, generateDefaultDockerfile(), 'utf-8');
170
+ return p;
171
+ })();
172
+ return { dockerComposePath, envServerPath, caddyfilePath, dockerfilePath };
173
+ }
174
+ // ─── Preflight ────────────────────────────────────────────────────────────────
175
+ function preflight(cwd) {
176
+ if (!fs.existsSync(path.join(cwd, '.uglyapp'))) {
177
+ throw new Error('.uglyapp not found. Run `ugly-app configure` first.');
178
+ }
179
+ const envPath = path.join(cwd, '.env');
180
+ if (!fs.existsSync(envPath)) {
181
+ throw new Error('.env not found. Create it with STORAGE_PUBLIC_BUCKET set.');
182
+ }
183
+ const envContent = fs.readFileSync(envPath, 'utf-8');
184
+ if (!/^STORAGE_PUBLIC_BUCKET=/m.test(envContent)) {
185
+ throw new Error('STORAGE_PUBLIC_BUCKET must be set in .env before deploying.');
186
+ }
187
+ }
188
+ // ─── Asset pipeline ───────────────────────────────────────────────────────────
189
+ function isR2Configured(cwd) {
190
+ const envPath = path.join(cwd, '.env');
191
+ const content = fs.existsSync(envPath) ? fs.readFileSync(envPath, 'utf-8') : '';
192
+ return (/^STORAGE_ACCOUNT_ID=.+/m.test(content) &&
193
+ /^STORAGE_ACCESS_KEY_ID=.+/m.test(content) &&
194
+ /^STORAGE_SECRET_ACCESS_KEY=.+/m.test(content));
195
+ }
196
+ async function publishAssetsLocally() {
197
+ console.log(' → Publishing assets to R2...');
198
+ // Direct import avoids shelling out and needing a pre-built CLI
199
+ // publishAssets does not accept a cwd parameter — it uses process.cwd() internally
200
+ const { publishAssets } = await import('./publishAssets.js');
201
+ await publishAssets();
202
+ }
203
+ function publishAssetsViaMinIO(opts) {
204
+ const { ip, privateKeyPath, platform, cwd, dockerComposePath, envServerPath } = opts;
205
+ console.log(' → Syncing assets to server for MinIO publish...');
206
+ runRsync([
207
+ path.join(cwd, 'dist', 'server') + '/',
208
+ path.join(cwd, 'dist', 'client') + '/',
209
+ path.join(cwd, 'shared', 'Build.ts'),
210
+ path.join(cwd, 'package.json'),
211
+ path.join(cwd, 'package-lock.json'),
212
+ dockerComposePath,
213
+ envServerPath,
214
+ ], ip, privateKeyPath, platform, []);
215
+ console.log(' → Starting MinIO...');
216
+ runSsh(ip, privateKeyPath, platform, 'cd /srv/app && docker compose -f docker-compose.prod.yml up -d minio');
217
+ console.log(' → Waiting for MinIO...');
218
+ runSsh(ip, privateKeyPath, platform, 'for i in $(seq 1 20); do curl -sf http://localhost:9000/minio/health/live && break || sleep 3; done');
219
+ console.log(' → Installing dependencies on server...');
220
+ runSsh(ip, privateKeyPath, platform, 'cd /srv/app && npm ci --omit=dev');
221
+ console.log(' → Creating MinIO bucket...');
222
+ runSsh(ip, privateKeyPath, platform, `BUCKET=$(grep '^STORAGE_PUBLIC_BUCKET=' /srv/app/.env.server | cut -d= -f2) && ` +
223
+ `docker compose -f /srv/app/docker-compose.prod.yml exec -T minio ` +
224
+ `sh -c "mc alias set local http://localhost:9000 minioadmin minioadmin && mc mb --ignore-existing local/$BUCKET"`);
225
+ console.log(' → Publishing assets to MinIO...');
226
+ runSsh(ip, privateKeyPath, platform, `cd /srv/app && env $(grep -v '^#' .env.server | grep '=' | xargs -d '\\n') node dist/server/cli/index.js publish:assets`);
227
+ }
228
+ // ─── Server sync + start ──────────────────────────────────────────────────────
229
+ function syncServerFiles(opts) {
230
+ const { ip, privateKeyPath, platform, cwd, dockerComposePath, envServerPath, caddyfilePath, dockerfilePath } = opts;
231
+ const paths = [
232
+ path.join(cwd, 'dist', 'server') + '/',
233
+ path.join(cwd, 'package.json'),
234
+ path.join(cwd, 'package-lock.json'),
235
+ dockerComposePath,
236
+ envServerPath,
237
+ dockerfilePath,
238
+ ];
239
+ if (caddyfilePath)
240
+ paths.push(caddyfilePath);
241
+ runRsync(paths, ip, privateKeyPath, platform, ['--exclude=dist/client/', '--exclude=node_modules/', '--exclude=.git/']);
242
+ }
243
+ function startAndDeploy(opts) {
244
+ const { ip, privateKeyPath, platform, url } = opts;
245
+ console.log(' → Starting services...');
246
+ runSsh(ip, privateKeyPath, platform, 'cd /srv/app && docker compose -f docker-compose.prod.yml up -d mongo redis nats minio');
247
+ console.log(' → Waiting for MongoDB...');
248
+ runSsh(ip, privateKeyPath, platform, `for i in $(seq 1 30); do ` +
249
+ `docker compose -f /srv/app/docker-compose.prod.yml exec -T mongo mongosh --quiet --eval "db.adminCommand('ping')" 2>/dev/null && break || sleep 2; ` +
250
+ `done`);
251
+ console.log(' → Installing dependencies...');
252
+ runSsh(ip, privateKeyPath, platform, 'cd /srv/app && npm ci --omit=dev');
253
+ console.log(' → Running db:init...');
254
+ runSsh(ip, privateKeyPath, platform, `cd /srv/app && env $(grep -v '^#' .env.server | grep '=' | xargs -d '\\n') node dist/server/cli/index.js db:init`);
255
+ console.log(' → Running db:migrate...');
256
+ runSsh(ip, privateKeyPath, platform, `cd /srv/app && env $(grep -v '^#' .env.server | grep '=' | xargs -d '\\n') node dist/server/cli/index.js db:migrate`);
257
+ console.log(' → Starting app...');
258
+ runSsh(ip, privateKeyPath, platform, 'cd /srv/app && docker compose -f docker-compose.prod.yml up -d --build');
259
+ console.log(` ✓ Deploy complete — ${url}`);
260
+ }
261
+ // ─── Core deploy (shared by single + multi) ───────────────────────────────────
262
+ async function deploySingleServer(opts) {
263
+ const { client, tag, label, cwd, platform, dockerComposePath, envServerPath, caddyfilePath, dockerfilePath } = opts;
264
+ const prefix = label ? `[${label}] ` : '';
265
+ const log = (msg) => console.log(`${prefix}${msg}`);
266
+ // Detect SSH key
267
+ const { privateKeyPath, publicKey } = detectSshKey();
268
+ const sshKeyId = await ensureVultrSshKey(client, publicKey);
269
+ // Step [2/7]: Check for existing server
270
+ log('[2/7] Checking for existing server...');
271
+ const instances = await client.listInstances();
272
+ let ip = instances.find((i) => i.tags.includes(tag))?.main_ip ?? null;
273
+ if (!ip) {
274
+ log(' ✓ No existing server — provisioning');
275
+ // Prompt for plan/region only when provisioning is needed
276
+ const plan = opts.plan ?? await prompt(' Plan', DEFAULT_PLAN);
277
+ const region = opts.region ?? await prompt(' Region', DEFAULT_REGION);
278
+ // Step [3/7]: Provisioning server
279
+ log('[3/7] Provisioning server...');
280
+ const instance = await client.createInstance({
281
+ plan,
282
+ region,
283
+ osId: UBUNTU_22_OS_ID,
284
+ userData: STARTUP_SCRIPT,
285
+ sshKeyIds: [sshKeyId],
286
+ tags: [tag],
287
+ });
288
+ ip = await pollInstanceReady(client, instance.id);
289
+ log(` ✓ Server ready — IP: ${ip}`);
290
+ }
291
+ else {
292
+ log(` ✓ Server already exists — IP: ${ip}`);
293
+ log('[3/7] Provisioning server... (skipped)');
294
+ }
295
+ // Step [4/7]: Waiting for SSH
296
+ log('[4/7] Waiting for SSH...');
297
+ await pollSshReady(ip);
298
+ log(' ✓ SSH ready');
299
+ // Step [5/7]: Building & publishing assets
300
+ log('[5/7] Building & publishing assets...');
301
+ // Build (only if not already built for multi)
302
+ if (!opts.builtLocally) {
303
+ execSync('npm run build', { stdio: 'inherit', cwd });
304
+ }
305
+ if (isR2Configured(cwd)) {
306
+ await publishAssetsLocally();
307
+ }
308
+ else {
309
+ publishAssetsViaMinIO({ ip, privateKeyPath, platform, cwd, dockerComposePath, envServerPath });
310
+ }
311
+ log(' ✓ Assets published');
312
+ // Step [6/7]: Syncing files to server
313
+ log('[6/7] Syncing files to server...');
314
+ syncServerFiles({ ip, privateKeyPath, platform, cwd, dockerComposePath, envServerPath, caddyfilePath, dockerfilePath });
315
+ log(' ✓ Files synced');
316
+ // Step [7/7]: Starting services & deploying
317
+ log('[7/7] Starting services & deploying...');
318
+ const url = opts.domain ? `https://${opts.domain}` : `http://${ip}:3000`;
319
+ startAndDeploy({ ip, privateKeyPath, platform, url });
320
+ return { ip, url };
321
+ }
322
+ // ─── Public commands ──────────────────────────────────────────────────────────
323
+ export async function runDeploySingle() {
324
+ const cwd = process.cwd();
325
+ preflight(cwd);
326
+ const config = readUglyAppConfig(cwd);
327
+ const platform = getPlatformOrThrow();
328
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ugly-deploy-'));
329
+ try {
330
+ const generated = prepareGeneratedFiles({ cwd, domain: config.domain, tmpDir });
331
+ console.log('\n[1/7] Checking Vultr credentials...');
332
+ const apiKey = await loadOrPromptVultrKey();
333
+ const client = createVultrClient(apiKey);
334
+ console.log(' ✓ Credentials ready');
335
+ const { ip } = await deploySingleServer({
336
+ client,
337
+ tag: config.projectId,
338
+ label: '',
339
+ cwd,
340
+ domain: config.domain,
341
+ plan: undefined,
342
+ region: undefined,
343
+ platform,
344
+ ...generated,
345
+ builtLocally: false,
346
+ });
347
+ if (config.domain) {
348
+ console.log(`\n ! Set DNS A record: ${config.domain} → ${ip}`);
349
+ console.log(' Caddy will provision SSL automatically once DNS propagates.');
350
+ }
351
+ }
352
+ finally {
353
+ fs.rmSync(tmpDir, { recursive: true, force: true });
354
+ }
355
+ }
356
+ export async function runDeployMulti() {
357
+ const cwd = process.cwd();
358
+ preflight(cwd);
359
+ const config = readUglyAppConfig(cwd);
360
+ const platform = getPlatformOrThrow();
361
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ugly-deploy-'));
362
+ try {
363
+ const generated = prepareGeneratedFiles({ cwd, domain: config.domain, tmpDir });
364
+ console.log('\n[1/7] Checking Vultr credentials...');
365
+ const apiKey = await loadOrPromptVultrKey();
366
+ const client = createVultrClient(apiKey);
367
+ console.log(' ✓ Credentials ready');
368
+ const countStr = await prompt(' How many servers?', '2');
369
+ const count = parseInt(countStr, 10);
370
+ if (!Number.isInteger(count) || count < 1)
371
+ throw new Error('Server count must be a positive integer.');
372
+ // Build once before parallel work
373
+ console.log('\n → Building project...');
374
+ execSync('npm run build', { stdio: 'inherit', cwd });
375
+ const r2 = isR2Configured(cwd);
376
+ if (r2) {
377
+ console.log(' → Publishing assets to R2...');
378
+ await publishAssetsLocally();
379
+ }
380
+ // Find existing servers
381
+ const allInstances = await client.listInstances();
382
+ // Check for extra servers (scale-down warning)
383
+ const allTagged = allInstances.filter((i) => i.tags.some((t) => t.startsWith(`${config.projectId}-`)));
384
+ const extraTags = allTagged
385
+ .filter((i) => i.tags.some((t) => {
386
+ const n = parseInt(t.replace(`${config.projectId}-`, ''), 10);
387
+ return !isNaN(n) && n >= count;
388
+ }))
389
+ .map((i) => i.tags.find((t) => t.startsWith(`${config.projectId}-`)));
390
+ if (extraTags.length > 0) {
391
+ console.log(`\n ! Existing servers not targeted: ${extraTags.join(', ')}`);
392
+ console.log(' Delete them manually via the Vultr dashboard or vultr-cli.\n');
393
+ }
394
+ // Deploy all servers in parallel
395
+ const results = await Promise.allSettled(Array.from({ length: count }, (_, i) => deploySingleServer({
396
+ client,
397
+ tag: `${config.projectId}-${i}`,
398
+ label: `${config.projectId}-${i}`,
399
+ cwd,
400
+ domain: config.domain,
401
+ plan: undefined,
402
+ region: undefined,
403
+ platform,
404
+ ...generated,
405
+ builtLocally: true,
406
+ })));
407
+ console.log('\nServers:');
408
+ let anyFailed = false;
409
+ for (let i = 0; i < results.length; i++) {
410
+ const r = results[i];
411
+ const tag = `${config.projectId}-${i}`;
412
+ if (r.status === 'fulfilled') {
413
+ console.log(` ${tag} (${r.value.ip}): ✓ deployed`);
414
+ }
415
+ else {
416
+ console.log(` ${tag}: ✗ failed — ${r.reason.message}`);
417
+ anyFailed = true;
418
+ }
419
+ }
420
+ if (anyFailed)
421
+ process.exit(1);
422
+ }
423
+ finally {
424
+ fs.rmSync(tmpDir, { recursive: true, force: true });
425
+ }
426
+ }
427
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/cli/deploy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function generateDockerComposeYml(opts: {
2
+ domain: string | undefined;
3
+ }): string;
4
+ export declare function generateEnvServer(envContent: string): string;
5
+ export declare function generateCaddyfile(domain: string): string;
6
+ export declare function generateDefaultDockerfile(): string;
7
+ //# sourceMappingURL=deployGenerators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployGenerators.d.ts","sourceRoot":"","sources":["../../src/cli/deployGenerators.ts"],"names":[],"mappings":"AAAA,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,MAAM,CAkDrF;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAiB5D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAQlD"}
@@ -0,0 +1,80 @@
1
+ export function generateDockerComposeYml(opts) {
2
+ const caddy = opts.domain
3
+ ? `
4
+ caddy:
5
+ image: caddy:2-alpine
6
+ restart: always
7
+ ports: ["80:80", "443:443"]
8
+ volumes:
9
+ - ./Caddyfile:/etc/caddy/Caddyfile
10
+ - caddy_data:/data
11
+ depends_on: [app]`
12
+ : '';
13
+ const caddyVolume = opts.domain ? '\n caddy_data:' : '';
14
+ return `services:
15
+ mongo:
16
+ image: mongo:7
17
+ restart: always
18
+ volumes: [mongo_data:/data/db]
19
+
20
+ redis:
21
+ image: redis:7-alpine
22
+ restart: always
23
+
24
+ nats:
25
+ image: nats:2-alpine
26
+ restart: always
27
+
28
+ minio:
29
+ image: minio/minio
30
+ restart: always
31
+ command: server /data --console-address ":9001"
32
+ environment:
33
+ MINIO_ROOT_USER: minioadmin
34
+ MINIO_ROOT_PASSWORD: minioadmin
35
+ volumes: [minio_data:/data]
36
+ ports: ["9000:9000"]
37
+
38
+ app:
39
+ build: .
40
+ restart: always
41
+ env_file: .env.server
42
+ depends_on: [mongo, redis, nats, minio]
43
+ ports: ["3000:3000"]
44
+ ${caddy}
45
+ volumes:
46
+ mongo_data:
47
+ minio_data:${caddyVolume}
48
+ `;
49
+ }
50
+ export function generateEnvServer(envContent) {
51
+ return envContent
52
+ .split('\n')
53
+ .map((line) => {
54
+ // MONGODB_URI=mongodb://localhost:<port>/<db> → mongodb://mongo:27017/<db>
55
+ const mongoMatch = line.match(/^(MONGODB_URI=mongodb:\/\/)localhost:\d+(\/.*)?$/);
56
+ if (mongoMatch)
57
+ return `MONGODB_URI=mongodb://mongo:27017${mongoMatch[2] ?? '/'}`;
58
+ // REDIS_URL=redis://localhost:<port> → redis://redis:6379
59
+ if (/^REDIS_URL=redis:\/\/localhost:\d+/.test(line))
60
+ return 'REDIS_URL=redis://redis:6379';
61
+ // NATS_URL=nats://localhost:<port> → nats://nats:4222
62
+ if (/^NATS_URL=nats:\/\/localhost:\d+/.test(line))
63
+ return 'NATS_URL=nats://nats:4222';
64
+ return line;
65
+ })
66
+ .join('\n');
67
+ }
68
+ export function generateCaddyfile(domain) {
69
+ return `${domain} {\n reverse_proxy app:3000\n}\n`;
70
+ }
71
+ export function generateDefaultDockerfile() {
72
+ return `FROM node:20-alpine
73
+ WORKDIR /app
74
+ COPY package.json package-lock.json ./
75
+ RUN npm ci --omit=dev
76
+ COPY dist/server/ ./dist/server/
77
+ CMD ["node", "dist/server/index.js"]
78
+ `;
79
+ }
80
+ //# sourceMappingURL=deployGenerators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployGenerators.js","sourceRoot":"","sources":["../../src/cli/deployGenerators.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,wBAAwB,CAAC,IAAoC;IAC3E,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM;QACvB,CAAC,CAAC;;;;;;;;sBAQgB;QAClB,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;IAEzD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8BP,KAAK;;;eAGQ,WAAW;CACzB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,UAAkB;IAClD,OAAO,UAAU;SACd,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,2EAA2E;QAC3E,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAClF,IAAI,UAAU;YAAE,OAAO,oCAAoC,UAAU,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;QAElF,0DAA0D;QAC1D,IAAI,oCAAoC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,8BAA8B,CAAC;QAE3F,sDAAsD;QACtD,IAAI,kCAAkC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,2BAA2B,CAAC;QAEtF,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,OAAO,GAAG,MAAM,qCAAqC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,yBAAyB;IACvC,OAAO;;;;;;CAMR,CAAC;AACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=deployGenerators.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployGenerators.test.d.ts","sourceRoot":"","sources":["../../src/cli/deployGenerators.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,65 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { generateCaddyfile, generateDefaultDockerfile, generateDockerComposeYml, generateEnvServer, } from './deployGenerators.js';
3
+ describe('generateDockerComposeYml', () => {
4
+ it('includes all base services', () => {
5
+ const yml = generateDockerComposeYml({ domain: undefined });
6
+ expect(yml).toContain('image: mongo:7');
7
+ expect(yml).toContain('image: redis:7-alpine');
8
+ expect(yml).toContain('image: nats:2-alpine');
9
+ expect(yml).toContain('image: minio/minio');
10
+ expect(yml).toContain('build: .');
11
+ expect(yml).not.toContain('caddy');
12
+ });
13
+ it('includes caddy when domain is set', () => {
14
+ const yml = generateDockerComposeYml({ domain: 'myapp.com' });
15
+ expect(yml).toContain('image: caddy:2-alpine');
16
+ expect(yml).toContain('caddy_data');
17
+ expect(yml).toContain('80:80');
18
+ expect(yml).toContain('443:443');
19
+ });
20
+ it('uses .env.server for app env_file', () => {
21
+ const yml = generateDockerComposeYml({ domain: undefined });
22
+ expect(yml).toContain('env_file: .env.server');
23
+ expect(yml).not.toContain('env_file: .env\n');
24
+ });
25
+ });
26
+ describe('generateEnvServer', () => {
27
+ it('rewrites MONGODB_URI localhost to mongo service', () => {
28
+ const input = 'MONGODB_URI=mongodb://localhost:3003/mydb\nOTHER=val';
29
+ const output = generateEnvServer(input);
30
+ expect(output).toContain('MONGODB_URI=mongodb://mongo:27017/mydb');
31
+ expect(output).toContain('OTHER=val');
32
+ });
33
+ it('rewrites REDIS_URL to redis service', () => {
34
+ const output = generateEnvServer('REDIS_URL=redis://localhost:3004');
35
+ expect(output).toContain('REDIS_URL=redis://redis:6379');
36
+ });
37
+ it('rewrites NATS_URL to nats service', () => {
38
+ const output = generateEnvServer('NATS_URL=nats://localhost:3005');
39
+ expect(output).toContain('NATS_URL=nats://nats:4222');
40
+ });
41
+ it('passes through unrecognised vars unchanged', () => {
42
+ const output = generateEnvServer('FOO=bar\nBAZ=qux');
43
+ expect(output).toContain('FOO=bar');
44
+ expect(output).toContain('BAZ=qux');
45
+ });
46
+ it('handles empty input gracefully (no crash)', () => {
47
+ expect(() => generateEnvServer('')).not.toThrow();
48
+ });
49
+ });
50
+ describe('generateCaddyfile', () => {
51
+ it('produces reverse_proxy directive for domain', () => {
52
+ const out = generateCaddyfile('myapp.com');
53
+ expect(out).toContain('myapp.com {');
54
+ expect(out).toContain('reverse_proxy app:3000');
55
+ });
56
+ });
57
+ describe('generateDefaultDockerfile', () => {
58
+ it('copies dist/server and runs node', () => {
59
+ const out = generateDefaultDockerfile();
60
+ expect(out).toContain('COPY dist/server/ ./dist/server/');
61
+ expect(out).toContain('CMD ["node", "dist/server/index.js"]');
62
+ expect(out).toContain('npm ci --omit=dev');
63
+ });
64
+ });
65
+ //# sourceMappingURL=deployGenerators.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deployGenerators.test.js","sourceRoot":"","sources":["../../src/cli/deployGenerators.test.ts"],"names":[],"mappings":"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"}