@omg-dev/cli 0.4.31 → 0.4.32
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/dist/omg.mjs +183 -6
- package/package.json +1 -1
package/dist/omg.mjs
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/index.ts
|
|
5
|
-
import { readFileSync as
|
|
6
|
-
import { join as
|
|
5
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
6
|
+
import { join as join6, resolve as resolve3, basename, dirname as dirname3 } from "path";
|
|
7
7
|
|
|
8
8
|
// src/config.ts
|
|
9
9
|
import { homedir } from "os";
|
|
@@ -446,6 +446,30 @@ function getStatus(token, slug) {
|
|
|
446
446
|
function listApps(token) {
|
|
447
447
|
return controlPlane("/api/cli/apps/list", token);
|
|
448
448
|
}
|
|
449
|
+
function envList(token, slug) {
|
|
450
|
+
return controlPlane(`/api/cli/env/list?slug=${encodeURIComponent(slug)}`, token);
|
|
451
|
+
}
|
|
452
|
+
function envPull(token, slug) {
|
|
453
|
+
return controlPlane(`/api/cli/env/pull?slug=${encodeURIComponent(slug)}`, token);
|
|
454
|
+
}
|
|
455
|
+
function envSet(token, slug, vars) {
|
|
456
|
+
return controlPlane("/api/cli/env/set", token, {
|
|
457
|
+
method: "POST",
|
|
458
|
+
body: JSON.stringify({ slug, vars })
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
function envRemove(token, slug, keys) {
|
|
462
|
+
return controlPlane("/api/cli/env/rm", token, {
|
|
463
|
+
method: "POST",
|
|
464
|
+
body: JSON.stringify({ slug, keys })
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
function envImport(token, slug, contents) {
|
|
468
|
+
return controlPlane("/api/cli/env/import", token, {
|
|
469
|
+
method: "POST",
|
|
470
|
+
body: JSON.stringify({ slug, contents })
|
|
471
|
+
});
|
|
472
|
+
}
|
|
449
473
|
function getComputerConnectConfig(token) {
|
|
450
474
|
return controlPlane("/api/cli/computer/connect", token);
|
|
451
475
|
}
|
|
@@ -654,7 +678,7 @@ async function deploy(opts) {
|
|
|
654
678
|
if (collected.files.length === 0)
|
|
655
679
|
throw new Error(`No files to deploy in ${root}`);
|
|
656
680
|
for (const s of collected.skippedSecrets) {
|
|
657
|
-
onProgress(`skipping ${s} \u2014
|
|
681
|
+
onProgress(`skipping ${s} \u2014 import it with \`omg env push --file ${s}\``);
|
|
658
682
|
}
|
|
659
683
|
for (const s of collected.skippedLarge)
|
|
660
684
|
onProgress(`skipping ${s} \u2014 over the per-file limit`);
|
|
@@ -1306,6 +1330,145 @@ async function runDev(options) {
|
|
|
1306
1330
|
}
|
|
1307
1331
|
}
|
|
1308
1332
|
|
|
1333
|
+
// src/env.ts
|
|
1334
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync2 } from "fs";
|
|
1335
|
+
import { join as join5 } from "path";
|
|
1336
|
+
async function defaultReadStdin() {
|
|
1337
|
+
const chunks = [];
|
|
1338
|
+
for await (const chunk of process.stdin)
|
|
1339
|
+
chunks.push(chunk);
|
|
1340
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
1341
|
+
}
|
|
1342
|
+
function formatList(vars, out) {
|
|
1343
|
+
if (!vars.length) {
|
|
1344
|
+
out("No env vars set.");
|
|
1345
|
+
out("");
|
|
1346
|
+
out(" omg env set KEY=value set one");
|
|
1347
|
+
out(" omg env push --file .env import a local .env");
|
|
1348
|
+
return;
|
|
1349
|
+
}
|
|
1350
|
+
const width = Math.max(...vars.map((v) => v.key.length));
|
|
1351
|
+
for (const v of vars)
|
|
1352
|
+
out(` ${v.key.padEnd(width)} ${v.preview}`);
|
|
1353
|
+
}
|
|
1354
|
+
async function collectAssignments(args, readStdin) {
|
|
1355
|
+
const vars = {};
|
|
1356
|
+
for (let i = 0;i < args.length; i++) {
|
|
1357
|
+
const arg = args[i];
|
|
1358
|
+
const eq = arg.indexOf("=");
|
|
1359
|
+
if (eq > 0) {
|
|
1360
|
+
vars[arg.slice(0, eq)] = arg.slice(eq + 1);
|
|
1361
|
+
continue;
|
|
1362
|
+
}
|
|
1363
|
+
if (args[i + 1] === "-") {
|
|
1364
|
+
vars[arg] = (await readStdin()).replace(/\n$/, "");
|
|
1365
|
+
i++;
|
|
1366
|
+
continue;
|
|
1367
|
+
}
|
|
1368
|
+
throw new Error(`Expected KEY=value (or \`${arg} -\` to read the value from stdin), got "${arg}"`);
|
|
1369
|
+
}
|
|
1370
|
+
return vars;
|
|
1371
|
+
}
|
|
1372
|
+
function toDotenv(env) {
|
|
1373
|
+
return Object.keys(env).sort().map((k) => {
|
|
1374
|
+
const v = env[k] ?? "";
|
|
1375
|
+
const needsQuotes = /[\s"'#$`\\]/.test(v) || v === "";
|
|
1376
|
+
return `${k}=${needsQuotes ? JSON.stringify(v) : v}`;
|
|
1377
|
+
}).join(`
|
|
1378
|
+
`) + `
|
|
1379
|
+
`;
|
|
1380
|
+
}
|
|
1381
|
+
async function runEnv(opts) {
|
|
1382
|
+
const { args, slug, token, root, flag, out } = opts;
|
|
1383
|
+
const readStdin = opts.readStdin ?? defaultReadStdin;
|
|
1384
|
+
const sub = args[0] ?? "list";
|
|
1385
|
+
const rest = args.slice(1);
|
|
1386
|
+
switch (sub) {
|
|
1387
|
+
case "list":
|
|
1388
|
+
case "ls": {
|
|
1389
|
+
const { vars } = await envList(token, slug);
|
|
1390
|
+
formatList(vars, out);
|
|
1391
|
+
return 0;
|
|
1392
|
+
}
|
|
1393
|
+
case "set": {
|
|
1394
|
+
if (!rest.length) {
|
|
1395
|
+
out("Usage: omg env set KEY=value [KEY2=value2 ...]");
|
|
1396
|
+
out(" omg env set KEY - read the value from stdin");
|
|
1397
|
+
return 1;
|
|
1398
|
+
}
|
|
1399
|
+
const vars = await collectAssignments(rest, readStdin);
|
|
1400
|
+
const res = await envSet(token, slug, vars);
|
|
1401
|
+
for (const k of res.created)
|
|
1402
|
+
out(` + ${k}`);
|
|
1403
|
+
for (const k of res.updated)
|
|
1404
|
+
out(` ~ ${k} (updated)`);
|
|
1405
|
+
out("");
|
|
1406
|
+
out("Applies on next `omg deploy`.");
|
|
1407
|
+
return 0;
|
|
1408
|
+
}
|
|
1409
|
+
case "rm":
|
|
1410
|
+
case "remove":
|
|
1411
|
+
case "unset": {
|
|
1412
|
+
if (!rest.length) {
|
|
1413
|
+
out("Usage: omg env rm KEY [KEY2 ...]");
|
|
1414
|
+
return 1;
|
|
1415
|
+
}
|
|
1416
|
+
const res = await envRemove(token, slug, rest);
|
|
1417
|
+
for (const k of res.removed)
|
|
1418
|
+
out(` - ${k}`);
|
|
1419
|
+
for (const k of res.missing)
|
|
1420
|
+
out(` ? ${k} was not set`);
|
|
1421
|
+
if (res.removed.length) {
|
|
1422
|
+
out("");
|
|
1423
|
+
out("Applies on next `omg deploy`.");
|
|
1424
|
+
}
|
|
1425
|
+
return res.removed.length === 0 && res.missing.length ? 1 : 0;
|
|
1426
|
+
}
|
|
1427
|
+
case "pull": {
|
|
1428
|
+
const target = join5(root, flag("out") ?? ".env");
|
|
1429
|
+
if (existsSync2(target) && !args.includes("--force")) {
|
|
1430
|
+
out(`${target} already exists. Re-run with --force to overwrite.`);
|
|
1431
|
+
return 1;
|
|
1432
|
+
}
|
|
1433
|
+
const { env } = await envPull(token, slug);
|
|
1434
|
+
const keys = Object.keys(env);
|
|
1435
|
+
if (!keys.length) {
|
|
1436
|
+
out(`No env vars set for ${slug} \u2014 nothing to pull.`);
|
|
1437
|
+
return 0;
|
|
1438
|
+
}
|
|
1439
|
+
writeFileSync4(target, toDotenv(env), { mode: 384 });
|
|
1440
|
+
out(`Wrote ${keys.length} var${keys.length === 1 ? "" : "s"} to ${target}`);
|
|
1441
|
+
out("Add it to .gitignore \u2014 it holds real secrets.");
|
|
1442
|
+
return 0;
|
|
1443
|
+
}
|
|
1444
|
+
case "push":
|
|
1445
|
+
case "import": {
|
|
1446
|
+
const source = join5(root, flag("file") ?? ".env");
|
|
1447
|
+
if (!existsSync2(source)) {
|
|
1448
|
+
out(`No file at ${source}. Point at one with --file <path>.`);
|
|
1449
|
+
return 1;
|
|
1450
|
+
}
|
|
1451
|
+
const res = await envImport(token, slug, readFileSync4(source, "utf8"));
|
|
1452
|
+
for (const k of res.created)
|
|
1453
|
+
out(` + ${k}`);
|
|
1454
|
+
for (const k of res.updated)
|
|
1455
|
+
out(` ~ ${k} (updated)`);
|
|
1456
|
+
out("");
|
|
1457
|
+
out("Applies on next `omg deploy`.");
|
|
1458
|
+
return 0;
|
|
1459
|
+
}
|
|
1460
|
+
default:
|
|
1461
|
+
out(`Unknown: omg env ${sub}`);
|
|
1462
|
+
out("");
|
|
1463
|
+
out(" omg env list (masked)");
|
|
1464
|
+
out(" omg env set KEY=value set one or many");
|
|
1465
|
+
out(" omg env rm KEY remove");
|
|
1466
|
+
out(" omg env pull [--out .env] write real values locally");
|
|
1467
|
+
out(" omg env push [--file .env] import a local .env");
|
|
1468
|
+
return 1;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1309
1472
|
// src/index.ts
|
|
1310
1473
|
var argv = process.argv.slice(2);
|
|
1311
1474
|
var cmd = argv[0] ?? "help";
|
|
@@ -1319,15 +1482,15 @@ var out = (msg = "") => process.stdout.write(msg + `
|
|
|
1319
1482
|
var step = (msg) => out(` ${msg}`);
|
|
1320
1483
|
function readLink(root) {
|
|
1321
1484
|
try {
|
|
1322
|
-
return JSON.parse(
|
|
1485
|
+
return JSON.parse(readFileSync5(join6(root, LINK_FILE), "utf8"));
|
|
1323
1486
|
} catch {
|
|
1324
1487
|
return null;
|
|
1325
1488
|
}
|
|
1326
1489
|
}
|
|
1327
1490
|
function writeLink(root, link) {
|
|
1328
|
-
const path =
|
|
1491
|
+
const path = join6(root, LINK_FILE);
|
|
1329
1492
|
mkdirSync3(dirname3(path), { recursive: true });
|
|
1330
|
-
|
|
1493
|
+
writeFileSync5(path, JSON.stringify(link, null, 2) + `
|
|
1331
1494
|
`);
|
|
1332
1495
|
}
|
|
1333
1496
|
var HELP = `omg \u2014 deploy a local project to omg.dev
|
|
@@ -1335,6 +1498,11 @@ var HELP = `omg \u2014 deploy a local project to omg.dev
|
|
|
1335
1498
|
omg create <name> [--no-install]
|
|
1336
1499
|
omg deploy [--name <name>] [--dir <path>] [--no-wait]
|
|
1337
1500
|
omg status [--dir <path>]
|
|
1501
|
+
omg env list env vars (masked)
|
|
1502
|
+
omg env set KEY=value [KEY2=v2 ...] set (KEY - reads stdin)
|
|
1503
|
+
omg env rm KEY [KEY2 ...] remove
|
|
1504
|
+
omg env pull [--out .env] [--force] write real values locally
|
|
1505
|
+
omg env push [--file .env] import a local .env
|
|
1338
1506
|
omg link <slug> [--dir <path>]
|
|
1339
1507
|
omg login [--token <omg_sk_...>]
|
|
1340
1508
|
omg logout
|
|
@@ -1435,6 +1603,15 @@ async function main() {
|
|
|
1435
1603
|
out(`${link.slug}: ${status}`);
|
|
1436
1604
|
return 0;
|
|
1437
1605
|
}
|
|
1606
|
+
case "env": {
|
|
1607
|
+
const token = await requireToken();
|
|
1608
|
+
const link = readLink(root);
|
|
1609
|
+
if (!link?.slug) {
|
|
1610
|
+
out("Not linked to an app. Run `omg deploy` or `omg link <slug>` first.");
|
|
1611
|
+
return 1;
|
|
1612
|
+
}
|
|
1613
|
+
return runEnv({ args: argv.slice(1), slug: link.slug, token, root, flag, out });
|
|
1614
|
+
}
|
|
1438
1615
|
case "deploy": {
|
|
1439
1616
|
const token = await requireToken();
|
|
1440
1617
|
const link = readLink(root);
|