deepspace 0.3.6 → 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 +487 -156
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +14 -50
- package/dist/index.js.map +1 -1
- package/dist/worker.d.ts +65 -22
- package/dist/worker.js +6 -6
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
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
|
|
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";
|
|
@@ -14,7 +14,24 @@ import { join as join2 } from "path";
|
|
|
14
14
|
import { homedir } from "os";
|
|
15
15
|
import { exec } from "child_process";
|
|
16
16
|
import { platform } from "os";
|
|
17
|
+
import * as p2 from "@clack/prompts";
|
|
18
|
+
|
|
19
|
+
// src/cli/lib/spinner.ts
|
|
17
20
|
import * as p from "@clack/prompts";
|
|
21
|
+
function createSpinner() {
|
|
22
|
+
if (process.stdout.isTTY) return p.spinner();
|
|
23
|
+
return {
|
|
24
|
+
start: (msg) => {
|
|
25
|
+
if (msg) console.log(msg);
|
|
26
|
+
},
|
|
27
|
+
stop: (msg) => {
|
|
28
|
+
if (msg) console.log(msg);
|
|
29
|
+
},
|
|
30
|
+
message: (msg) => {
|
|
31
|
+
if (msg) console.log(msg);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
18
35
|
|
|
19
36
|
// src/cli/env.ts
|
|
20
37
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -261,36 +278,36 @@ var login_default = defineCommand({
|
|
|
261
278
|
console.log("Logged in");
|
|
262
279
|
return;
|
|
263
280
|
}
|
|
264
|
-
|
|
265
|
-
const s =
|
|
281
|
+
p2.intro("DeepSpace Login");
|
|
282
|
+
const s = createSpinner();
|
|
266
283
|
s.start("Creating login session...");
|
|
267
284
|
const sessionRes = await fetch(`${AUTH_URL}/api/auth/cli/session`, { method: "POST" });
|
|
268
285
|
if (!sessionRes.ok) {
|
|
269
286
|
s.stop("Failed");
|
|
270
|
-
|
|
287
|
+
p2.cancel("Could not create login session");
|
|
271
288
|
process.exit(1);
|
|
272
289
|
}
|
|
273
290
|
const sessionData = await sessionRes.json();
|
|
274
291
|
if (!sessionData.sessionId || !sessionData.loginUrl) {
|
|
275
292
|
s.stop("Failed");
|
|
276
|
-
|
|
293
|
+
p2.cancel("Could not create login session");
|
|
277
294
|
process.exit(1);
|
|
278
295
|
}
|
|
279
296
|
const { sessionId, loginUrl } = sessionData;
|
|
280
297
|
s.stop("Opening browser...");
|
|
281
|
-
|
|
298
|
+
p2.log.info(`If the browser doesn't open, visit:
|
|
282
299
|
${loginUrl}`);
|
|
283
300
|
openBrowser(loginUrl);
|
|
284
301
|
s.start("Waiting for authentication...");
|
|
285
302
|
const result = await pollForCompletion(sessionId);
|
|
286
303
|
if (!result) {
|
|
287
304
|
s.stop("Timed out");
|
|
288
|
-
|
|
305
|
+
p2.cancel("Login timed out. Run `deepspace login` to try again.");
|
|
289
306
|
process.exit(1);
|
|
290
307
|
}
|
|
291
308
|
storeCredentials(result.sessionToken, result.jwt);
|
|
292
309
|
s.stop("Authenticated");
|
|
293
|
-
|
|
310
|
+
p2.outro(`Logged in as ${result.name ?? result.email}`);
|
|
294
311
|
}
|
|
295
312
|
});
|
|
296
313
|
async function pollForCompletion(sessionId) {
|
|
@@ -328,7 +345,7 @@ function openBrowser(url) {
|
|
|
328
345
|
});
|
|
329
346
|
}
|
|
330
347
|
function sleep(ms) {
|
|
331
|
-
return new Promise((
|
|
348
|
+
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
332
349
|
}
|
|
333
350
|
async function doEmailLogin(email, password) {
|
|
334
351
|
const res = await fetch(`${AUTH_URL}/api/auth/sign-in/email`, {
|
|
@@ -422,13 +439,13 @@ async function ensureToken() {
|
|
|
422
439
|
return existing;
|
|
423
440
|
}
|
|
424
441
|
}
|
|
425
|
-
const
|
|
426
|
-
if (!
|
|
442
|
+
const token2 = await exchangeSession(AUTH_URL3, sessionToken);
|
|
443
|
+
if (!token2) {
|
|
427
444
|
throw new Error("Session expired. Run `deepspace login` to re-authenticate.");
|
|
428
445
|
}
|
|
429
446
|
mkdirSync2(DIR2, { recursive: true });
|
|
430
|
-
writeFileSync3(TOKEN_PATH2,
|
|
431
|
-
return
|
|
447
|
+
writeFileSync3(TOKEN_PATH2, token2, { mode: 384 });
|
|
448
|
+
return token2;
|
|
432
449
|
}
|
|
433
450
|
function isTokenValid(jwt) {
|
|
434
451
|
try {
|
|
@@ -471,16 +488,16 @@ var dev_default = defineCommand3({
|
|
|
471
488
|
console.error("No wrangler.toml found. Are you in a DeepSpace app directory?");
|
|
472
489
|
process.exit(1);
|
|
473
490
|
}
|
|
474
|
-
let
|
|
491
|
+
let token2;
|
|
475
492
|
try {
|
|
476
|
-
|
|
493
|
+
token2 = await ensureToken();
|
|
477
494
|
} catch (err) {
|
|
478
495
|
console.error(err.message);
|
|
479
496
|
process.exit(1);
|
|
480
497
|
}
|
|
481
498
|
let payload;
|
|
482
499
|
try {
|
|
483
|
-
payload = JSON.parse(atob(
|
|
500
|
+
payload = JSON.parse(atob(token2.split(".")[1]));
|
|
484
501
|
} catch {
|
|
485
502
|
console.error("Malformed session token. Run `npx deepspace login`.");
|
|
486
503
|
process.exit(1);
|
|
@@ -488,7 +505,7 @@ var dev_default = defineCommand3({
|
|
|
488
505
|
console.log(`Logged in as ${payload.name ?? payload.email}`);
|
|
489
506
|
console.log(`Environment: ${env}`);
|
|
490
507
|
console.log(`Port: ${port}`);
|
|
491
|
-
await writeDevVars(appDir, env, payload.sub,
|
|
508
|
+
await writeDevVars(appDir, env, payload.sub, token2);
|
|
492
509
|
console.log("Starting dev server...\n");
|
|
493
510
|
const vite = spawn(
|
|
494
511
|
"npx",
|
|
@@ -681,7 +698,33 @@ function isAlive(pid) {
|
|
|
681
698
|
import { defineCommand as defineCommand5 } from "citty";
|
|
682
699
|
import { existsSync as existsSync5 } from "fs";
|
|
683
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
|
|
684
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
|
|
685
728
|
var DEFAULT_PORT3 = 5173;
|
|
686
729
|
var test_default = defineCommand5({
|
|
687
730
|
meta: {
|
|
@@ -708,17 +751,17 @@ var test_default = defineCommand5({
|
|
|
708
751
|
console.error("No wrangler.toml found. Are you in a DeepSpace app directory?");
|
|
709
752
|
process.exit(1);
|
|
710
753
|
}
|
|
711
|
-
let
|
|
754
|
+
let token2;
|
|
712
755
|
let ownerId;
|
|
713
756
|
try {
|
|
714
|
-
|
|
715
|
-
const payload = JSON.parse(atob(
|
|
757
|
+
token2 = await ensureToken();
|
|
758
|
+
const payload = JSON.parse(atob(token2.split(".")[1]));
|
|
716
759
|
ownerId = payload.sub;
|
|
717
760
|
} catch (err) {
|
|
718
761
|
console.error("`deepspace test` requires you to be logged in. Run `deepspace login` first.");
|
|
719
762
|
process.exit(1);
|
|
720
763
|
}
|
|
721
|
-
await writeDevVars(appDir, "dev", ownerId,
|
|
764
|
+
await writeDevVars(appDir, "dev", ownerId, token2);
|
|
722
765
|
if (suite !== "unit") {
|
|
723
766
|
ensurePlaywright(appDir);
|
|
724
767
|
}
|
|
@@ -756,7 +799,7 @@ var test_default = defineCommand5({
|
|
|
756
799
|
}
|
|
757
800
|
});
|
|
758
801
|
function runPlaywright(appDir, testFiles, port) {
|
|
759
|
-
const result =
|
|
802
|
+
const result = spawnSync3("npx", [
|
|
760
803
|
"playwright",
|
|
761
804
|
"test",
|
|
762
805
|
"--config",
|
|
@@ -771,30 +814,13 @@ function runPlaywright(appDir, testFiles, port) {
|
|
|
771
814
|
return result.status ?? 1;
|
|
772
815
|
}
|
|
773
816
|
function runVitest(appDir) {
|
|
774
|
-
const result =
|
|
817
|
+
const result = spawnSync3("npx", ["vitest", "run", "--passWithNoTests"], {
|
|
775
818
|
cwd: appDir,
|
|
776
819
|
stdio: "inherit",
|
|
777
820
|
shell: process.platform === "win32"
|
|
778
821
|
});
|
|
779
822
|
return result.status ?? 1;
|
|
780
823
|
}
|
|
781
|
-
function ensurePlaywright(appDir) {
|
|
782
|
-
try {
|
|
783
|
-
execSync("npx playwright --version", { cwd: appDir, stdio: "pipe" });
|
|
784
|
-
} catch {
|
|
785
|
-
console.log("Installing Playwright...");
|
|
786
|
-
execSync("npm install -D @playwright/test", { cwd: appDir, stdio: "pipe" });
|
|
787
|
-
}
|
|
788
|
-
const isLinux = process.platform === "linux";
|
|
789
|
-
const isRoot = isLinux && typeof process.getuid === "function" && process.getuid() === 0;
|
|
790
|
-
const args = isRoot ? ["install", "--with-deps", "chromium"] : ["install", "chromium"];
|
|
791
|
-
const result = spawnSync2("npx", ["playwright", ...args], { cwd: appDir, stdio: "inherit" });
|
|
792
|
-
if (result.status !== 0) {
|
|
793
|
-
console.error("\nPlaywright install failed. On Linux, system libs may be missing \u2014 try:");
|
|
794
|
-
console.error(" sudo npx playwright install --with-deps chromium");
|
|
795
|
-
process.exit(1);
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
824
|
function resolvePort3(arg) {
|
|
799
825
|
const raw = arg ?? process.env.DEEPSPACE_PORT;
|
|
800
826
|
if (!raw) return DEFAULT_PORT3;
|
|
@@ -806,9 +832,57 @@ function resolvePort3(arg) {
|
|
|
806
832
|
return n;
|
|
807
833
|
}
|
|
808
834
|
|
|
809
|
-
// src/cli/commands/
|
|
835
|
+
// src/cli/commands/screenshot.ts
|
|
810
836
|
import { defineCommand as defineCommand6 } from "citty";
|
|
811
|
-
import
|
|
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";
|
|
885
|
+
import * as p3 from "@clack/prompts";
|
|
812
886
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
813
887
|
import { join as join7 } from "path";
|
|
814
888
|
import { homedir as homedir4 } from "os";
|
|
@@ -829,8 +903,8 @@ function saveAccounts(accounts) {
|
|
|
829
903
|
writeFileSync4(ACCOUNTS_PATH, JSON.stringify(accounts, null, 2), { mode: 384 });
|
|
830
904
|
}
|
|
831
905
|
function sessionCookie() {
|
|
832
|
-
const
|
|
833
|
-
return `${SESSION_COOKIE2}=${encodeURIComponent(
|
|
906
|
+
const token2 = readFileSync4(SESSION_PATH2, "utf-8").trim();
|
|
907
|
+
return `${SESSION_COOKIE2}=${encodeURIComponent(token2)}`;
|
|
834
908
|
}
|
|
835
909
|
async function fetchRemoteAccounts() {
|
|
836
910
|
const res = await fetch(`${AUTH_URL4}/api/auth/test-accounts`, {
|
|
@@ -852,7 +926,7 @@ async function deleteRemote(id) {
|
|
|
852
926
|
throw new Error(data.error ?? `DELETE returned ${res.status}`);
|
|
853
927
|
}
|
|
854
928
|
}
|
|
855
|
-
var create =
|
|
929
|
+
var create = defineCommand7({
|
|
856
930
|
meta: {
|
|
857
931
|
name: "create",
|
|
858
932
|
description: "Create a test account"
|
|
@@ -922,7 +996,7 @@ var create = defineCommand6({
|
|
|
922
996
|
Saved to ${ACCOUNTS_PATH}`);
|
|
923
997
|
}
|
|
924
998
|
});
|
|
925
|
-
var list =
|
|
999
|
+
var list = defineCommand7({
|
|
926
1000
|
meta: {
|
|
927
1001
|
name: "list",
|
|
928
1002
|
description: "List your test accounts"
|
|
@@ -957,7 +1031,7 @@ var list = defineCommand6({
|
|
|
957
1031
|
}
|
|
958
1032
|
}
|
|
959
1033
|
});
|
|
960
|
-
var del =
|
|
1034
|
+
var del = defineCommand7({
|
|
961
1035
|
meta: {
|
|
962
1036
|
name: "delete",
|
|
963
1037
|
description: "Delete a test account by --email or --id"
|
|
@@ -1014,7 +1088,7 @@ var del = defineCommand6({
|
|
|
1014
1088
|
console.log(`Test account deleted${targetEmail ? `: ${targetEmail}` : `: ${targetId}`}`);
|
|
1015
1089
|
}
|
|
1016
1090
|
});
|
|
1017
|
-
var clear =
|
|
1091
|
+
var clear = defineCommand7({
|
|
1018
1092
|
meta: {
|
|
1019
1093
|
name: "clear",
|
|
1020
1094
|
description: "Delete all your test accounts (or those matching --label)"
|
|
@@ -1048,11 +1122,11 @@ var clear = defineCommand6({
|
|
|
1048
1122
|
}
|
|
1049
1123
|
if (!args.yes) {
|
|
1050
1124
|
const subject = args.label ? `${targets.length} test account(s) labeled '${args.label}'` : `all ${targets.length} test account(s)`;
|
|
1051
|
-
const confirmed = await
|
|
1125
|
+
const confirmed = await p3.confirm({
|
|
1052
1126
|
message: `Delete ${subject}? This is not reversible.`,
|
|
1053
1127
|
initialValue: false
|
|
1054
1128
|
});
|
|
1055
|
-
if (
|
|
1129
|
+
if (p3.isCancel(confirmed) || !confirmed) {
|
|
1056
1130
|
console.log("Cancelled.");
|
|
1057
1131
|
return;
|
|
1058
1132
|
}
|
|
@@ -1080,7 +1154,7 @@ Failed:`);
|
|
|
1080
1154
|
}
|
|
1081
1155
|
}
|
|
1082
1156
|
});
|
|
1083
|
-
var test_accounts_default =
|
|
1157
|
+
var test_accounts_default = defineCommand7({
|
|
1084
1158
|
meta: {
|
|
1085
1159
|
name: "test-accounts",
|
|
1086
1160
|
description: "Manage test accounts for development"
|
|
@@ -1094,12 +1168,12 @@ var test_accounts_default = defineCommand6({
|
|
|
1094
1168
|
});
|
|
1095
1169
|
|
|
1096
1170
|
// src/cli/commands/deploy.ts
|
|
1097
|
-
import { defineCommand as
|
|
1171
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
1098
1172
|
import { execSync as execSync2 } from "child_process";
|
|
1099
1173
|
import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync7 } from "fs";
|
|
1100
1174
|
import { parse as parseToml2 } from "smol-toml";
|
|
1101
|
-
import { join as join8, resolve as
|
|
1102
|
-
import * as
|
|
1175
|
+
import { join as join8, resolve as resolve4, dirname } from "path";
|
|
1176
|
+
import * as p4 from "@clack/prompts";
|
|
1103
1177
|
|
|
1104
1178
|
// src/server/rooms/binding-manifest.ts
|
|
1105
1179
|
var AUTO_PROVISION_SENTINEL = "auto";
|
|
@@ -1359,7 +1433,7 @@ function sanitizeAppName(raw) {
|
|
|
1359
1433
|
|
|
1360
1434
|
// src/cli/commands/deploy.ts
|
|
1361
1435
|
var DEPLOY_URL = process.env.DEEPSPACE_DEPLOY_URL ?? ENVS.prod.deploy;
|
|
1362
|
-
var deploy_default =
|
|
1436
|
+
var deploy_default = defineCommand8({
|
|
1363
1437
|
meta: {
|
|
1364
1438
|
name: "deploy",
|
|
1365
1439
|
description: "Build and deploy your DeepSpace app"
|
|
@@ -1372,30 +1446,30 @@ var deploy_default = defineCommand7({
|
|
|
1372
1446
|
}
|
|
1373
1447
|
},
|
|
1374
1448
|
async run({ args }) {
|
|
1375
|
-
const appDir =
|
|
1376
|
-
|
|
1449
|
+
const appDir = resolve4(args.dir ?? ".");
|
|
1450
|
+
p4.intro("Deploying DeepSpace app");
|
|
1377
1451
|
const wranglerPath = join8(appDir, "wrangler.toml");
|
|
1378
1452
|
if (!existsSync7(wranglerPath)) {
|
|
1379
|
-
|
|
1453
|
+
p4.cancel("No wrangler.toml found. Are you in a DeepSpace app directory?");
|
|
1380
1454
|
process.exit(1);
|
|
1381
1455
|
}
|
|
1382
1456
|
const wranglerConfig = parseToml2(readFileSync5(wranglerPath, "utf-8"));
|
|
1383
1457
|
const nameRes = resolveAppName(wranglerConfig.name);
|
|
1384
1458
|
if (!nameRes.ok) {
|
|
1385
|
-
|
|
1459
|
+
p4.cancel(`wrangler.toml: ${nameRes.reason}`);
|
|
1386
1460
|
process.exit(1);
|
|
1387
1461
|
}
|
|
1388
|
-
if (nameRes.warning)
|
|
1462
|
+
if (nameRes.warning) p4.log.warn(nameRes.warning);
|
|
1389
1463
|
const appName = nameRes.name;
|
|
1390
|
-
|
|
1391
|
-
let
|
|
1464
|
+
p4.log.info(`App: ${appName}`);
|
|
1465
|
+
let token2;
|
|
1392
1466
|
try {
|
|
1393
|
-
|
|
1467
|
+
token2 = await ensureToken();
|
|
1394
1468
|
} catch (err) {
|
|
1395
|
-
|
|
1469
|
+
p4.cancel(err.message);
|
|
1396
1470
|
process.exit(1);
|
|
1397
1471
|
}
|
|
1398
|
-
const s =
|
|
1472
|
+
const s = createSpinner();
|
|
1399
1473
|
s.start("Building...");
|
|
1400
1474
|
try {
|
|
1401
1475
|
execSync2("npx vite build", { cwd: appDir, stdio: "pipe" });
|
|
@@ -1407,25 +1481,25 @@ var deploy_default = defineCommand7({
|
|
|
1407
1481
|
s.stop("Built");
|
|
1408
1482
|
const deployConfigPath = join8(appDir, ".wrangler", "deploy", "config.json");
|
|
1409
1483
|
if (!existsSync7(deployConfigPath)) {
|
|
1410
|
-
|
|
1484
|
+
p4.cancel("Build output config not found at .wrangler/deploy/config.json");
|
|
1411
1485
|
process.exit(1);
|
|
1412
1486
|
}
|
|
1413
1487
|
const deployConfig = JSON.parse(readFileSync5(deployConfigPath, "utf-8"));
|
|
1414
|
-
const outputWranglerPath =
|
|
1488
|
+
const outputWranglerPath = resolve4(dirname(deployConfigPath), deployConfig.configPath);
|
|
1415
1489
|
if (!existsSync7(outputWranglerPath)) {
|
|
1416
|
-
|
|
1490
|
+
p4.cancel(`Output wrangler.json not found at ${outputWranglerPath}`);
|
|
1417
1491
|
process.exit(1);
|
|
1418
1492
|
}
|
|
1419
1493
|
const outputConfig = JSON.parse(readFileSync5(outputWranglerPath, "utf-8"));
|
|
1420
1494
|
const workerDir = dirname(outputWranglerPath);
|
|
1421
1495
|
const workerBundlePath = join8(workerDir, outputConfig.main);
|
|
1422
|
-
const clientDir = outputConfig.assets?.directory ?
|
|
1496
|
+
const clientDir = outputConfig.assets?.directory ? resolve4(workerDir, outputConfig.assets.directory) : null;
|
|
1423
1497
|
if (!existsSync7(workerBundlePath)) {
|
|
1424
|
-
|
|
1498
|
+
p4.cancel(`Worker bundle not found at ${workerBundlePath}`);
|
|
1425
1499
|
process.exit(1);
|
|
1426
1500
|
}
|
|
1427
1501
|
if (!clientDir || !existsSync7(clientDir)) {
|
|
1428
|
-
|
|
1502
|
+
p4.cancel(`Client assets not found at ${clientDir}`);
|
|
1429
1503
|
process.exit(1);
|
|
1430
1504
|
}
|
|
1431
1505
|
s.start("Collecting assets...");
|
|
@@ -1442,19 +1516,19 @@ var deploy_default = defineCommand7({
|
|
|
1442
1516
|
sqlite: sqliteClasses.has(b.class_name)
|
|
1443
1517
|
}));
|
|
1444
1518
|
if (doManifest?.length) {
|
|
1445
|
-
|
|
1519
|
+
p4.log.info(`DO manifest: ${doManifest.length} binding(s)`);
|
|
1446
1520
|
}
|
|
1447
1521
|
const customBindings = bindingManifestFromOutputConfig(outputConfig);
|
|
1448
1522
|
const validation = validateBindingManifest(customBindings);
|
|
1449
1523
|
if (!validation.valid) {
|
|
1450
|
-
|
|
1524
|
+
p4.cancel(
|
|
1451
1525
|
`Invalid binding(s) in wrangler.toml:
|
|
1452
1526
|
` + validation.errors.map((e) => ` \u2022 ${e.reason}`).join("\n")
|
|
1453
1527
|
);
|
|
1454
1528
|
process.exit(1);
|
|
1455
1529
|
}
|
|
1456
1530
|
if (customBindings.length) {
|
|
1457
|
-
|
|
1531
|
+
p4.log.info(
|
|
1458
1532
|
`Custom bindings: ${customBindings.map((b) => `${b.name} (${b.type})`).join(", ")}`
|
|
1459
1533
|
);
|
|
1460
1534
|
}
|
|
@@ -1466,7 +1540,7 @@ var deploy_default = defineCommand7({
|
|
|
1466
1540
|
try {
|
|
1467
1541
|
userSecrets = parseDevVars(customSection);
|
|
1468
1542
|
} catch (err) {
|
|
1469
|
-
|
|
1543
|
+
p4.cancel(`.dev.vars: ${err.message}`);
|
|
1470
1544
|
process.exit(1);
|
|
1471
1545
|
}
|
|
1472
1546
|
}
|
|
@@ -1478,20 +1552,20 @@ var deploy_default = defineCommand7({
|
|
|
1478
1552
|
]);
|
|
1479
1553
|
for (const name of userSecretNames) {
|
|
1480
1554
|
if (RESERVED_BINDING_NAMES.has(name)) {
|
|
1481
|
-
|
|
1555
|
+
p4.cancel(
|
|
1482
1556
|
`.dev.vars: "${name}" is a reserved binding name and cannot be used as an app secret.`
|
|
1483
1557
|
);
|
|
1484
1558
|
process.exit(1);
|
|
1485
1559
|
}
|
|
1486
1560
|
if (declaredBindingNames.has(name)) {
|
|
1487
|
-
|
|
1561
|
+
p4.cancel(
|
|
1488
1562
|
`.dev.vars: "${name}" collides with a binding declared in wrangler.toml \u2014 rename one or the other.`
|
|
1489
1563
|
);
|
|
1490
1564
|
process.exit(1);
|
|
1491
1565
|
}
|
|
1492
1566
|
}
|
|
1493
1567
|
if (userSecretNames.length) {
|
|
1494
|
-
|
|
1568
|
+
p4.log.info(`App secrets (from .dev.vars): ${userSecretNames.join(", ")}`);
|
|
1495
1569
|
}
|
|
1496
1570
|
s.start(`Deploying to ${appName}.app.space...`);
|
|
1497
1571
|
const form = new FormData();
|
|
@@ -1508,13 +1582,13 @@ var deploy_default = defineCommand7({
|
|
|
1508
1582
|
}
|
|
1509
1583
|
const res = await fetch(`${DEPLOY_URL}/api/deploy/${appName}`, {
|
|
1510
1584
|
method: "POST",
|
|
1511
|
-
headers: { Authorization: `Bearer ${
|
|
1585
|
+
headers: { Authorization: `Bearer ${token2}` },
|
|
1512
1586
|
body: form
|
|
1513
1587
|
});
|
|
1514
1588
|
const body = await res.json().catch(() => ({}));
|
|
1515
1589
|
if (!res.ok || !body.success) {
|
|
1516
1590
|
s.stop("Deploy failed");
|
|
1517
|
-
|
|
1591
|
+
p4.cancel(body.error ?? `Deployment error (${res.status})`);
|
|
1518
1592
|
process.exit(1);
|
|
1519
1593
|
}
|
|
1520
1594
|
if (body.url) {
|
|
@@ -1522,15 +1596,15 @@ var deploy_default = defineCommand7({
|
|
|
1522
1596
|
const ok = await waitForAssetsReady(body.url, 9e4);
|
|
1523
1597
|
if (!ok) {
|
|
1524
1598
|
s.stop("Deployed (edge propagation still in progress after 90s)");
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1599
|
+
p4.log.warn("First requests may briefly hit the assets transitional page; retry in a minute.");
|
|
1600
|
+
p4.log.success(`Live at: ${body.url}`);
|
|
1601
|
+
p4.outro("Done");
|
|
1528
1602
|
return;
|
|
1529
1603
|
}
|
|
1530
1604
|
}
|
|
1531
1605
|
s.stop("Deployed!");
|
|
1532
|
-
|
|
1533
|
-
|
|
1606
|
+
p4.log.success(`Live at: ${body.url}`);
|
|
1607
|
+
p4.outro("Done");
|
|
1534
1608
|
}
|
|
1535
1609
|
});
|
|
1536
1610
|
async function waitForAssetsReady(url, timeoutMs) {
|
|
@@ -1573,13 +1647,13 @@ function collectAssets(dir) {
|
|
|
1573
1647
|
}
|
|
1574
1648
|
|
|
1575
1649
|
// src/cli/commands/undeploy.ts
|
|
1576
|
-
import { defineCommand as
|
|
1650
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
1577
1651
|
import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
|
|
1578
1652
|
import { join as join9 } from "path";
|
|
1579
1653
|
import { parse as parseToml3 } from "smol-toml";
|
|
1580
|
-
import * as
|
|
1654
|
+
import * as p5 from "@clack/prompts";
|
|
1581
1655
|
var DEPLOY_URL2 = process.env.DEEPSPACE_DEPLOY_URL ?? ENVS.prod.deploy;
|
|
1582
|
-
var undeploy_default =
|
|
1656
|
+
var undeploy_default = defineCommand9({
|
|
1583
1657
|
meta: {
|
|
1584
1658
|
name: "undeploy",
|
|
1585
1659
|
description: "Remove a deployed DeepSpace app"
|
|
@@ -1601,37 +1675,37 @@ var undeploy_default = defineCommand8({
|
|
|
1601
1675
|
}
|
|
1602
1676
|
}
|
|
1603
1677
|
if (!appName) {
|
|
1604
|
-
|
|
1678
|
+
p5.cancel("Provide an app name or run from a DeepSpace app directory.");
|
|
1605
1679
|
process.exit(1);
|
|
1606
1680
|
}
|
|
1607
|
-
let
|
|
1681
|
+
let token2;
|
|
1608
1682
|
try {
|
|
1609
|
-
|
|
1683
|
+
token2 = await ensureToken();
|
|
1610
1684
|
} catch (err) {
|
|
1611
|
-
|
|
1685
|
+
p5.cancel(err.message);
|
|
1612
1686
|
process.exit(1);
|
|
1613
1687
|
}
|
|
1614
|
-
|
|
1615
|
-
const s =
|
|
1688
|
+
p5.intro(`Undeploying ${appName}`);
|
|
1689
|
+
const s = createSpinner();
|
|
1616
1690
|
s.start("Removing...");
|
|
1617
1691
|
const res = await fetch(`${DEPLOY_URL2}/api/deploy/${appName}`, {
|
|
1618
1692
|
method: "DELETE",
|
|
1619
|
-
headers: { Authorization: `Bearer ${
|
|
1693
|
+
headers: { Authorization: `Bearer ${token2}` }
|
|
1620
1694
|
});
|
|
1621
1695
|
const body = await res.json().catch(() => ({}));
|
|
1622
1696
|
if (!res.ok || !body.success) {
|
|
1623
1697
|
s.stop("Failed");
|
|
1624
|
-
|
|
1698
|
+
p5.cancel(body.error ?? `Undeploy error (${res.status})`);
|
|
1625
1699
|
process.exit(1);
|
|
1626
1700
|
}
|
|
1627
1701
|
s.stop("Removed");
|
|
1628
|
-
|
|
1702
|
+
p5.outro(`${appName}.app.space has been taken down`);
|
|
1629
1703
|
}
|
|
1630
1704
|
});
|
|
1631
1705
|
|
|
1632
1706
|
// src/cli/commands/whoami.ts
|
|
1633
|
-
import { defineCommand as
|
|
1634
|
-
var whoami_default =
|
|
1707
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
1708
|
+
var whoami_default = defineCommand10({
|
|
1635
1709
|
meta: {
|
|
1636
1710
|
name: "whoami",
|
|
1637
1711
|
description: "Show the currently logged-in user"
|
|
@@ -1685,16 +1759,16 @@ var whoami_default = defineCommand9({
|
|
|
1685
1759
|
});
|
|
1686
1760
|
|
|
1687
1761
|
// src/cli/commands/add.ts
|
|
1688
|
-
import { defineCommand as
|
|
1762
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
1689
1763
|
import { existsSync as existsSync9 } from "fs";
|
|
1690
|
-
import { resolve as
|
|
1764
|
+
import { resolve as resolve5, join as join10 } from "path";
|
|
1691
1765
|
import { execSync as execSync3 } from "child_process";
|
|
1692
1766
|
function findScript(from) {
|
|
1693
1767
|
const candidate = join10(from, ".deepspace", "scripts", "add-feature.cjs");
|
|
1694
1768
|
if (existsSync9(candidate)) return candidate;
|
|
1695
1769
|
return null;
|
|
1696
1770
|
}
|
|
1697
|
-
var add_default =
|
|
1771
|
+
var add_default = defineCommand11({
|
|
1698
1772
|
meta: {
|
|
1699
1773
|
name: "add",
|
|
1700
1774
|
description: "Add a feature to your DeepSpace app"
|
|
@@ -1723,7 +1797,7 @@ var add_default = defineCommand10({
|
|
|
1723
1797
|
}
|
|
1724
1798
|
},
|
|
1725
1799
|
run({ args }) {
|
|
1726
|
-
const appDir =
|
|
1800
|
+
const appDir = resolve5(args.dir ?? ".");
|
|
1727
1801
|
const script = findScript(appDir);
|
|
1728
1802
|
if (!script) {
|
|
1729
1803
|
console.error("No .deepspace/scripts/add-feature.cjs found.");
|
|
@@ -1748,15 +1822,15 @@ var add_default = defineCommand10({
|
|
|
1748
1822
|
});
|
|
1749
1823
|
|
|
1750
1824
|
// src/cli/commands/domain.ts
|
|
1751
|
-
import { defineCommand as
|
|
1825
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
1752
1826
|
import { execSync as execSync4 } from "child_process";
|
|
1753
1827
|
|
|
1754
1828
|
// src/cli/lib/app-context.ts
|
|
1755
1829
|
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
1756
|
-
import { join as join11, resolve as
|
|
1830
|
+
import { join as join11, resolve as resolve6 } from "path";
|
|
1757
1831
|
import { parse as parseToml4 } from "smol-toml";
|
|
1758
1832
|
function detectAppName(cwd = process.cwd()) {
|
|
1759
|
-
const wranglerPath = join11(
|
|
1833
|
+
const wranglerPath = join11(resolve6(cwd), "wrangler.toml");
|
|
1760
1834
|
if (!existsSync10(wranglerPath)) return null;
|
|
1761
1835
|
try {
|
|
1762
1836
|
const cfg = parseToml4(readFileSync7(wranglerPath, "utf-8"));
|
|
@@ -1776,11 +1850,11 @@ function requireAppName(explicit, cwd) {
|
|
|
1776
1850
|
|
|
1777
1851
|
// src/cli/commands/domain.ts
|
|
1778
1852
|
var API_URL = process.env.DEEPSPACE_API_URL ?? ENVS.prod.api;
|
|
1779
|
-
async function api(
|
|
1853
|
+
async function api(token2, path, init) {
|
|
1780
1854
|
const res = await fetch(`${API_URL}${path}`, {
|
|
1781
1855
|
...init,
|
|
1782
1856
|
headers: {
|
|
1783
|
-
Authorization: `Bearer ${
|
|
1857
|
+
Authorization: `Bearer ${token2}`,
|
|
1784
1858
|
"Content-Type": "application/json",
|
|
1785
1859
|
...init?.headers ?? {}
|
|
1786
1860
|
}
|
|
@@ -1796,6 +1870,18 @@ async function api(token, path, init) {
|
|
|
1796
1870
|
}
|
|
1797
1871
|
return JSON.parse(text);
|
|
1798
1872
|
}
|
|
1873
|
+
function scrubInternal(value) {
|
|
1874
|
+
if (Array.isArray(value)) return value.map(scrubInternal);
|
|
1875
|
+
if (value && typeof value === "object") {
|
|
1876
|
+
const out = {};
|
|
1877
|
+
for (const [k, v] of Object.entries(value)) {
|
|
1878
|
+
if (k === "costCents") continue;
|
|
1879
|
+
out[k] = scrubInternal(v);
|
|
1880
|
+
}
|
|
1881
|
+
return out;
|
|
1882
|
+
}
|
|
1883
|
+
return value;
|
|
1884
|
+
}
|
|
1799
1885
|
function fmtCents(cents) {
|
|
1800
1886
|
if (cents === null || cents === void 0) return "\u2014";
|
|
1801
1887
|
return `$${(cents / 100).toFixed(2)}`;
|
|
@@ -1809,15 +1895,15 @@ async function confirm2(message) {
|
|
|
1809
1895
|
throw new Error(`${message} \u2014 pass --yes to confirm non-interactively`);
|
|
1810
1896
|
}
|
|
1811
1897
|
process.stdout.write(`${message} [y/N] `);
|
|
1812
|
-
return new Promise((
|
|
1898
|
+
return new Promise((resolve7) => {
|
|
1813
1899
|
process.stdin.setEncoding("utf-8");
|
|
1814
1900
|
process.stdin.once("data", (data) => {
|
|
1815
1901
|
const answer = data.toString().trim().toLowerCase();
|
|
1816
|
-
|
|
1902
|
+
resolve7(answer === "y" || answer === "yes");
|
|
1817
1903
|
});
|
|
1818
1904
|
});
|
|
1819
1905
|
}
|
|
1820
|
-
var search =
|
|
1906
|
+
var search = defineCommand12({
|
|
1821
1907
|
meta: { name: "search", description: "Search for available domains" },
|
|
1822
1908
|
args: {
|
|
1823
1909
|
query: { type: "positional", description: "Domain or keyword", required: true },
|
|
@@ -1825,14 +1911,14 @@ var search = defineCommand11({
|
|
|
1825
1911
|
json: { type: "boolean", description: "Emit JSON instead of a table" }
|
|
1826
1912
|
},
|
|
1827
1913
|
async run({ args }) {
|
|
1828
|
-
const
|
|
1914
|
+
const token2 = await ensureToken();
|
|
1829
1915
|
const limit = parseInt(args.limit ?? "10", 10) || 10;
|
|
1830
1916
|
const result = await api(
|
|
1831
|
-
|
|
1917
|
+
token2,
|
|
1832
1918
|
`/api/domains/search?q=${encodeURIComponent(args.query)}&limit=${limit}`
|
|
1833
1919
|
);
|
|
1834
1920
|
if (args.json) {
|
|
1835
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
1921
|
+
process.stdout.write(JSON.stringify(scrubInternal(result), null, 2) + "\n");
|
|
1836
1922
|
return;
|
|
1837
1923
|
}
|
|
1838
1924
|
if (result.domains.length === 0) {
|
|
@@ -1847,20 +1933,20 @@ var search = defineCommand11({
|
|
|
1847
1933
|
}
|
|
1848
1934
|
}
|
|
1849
1935
|
});
|
|
1850
|
-
var buy =
|
|
1936
|
+
var buy = defineCommand12({
|
|
1851
1937
|
meta: { name: "buy", description: "Buy a domain and attach it to an app" },
|
|
1852
1938
|
args: {
|
|
1853
1939
|
domain: { type: "positional", description: "Domain to buy", required: true },
|
|
1854
1940
|
app: { type: "string", description: "App to attach (defaults to ./wrangler.toml)" },
|
|
1855
1941
|
yes: { type: "boolean", description: "Skip the confirmation prompt", default: false },
|
|
1856
|
-
|
|
1857
|
-
|
|
1942
|
+
open: { type: "boolean", description: "Open browser at Stripe URL (use --no-open to print URL only)", default: true },
|
|
1943
|
+
wait: { type: "boolean", description: "Poll until provisioning completes (use --no-wait to exit after session creation)", default: true },
|
|
1858
1944
|
json: { type: "boolean", description: "Emit JSON to stdout", default: false }
|
|
1859
1945
|
},
|
|
1860
1946
|
async run({ args }) {
|
|
1861
|
-
const
|
|
1947
|
+
const token2 = await ensureToken();
|
|
1862
1948
|
const appName = requireAppName(args.app);
|
|
1863
|
-
const priceCheck = await api(
|
|
1949
|
+
const priceCheck = await api(token2, "/api/domains/check", {
|
|
1864
1950
|
method: "POST",
|
|
1865
1951
|
body: JSON.stringify({ domains: [args.domain] })
|
|
1866
1952
|
});
|
|
@@ -1881,7 +1967,7 @@ var buy = defineCommand11({
|
|
|
1881
1967
|
}
|
|
1882
1968
|
}
|
|
1883
1969
|
const checkout = await api(
|
|
1884
|
-
|
|
1970
|
+
token2,
|
|
1885
1971
|
"/api/domains/checkout",
|
|
1886
1972
|
{
|
|
1887
1973
|
method: "POST",
|
|
@@ -1889,14 +1975,14 @@ var buy = defineCommand11({
|
|
|
1889
1975
|
}
|
|
1890
1976
|
);
|
|
1891
1977
|
if (args.json) {
|
|
1892
|
-
process.stdout.write(JSON.stringify({ ...checkout, expectedTime, registrar: result.registrar }, null, 2) + "\n");
|
|
1978
|
+
process.stdout.write(JSON.stringify(scrubInternal({ ...checkout, expectedTime, registrar: result.registrar }), null, 2) + "\n");
|
|
1893
1979
|
} else {
|
|
1894
1980
|
console.log(`Stripe Checkout: ${checkout.url}`);
|
|
1895
1981
|
}
|
|
1896
|
-
if (
|
|
1982
|
+
if (args.open && process.stdin.isTTY) {
|
|
1897
1983
|
openBrowser2(checkout.url);
|
|
1898
1984
|
}
|
|
1899
|
-
if (args
|
|
1985
|
+
if (!args.wait) return;
|
|
1900
1986
|
const timeoutMs = result.registrar === "cloudflare" ? 5 * 60 * 1e3 : 60 * 60 * 1e3;
|
|
1901
1987
|
if (!args.json) {
|
|
1902
1988
|
console.log(`Waiting for payment & provisioning (up to ${expectedTime}). Press Ctrl-C anytime \u2014`);
|
|
@@ -1908,7 +1994,7 @@ var buy = defineCommand11({
|
|
|
1908
1994
|
await new Promise((r) => setTimeout(r, 5e3));
|
|
1909
1995
|
try {
|
|
1910
1996
|
const detail = await api(
|
|
1911
|
-
|
|
1997
|
+
token2,
|
|
1912
1998
|
`/api/domains/${checkout.purchaseId}`
|
|
1913
1999
|
);
|
|
1914
2000
|
if (detail.domain.status !== lastStatus) {
|
|
@@ -1917,7 +2003,7 @@ var buy = defineCommand11({
|
|
|
1917
2003
|
}
|
|
1918
2004
|
if (detail.domain.status === "active") {
|
|
1919
2005
|
if (args.json) {
|
|
1920
|
-
process.stdout.write(JSON.stringify({ ...checkout, status: "active", domain: args.domain }, null, 2) + "\n");
|
|
2006
|
+
process.stdout.write(JSON.stringify(scrubInternal({ ...checkout, status: "active", domain: args.domain }), null, 2) + "\n");
|
|
1921
2007
|
} else {
|
|
1922
2008
|
console.log(`\u2713 ${args.domain} is live and pointing at ${appName}`);
|
|
1923
2009
|
}
|
|
@@ -1936,16 +2022,16 @@ var buy = defineCommand11({
|
|
|
1936
2022
|
process.exit(1);
|
|
1937
2023
|
}
|
|
1938
2024
|
});
|
|
1939
|
-
var list2 =
|
|
2025
|
+
var list2 = defineCommand12({
|
|
1940
2026
|
meta: { name: "list", description: "List your domains" },
|
|
1941
2027
|
args: {
|
|
1942
2028
|
json: { type: "boolean", description: "Emit JSON" }
|
|
1943
2029
|
},
|
|
1944
2030
|
async run({ args }) {
|
|
1945
|
-
const
|
|
1946
|
-
const result = await api(
|
|
2031
|
+
const token2 = await ensureToken();
|
|
2032
|
+
const result = await api(token2, "/api/domains");
|
|
1947
2033
|
if (args.json) {
|
|
1948
|
-
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
2034
|
+
process.stdout.write(JSON.stringify(scrubInternal(result), null, 2) + "\n");
|
|
1949
2035
|
return;
|
|
1950
2036
|
}
|
|
1951
2037
|
if (result.domains.length === 0) {
|
|
@@ -1960,22 +2046,22 @@ var list2 = defineCommand11({
|
|
|
1960
2046
|
}
|
|
1961
2047
|
}
|
|
1962
2048
|
});
|
|
1963
|
-
var status =
|
|
2049
|
+
var status = defineCommand12({
|
|
1964
2050
|
meta: { name: "status", description: "Show details for one domain" },
|
|
1965
2051
|
args: {
|
|
1966
2052
|
domain: { type: "positional", description: "Domain", required: true },
|
|
1967
2053
|
json: { type: "boolean" }
|
|
1968
2054
|
},
|
|
1969
2055
|
async run({ args }) {
|
|
1970
|
-
const
|
|
1971
|
-
const all = await api(
|
|
2056
|
+
const token2 = await ensureToken();
|
|
2057
|
+
const all = await api(token2, "/api/domains");
|
|
1972
2058
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
1973
2059
|
if (!found) {
|
|
1974
2060
|
console.error(`No domain ${args.domain} in your account`);
|
|
1975
2061
|
process.exit(1);
|
|
1976
2062
|
}
|
|
1977
2063
|
if (args.json) {
|
|
1978
|
-
process.stdout.write(JSON.stringify(found, null, 2) + "\n");
|
|
2064
|
+
process.stdout.write(JSON.stringify(scrubInternal(found), null, 2) + "\n");
|
|
1979
2065
|
return;
|
|
1980
2066
|
}
|
|
1981
2067
|
console.log(`Domain: ${found.domain}`);
|
|
@@ -1988,7 +2074,7 @@ var status = defineCommand11({
|
|
|
1988
2074
|
console.log(`Charged: ${fmtCents(found.chargedCents)}/yr`);
|
|
1989
2075
|
}
|
|
1990
2076
|
});
|
|
1991
|
-
var attach =
|
|
2077
|
+
var attach = defineCommand12({
|
|
1992
2078
|
meta: { name: "attach", description: "Re-point a domain at a different app" },
|
|
1993
2079
|
args: {
|
|
1994
2080
|
domain: { type: "positional", description: "Domain to re-point", required: true },
|
|
@@ -1996,16 +2082,16 @@ var attach = defineCommand11({
|
|
|
1996
2082
|
json: { type: "boolean" }
|
|
1997
2083
|
},
|
|
1998
2084
|
async run({ args }) {
|
|
1999
|
-
const
|
|
2085
|
+
const token2 = await ensureToken();
|
|
2000
2086
|
const targetApp = requireAppName(args.app);
|
|
2001
|
-
const all = await api(
|
|
2087
|
+
const all = await api(token2, "/api/domains");
|
|
2002
2088
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2003
2089
|
if (!found) {
|
|
2004
2090
|
console.error(`No domain ${args.domain} in your account`);
|
|
2005
2091
|
process.exit(1);
|
|
2006
2092
|
}
|
|
2007
2093
|
const result = await api(
|
|
2008
|
-
|
|
2094
|
+
token2,
|
|
2009
2095
|
`/api/domains/${found.id}/reattach`,
|
|
2010
2096
|
{
|
|
2011
2097
|
method: "POST",
|
|
@@ -2019,7 +2105,7 @@ var attach = defineCommand11({
|
|
|
2019
2105
|
console.log(`\u2713 ${args.domain} now points at ${targetApp}`);
|
|
2020
2106
|
}
|
|
2021
2107
|
});
|
|
2022
|
-
var detach =
|
|
2108
|
+
var detach = defineCommand12({
|
|
2023
2109
|
meta: {
|
|
2024
2110
|
name: "detach",
|
|
2025
2111
|
description: "Stop routing the domain (keeps the registration; auto-renew unchanged)"
|
|
@@ -2029,8 +2115,8 @@ var detach = defineCommand11({
|
|
|
2029
2115
|
yes: { type: "boolean", description: "Skip the confirmation prompt" }
|
|
2030
2116
|
},
|
|
2031
2117
|
async run({ args }) {
|
|
2032
|
-
const
|
|
2033
|
-
const all = await api(
|
|
2118
|
+
const token2 = await ensureToken();
|
|
2119
|
+
const all = await api(token2, "/api/domains");
|
|
2034
2120
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2035
2121
|
if (!found) {
|
|
2036
2122
|
console.error(`No domain ${args.domain} in your account`);
|
|
@@ -2045,11 +2131,11 @@ var detach = defineCommand11({
|
|
|
2045
2131
|
return;
|
|
2046
2132
|
}
|
|
2047
2133
|
}
|
|
2048
|
-
await api(
|
|
2134
|
+
await api(token2, `/api/domains/${found.id}`, { method: "DELETE" });
|
|
2049
2135
|
console.log(`\u2713 ${args.domain} detached. Use \`deepspace domain attach\` to re-route, or \`renew --auto off\` to stop auto-renewal.`);
|
|
2050
2136
|
}
|
|
2051
2137
|
});
|
|
2052
|
-
var renew =
|
|
2138
|
+
var renew = defineCommand12({
|
|
2053
2139
|
meta: { name: "renew", description: "Toggle auto-renewal at the registrar" },
|
|
2054
2140
|
args: {
|
|
2055
2141
|
domain: { type: "positional", description: "Domain", required: true },
|
|
@@ -2060,15 +2146,15 @@ var renew = defineCommand11({
|
|
|
2060
2146
|
console.error('--auto must be "on" or "off"');
|
|
2061
2147
|
process.exit(1);
|
|
2062
2148
|
}
|
|
2063
|
-
const
|
|
2064
|
-
const all = await api(
|
|
2149
|
+
const token2 = await ensureToken();
|
|
2150
|
+
const all = await api(token2, "/api/domains");
|
|
2065
2151
|
const found = all.domains.find((d) => d.domain === args.domain);
|
|
2066
2152
|
if (!found) {
|
|
2067
2153
|
console.error(`No domain ${args.domain} in your account`);
|
|
2068
2154
|
process.exit(1);
|
|
2069
2155
|
}
|
|
2070
2156
|
const enabled = args.auto === "on";
|
|
2071
|
-
await api(
|
|
2157
|
+
await api(token2, `/api/domains/${found.id}/auto-renew`, {
|
|
2072
2158
|
method: "POST",
|
|
2073
2159
|
body: JSON.stringify({ autoRenew: enabled })
|
|
2074
2160
|
});
|
|
@@ -2083,13 +2169,13 @@ function openBrowser2(url) {
|
|
|
2083
2169
|
} catch {
|
|
2084
2170
|
}
|
|
2085
2171
|
}
|
|
2086
|
-
var domain_default =
|
|
2172
|
+
var domain_default = defineCommand12({
|
|
2087
2173
|
meta: { name: "domain", description: "Buy and manage custom domains" },
|
|
2088
2174
|
subCommands: { search, buy, list: list2, status, attach, detach, renew }
|
|
2089
2175
|
});
|
|
2090
2176
|
|
|
2091
2177
|
// src/cli/commands/integrations.ts
|
|
2092
|
-
import { defineCommand as
|
|
2178
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
2093
2179
|
|
|
2094
2180
|
// src/cli/commands/_invoke-impl.ts
|
|
2095
2181
|
import { readFileSync as readFileSync8 } from "fs";
|
|
@@ -2263,7 +2349,7 @@ async function runInvoke(args) {
|
|
|
2263
2349
|
}
|
|
2264
2350
|
|
|
2265
2351
|
// src/cli/commands/integrations.ts
|
|
2266
|
-
var list3 =
|
|
2352
|
+
var list3 = defineCommand13({
|
|
2267
2353
|
meta: {
|
|
2268
2354
|
name: "list",
|
|
2269
2355
|
description: "List all available integrations"
|
|
@@ -2284,7 +2370,7 @@ var list3 = defineCommand12({
|
|
|
2284
2370
|
}
|
|
2285
2371
|
}
|
|
2286
2372
|
});
|
|
2287
|
-
var info =
|
|
2373
|
+
var info = defineCommand13({
|
|
2288
2374
|
meta: {
|
|
2289
2375
|
name: "info",
|
|
2290
2376
|
description: "Print schema + example body for an integration endpoint"
|
|
@@ -2310,7 +2396,7 @@ var info = defineCommand12({
|
|
|
2310
2396
|
}
|
|
2311
2397
|
}
|
|
2312
2398
|
});
|
|
2313
|
-
var invoke =
|
|
2399
|
+
var invoke = defineCommand13({
|
|
2314
2400
|
meta: {
|
|
2315
2401
|
name: "invoke",
|
|
2316
2402
|
description: "Invoke a platform integration as the logged-in user"
|
|
@@ -2363,7 +2449,7 @@ var invoke = defineCommand12({
|
|
|
2363
2449
|
}
|
|
2364
2450
|
}
|
|
2365
2451
|
});
|
|
2366
|
-
var integrations_default =
|
|
2452
|
+
var integrations_default = defineCommand13({
|
|
2367
2453
|
meta: {
|
|
2368
2454
|
name: "integrations",
|
|
2369
2455
|
description: "List, inspect, and invoke platform integrations"
|
|
@@ -2376,8 +2462,8 @@ var integrations_default = defineCommand12({
|
|
|
2376
2462
|
});
|
|
2377
2463
|
|
|
2378
2464
|
// src/cli/commands/invoke.ts
|
|
2379
|
-
import { defineCommand as
|
|
2380
|
-
var invoke_default =
|
|
2465
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
2466
|
+
var invoke_default = defineCommand14({
|
|
2381
2467
|
meta: {
|
|
2382
2468
|
name: "invoke",
|
|
2383
2469
|
description: "Invoke a platform integration as the logged-in user"
|
|
@@ -2449,13 +2535,256 @@ var invoke_default = defineCommand13({
|
|
|
2449
2535
|
}
|
|
2450
2536
|
});
|
|
2451
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
|
+
|
|
2452
2781
|
// src/cli/cli.ts
|
|
2453
2782
|
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
2454
2783
|
var pkg = JSON.parse(readFileSync9(join12(__dirname, "..", "package.json"), "utf-8"));
|
|
2455
2784
|
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync11("/etc/ssl/certs/ca-certificates.crt")) {
|
|
2456
2785
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
2457
2786
|
}
|
|
2458
|
-
var
|
|
2787
|
+
var create3 = defineCommand16({
|
|
2459
2788
|
meta: {
|
|
2460
2789
|
name: "create",
|
|
2461
2790
|
description: "Create a new DeepSpace app"
|
|
@@ -2474,23 +2803,25 @@ var create2 = defineCommand14({
|
|
|
2474
2803
|
execSync5(`npm create deepspace@latest${name}`, { stdio: "inherit" });
|
|
2475
2804
|
}
|
|
2476
2805
|
});
|
|
2477
|
-
var main =
|
|
2806
|
+
var main = defineCommand16({
|
|
2478
2807
|
meta: {
|
|
2479
2808
|
name: "deepspace",
|
|
2480
2809
|
version: pkg.version,
|
|
2481
2810
|
description: "DeepSpace SDK CLI"
|
|
2482
2811
|
},
|
|
2483
2812
|
subCommands: {
|
|
2484
|
-
create:
|
|
2813
|
+
create: create3,
|
|
2485
2814
|
login: login_default,
|
|
2486
2815
|
logout: logout_default,
|
|
2487
2816
|
whoami: whoami_default,
|
|
2488
2817
|
dev: dev_default,
|
|
2489
2818
|
kill: kill_default,
|
|
2490
2819
|
test: test_default,
|
|
2820
|
+
screenshot: screenshot_default,
|
|
2491
2821
|
"test-accounts": test_accounts_default,
|
|
2492
2822
|
add: add_default,
|
|
2493
2823
|
integrations: integrations_default,
|
|
2824
|
+
"managed-repos": managed_repos_default,
|
|
2494
2825
|
invoke: invoke_default,
|
|
2495
2826
|
deploy: deploy_default,
|
|
2496
2827
|
undeploy: undeploy_default,
|