@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.
Files changed (2) hide show
  1. package/dist/omg.mjs +183 -6
  2. 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 readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "fs";
6
- import { join as join5, resolve as resolve3, basename, dirname as dirname3 } from "path";
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 set secrets in project settings, not the artifact`);
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(readFileSync4(join5(root, LINK_FILE), "utf8"));
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 = join5(root, LINK_FILE);
1491
+ const path = join6(root, LINK_FILE);
1329
1492
  mkdirSync3(dirname3(path), { recursive: true });
1330
- writeFileSync4(path, JSON.stringify(link, null, 2) + `
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omg-dev/cli",
3
- "version": "0.4.31",
3
+ "version": "0.4.32",
4
4
  "description": "Deploy and develop omg apps from your terminal.",
5
5
  "type": "module",
6
6
  "bin": {