deepspace 0.3.7 → 0.3.8

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/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/cli.ts
4
- import { defineCommand as defineCommand14, runMain } from "citty";
4
+ import { defineCommand as defineCommand16, runMain } from "citty";
5
5
  import { execSync as execSync5 } from "child_process";
6
6
  import { readFileSync as readFileSync9, existsSync as existsSync11 } from "fs";
7
7
  import { dirname as dirname2, join as join12 } from "path";
@@ -345,7 +345,7 @@ function openBrowser(url) {
345
345
  });
346
346
  }
347
347
  function sleep(ms) {
348
- return new Promise((resolve6) => setTimeout(resolve6, ms));
348
+ return new Promise((resolve7) => setTimeout(resolve7, ms));
349
349
  }
350
350
  async function doEmailLogin(email, password) {
351
351
  const res = await fetch(`${AUTH_URL}/api/auth/sign-in/email`, {
@@ -439,13 +439,13 @@ async function ensureToken() {
439
439
  return existing;
440
440
  }
441
441
  }
442
- const token = await exchangeSession(AUTH_URL3, sessionToken);
443
- if (!token) {
442
+ const token2 = await exchangeSession(AUTH_URL3, sessionToken);
443
+ if (!token2) {
444
444
  throw new Error("Session expired. Run `deepspace login` to re-authenticate.");
445
445
  }
446
446
  mkdirSync2(DIR2, { recursive: true });
447
- writeFileSync3(TOKEN_PATH2, token, { mode: 384 });
448
- return token;
447
+ writeFileSync3(TOKEN_PATH2, token2, { mode: 384 });
448
+ return token2;
449
449
  }
450
450
  function isTokenValid(jwt) {
451
451
  try {
@@ -488,16 +488,16 @@ var dev_default = defineCommand3({
488
488
  console.error("No wrangler.toml found. Are you in a DeepSpace app directory?");
489
489
  process.exit(1);
490
490
  }
491
- let token;
491
+ let token2;
492
492
  try {
493
- token = await ensureToken();
493
+ token2 = await ensureToken();
494
494
  } catch (err) {
495
495
  console.error(err.message);
496
496
  process.exit(1);
497
497
  }
498
498
  let payload;
499
499
  try {
500
- payload = JSON.parse(atob(token.split(".")[1]));
500
+ payload = JSON.parse(atob(token2.split(".")[1]));
501
501
  } catch {
502
502
  console.error("Malformed session token. Run `npx deepspace login`.");
503
503
  process.exit(1);
@@ -505,7 +505,7 @@ var dev_default = defineCommand3({
505
505
  console.log(`Logged in as ${payload.name ?? payload.email}`);
506
506
  console.log(`Environment: ${env}`);
507
507
  console.log(`Port: ${port}`);
508
- await writeDevVars(appDir, env, payload.sub, token);
508
+ await writeDevVars(appDir, env, payload.sub, token2);
509
509
  console.log("Starting dev server...\n");
510
510
  const vite = spawn(
511
511
  "npx",
@@ -698,7 +698,33 @@ function isAlive(pid) {
698
698
  import { defineCommand as defineCommand5 } from "citty";
699
699
  import { existsSync as existsSync5 } from "fs";
700
700
  import { join as join6, resolve as resolve2 } from "path";
701
+ import { spawnSync as spawnSync3 } from "child_process";
702
+
703
+ // src/cli/lib/playwright.ts
701
704
  import { execSync, spawnSync as spawnSync2 } from "child_process";
705
+ function ensurePlaywright(appDir) {
706
+ try {
707
+ execSync("npx playwright --version", { cwd: appDir, stdio: "pipe" });
708
+ } catch {
709
+ console.log("Installing Playwright...");
710
+ execSync("npm install -D @playwright/test", { cwd: appDir, stdio: "pipe" });
711
+ }
712
+ const isLinux = process.platform === "linux";
713
+ const isRoot = isLinux && typeof process.getuid === "function" && process.getuid() === 0;
714
+ const args = isRoot ? ["install", "--with-deps", "chromium"] : ["install", "chromium"];
715
+ const result = spawnSync2("npx", ["playwright", ...args], {
716
+ cwd: appDir,
717
+ stdio: "inherit",
718
+ shell: process.platform === "win32"
719
+ });
720
+ if (result.status !== 0) {
721
+ console.error("\nPlaywright install failed. On Linux, system libs may be missing. Try:");
722
+ console.error(" sudo npx playwright install --with-deps chromium");
723
+ process.exit(1);
724
+ }
725
+ }
726
+
727
+ // src/cli/commands/test.ts
702
728
  var DEFAULT_PORT3 = 5173;
703
729
  var test_default = defineCommand5({
704
730
  meta: {
@@ -725,17 +751,17 @@ var test_default = defineCommand5({
725
751
  console.error("No wrangler.toml found. Are you in a DeepSpace app directory?");
726
752
  process.exit(1);
727
753
  }
728
- let token;
754
+ let token2;
729
755
  let ownerId;
730
756
  try {
731
- token = await ensureToken();
732
- const payload = JSON.parse(atob(token.split(".")[1]));
757
+ token2 = await ensureToken();
758
+ const payload = JSON.parse(atob(token2.split(".")[1]));
733
759
  ownerId = payload.sub;
734
760
  } catch (err) {
735
761
  console.error("`deepspace test` requires you to be logged in. Run `deepspace login` first.");
736
762
  process.exit(1);
737
763
  }
738
- await writeDevVars(appDir, "dev", ownerId, token);
764
+ await writeDevVars(appDir, "dev", ownerId, token2);
739
765
  if (suite !== "unit") {
740
766
  ensurePlaywright(appDir);
741
767
  }
@@ -773,7 +799,7 @@ var test_default = defineCommand5({
773
799
  }
774
800
  });
775
801
  function runPlaywright(appDir, testFiles, port) {
776
- const result = spawnSync2("npx", [
802
+ const result = spawnSync3("npx", [
777
803
  "playwright",
778
804
  "test",
779
805
  "--config",
@@ -788,30 +814,13 @@ function runPlaywright(appDir, testFiles, port) {
788
814
  return result.status ?? 1;
789
815
  }
790
816
  function runVitest(appDir) {
791
- const result = spawnSync2("npx", ["vitest", "run", "--passWithNoTests"], {
817
+ const result = spawnSync3("npx", ["vitest", "run", "--passWithNoTests"], {
792
818
  cwd: appDir,
793
819
  stdio: "inherit",
794
820
  shell: process.platform === "win32"
795
821
  });
796
822
  return result.status ?? 1;
797
823
  }
798
- function ensurePlaywright(appDir) {
799
- try {
800
- execSync("npx playwright --version", { cwd: appDir, stdio: "pipe" });
801
- } catch {
802
- console.log("Installing Playwright...");
803
- execSync("npm install -D @playwright/test", { cwd: appDir, stdio: "pipe" });
804
- }
805
- const isLinux = process.platform === "linux";
806
- const isRoot = isLinux && typeof process.getuid === "function" && process.getuid() === 0;
807
- const args = isRoot ? ["install", "--with-deps", "chromium"] : ["install", "chromium"];
808
- const result = spawnSync2("npx", ["playwright", ...args], { cwd: appDir, stdio: "inherit" });
809
- if (result.status !== 0) {
810
- console.error("\nPlaywright install failed. On Linux, system libs may be missing \u2014 try:");
811
- console.error(" sudo npx playwright install --with-deps chromium");
812
- process.exit(1);
813
- }
814
- }
815
824
  function resolvePort3(arg) {
816
825
  const raw = arg ?? process.env.DEEPSPACE_PORT;
817
826
  if (!raw) return DEFAULT_PORT3;
@@ -823,8 +832,56 @@ function resolvePort3(arg) {
823
832
  return n;
824
833
  }
825
834
 
826
- // src/cli/commands/test-accounts.ts
835
+ // src/cli/commands/screenshot.ts
827
836
  import { defineCommand as defineCommand6 } from "citty";
837
+ import { spawnSync as spawnSync4 } from "child_process";
838
+ import { resolve as resolve3 } from "path";
839
+ var screenshot_default = defineCommand6({
840
+ meta: {
841
+ name: "screenshot",
842
+ description: "Take a Playwright screenshot, installing Chromium on demand"
843
+ },
844
+ args: {
845
+ url: {
846
+ type: "positional",
847
+ description: "URL to capture, for example http://localhost:5173/",
848
+ required: true
849
+ },
850
+ output: {
851
+ type: "positional",
852
+ description: "Output image path, for example screenshot.png",
853
+ required: true
854
+ },
855
+ "full-page": {
856
+ type: "boolean",
857
+ description: "Capture the full scrollable page",
858
+ required: false
859
+ },
860
+ "wait-for-timeout": {
861
+ type: "string",
862
+ description: "Milliseconds to wait before capture",
863
+ required: false
864
+ }
865
+ },
866
+ run({ args }) {
867
+ const appDir = resolve3(".");
868
+ ensurePlaywright(appDir);
869
+ const playwrightArgs = ["playwright", "screenshot", args.url, args.output];
870
+ if (args["full-page"]) playwrightArgs.push("--full-page");
871
+ if (args["wait-for-timeout"]) {
872
+ playwrightArgs.push("--wait-for-timeout", String(args["wait-for-timeout"]));
873
+ }
874
+ const result = spawnSync4("npx", playwrightArgs, {
875
+ cwd: appDir,
876
+ stdio: "inherit",
877
+ shell: process.platform === "win32"
878
+ });
879
+ process.exit(result.status ?? 1);
880
+ }
881
+ });
882
+
883
+ // src/cli/commands/test-accounts.ts
884
+ import { defineCommand as defineCommand7 } from "citty";
828
885
  import * as p3 from "@clack/prompts";
829
886
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
830
887
  import { join as join7 } from "path";
@@ -846,8 +903,8 @@ function saveAccounts(accounts) {
846
903
  writeFileSync4(ACCOUNTS_PATH, JSON.stringify(accounts, null, 2), { mode: 384 });
847
904
  }
848
905
  function sessionCookie() {
849
- const token = readFileSync4(SESSION_PATH2, "utf-8").trim();
850
- return `${SESSION_COOKIE2}=${encodeURIComponent(token)}`;
906
+ const token2 = readFileSync4(SESSION_PATH2, "utf-8").trim();
907
+ return `${SESSION_COOKIE2}=${encodeURIComponent(token2)}`;
851
908
  }
852
909
  async function fetchRemoteAccounts() {
853
910
  const res = await fetch(`${AUTH_URL4}/api/auth/test-accounts`, {
@@ -869,7 +926,7 @@ async function deleteRemote(id) {
869
926
  throw new Error(data.error ?? `DELETE returned ${res.status}`);
870
927
  }
871
928
  }
872
- var create = defineCommand6({
929
+ var create = defineCommand7({
873
930
  meta: {
874
931
  name: "create",
875
932
  description: "Create a test account"
@@ -939,7 +996,7 @@ var create = defineCommand6({
939
996
  Saved to ${ACCOUNTS_PATH}`);
940
997
  }
941
998
  });
942
- var list = defineCommand6({
999
+ var list = defineCommand7({
943
1000
  meta: {
944
1001
  name: "list",
945
1002
  description: "List your test accounts"
@@ -974,7 +1031,7 @@ var list = defineCommand6({
974
1031
  }
975
1032
  }
976
1033
  });
977
- var del = defineCommand6({
1034
+ var del = defineCommand7({
978
1035
  meta: {
979
1036
  name: "delete",
980
1037
  description: "Delete a test account by --email or --id"
@@ -1031,7 +1088,7 @@ var del = defineCommand6({
1031
1088
  console.log(`Test account deleted${targetEmail ? `: ${targetEmail}` : `: ${targetId}`}`);
1032
1089
  }
1033
1090
  });
1034
- var clear = defineCommand6({
1091
+ var clear = defineCommand7({
1035
1092
  meta: {
1036
1093
  name: "clear",
1037
1094
  description: "Delete all your test accounts (or those matching --label)"
@@ -1097,7 +1154,7 @@ Failed:`);
1097
1154
  }
1098
1155
  }
1099
1156
  });
1100
- var test_accounts_default = defineCommand6({
1157
+ var test_accounts_default = defineCommand7({
1101
1158
  meta: {
1102
1159
  name: "test-accounts",
1103
1160
  description: "Manage test accounts for development"
@@ -1111,11 +1168,11 @@ var test_accounts_default = defineCommand6({
1111
1168
  });
1112
1169
 
1113
1170
  // src/cli/commands/deploy.ts
1114
- import { defineCommand as defineCommand7 } from "citty";
1171
+ import { defineCommand as defineCommand8 } from "citty";
1115
1172
  import { execSync as execSync2 } from "child_process";
1116
1173
  import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync7 } from "fs";
1117
1174
  import { parse as parseToml2 } from "smol-toml";
1118
- import { join as join8, resolve as resolve3, dirname } from "path";
1175
+ import { join as join8, resolve as resolve4, dirname } from "path";
1119
1176
  import * as p4 from "@clack/prompts";
1120
1177
 
1121
1178
  // src/server/rooms/binding-manifest.ts
@@ -1376,7 +1433,7 @@ function sanitizeAppName(raw) {
1376
1433
 
1377
1434
  // src/cli/commands/deploy.ts
1378
1435
  var DEPLOY_URL = process.env.DEEPSPACE_DEPLOY_URL ?? ENVS.prod.deploy;
1379
- var deploy_default = defineCommand7({
1436
+ var deploy_default = defineCommand8({
1380
1437
  meta: {
1381
1438
  name: "deploy",
1382
1439
  description: "Build and deploy your DeepSpace app"
@@ -1389,7 +1446,7 @@ var deploy_default = defineCommand7({
1389
1446
  }
1390
1447
  },
1391
1448
  async run({ args }) {
1392
- const appDir = resolve3(args.dir ?? ".");
1449
+ const appDir = resolve4(args.dir ?? ".");
1393
1450
  p4.intro("Deploying DeepSpace app");
1394
1451
  const wranglerPath = join8(appDir, "wrangler.toml");
1395
1452
  if (!existsSync7(wranglerPath)) {
@@ -1405,9 +1462,9 @@ var deploy_default = defineCommand7({
1405
1462
  if (nameRes.warning) p4.log.warn(nameRes.warning);
1406
1463
  const appName = nameRes.name;
1407
1464
  p4.log.info(`App: ${appName}`);
1408
- let token;
1465
+ let token2;
1409
1466
  try {
1410
- token = await ensureToken();
1467
+ token2 = await ensureToken();
1411
1468
  } catch (err) {
1412
1469
  p4.cancel(err.message);
1413
1470
  process.exit(1);
@@ -1428,7 +1485,7 @@ var deploy_default = defineCommand7({
1428
1485
  process.exit(1);
1429
1486
  }
1430
1487
  const deployConfig = JSON.parse(readFileSync5(deployConfigPath, "utf-8"));
1431
- const outputWranglerPath = resolve3(dirname(deployConfigPath), deployConfig.configPath);
1488
+ const outputWranglerPath = resolve4(dirname(deployConfigPath), deployConfig.configPath);
1432
1489
  if (!existsSync7(outputWranglerPath)) {
1433
1490
  p4.cancel(`Output wrangler.json not found at ${outputWranglerPath}`);
1434
1491
  process.exit(1);
@@ -1436,7 +1493,7 @@ var deploy_default = defineCommand7({
1436
1493
  const outputConfig = JSON.parse(readFileSync5(outputWranglerPath, "utf-8"));
1437
1494
  const workerDir = dirname(outputWranglerPath);
1438
1495
  const workerBundlePath = join8(workerDir, outputConfig.main);
1439
- const clientDir = outputConfig.assets?.directory ? resolve3(workerDir, outputConfig.assets.directory) : null;
1496
+ const clientDir = outputConfig.assets?.directory ? resolve4(workerDir, outputConfig.assets.directory) : null;
1440
1497
  if (!existsSync7(workerBundlePath)) {
1441
1498
  p4.cancel(`Worker bundle not found at ${workerBundlePath}`);
1442
1499
  process.exit(1);
@@ -1525,7 +1582,7 @@ var deploy_default = defineCommand7({
1525
1582
  }
1526
1583
  const res = await fetch(`${DEPLOY_URL}/api/deploy/${appName}`, {
1527
1584
  method: "POST",
1528
- headers: { Authorization: `Bearer ${token}` },
1585
+ headers: { Authorization: `Bearer ${token2}` },
1529
1586
  body: form
1530
1587
  });
1531
1588
  const body = await res.json().catch(() => ({}));
@@ -1590,13 +1647,13 @@ function collectAssets(dir) {
1590
1647
  }
1591
1648
 
1592
1649
  // src/cli/commands/undeploy.ts
1593
- import { defineCommand as defineCommand8 } from "citty";
1650
+ import { defineCommand as defineCommand9 } from "citty";
1594
1651
  import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
1595
1652
  import { join as join9 } from "path";
1596
1653
  import { parse as parseToml3 } from "smol-toml";
1597
1654
  import * as p5 from "@clack/prompts";
1598
1655
  var DEPLOY_URL2 = process.env.DEEPSPACE_DEPLOY_URL ?? ENVS.prod.deploy;
1599
- var undeploy_default = defineCommand8({
1656
+ var undeploy_default = defineCommand9({
1600
1657
  meta: {
1601
1658
  name: "undeploy",
1602
1659
  description: "Remove a deployed DeepSpace app"
@@ -1621,9 +1678,9 @@ var undeploy_default = defineCommand8({
1621
1678
  p5.cancel("Provide an app name or run from a DeepSpace app directory.");
1622
1679
  process.exit(1);
1623
1680
  }
1624
- let token;
1681
+ let token2;
1625
1682
  try {
1626
- token = await ensureToken();
1683
+ token2 = await ensureToken();
1627
1684
  } catch (err) {
1628
1685
  p5.cancel(err.message);
1629
1686
  process.exit(1);
@@ -1633,7 +1690,7 @@ var undeploy_default = defineCommand8({
1633
1690
  s.start("Removing...");
1634
1691
  const res = await fetch(`${DEPLOY_URL2}/api/deploy/${appName}`, {
1635
1692
  method: "DELETE",
1636
- headers: { Authorization: `Bearer ${token}` }
1693
+ headers: { Authorization: `Bearer ${token2}` }
1637
1694
  });
1638
1695
  const body = await res.json().catch(() => ({}));
1639
1696
  if (!res.ok || !body.success) {
@@ -1647,8 +1704,8 @@ var undeploy_default = defineCommand8({
1647
1704
  });
1648
1705
 
1649
1706
  // src/cli/commands/whoami.ts
1650
- import { defineCommand as defineCommand9 } from "citty";
1651
- var whoami_default = defineCommand9({
1707
+ import { defineCommand as defineCommand10 } from "citty";
1708
+ var whoami_default = defineCommand10({
1652
1709
  meta: {
1653
1710
  name: "whoami",
1654
1711
  description: "Show the currently logged-in user"
@@ -1702,16 +1759,16 @@ var whoami_default = defineCommand9({
1702
1759
  });
1703
1760
 
1704
1761
  // src/cli/commands/add.ts
1705
- import { defineCommand as defineCommand10 } from "citty";
1762
+ import { defineCommand as defineCommand11 } from "citty";
1706
1763
  import { existsSync as existsSync9 } from "fs";
1707
- import { resolve as resolve4, join as join10 } from "path";
1764
+ import { resolve as resolve5, join as join10 } from "path";
1708
1765
  import { execSync as execSync3 } from "child_process";
1709
1766
  function findScript(from) {
1710
1767
  const candidate = join10(from, ".deepspace", "scripts", "add-feature.cjs");
1711
1768
  if (existsSync9(candidate)) return candidate;
1712
1769
  return null;
1713
1770
  }
1714
- var add_default = defineCommand10({
1771
+ var add_default = defineCommand11({
1715
1772
  meta: {
1716
1773
  name: "add",
1717
1774
  description: "Add a feature to your DeepSpace app"
@@ -1740,7 +1797,7 @@ var add_default = defineCommand10({
1740
1797
  }
1741
1798
  },
1742
1799
  run({ args }) {
1743
- const appDir = resolve4(args.dir ?? ".");
1800
+ const appDir = resolve5(args.dir ?? ".");
1744
1801
  const script = findScript(appDir);
1745
1802
  if (!script) {
1746
1803
  console.error("No .deepspace/scripts/add-feature.cjs found.");
@@ -1765,15 +1822,15 @@ var add_default = defineCommand10({
1765
1822
  });
1766
1823
 
1767
1824
  // src/cli/commands/domain.ts
1768
- import { defineCommand as defineCommand11 } from "citty";
1825
+ import { defineCommand as defineCommand12 } from "citty";
1769
1826
  import { execSync as execSync4 } from "child_process";
1770
1827
 
1771
1828
  // src/cli/lib/app-context.ts
1772
1829
  import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
1773
- import { join as join11, resolve as resolve5 } from "path";
1830
+ import { join as join11, resolve as resolve6 } from "path";
1774
1831
  import { parse as parseToml4 } from "smol-toml";
1775
1832
  function detectAppName(cwd = process.cwd()) {
1776
- const wranglerPath = join11(resolve5(cwd), "wrangler.toml");
1833
+ const wranglerPath = join11(resolve6(cwd), "wrangler.toml");
1777
1834
  if (!existsSync10(wranglerPath)) return null;
1778
1835
  try {
1779
1836
  const cfg = parseToml4(readFileSync7(wranglerPath, "utf-8"));
@@ -1793,11 +1850,11 @@ function requireAppName(explicit, cwd) {
1793
1850
 
1794
1851
  // src/cli/commands/domain.ts
1795
1852
  var API_URL = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
1796
- async function api(token, path, init) {
1853
+ async function api(token2, path, init) {
1797
1854
  const res = await fetch(`${API_URL}${path}`, {
1798
1855
  ...init,
1799
1856
  headers: {
1800
- Authorization: `Bearer ${token}`,
1857
+ Authorization: `Bearer ${token2}`,
1801
1858
  "Content-Type": "application/json",
1802
1859
  ...init?.headers ?? {}
1803
1860
  }
@@ -1838,15 +1895,15 @@ async function confirm2(message) {
1838
1895
  throw new Error(`${message} \u2014 pass --yes to confirm non-interactively`);
1839
1896
  }
1840
1897
  process.stdout.write(`${message} [y/N] `);
1841
- return new Promise((resolve6) => {
1898
+ return new Promise((resolve7) => {
1842
1899
  process.stdin.setEncoding("utf-8");
1843
1900
  process.stdin.once("data", (data) => {
1844
1901
  const answer = data.toString().trim().toLowerCase();
1845
- resolve6(answer === "y" || answer === "yes");
1902
+ resolve7(answer === "y" || answer === "yes");
1846
1903
  });
1847
1904
  });
1848
1905
  }
1849
- var search = defineCommand11({
1906
+ var search = defineCommand12({
1850
1907
  meta: { name: "search", description: "Search for available domains" },
1851
1908
  args: {
1852
1909
  query: { type: "positional", description: "Domain or keyword", required: true },
@@ -1854,10 +1911,10 @@ var search = defineCommand11({
1854
1911
  json: { type: "boolean", description: "Emit JSON instead of a table" }
1855
1912
  },
1856
1913
  async run({ args }) {
1857
- const token = await ensureToken();
1914
+ const token2 = await ensureToken();
1858
1915
  const limit = parseInt(args.limit ?? "10", 10) || 10;
1859
1916
  const result = await api(
1860
- token,
1917
+ token2,
1861
1918
  `/api/domains/search?q=${encodeURIComponent(args.query)}&limit=${limit}`
1862
1919
  );
1863
1920
  if (args.json) {
@@ -1876,7 +1933,7 @@ var search = defineCommand11({
1876
1933
  }
1877
1934
  }
1878
1935
  });
1879
- var buy = defineCommand11({
1936
+ var buy = defineCommand12({
1880
1937
  meta: { name: "buy", description: "Buy a domain and attach it to an app" },
1881
1938
  args: {
1882
1939
  domain: { type: "positional", description: "Domain to buy", required: true },
@@ -1887,9 +1944,9 @@ var buy = defineCommand11({
1887
1944
  json: { type: "boolean", description: "Emit JSON to stdout", default: false }
1888
1945
  },
1889
1946
  async run({ args }) {
1890
- const token = await ensureToken();
1947
+ const token2 = await ensureToken();
1891
1948
  const appName = requireAppName(args.app);
1892
- const priceCheck = await api(token, "/api/domains/check", {
1949
+ const priceCheck = await api(token2, "/api/domains/check", {
1893
1950
  method: "POST",
1894
1951
  body: JSON.stringify({ domains: [args.domain] })
1895
1952
  });
@@ -1910,7 +1967,7 @@ var buy = defineCommand11({
1910
1967
  }
1911
1968
  }
1912
1969
  const checkout = await api(
1913
- token,
1970
+ token2,
1914
1971
  "/api/domains/checkout",
1915
1972
  {
1916
1973
  method: "POST",
@@ -1937,7 +1994,7 @@ var buy = defineCommand11({
1937
1994
  await new Promise((r) => setTimeout(r, 5e3));
1938
1995
  try {
1939
1996
  const detail = await api(
1940
- token,
1997
+ token2,
1941
1998
  `/api/domains/${checkout.purchaseId}`
1942
1999
  );
1943
2000
  if (detail.domain.status !== lastStatus) {
@@ -1965,14 +2022,14 @@ var buy = defineCommand11({
1965
2022
  process.exit(1);
1966
2023
  }
1967
2024
  });
1968
- var list2 = defineCommand11({
2025
+ var list2 = defineCommand12({
1969
2026
  meta: { name: "list", description: "List your domains" },
1970
2027
  args: {
1971
2028
  json: { type: "boolean", description: "Emit JSON" }
1972
2029
  },
1973
2030
  async run({ args }) {
1974
- const token = await ensureToken();
1975
- const result = await api(token, "/api/domains");
2031
+ const token2 = await ensureToken();
2032
+ const result = await api(token2, "/api/domains");
1976
2033
  if (args.json) {
1977
2034
  process.stdout.write(JSON.stringify(scrubInternal(result), null, 2) + "\n");
1978
2035
  return;
@@ -1989,15 +2046,15 @@ var list2 = defineCommand11({
1989
2046
  }
1990
2047
  }
1991
2048
  });
1992
- var status = defineCommand11({
2049
+ var status = defineCommand12({
1993
2050
  meta: { name: "status", description: "Show details for one domain" },
1994
2051
  args: {
1995
2052
  domain: { type: "positional", description: "Domain", required: true },
1996
2053
  json: { type: "boolean" }
1997
2054
  },
1998
2055
  async run({ args }) {
1999
- const token = await ensureToken();
2000
- const all = await api(token, "/api/domains");
2056
+ const token2 = await ensureToken();
2057
+ const all = await api(token2, "/api/domains");
2001
2058
  const found = all.domains.find((d) => d.domain === args.domain);
2002
2059
  if (!found) {
2003
2060
  console.error(`No domain ${args.domain} in your account`);
@@ -2017,7 +2074,7 @@ var status = defineCommand11({
2017
2074
  console.log(`Charged: ${fmtCents(found.chargedCents)}/yr`);
2018
2075
  }
2019
2076
  });
2020
- var attach = defineCommand11({
2077
+ var attach = defineCommand12({
2021
2078
  meta: { name: "attach", description: "Re-point a domain at a different app" },
2022
2079
  args: {
2023
2080
  domain: { type: "positional", description: "Domain to re-point", required: true },
@@ -2025,16 +2082,16 @@ var attach = defineCommand11({
2025
2082
  json: { type: "boolean" }
2026
2083
  },
2027
2084
  async run({ args }) {
2028
- const token = await ensureToken();
2085
+ const token2 = await ensureToken();
2029
2086
  const targetApp = requireAppName(args.app);
2030
- const all = await api(token, "/api/domains");
2087
+ const all = await api(token2, "/api/domains");
2031
2088
  const found = all.domains.find((d) => d.domain === args.domain);
2032
2089
  if (!found) {
2033
2090
  console.error(`No domain ${args.domain} in your account`);
2034
2091
  process.exit(1);
2035
2092
  }
2036
2093
  const result = await api(
2037
- token,
2094
+ token2,
2038
2095
  `/api/domains/${found.id}/reattach`,
2039
2096
  {
2040
2097
  method: "POST",
@@ -2048,7 +2105,7 @@ var attach = defineCommand11({
2048
2105
  console.log(`\u2713 ${args.domain} now points at ${targetApp}`);
2049
2106
  }
2050
2107
  });
2051
- var detach = defineCommand11({
2108
+ var detach = defineCommand12({
2052
2109
  meta: {
2053
2110
  name: "detach",
2054
2111
  description: "Stop routing the domain (keeps the registration; auto-renew unchanged)"
@@ -2058,8 +2115,8 @@ var detach = defineCommand11({
2058
2115
  yes: { type: "boolean", description: "Skip the confirmation prompt" }
2059
2116
  },
2060
2117
  async run({ args }) {
2061
- const token = await ensureToken();
2062
- const all = await api(token, "/api/domains");
2118
+ const token2 = await ensureToken();
2119
+ const all = await api(token2, "/api/domains");
2063
2120
  const found = all.domains.find((d) => d.domain === args.domain);
2064
2121
  if (!found) {
2065
2122
  console.error(`No domain ${args.domain} in your account`);
@@ -2074,11 +2131,11 @@ var detach = defineCommand11({
2074
2131
  return;
2075
2132
  }
2076
2133
  }
2077
- await api(token, `/api/domains/${found.id}`, { method: "DELETE" });
2134
+ await api(token2, `/api/domains/${found.id}`, { method: "DELETE" });
2078
2135
  console.log(`\u2713 ${args.domain} detached. Use \`deepspace domain attach\` to re-route, or \`renew --auto off\` to stop auto-renewal.`);
2079
2136
  }
2080
2137
  });
2081
- var renew = defineCommand11({
2138
+ var renew = defineCommand12({
2082
2139
  meta: { name: "renew", description: "Toggle auto-renewal at the registrar" },
2083
2140
  args: {
2084
2141
  domain: { type: "positional", description: "Domain", required: true },
@@ -2089,15 +2146,15 @@ var renew = defineCommand11({
2089
2146
  console.error('--auto must be "on" or "off"');
2090
2147
  process.exit(1);
2091
2148
  }
2092
- const token = await ensureToken();
2093
- const all = await api(token, "/api/domains");
2149
+ const token2 = await ensureToken();
2150
+ const all = await api(token2, "/api/domains");
2094
2151
  const found = all.domains.find((d) => d.domain === args.domain);
2095
2152
  if (!found) {
2096
2153
  console.error(`No domain ${args.domain} in your account`);
2097
2154
  process.exit(1);
2098
2155
  }
2099
2156
  const enabled = args.auto === "on";
2100
- await api(token, `/api/domains/${found.id}/auto-renew`, {
2157
+ await api(token2, `/api/domains/${found.id}/auto-renew`, {
2101
2158
  method: "POST",
2102
2159
  body: JSON.stringify({ autoRenew: enabled })
2103
2160
  });
@@ -2112,13 +2169,13 @@ function openBrowser2(url) {
2112
2169
  } catch {
2113
2170
  }
2114
2171
  }
2115
- var domain_default = defineCommand11({
2172
+ var domain_default = defineCommand12({
2116
2173
  meta: { name: "domain", description: "Buy and manage custom domains" },
2117
2174
  subCommands: { search, buy, list: list2, status, attach, detach, renew }
2118
2175
  });
2119
2176
 
2120
2177
  // src/cli/commands/integrations.ts
2121
- import { defineCommand as defineCommand12 } from "citty";
2178
+ import { defineCommand as defineCommand13 } from "citty";
2122
2179
 
2123
2180
  // src/cli/commands/_invoke-impl.ts
2124
2181
  import { readFileSync as readFileSync8 } from "fs";
@@ -2292,7 +2349,7 @@ async function runInvoke(args) {
2292
2349
  }
2293
2350
 
2294
2351
  // src/cli/commands/integrations.ts
2295
- var list3 = defineCommand12({
2352
+ var list3 = defineCommand13({
2296
2353
  meta: {
2297
2354
  name: "list",
2298
2355
  description: "List all available integrations"
@@ -2313,7 +2370,7 @@ var list3 = defineCommand12({
2313
2370
  }
2314
2371
  }
2315
2372
  });
2316
- var info = defineCommand12({
2373
+ var info = defineCommand13({
2317
2374
  meta: {
2318
2375
  name: "info",
2319
2376
  description: "Print schema + example body for an integration endpoint"
@@ -2339,7 +2396,7 @@ var info = defineCommand12({
2339
2396
  }
2340
2397
  }
2341
2398
  });
2342
- var invoke = defineCommand12({
2399
+ var invoke = defineCommand13({
2343
2400
  meta: {
2344
2401
  name: "invoke",
2345
2402
  description: "Invoke a platform integration as the logged-in user"
@@ -2392,7 +2449,7 @@ var invoke = defineCommand12({
2392
2449
  }
2393
2450
  }
2394
2451
  });
2395
- var integrations_default = defineCommand12({
2452
+ var integrations_default = defineCommand13({
2396
2453
  meta: {
2397
2454
  name: "integrations",
2398
2455
  description: "List, inspect, and invoke platform integrations"
@@ -2405,8 +2462,8 @@ var integrations_default = defineCommand12({
2405
2462
  });
2406
2463
 
2407
2464
  // src/cli/commands/invoke.ts
2408
- import { defineCommand as defineCommand13 } from "citty";
2409
- var invoke_default = defineCommand13({
2465
+ import { defineCommand as defineCommand14 } from "citty";
2466
+ var invoke_default = defineCommand14({
2410
2467
  meta: {
2411
2468
  name: "invoke",
2412
2469
  description: "Invoke a platform integration as the logged-in user"
@@ -2478,13 +2535,256 @@ var invoke_default = defineCommand13({
2478
2535
  }
2479
2536
  });
2480
2537
 
2538
+ // src/cli/commands/managed-repos.ts
2539
+ import { defineCommand as defineCommand15 } from "citty";
2540
+ var API_URL3 = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
2541
+ var SIMPLE_APP_ID = /^[a-z0-9][a-z0-9_.:-]{0,119}$/i;
2542
+ var SIMPLE_APP_NAME = /^[a-z0-9][a-z0-9_-]{0,119}$/i;
2543
+ async function api2(token2, path, init) {
2544
+ const res = await fetch(`${API_URL3}${path}`, {
2545
+ ...init,
2546
+ headers: {
2547
+ Authorization: `Bearer ${token2}`,
2548
+ "Content-Type": "application/json",
2549
+ ...init?.headers ?? {}
2550
+ }
2551
+ });
2552
+ const text = await res.text();
2553
+ if (!res.ok) {
2554
+ let msg = text;
2555
+ try {
2556
+ msg = JSON.parse(text).error ?? text;
2557
+ } catch {
2558
+ }
2559
+ throw new Error(`API ${path} (${res.status}): ${msg}`);
2560
+ }
2561
+ return JSON.parse(text);
2562
+ }
2563
+ function defaultAppId(appName) {
2564
+ return `cli-${slugId(appName)}`;
2565
+ }
2566
+ function slugId(raw) {
2567
+ return raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "app";
2568
+ }
2569
+ function assertSimple(value, pattern, label) {
2570
+ if (!pattern.test(value)) {
2571
+ throw new Error(`${label} must start with a letter or number and contain only simple identifier characters.`);
2572
+ }
2573
+ }
2574
+ function printQuota(quota) {
2575
+ console.log(`Repo quota: ${quota.activeCount} / ${quota.limit} active (${quota.remaining} remaining)`);
2576
+ }
2577
+ function printRepo(repo) {
2578
+ console.log(`${repo.fullName}`);
2579
+ console.log(` ID: ${repo.id}`);
2580
+ console.log(` App: ${repo.appName}`);
2581
+ console.log(` App ID: ${repo.appId}`);
2582
+ console.log(` URL: ${repo.htmlUrl}`);
2583
+ console.log(` Clone: ${repo.cloneUrl}`);
2584
+ }
2585
+ async function confirm3(message) {
2586
+ if (!process.stdin.isTTY) {
2587
+ throw new Error(`${message} \u2014 pass --yes to confirm non-interactively`);
2588
+ }
2589
+ process.stdout.write(`${message} [y/N] `);
2590
+ return new Promise((resolve7) => {
2591
+ process.stdin.setEncoding("utf-8");
2592
+ process.stdin.once("data", (data) => {
2593
+ const answer = data.toString().trim().toLowerCase();
2594
+ resolve7(answer === "y" || answer === "yes");
2595
+ });
2596
+ });
2597
+ }
2598
+ var list4 = defineCommand15({
2599
+ meta: {
2600
+ name: "list",
2601
+ description: "List your DeepSpace-managed repos and quota"
2602
+ },
2603
+ args: {
2604
+ json: {
2605
+ type: "boolean",
2606
+ description: "Emit JSON instead of human output",
2607
+ default: false
2608
+ }
2609
+ },
2610
+ async run({ args }) {
2611
+ const token2 = await ensureToken();
2612
+ const result = await api2(token2, "/api/github/repos");
2613
+ if (args.json) {
2614
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
2615
+ return;
2616
+ }
2617
+ printQuota(result.quota);
2618
+ if (result.repos.length === 0) {
2619
+ console.log("No DeepSpace-managed repos. Create one with `deepspace managed-repos create <app-name>`.");
2620
+ return;
2621
+ }
2622
+ console.log("");
2623
+ for (const repo of result.repos) {
2624
+ printRepo(repo);
2625
+ }
2626
+ }
2627
+ });
2628
+ var create2 = defineCommand15({
2629
+ meta: {
2630
+ name: "create",
2631
+ description: "Create a private DeepSpace-managed GitHub repo"
2632
+ },
2633
+ args: {
2634
+ appName: {
2635
+ type: "positional",
2636
+ description: "Working app name for this repo",
2637
+ required: true
2638
+ },
2639
+ appId: {
2640
+ type: "string",
2641
+ description: "Stable DeepSpace repo app id (defaults to cli-<app-name>)",
2642
+ required: false
2643
+ },
2644
+ nameHint: {
2645
+ type: "string",
2646
+ description: "Repo-name hint (defaults to app name)",
2647
+ required: false
2648
+ },
2649
+ json: {
2650
+ type: "boolean",
2651
+ description: "Emit JSON instead of human output",
2652
+ default: false
2653
+ }
2654
+ },
2655
+ async run({ args }) {
2656
+ const appName = String(args.appName);
2657
+ const appId = args.appId ? String(args.appId) : defaultAppId(appName);
2658
+ const nameHint = args.nameHint ? String(args.nameHint) : void 0;
2659
+ try {
2660
+ assertSimple(appName, SIMPLE_APP_NAME, "appName");
2661
+ assertSimple(appId, SIMPLE_APP_ID, "appId");
2662
+ if (nameHint) assertSimple(nameHint, SIMPLE_APP_NAME, "nameHint");
2663
+ } catch (err) {
2664
+ console.error(err.message);
2665
+ process.exit(1);
2666
+ }
2667
+ const token2 = await ensureToken();
2668
+ const result = await api2(token2, "/api/github/repos", {
2669
+ method: "POST",
2670
+ body: JSON.stringify({ appName, appId, ...nameHint ? { nameHint } : {} })
2671
+ });
2672
+ if (args.json) {
2673
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
2674
+ return;
2675
+ }
2676
+ console.log(result.alreadyExists ? "Existing DeepSpace-managed repo:" : "Created DeepSpace-managed repo:");
2677
+ printRepo(result.repo);
2678
+ }
2679
+ });
2680
+ var token = defineCommand15({
2681
+ meta: {
2682
+ name: "token",
2683
+ description: "Mint a short-lived GitHub token for a DeepSpace-managed repo"
2684
+ },
2685
+ args: {
2686
+ repoId: {
2687
+ type: "positional",
2688
+ description: "Repo id from `deepspace managed-repos list`",
2689
+ required: true
2690
+ },
2691
+ json: {
2692
+ type: "boolean",
2693
+ description: "Emit JSON instead of human output",
2694
+ default: false
2695
+ }
2696
+ },
2697
+ async run({ args }) {
2698
+ const jwt = await ensureToken();
2699
+ const result = await api2(
2700
+ jwt,
2701
+ `/api/github/repos/${encodeURIComponent(String(args.repoId))}/agent-token`,
2702
+ { method: "POST" }
2703
+ );
2704
+ if (args.json) {
2705
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
2706
+ return;
2707
+ }
2708
+ console.log(`Repo: ${result.repo.fullName}`);
2709
+ console.log(`Expires: ${result.token.expiresAt}`);
2710
+ console.log(`Token: ${result.token.token}`);
2711
+ console.log("");
2712
+ console.log(`Clone: git clone https://x-access-token:${encodeURIComponent(result.token.token)}@github.com/${result.repo.fullName}.git`);
2713
+ }
2714
+ });
2715
+ var remove = defineCommand15({
2716
+ meta: {
2717
+ name: "delete",
2718
+ description: "Delete a DeepSpace-managed GitHub repo"
2719
+ },
2720
+ args: {
2721
+ repoId: {
2722
+ type: "positional",
2723
+ description: "Repo id from `deepspace managed-repos list`",
2724
+ required: true
2725
+ },
2726
+ yes: {
2727
+ type: "boolean",
2728
+ description: "Skip the confirmation prompt",
2729
+ default: false
2730
+ },
2731
+ json: {
2732
+ type: "boolean",
2733
+ description: "Emit JSON instead of human output",
2734
+ default: false
2735
+ }
2736
+ },
2737
+ async run({ args }) {
2738
+ if (!args.yes) {
2739
+ try {
2740
+ const ok = await confirm3(
2741
+ "Delete this DeepSpace-managed GitHub repo? This removes the GitHub repository and counts against your daily delete quota."
2742
+ );
2743
+ if (!ok) {
2744
+ console.log("Cancelled.");
2745
+ return;
2746
+ }
2747
+ } catch (err) {
2748
+ console.error(err.message);
2749
+ process.exit(1);
2750
+ }
2751
+ }
2752
+ const jwt = await ensureToken();
2753
+ const result = await api2(
2754
+ jwt,
2755
+ `/api/github/repos/${encodeURIComponent(String(args.repoId))}`,
2756
+ { method: "DELETE" }
2757
+ );
2758
+ if (args.json) {
2759
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
2760
+ return;
2761
+ }
2762
+ console.log(`Deleted ${result.repo.fullName}`);
2763
+ console.log(
2764
+ `Delete quota: ${result.deletionQuota.deletedCount} / ${result.deletionQuota.limit} used today (${result.deletionQuota.remaining} remaining)`
2765
+ );
2766
+ }
2767
+ });
2768
+ var managed_repos_default = defineCommand15({
2769
+ meta: {
2770
+ name: "managed-repos",
2771
+ description: "Create and manage DeepSpace-owned GitHub repos"
2772
+ },
2773
+ subCommands: {
2774
+ list: list4,
2775
+ create: create2,
2776
+ token,
2777
+ delete: remove
2778
+ }
2779
+ });
2780
+
2481
2781
  // src/cli/cli.ts
2482
2782
  var __dirname = dirname2(fileURLToPath(import.meta.url));
2483
2783
  var pkg = JSON.parse(readFileSync9(join12(__dirname, "..", "package.json"), "utf-8"));
2484
2784
  if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync11("/etc/ssl/certs/ca-certificates.crt")) {
2485
2785
  process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
2486
2786
  }
2487
- var create2 = defineCommand14({
2787
+ var create3 = defineCommand16({
2488
2788
  meta: {
2489
2789
  name: "create",
2490
2790
  description: "Create a new DeepSpace app"
@@ -2503,23 +2803,25 @@ var create2 = defineCommand14({
2503
2803
  execSync5(`npm create deepspace@latest${name}`, { stdio: "inherit" });
2504
2804
  }
2505
2805
  });
2506
- var main = defineCommand14({
2806
+ var main = defineCommand16({
2507
2807
  meta: {
2508
2808
  name: "deepspace",
2509
2809
  version: pkg.version,
2510
2810
  description: "DeepSpace SDK CLI"
2511
2811
  },
2512
2812
  subCommands: {
2513
- create: create2,
2813
+ create: create3,
2514
2814
  login: login_default,
2515
2815
  logout: logout_default,
2516
2816
  whoami: whoami_default,
2517
2817
  dev: dev_default,
2518
2818
  kill: kill_default,
2519
2819
  test: test_default,
2820
+ screenshot: screenshot_default,
2520
2821
  "test-accounts": test_accounts_default,
2521
2822
  add: add_default,
2522
2823
  integrations: integrations_default,
2824
+ "managed-repos": managed_repos_default,
2523
2825
  invoke: invoke_default,
2524
2826
  deploy: deploy_default,
2525
2827
  undeploy: undeploy_default,