deepspace 0.2.7 → 0.3.2
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 +679 -49
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -9
- package/dist/index.js.map +1 -1
- package/dist/worker.d.ts +446 -1
- package/dist/worker.js +438 -0
- 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 defineCommand14, 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";
|
|
@@ -75,12 +75,127 @@ async function mintAppOwnerJwt(authUrl, callerJwt, appName) {
|
|
|
75
75
|
}
|
|
76
76
|
return body.token;
|
|
77
77
|
}
|
|
78
|
+
var SDK_MANAGED_KEYS = /* @__PURE__ */ new Set([
|
|
79
|
+
"AUTH_JWT_PUBLIC_KEY",
|
|
80
|
+
"AUTH_JWT_ISSUER",
|
|
81
|
+
"AUTH_WORKER_URL",
|
|
82
|
+
"API_WORKER_URL",
|
|
83
|
+
"PLATFORM_WORKER_URL",
|
|
84
|
+
"OWNER_USER_ID",
|
|
85
|
+
"APP_OWNER_JWT",
|
|
86
|
+
"INTERNAL_STORAGE_HMAC_SECRET",
|
|
87
|
+
"ALLOW_DEBUG_ROUTES"
|
|
88
|
+
]);
|
|
89
|
+
var DEV_VARS_DIVIDER = "# --- not managed by the SDK; preserved across dev/test runs ---";
|
|
90
|
+
function extractCustomDevVars(content) {
|
|
91
|
+
const lines = content.split("\n");
|
|
92
|
+
const out = [];
|
|
93
|
+
let i = 0;
|
|
94
|
+
while (i < lines.length) {
|
|
95
|
+
const line = lines[i];
|
|
96
|
+
if (line.trim() === DEV_VARS_DIVIDER.trim()) {
|
|
97
|
+
i++;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const eq = line.indexOf("=");
|
|
101
|
+
const keyMatch = eq >= 0 ? line.slice(0, eq).match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*$/) : null;
|
|
102
|
+
if (!keyMatch) {
|
|
103
|
+
out.push(line);
|
|
104
|
+
i++;
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const key = keyMatch[1];
|
|
108
|
+
const valStart = line.slice(eq + 1);
|
|
109
|
+
const block = [line];
|
|
110
|
+
if (valStart.startsWith('"') && !hasUnescapedQuote(valStart.slice(1))) {
|
|
111
|
+
i++;
|
|
112
|
+
while (i < lines.length) {
|
|
113
|
+
block.push(lines[i]);
|
|
114
|
+
const closed = hasUnescapedQuote(lines[i]);
|
|
115
|
+
i++;
|
|
116
|
+
if (closed) break;
|
|
117
|
+
}
|
|
118
|
+
} else {
|
|
119
|
+
i++;
|
|
120
|
+
}
|
|
121
|
+
if (!SDK_MANAGED_KEYS.has(key)) {
|
|
122
|
+
out.push(...block);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
while (out.length && out[out.length - 1].trim() === "") out.pop();
|
|
126
|
+
return out.join("\n");
|
|
127
|
+
}
|
|
128
|
+
function hasUnescapedQuote(s) {
|
|
129
|
+
let escaped = false;
|
|
130
|
+
for (const ch of s) {
|
|
131
|
+
if (escaped) {
|
|
132
|
+
escaped = false;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (ch === "\\") {
|
|
136
|
+
escaped = true;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (ch === '"') return true;
|
|
140
|
+
}
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
function parseDevVars(content) {
|
|
144
|
+
const result = {};
|
|
145
|
+
const lines = content.split("\n");
|
|
146
|
+
let i = 0;
|
|
147
|
+
while (i < lines.length) {
|
|
148
|
+
const line = lines[i];
|
|
149
|
+
const trimmed = line.trim();
|
|
150
|
+
if (!trimmed || trimmed.startsWith("#")) {
|
|
151
|
+
i++;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const eq = line.indexOf("=");
|
|
155
|
+
if (eq < 0) {
|
|
156
|
+
i++;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const keyMatch = line.slice(0, eq).match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*$/);
|
|
160
|
+
if (!keyMatch) {
|
|
161
|
+
i++;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const key = keyMatch[1];
|
|
165
|
+
let value = line.slice(eq + 1);
|
|
166
|
+
let closed = !value.startsWith('"') || hasUnescapedQuote(value.slice(1));
|
|
167
|
+
if (!closed) {
|
|
168
|
+
i++;
|
|
169
|
+
while (i < lines.length) {
|
|
170
|
+
value += "\n" + lines[i];
|
|
171
|
+
if (hasUnescapedQuote(lines[i])) {
|
|
172
|
+
closed = true;
|
|
173
|
+
i++;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
i++;
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
i++;
|
|
180
|
+
}
|
|
181
|
+
if (value.startsWith('"') && !closed) {
|
|
182
|
+
throw new Error(
|
|
183
|
+
`parseDevVars: unterminated quoted value for key "${key}" \u2014 check your .dev.vars file for a missing closing quote.`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
if (value.startsWith('"') && value.endsWith('"') && value.length >= 2) {
|
|
187
|
+
value = value.slice(1, -1).replace(/\\"/g, '"');
|
|
188
|
+
}
|
|
189
|
+
result[key] = value;
|
|
190
|
+
}
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
78
193
|
async function writeDevVars(appDir, env, ownerId, callerJwt) {
|
|
79
194
|
const urls = ENVS[env];
|
|
80
195
|
const publicKey = await fetchPublicKey(urls.auth);
|
|
81
196
|
const appName = readAppName(appDir);
|
|
82
197
|
const appOwnerJwt = await mintAppOwnerJwt(urls.auth, callerJwt, appName);
|
|
83
|
-
const
|
|
198
|
+
const sdkVars = [
|
|
84
199
|
`AUTH_JWT_PUBLIC_KEY="${publicKey}"`,
|
|
85
200
|
`AUTH_JWT_ISSUER=${urls.auth}/api/auth`,
|
|
86
201
|
`AUTH_WORKER_URL=${urls.auth}`,
|
|
@@ -93,7 +208,16 @@ async function writeDevVars(appDir, env, ownerId, callerJwt) {
|
|
|
93
208
|
// Production secrets never set this, so deployed apps 404 the route.
|
|
94
209
|
`ALLOW_DEBUG_ROUTES=true`
|
|
95
210
|
].join("\n");
|
|
96
|
-
|
|
211
|
+
const devVarsPath = join(appDir, ".dev.vars");
|
|
212
|
+
const existing = existsSync(devVarsPath) ? readFileSync(devVarsPath, "utf-8") : "";
|
|
213
|
+
const custom = extractCustomDevVars(existing);
|
|
214
|
+
const body = custom ? `${sdkVars}
|
|
215
|
+
|
|
216
|
+
${DEV_VARS_DIVIDER}
|
|
217
|
+
${custom}
|
|
218
|
+
` : `${sdkVars}
|
|
219
|
+
`;
|
|
220
|
+
writeFileSync(devVarsPath, body);
|
|
97
221
|
}
|
|
98
222
|
|
|
99
223
|
// src/cli/session.ts
|
|
@@ -392,13 +516,174 @@ function resolvePort(arg) {
|
|
|
392
516
|
return n;
|
|
393
517
|
}
|
|
394
518
|
|
|
395
|
-
// src/cli/commands/
|
|
519
|
+
// src/cli/commands/kill.ts
|
|
396
520
|
import { defineCommand as defineCommand4 } from "citty";
|
|
521
|
+
import { spawnSync } from "child_process";
|
|
522
|
+
import { setTimeout as wait } from "timers/promises";
|
|
523
|
+
var DEFAULT_PORT2 = 5173;
|
|
524
|
+
var SIGTERM_GRACE_MS = 1500;
|
|
525
|
+
var IS_WIN = process.platform === "win32";
|
|
526
|
+
var kill_default = defineCommand4({
|
|
527
|
+
meta: {
|
|
528
|
+
name: "kill",
|
|
529
|
+
description: "Kill the local dev server and any orphaned workerd processes"
|
|
530
|
+
},
|
|
531
|
+
args: {
|
|
532
|
+
port: {
|
|
533
|
+
type: "string",
|
|
534
|
+
description: `Port the dev server is bound to (default ${DEFAULT_PORT2}, or $DEEPSPACE_PORT)`,
|
|
535
|
+
required: false
|
|
536
|
+
},
|
|
537
|
+
all: {
|
|
538
|
+
type: "boolean",
|
|
539
|
+
description: "Also kill stray workerd/wrangler processes across all ports",
|
|
540
|
+
default: false
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
async run({ args }) {
|
|
544
|
+
const port = resolvePort2(args.port);
|
|
545
|
+
const targets = /* @__PURE__ */ new Set();
|
|
546
|
+
for (const pid of listenerPids(port)) targets.add(pid);
|
|
547
|
+
for (const pid of [...targets]) {
|
|
548
|
+
for (const child of childPids(pid)) targets.add(child);
|
|
549
|
+
}
|
|
550
|
+
if (args.all) {
|
|
551
|
+
for (const pid of processPidsByName(["workerd", "wrangler", "vite"])) {
|
|
552
|
+
targets.add(pid);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (targets.size === 0) {
|
|
556
|
+
console.log(
|
|
557
|
+
args.all ? `Nothing listening on :${port} and no stray workerd/wrangler/vite processes found.` : `Nothing listening on :${port}. (Pass --all to sweep stray workerd/wrangler.)`
|
|
558
|
+
);
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
for (const pid of targets) {
|
|
562
|
+
if (sendSignal(pid, "SIGTERM")) {
|
|
563
|
+
console.log(`SIGTERM \u2192 pid ${pid}`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
await wait(SIGTERM_GRACE_MS);
|
|
567
|
+
const stillAlive = [];
|
|
568
|
+
for (const pid of targets) {
|
|
569
|
+
if (isAlive(pid)) stillAlive.push(pid);
|
|
570
|
+
}
|
|
571
|
+
for (const pid of stillAlive) {
|
|
572
|
+
if (sendSignal(pid, "SIGKILL")) {
|
|
573
|
+
console.log(`SIGKILL \u2192 pid ${pid} (did not exit on SIGTERM)`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
await wait(200);
|
|
577
|
+
const remaining = listenerPids(port);
|
|
578
|
+
if (remaining.length > 0) {
|
|
579
|
+
console.error(
|
|
580
|
+
`Port ${port} is still held by pid(s) ${remaining.join(", ")} \u2014 try \`deepspace kill --port ${port}\` again, or kill manually.`
|
|
581
|
+
);
|
|
582
|
+
process.exit(1);
|
|
583
|
+
}
|
|
584
|
+
console.log(`Port ${port} is free.`);
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
function resolvePort2(arg) {
|
|
588
|
+
const raw = arg ?? process.env.DEEPSPACE_PORT;
|
|
589
|
+
if (!raw) return DEFAULT_PORT2;
|
|
590
|
+
const n = Number(raw);
|
|
591
|
+
if (!Number.isInteger(n) || n < 1 || n > 65535) {
|
|
592
|
+
console.error(`Invalid port: ${raw}. Must be an integer between 1 and 65535.`);
|
|
593
|
+
process.exit(1);
|
|
594
|
+
}
|
|
595
|
+
return n;
|
|
596
|
+
}
|
|
597
|
+
function listenerPids(port) {
|
|
598
|
+
if (IS_WIN) {
|
|
599
|
+
return runPowershell(
|
|
600
|
+
`Get-NetTCPConnection -LocalPort ${port} -State Listen -ErrorAction SilentlyContinue | Select-Object -ExpandProperty OwningProcess`
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
return run(["lsof", "-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-t"]);
|
|
604
|
+
}
|
|
605
|
+
function childPids(parentPid) {
|
|
606
|
+
if (IS_WIN) {
|
|
607
|
+
return runPowershell(
|
|
608
|
+
`Get-CimInstance Win32_Process -Filter "ParentProcessId=${parentPid}" | Select-Object -ExpandProperty ProcessId`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
return run(["pgrep", "-P", String(parentPid)]);
|
|
612
|
+
}
|
|
613
|
+
function processPidsByName(names) {
|
|
614
|
+
const all = /* @__PURE__ */ new Set();
|
|
615
|
+
if (IS_WIN) {
|
|
616
|
+
const orClauses = names.map((n) => `($_.Name -like '*${n}*') -or ($_.CommandLine -like '*${n}*')`).join(" -or ");
|
|
617
|
+
const script = `Get-CimInstance Win32_Process | Where-Object { ${orClauses} } | Select-Object -ExpandProperty ProcessId`;
|
|
618
|
+
for (const pid of runPowershell(script)) {
|
|
619
|
+
if (pid !== process.pid) all.add(pid);
|
|
620
|
+
}
|
|
621
|
+
return [...all];
|
|
622
|
+
}
|
|
623
|
+
for (const name of names) {
|
|
624
|
+
for (const pid of run(["pgrep", "-f", name])) {
|
|
625
|
+
if (pid !== process.pid) all.add(pid);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
return [...all];
|
|
629
|
+
}
|
|
630
|
+
function run(cmd) {
|
|
631
|
+
try {
|
|
632
|
+
const r = spawnSync(cmd[0], cmd.slice(1), { encoding: "utf-8" });
|
|
633
|
+
if (r.status !== 0) return [];
|
|
634
|
+
return parsePidLines(r.stdout);
|
|
635
|
+
} catch {
|
|
636
|
+
return [];
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function runPowershell(script) {
|
|
640
|
+
const exe = pwshOrPowershell();
|
|
641
|
+
try {
|
|
642
|
+
const r = spawnSync(
|
|
643
|
+
exe,
|
|
644
|
+
["-NoProfile", "-NonInteractive", "-Command", script],
|
|
645
|
+
{ encoding: "utf-8" }
|
|
646
|
+
);
|
|
647
|
+
if (r.status !== 0) return [];
|
|
648
|
+
return parsePidLines(r.stdout);
|
|
649
|
+
} catch {
|
|
650
|
+
return [];
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
function pwshOrPowershell() {
|
|
654
|
+
const probe = spawnSync("pwsh", ["-NoProfile", "-Command", "$PSVersionTable.PSVersion.Major"], {
|
|
655
|
+
encoding: "utf-8"
|
|
656
|
+
});
|
|
657
|
+
if (probe.status === 0) return "pwsh";
|
|
658
|
+
return "powershell.exe";
|
|
659
|
+
}
|
|
660
|
+
function parsePidLines(stdout) {
|
|
661
|
+
return stdout.split(/\s+/).map((s) => Number.parseInt(s, 10)).filter((n) => Number.isFinite(n) && n > 0);
|
|
662
|
+
}
|
|
663
|
+
function sendSignal(pid, signal) {
|
|
664
|
+
try {
|
|
665
|
+
process.kill(pid, signal);
|
|
666
|
+
return true;
|
|
667
|
+
} catch {
|
|
668
|
+
return false;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
function isAlive(pid) {
|
|
672
|
+
try {
|
|
673
|
+
process.kill(pid, 0);
|
|
674
|
+
return true;
|
|
675
|
+
} catch {
|
|
676
|
+
return false;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
// src/cli/commands/test.ts
|
|
681
|
+
import { defineCommand as defineCommand5 } from "citty";
|
|
397
682
|
import { existsSync as existsSync5 } from "fs";
|
|
398
683
|
import { join as join6, resolve as resolve2 } from "path";
|
|
399
|
-
import { execSync, spawnSync } from "child_process";
|
|
400
|
-
var
|
|
401
|
-
var test_default =
|
|
684
|
+
import { execSync, spawnSync as spawnSync2 } from "child_process";
|
|
685
|
+
var DEFAULT_PORT3 = 5173;
|
|
686
|
+
var test_default = defineCommand5({
|
|
402
687
|
meta: {
|
|
403
688
|
name: "test",
|
|
404
689
|
description: "Run tests for your DeepSpace app"
|
|
@@ -411,14 +696,14 @@ var test_default = defineCommand4({
|
|
|
411
696
|
},
|
|
412
697
|
port: {
|
|
413
698
|
type: "string",
|
|
414
|
-
description: `Port for vite/webServer (default ${
|
|
699
|
+
description: `Port for vite/webServer (default ${DEFAULT_PORT3}, or $DEEPSPACE_PORT)`,
|
|
415
700
|
required: false
|
|
416
701
|
}
|
|
417
702
|
},
|
|
418
703
|
async run({ args }) {
|
|
419
704
|
const appDir = resolve2(".");
|
|
420
705
|
const suite = args.suite ?? "default";
|
|
421
|
-
const port =
|
|
706
|
+
const port = resolvePort3(args.port);
|
|
422
707
|
if (!existsSync5(join6(appDir, "wrangler.toml"))) {
|
|
423
708
|
console.error("No wrangler.toml found. Are you in a DeepSpace app directory?");
|
|
424
709
|
process.exit(1);
|
|
@@ -471,7 +756,7 @@ var test_default = defineCommand4({
|
|
|
471
756
|
}
|
|
472
757
|
});
|
|
473
758
|
function runPlaywright(appDir, testFiles, port) {
|
|
474
|
-
const result =
|
|
759
|
+
const result = spawnSync2("npx", [
|
|
475
760
|
"playwright",
|
|
476
761
|
"test",
|
|
477
762
|
"--config",
|
|
@@ -486,7 +771,7 @@ function runPlaywright(appDir, testFiles, port) {
|
|
|
486
771
|
return result.status ?? 1;
|
|
487
772
|
}
|
|
488
773
|
function runVitest(appDir) {
|
|
489
|
-
const result =
|
|
774
|
+
const result = spawnSync2("npx", ["vitest", "run", "--passWithNoTests"], {
|
|
490
775
|
cwd: appDir,
|
|
491
776
|
stdio: "inherit",
|
|
492
777
|
shell: process.platform === "win32"
|
|
@@ -503,16 +788,16 @@ function ensurePlaywright(appDir) {
|
|
|
503
788
|
const isLinux = process.platform === "linux";
|
|
504
789
|
const isRoot = isLinux && typeof process.getuid === "function" && process.getuid() === 0;
|
|
505
790
|
const args = isRoot ? ["install", "--with-deps", "chromium"] : ["install", "chromium"];
|
|
506
|
-
const result =
|
|
791
|
+
const result = spawnSync2("npx", ["playwright", ...args], { cwd: appDir, stdio: "inherit" });
|
|
507
792
|
if (result.status !== 0) {
|
|
508
793
|
console.error("\nPlaywright install failed. On Linux, system libs may be missing \u2014 try:");
|
|
509
794
|
console.error(" sudo npx playwright install --with-deps chromium");
|
|
510
795
|
process.exit(1);
|
|
511
796
|
}
|
|
512
797
|
}
|
|
513
|
-
function
|
|
798
|
+
function resolvePort3(arg) {
|
|
514
799
|
const raw = arg ?? process.env.DEEPSPACE_PORT;
|
|
515
|
-
if (!raw) return
|
|
800
|
+
if (!raw) return DEFAULT_PORT3;
|
|
516
801
|
const n = Number(raw);
|
|
517
802
|
if (!Number.isInteger(n) || n < 1 || n > 65535) {
|
|
518
803
|
console.error(`Invalid port: ${raw}. Must be an integer between 1 and 65535.`);
|
|
@@ -522,7 +807,7 @@ function resolvePort2(arg) {
|
|
|
522
807
|
}
|
|
523
808
|
|
|
524
809
|
// src/cli/commands/test-accounts.ts
|
|
525
|
-
import { defineCommand as
|
|
810
|
+
import { defineCommand as defineCommand6 } from "citty";
|
|
526
811
|
import * as p2 from "@clack/prompts";
|
|
527
812
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync3 } from "fs";
|
|
528
813
|
import { join as join7 } from "path";
|
|
@@ -567,7 +852,7 @@ async function deleteRemote(id) {
|
|
|
567
852
|
throw new Error(data.error ?? `DELETE returned ${res.status}`);
|
|
568
853
|
}
|
|
569
854
|
}
|
|
570
|
-
var create =
|
|
855
|
+
var create = defineCommand6({
|
|
571
856
|
meta: {
|
|
572
857
|
name: "create",
|
|
573
858
|
description: "Create a test account"
|
|
@@ -637,7 +922,7 @@ var create = defineCommand5({
|
|
|
637
922
|
Saved to ${ACCOUNTS_PATH}`);
|
|
638
923
|
}
|
|
639
924
|
});
|
|
640
|
-
var list =
|
|
925
|
+
var list = defineCommand6({
|
|
641
926
|
meta: {
|
|
642
927
|
name: "list",
|
|
643
928
|
description: "List your test accounts"
|
|
@@ -672,7 +957,7 @@ var list = defineCommand5({
|
|
|
672
957
|
}
|
|
673
958
|
}
|
|
674
959
|
});
|
|
675
|
-
var del =
|
|
960
|
+
var del = defineCommand6({
|
|
676
961
|
meta: {
|
|
677
962
|
name: "delete",
|
|
678
963
|
description: "Delete a test account by --email or --id"
|
|
@@ -729,7 +1014,7 @@ var del = defineCommand5({
|
|
|
729
1014
|
console.log(`Test account deleted${targetEmail ? `: ${targetEmail}` : `: ${targetId}`}`);
|
|
730
1015
|
}
|
|
731
1016
|
});
|
|
732
|
-
var clear =
|
|
1017
|
+
var clear = defineCommand6({
|
|
733
1018
|
meta: {
|
|
734
1019
|
name: "clear",
|
|
735
1020
|
description: "Delete all your test accounts (or those matching --label)"
|
|
@@ -795,7 +1080,7 @@ Failed:`);
|
|
|
795
1080
|
}
|
|
796
1081
|
}
|
|
797
1082
|
});
|
|
798
|
-
var test_accounts_default =
|
|
1083
|
+
var test_accounts_default = defineCommand6({
|
|
799
1084
|
meta: {
|
|
800
1085
|
name: "test-accounts",
|
|
801
1086
|
description: "Manage test accounts for development"
|
|
@@ -809,14 +1094,272 @@ var test_accounts_default = defineCommand5({
|
|
|
809
1094
|
});
|
|
810
1095
|
|
|
811
1096
|
// src/cli/commands/deploy.ts
|
|
812
|
-
import { defineCommand as
|
|
1097
|
+
import { defineCommand as defineCommand7 } from "citty";
|
|
813
1098
|
import { execSync as execSync2 } from "child_process";
|
|
814
1099
|
import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync7 } from "fs";
|
|
815
1100
|
import { parse as parseToml2 } from "smol-toml";
|
|
816
1101
|
import { join as join8, resolve as resolve3, dirname } from "path";
|
|
817
1102
|
import * as p3 from "@clack/prompts";
|
|
1103
|
+
|
|
1104
|
+
// src/server/rooms/binding-manifest.ts
|
|
1105
|
+
var AUTO_PROVISION_SENTINEL = "auto";
|
|
1106
|
+
var VECTORIZE_METRICS = /* @__PURE__ */ new Set(["cosine", "euclidean", "dot-product"]);
|
|
1107
|
+
var ALLOWED_BINDING_TYPES = /* @__PURE__ */ new Set([
|
|
1108
|
+
"vectorize",
|
|
1109
|
+
"ai",
|
|
1110
|
+
"r2_bucket",
|
|
1111
|
+
"kv_namespace",
|
|
1112
|
+
"d1",
|
|
1113
|
+
"queue",
|
|
1114
|
+
"browser_rendering",
|
|
1115
|
+
"analytics_engine",
|
|
1116
|
+
"hyperdrive"
|
|
1117
|
+
]);
|
|
1118
|
+
var RESERVED_BINDING_NAMES = /* @__PURE__ */ new Set([
|
|
1119
|
+
"ASSETS",
|
|
1120
|
+
"PLATFORM_WORKER",
|
|
1121
|
+
"API_WORKER",
|
|
1122
|
+
"APP_NAME",
|
|
1123
|
+
"OWNER_USER_ID",
|
|
1124
|
+
"AUTH_JWT_PUBLIC_KEY",
|
|
1125
|
+
"AUTH_JWT_ISSUER",
|
|
1126
|
+
"AUTH_WORKER_URL",
|
|
1127
|
+
"APP_IDENTITY_TOKEN",
|
|
1128
|
+
"APP_OWNER_JWT",
|
|
1129
|
+
"INTERNAL_STORAGE_HMAC_SECRET",
|
|
1130
|
+
"USAGE_EVENTS"
|
|
1131
|
+
]);
|
|
1132
|
+
function validateBindingManifest(manifest) {
|
|
1133
|
+
if (!Array.isArray(manifest)) {
|
|
1134
|
+
return { valid: false, errors: [{ reason: "Manifest must be an array" }] };
|
|
1135
|
+
}
|
|
1136
|
+
const errors = [];
|
|
1137
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
1138
|
+
for (const entry of manifest) {
|
|
1139
|
+
if (!entry || typeof entry !== "object") {
|
|
1140
|
+
errors.push({ reason: `Entry must be an object (got ${entry === null ? "null" : typeof entry})` });
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
const e = entry;
|
|
1144
|
+
const type = e.type;
|
|
1145
|
+
const name = e.name;
|
|
1146
|
+
if (typeof type !== "string" || !ALLOWED_BINDING_TYPES.has(type)) {
|
|
1147
|
+
errors.push({
|
|
1148
|
+
reason: `Disallowed binding type: ${typeof type === "string" ? type : `(${typeof type})`}. Allowed: ${[...ALLOWED_BINDING_TYPES].sort().join(", ")}`
|
|
1149
|
+
});
|
|
1150
|
+
continue;
|
|
1151
|
+
}
|
|
1152
|
+
if (typeof name !== "string" || !name) {
|
|
1153
|
+
errors.push({ reason: `Binding of type "${type}" missing 'name' (string)` });
|
|
1154
|
+
continue;
|
|
1155
|
+
}
|
|
1156
|
+
if (RESERVED_BINDING_NAMES.has(name)) {
|
|
1157
|
+
errors.push({ reason: `Binding name "${name}" is reserved by the SDK` });
|
|
1158
|
+
continue;
|
|
1159
|
+
}
|
|
1160
|
+
if (seenNames.has(name)) {
|
|
1161
|
+
errors.push({ reason: `Duplicate binding name "${name}"` });
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
seenNames.add(name);
|
|
1165
|
+
const binding = entry;
|
|
1166
|
+
const fieldErr = requiredFieldError(binding);
|
|
1167
|
+
if (fieldErr) errors.push({ binding, reason: fieldErr });
|
|
1168
|
+
}
|
|
1169
|
+
if (errors.length) return { valid: false, errors };
|
|
1170
|
+
return { valid: true, bindings: manifest };
|
|
1171
|
+
}
|
|
1172
|
+
function requiredFieldError(b) {
|
|
1173
|
+
switch (b.type) {
|
|
1174
|
+
case "vectorize": {
|
|
1175
|
+
if (!b.index_name) return `vectorize binding "${b.name}" missing index_name (or "auto")`;
|
|
1176
|
+
if (b.index_name === AUTO_PROVISION_SENTINEL) {
|
|
1177
|
+
if (typeof b.dimensions !== "number" || b.dimensions <= 0) {
|
|
1178
|
+
return `vectorize binding "${b.name}" with index_name="auto" requires "dimensions" (positive number)`;
|
|
1179
|
+
}
|
|
1180
|
+
if (!b.metric || !VECTORIZE_METRICS.has(b.metric)) {
|
|
1181
|
+
return `vectorize binding "${b.name}" with index_name="auto" requires "metric" (one of: ${[...VECTORIZE_METRICS].join(", ")})`;
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return null;
|
|
1185
|
+
}
|
|
1186
|
+
case "r2_bucket":
|
|
1187
|
+
return b.bucket_name ? null : `r2_bucket binding "${b.name}" missing bucket_name (or "auto")`;
|
|
1188
|
+
case "kv_namespace": {
|
|
1189
|
+
if (!b.namespace_id) return `kv_namespace binding "${b.name}" missing namespace_id (or "auto")`;
|
|
1190
|
+
if (b.namespace_id === AUTO_PROVISION_SENTINEL && !b.title) {
|
|
1191
|
+
return `kv_namespace binding "${b.name}" with namespace_id="auto" requires "title"`;
|
|
1192
|
+
}
|
|
1193
|
+
return null;
|
|
1194
|
+
}
|
|
1195
|
+
case "d1": {
|
|
1196
|
+
if (!b.id) return `d1 binding "${b.name}" missing id (or "auto")`;
|
|
1197
|
+
if (b.id === AUTO_PROVISION_SENTINEL && !b.database_name) {
|
|
1198
|
+
return `d1 binding "${b.name}" with id="auto" requires "database_name"`;
|
|
1199
|
+
}
|
|
1200
|
+
return null;
|
|
1201
|
+
}
|
|
1202
|
+
case "queue":
|
|
1203
|
+
return b.queue_name ? null : `queue binding "${b.name}" missing queue_name (or "auto")`;
|
|
1204
|
+
case "hyperdrive":
|
|
1205
|
+
if (!b.id) return `hyperdrive binding "${b.name}" missing id`;
|
|
1206
|
+
if (b.id === AUTO_PROVISION_SENTINEL) {
|
|
1207
|
+
return `hyperdrive binding "${b.name}": auto-provisioning not yet supported (provide a real id)`;
|
|
1208
|
+
}
|
|
1209
|
+
return null;
|
|
1210
|
+
case "ai":
|
|
1211
|
+
case "browser_rendering":
|
|
1212
|
+
case "analytics_engine":
|
|
1213
|
+
return null;
|
|
1214
|
+
// no required fields beyond `name`
|
|
1215
|
+
default: {
|
|
1216
|
+
const _exhaustive = b;
|
|
1217
|
+
void _exhaustive;
|
|
1218
|
+
return null;
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
function bindingManifestFromOutputConfig(outputConfig) {
|
|
1223
|
+
const out = [];
|
|
1224
|
+
const aiBinding = pluckString(outputConfig.ai, "binding");
|
|
1225
|
+
if (aiBinding) out.push({ type: "ai", name: aiBinding });
|
|
1226
|
+
for (const v of asObjectArray(outputConfig.vectorize)) {
|
|
1227
|
+
const name = pluckString(v, "binding");
|
|
1228
|
+
const index_name = pluckString(v, "index_name");
|
|
1229
|
+
if (!name || !index_name) continue;
|
|
1230
|
+
const dimensions = pluckNumber(v, "dimensions");
|
|
1231
|
+
const metric = pluckString(v, "metric");
|
|
1232
|
+
out.push({
|
|
1233
|
+
type: "vectorize",
|
|
1234
|
+
name,
|
|
1235
|
+
index_name,
|
|
1236
|
+
...dimensions != null && { dimensions },
|
|
1237
|
+
...metric && (metric === "cosine" || metric === "euclidean" || metric === "dot-product") && { metric }
|
|
1238
|
+
});
|
|
1239
|
+
}
|
|
1240
|
+
for (const r of asObjectArray(outputConfig.r2_buckets)) {
|
|
1241
|
+
const name = pluckString(r, "binding");
|
|
1242
|
+
const bucket_name = pluckString(r, "bucket_name");
|
|
1243
|
+
if (name && bucket_name) out.push({ type: "r2_bucket", name, bucket_name });
|
|
1244
|
+
}
|
|
1245
|
+
for (const k of asObjectArray(outputConfig.kv_namespaces)) {
|
|
1246
|
+
const name = pluckString(k, "binding");
|
|
1247
|
+
const namespace_id = pluckString(k, "id");
|
|
1248
|
+
if (!name || !namespace_id) continue;
|
|
1249
|
+
const title = pluckString(k, "title");
|
|
1250
|
+
out.push({
|
|
1251
|
+
type: "kv_namespace",
|
|
1252
|
+
name,
|
|
1253
|
+
namespace_id,
|
|
1254
|
+
...title && { title }
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
for (const d of asObjectArray(outputConfig.d1_databases)) {
|
|
1258
|
+
const name = pluckString(d, "binding");
|
|
1259
|
+
const id = pluckString(d, "database_id");
|
|
1260
|
+
if (!name || !id) continue;
|
|
1261
|
+
const database_name = pluckString(d, "database_name");
|
|
1262
|
+
out.push({
|
|
1263
|
+
type: "d1",
|
|
1264
|
+
name,
|
|
1265
|
+
id,
|
|
1266
|
+
...database_name && { database_name }
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
const queues = isObject(outputConfig.queues) ? outputConfig.queues : null;
|
|
1270
|
+
for (const q of asObjectArray(queues?.producers)) {
|
|
1271
|
+
const name = pluckString(q, "binding");
|
|
1272
|
+
const queue_name = pluckString(q, "queue");
|
|
1273
|
+
if (name && queue_name) out.push({ type: "queue", name, queue_name });
|
|
1274
|
+
}
|
|
1275
|
+
const browserBinding = pluckString(outputConfig.browser, "binding");
|
|
1276
|
+
if (browserBinding) out.push({ type: "browser_rendering", name: browserBinding });
|
|
1277
|
+
for (const a of asObjectArray(outputConfig.analytics_engine_datasets)) {
|
|
1278
|
+
const name = pluckString(a, "binding");
|
|
1279
|
+
const dataset = pluckString(a, "dataset");
|
|
1280
|
+
if (name) out.push({ type: "analytics_engine", name, dataset: dataset ?? void 0 });
|
|
1281
|
+
}
|
|
1282
|
+
for (const h of asObjectArray(outputConfig.hyperdrive)) {
|
|
1283
|
+
const name = pluckString(h, "binding");
|
|
1284
|
+
const id = pluckString(h, "id");
|
|
1285
|
+
if (name && id) out.push({ type: "hyperdrive", name, id });
|
|
1286
|
+
}
|
|
1287
|
+
return out;
|
|
1288
|
+
}
|
|
1289
|
+
function isObject(v) {
|
|
1290
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
1291
|
+
}
|
|
1292
|
+
function pluckString(v, key) {
|
|
1293
|
+
if (!isObject(v)) return null;
|
|
1294
|
+
const val = v[key];
|
|
1295
|
+
return typeof val === "string" && val.length > 0 ? val : null;
|
|
1296
|
+
}
|
|
1297
|
+
function pluckNumber(v, key) {
|
|
1298
|
+
if (!isObject(v)) return null;
|
|
1299
|
+
const val = v[key];
|
|
1300
|
+
return typeof val === "number" && Number.isFinite(val) ? val : null;
|
|
1301
|
+
}
|
|
1302
|
+
function asObjectArray(v) {
|
|
1303
|
+
if (!Array.isArray(v)) return [];
|
|
1304
|
+
return v.filter(isObject);
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// src/server/rooms/app-name.ts
|
|
1308
|
+
var APP_NAME_RULES = {
|
|
1309
|
+
/** ^[a-z0-9](-?[a-z0-9])+$ — RFC 1035 host label, no consecutive dashes. */
|
|
1310
|
+
pattern: /^[a-z0-9](?:-?[a-z0-9])+$/,
|
|
1311
|
+
minLength: 2,
|
|
1312
|
+
maxLength: 63
|
|
1313
|
+
};
|
|
1314
|
+
function validateAppName(raw) {
|
|
1315
|
+
if (typeof raw !== "string") {
|
|
1316
|
+
return { valid: false, reason: "App name must be a string" };
|
|
1317
|
+
}
|
|
1318
|
+
const name = raw.trim();
|
|
1319
|
+
if (!name) {
|
|
1320
|
+
return { valid: false, reason: "App name is required" };
|
|
1321
|
+
}
|
|
1322
|
+
if (name.length < APP_NAME_RULES.minLength) {
|
|
1323
|
+
return { valid: false, reason: `App name "${name}" is too short (min ${APP_NAME_RULES.minLength} chars)` };
|
|
1324
|
+
}
|
|
1325
|
+
if (name.length > APP_NAME_RULES.maxLength) {
|
|
1326
|
+
return { valid: false, reason: `App name "${name}" is too long (max ${APP_NAME_RULES.maxLength} chars)` };
|
|
1327
|
+
}
|
|
1328
|
+
if (!APP_NAME_RULES.pattern.test(name)) {
|
|
1329
|
+
return {
|
|
1330
|
+
valid: false,
|
|
1331
|
+
reason: `App name "${name}" is invalid. Use lowercase letters, digits, and single hyphens only (must start + end with alphanumeric). Examples: my-app, search-v2, unison-search.`
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
return { valid: true, name };
|
|
1335
|
+
}
|
|
1336
|
+
function resolveAppName(raw) {
|
|
1337
|
+
const strict = validateAppName(raw);
|
|
1338
|
+
if (strict.valid) return { ok: true, name: strict.name };
|
|
1339
|
+
if (typeof raw !== "string") return { ok: false, reason: strict.reason };
|
|
1340
|
+
const trimmed = raw.trim();
|
|
1341
|
+
if (!trimmed) return { ok: false, reason: "App name is required" };
|
|
1342
|
+
const sanitized = sanitizeAppName(trimmed);
|
|
1343
|
+
const sanitizedStrict = validateAppName(sanitized);
|
|
1344
|
+
if (!sanitizedStrict.valid) {
|
|
1345
|
+
return {
|
|
1346
|
+
ok: false,
|
|
1347
|
+
reason: `App name "${trimmed}" can't be sanitized into a valid name (${sanitizedStrict.reason}). Pick something matching: lowercase letters, digits, single hyphens, ${APP_NAME_RULES.minLength}-${APP_NAME_RULES.maxLength} chars.`
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
return {
|
|
1351
|
+
ok: true,
|
|
1352
|
+
name: sanitized,
|
|
1353
|
+
warning: `App name "${trimmed}" doesn't conform to deploy rules \u2014 using "${sanitized}" instead. Update wrangler.toml's \`name\` to silence this warning.`
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
function sanitizeAppName(raw) {
|
|
1357
|
+
return raw.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
// src/cli/commands/deploy.ts
|
|
818
1361
|
var DEPLOY_URL = process.env.DEEPSPACE_DEPLOY_URL ?? ENVS.prod.deploy;
|
|
819
|
-
var deploy_default =
|
|
1362
|
+
var deploy_default = defineCommand7({
|
|
820
1363
|
meta: {
|
|
821
1364
|
name: "deploy",
|
|
822
1365
|
description: "Build and deploy your DeepSpace app"
|
|
@@ -837,11 +1380,13 @@ var deploy_default = defineCommand6({
|
|
|
837
1380
|
process.exit(1);
|
|
838
1381
|
}
|
|
839
1382
|
const wranglerConfig = parseToml2(readFileSync5(wranglerPath, "utf-8"));
|
|
840
|
-
const
|
|
841
|
-
if (!
|
|
842
|
-
p3.cancel(
|
|
1383
|
+
const nameRes = resolveAppName(wranglerConfig.name);
|
|
1384
|
+
if (!nameRes.ok) {
|
|
1385
|
+
p3.cancel(`wrangler.toml: ${nameRes.reason}`);
|
|
843
1386
|
process.exit(1);
|
|
844
1387
|
}
|
|
1388
|
+
if (nameRes.warning) p3.log.warn(nameRes.warning);
|
|
1389
|
+
const appName = nameRes.name;
|
|
845
1390
|
p3.log.info(`App: ${appName}`);
|
|
846
1391
|
let token;
|
|
847
1392
|
try {
|
|
@@ -899,6 +1444,55 @@ var deploy_default = defineCommand6({
|
|
|
899
1444
|
if (doManifest?.length) {
|
|
900
1445
|
p3.log.info(`DO manifest: ${doManifest.length} binding(s)`);
|
|
901
1446
|
}
|
|
1447
|
+
const customBindings = bindingManifestFromOutputConfig(outputConfig);
|
|
1448
|
+
const validation = validateBindingManifest(customBindings);
|
|
1449
|
+
if (!validation.valid) {
|
|
1450
|
+
p3.cancel(
|
|
1451
|
+
`Invalid binding(s) in wrangler.toml:
|
|
1452
|
+
` + validation.errors.map((e) => ` \u2022 ${e.reason}`).join("\n")
|
|
1453
|
+
);
|
|
1454
|
+
process.exit(1);
|
|
1455
|
+
}
|
|
1456
|
+
if (customBindings.length) {
|
|
1457
|
+
p3.log.info(
|
|
1458
|
+
`Custom bindings: ${customBindings.map((b) => `${b.name} (${b.type})`).join(", ")}`
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
const devVarsPath = join8(appDir, ".dev.vars");
|
|
1462
|
+
let userSecrets = {};
|
|
1463
|
+
if (existsSync7(devVarsPath)) {
|
|
1464
|
+
const customSection = extractCustomDevVars(readFileSync5(devVarsPath, "utf-8"));
|
|
1465
|
+
if (customSection) {
|
|
1466
|
+
try {
|
|
1467
|
+
userSecrets = parseDevVars(customSection);
|
|
1468
|
+
} catch (err) {
|
|
1469
|
+
p3.cancel(`.dev.vars: ${err.message}`);
|
|
1470
|
+
process.exit(1);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
const userSecretNames = Object.keys(userSecrets);
|
|
1475
|
+
const declaredBindingNames = /* @__PURE__ */ new Set([
|
|
1476
|
+
...customBindings.map((b) => b.name),
|
|
1477
|
+
...(doManifest ?? []).map((d) => d.binding)
|
|
1478
|
+
]);
|
|
1479
|
+
for (const name of userSecretNames) {
|
|
1480
|
+
if (RESERVED_BINDING_NAMES.has(name)) {
|
|
1481
|
+
p3.cancel(
|
|
1482
|
+
`.dev.vars: "${name}" is a reserved binding name and cannot be used as an app secret.`
|
|
1483
|
+
);
|
|
1484
|
+
process.exit(1);
|
|
1485
|
+
}
|
|
1486
|
+
if (declaredBindingNames.has(name)) {
|
|
1487
|
+
p3.cancel(
|
|
1488
|
+
`.dev.vars: "${name}" collides with a binding declared in wrangler.toml \u2014 rename one or the other.`
|
|
1489
|
+
);
|
|
1490
|
+
process.exit(1);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
if (userSecretNames.length) {
|
|
1494
|
+
p3.log.info(`App secrets (from .dev.vars): ${userSecretNames.join(", ")}`);
|
|
1495
|
+
}
|
|
902
1496
|
s.start(`Deploying to ${appName}.app.space...`);
|
|
903
1497
|
const form = new FormData();
|
|
904
1498
|
form.append("worker", new Blob([workerJs], { type: "application/javascript" }), "worker.js");
|
|
@@ -906,6 +1500,12 @@ var deploy_default = defineCommand6({
|
|
|
906
1500
|
if (doManifest) {
|
|
907
1501
|
form.append("doManifest", JSON.stringify(doManifest));
|
|
908
1502
|
}
|
|
1503
|
+
if (customBindings.length) {
|
|
1504
|
+
form.append("bindingManifest", JSON.stringify(customBindings));
|
|
1505
|
+
}
|
|
1506
|
+
if (userSecretNames.length) {
|
|
1507
|
+
form.append("userSecrets", JSON.stringify(userSecrets));
|
|
1508
|
+
}
|
|
909
1509
|
const res = await fetch(`${DEPLOY_URL}/api/deploy/${appName}`, {
|
|
910
1510
|
method: "POST",
|
|
911
1511
|
headers: { Authorization: `Bearer ${token}` },
|
|
@@ -917,11 +1517,40 @@ var deploy_default = defineCommand6({
|
|
|
917
1517
|
p3.cancel(body.error ?? `Deployment error (${res.status})`);
|
|
918
1518
|
process.exit(1);
|
|
919
1519
|
}
|
|
1520
|
+
if (body.url) {
|
|
1521
|
+
s.message("Waiting for edge propagation...");
|
|
1522
|
+
const ok = await waitForAssetsReady(body.url, 9e4);
|
|
1523
|
+
if (!ok) {
|
|
1524
|
+
s.stop("Deployed (edge propagation still in progress after 90s)");
|
|
1525
|
+
p3.log.warn("First requests may briefly hit the assets transitional page; retry in a minute.");
|
|
1526
|
+
p3.log.success(`Live at: ${body.url}`);
|
|
1527
|
+
p3.outro("Done");
|
|
1528
|
+
return;
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
920
1531
|
s.stop("Deployed!");
|
|
921
1532
|
p3.log.success(`Live at: ${body.url}`);
|
|
922
1533
|
p3.outro("Done");
|
|
923
1534
|
}
|
|
924
1535
|
});
|
|
1536
|
+
async function waitForAssetsReady(url, timeoutMs) {
|
|
1537
|
+
const deadline = Date.now() + timeoutMs;
|
|
1538
|
+
let attempt = 0;
|
|
1539
|
+
while (Date.now() < deadline) {
|
|
1540
|
+
attempt++;
|
|
1541
|
+
try {
|
|
1542
|
+
const res = await fetch(url, { redirect: "manual" });
|
|
1543
|
+
const body = await res.text();
|
|
1544
|
+
if (!body.includes("Assets have not yet deployed")) {
|
|
1545
|
+
return true;
|
|
1546
|
+
}
|
|
1547
|
+
} catch {
|
|
1548
|
+
}
|
|
1549
|
+
const wait2 = Math.min(8e3, 1e3 * 2 ** (attempt - 1));
|
|
1550
|
+
await new Promise((r) => setTimeout(r, wait2));
|
|
1551
|
+
}
|
|
1552
|
+
return false;
|
|
1553
|
+
}
|
|
925
1554
|
function collectAssets(dir) {
|
|
926
1555
|
const assets = [];
|
|
927
1556
|
function walk(d, prefix) {
|
|
@@ -944,13 +1573,13 @@ function collectAssets(dir) {
|
|
|
944
1573
|
}
|
|
945
1574
|
|
|
946
1575
|
// src/cli/commands/undeploy.ts
|
|
947
|
-
import { defineCommand as
|
|
1576
|
+
import { defineCommand as defineCommand8 } from "citty";
|
|
948
1577
|
import { readFileSync as readFileSync6, existsSync as existsSync8 } from "fs";
|
|
949
1578
|
import { join as join9 } from "path";
|
|
950
1579
|
import { parse as parseToml3 } from "smol-toml";
|
|
951
1580
|
import * as p4 from "@clack/prompts";
|
|
952
1581
|
var DEPLOY_URL2 = process.env.DEEPSPACE_DEPLOY_URL ?? ENVS.prod.deploy;
|
|
953
|
-
var undeploy_default =
|
|
1582
|
+
var undeploy_default = defineCommand8({
|
|
954
1583
|
meta: {
|
|
955
1584
|
name: "undeploy",
|
|
956
1585
|
description: "Remove a deployed DeepSpace app"
|
|
@@ -1001,8 +1630,8 @@ var undeploy_default = defineCommand7({
|
|
|
1001
1630
|
});
|
|
1002
1631
|
|
|
1003
1632
|
// src/cli/commands/whoami.ts
|
|
1004
|
-
import { defineCommand as
|
|
1005
|
-
var whoami_default =
|
|
1633
|
+
import { defineCommand as defineCommand9 } from "citty";
|
|
1634
|
+
var whoami_default = defineCommand9({
|
|
1006
1635
|
meta: {
|
|
1007
1636
|
name: "whoami",
|
|
1008
1637
|
description: "Show the currently logged-in user"
|
|
@@ -1056,7 +1685,7 @@ var whoami_default = defineCommand8({
|
|
|
1056
1685
|
});
|
|
1057
1686
|
|
|
1058
1687
|
// src/cli/commands/add.ts
|
|
1059
|
-
import { defineCommand as
|
|
1688
|
+
import { defineCommand as defineCommand10 } from "citty";
|
|
1060
1689
|
import { existsSync as existsSync9 } from "fs";
|
|
1061
1690
|
import { resolve as resolve4, join as join10 } from "path";
|
|
1062
1691
|
import { execSync as execSync3 } from "child_process";
|
|
@@ -1065,7 +1694,7 @@ function findScript(from) {
|
|
|
1065
1694
|
if (existsSync9(candidate)) return candidate;
|
|
1066
1695
|
return null;
|
|
1067
1696
|
}
|
|
1068
|
-
var add_default =
|
|
1697
|
+
var add_default = defineCommand10({
|
|
1069
1698
|
meta: {
|
|
1070
1699
|
name: "add",
|
|
1071
1700
|
description: "Add a feature to your DeepSpace app"
|
|
@@ -1119,7 +1748,7 @@ var add_default = defineCommand9({
|
|
|
1119
1748
|
});
|
|
1120
1749
|
|
|
1121
1750
|
// src/cli/commands/domain.ts
|
|
1122
|
-
import { defineCommand as
|
|
1751
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
1123
1752
|
import { execSync as execSync4 } from "child_process";
|
|
1124
1753
|
|
|
1125
1754
|
// src/cli/lib/app-context.ts
|
|
@@ -1188,7 +1817,7 @@ async function confirm2(message) {
|
|
|
1188
1817
|
});
|
|
1189
1818
|
});
|
|
1190
1819
|
}
|
|
1191
|
-
var search =
|
|
1820
|
+
var search = defineCommand11({
|
|
1192
1821
|
meta: { name: "search", description: "Search for available domains" },
|
|
1193
1822
|
args: {
|
|
1194
1823
|
query: { type: "positional", description: "Domain or keyword", required: true },
|
|
@@ -1218,7 +1847,7 @@ var search = defineCommand10({
|
|
|
1218
1847
|
}
|
|
1219
1848
|
}
|
|
1220
1849
|
});
|
|
1221
|
-
var buy =
|
|
1850
|
+
var buy = defineCommand11({
|
|
1222
1851
|
meta: { name: "buy", description: "Buy a domain and attach it to an app" },
|
|
1223
1852
|
args: {
|
|
1224
1853
|
domain: { type: "positional", description: "Domain to buy", required: true },
|
|
@@ -1307,7 +1936,7 @@ var buy = defineCommand10({
|
|
|
1307
1936
|
process.exit(1);
|
|
1308
1937
|
}
|
|
1309
1938
|
});
|
|
1310
|
-
var list2 =
|
|
1939
|
+
var list2 = defineCommand11({
|
|
1311
1940
|
meta: { name: "list", description: "List your domains" },
|
|
1312
1941
|
args: {
|
|
1313
1942
|
json: { type: "boolean", description: "Emit JSON" }
|
|
@@ -1331,7 +1960,7 @@ var list2 = defineCommand10({
|
|
|
1331
1960
|
}
|
|
1332
1961
|
}
|
|
1333
1962
|
});
|
|
1334
|
-
var status =
|
|
1963
|
+
var status = defineCommand11({
|
|
1335
1964
|
meta: { name: "status", description: "Show details for one domain" },
|
|
1336
1965
|
args: {
|
|
1337
1966
|
domain: { type: "positional", description: "Domain", required: true },
|
|
@@ -1359,7 +1988,7 @@ var status = defineCommand10({
|
|
|
1359
1988
|
console.log(`Charged: ${fmtCents(found.chargedCents)}/yr`);
|
|
1360
1989
|
}
|
|
1361
1990
|
});
|
|
1362
|
-
var attach =
|
|
1991
|
+
var attach = defineCommand11({
|
|
1363
1992
|
meta: { name: "attach", description: "Re-point a domain at a different app" },
|
|
1364
1993
|
args: {
|
|
1365
1994
|
domain: { type: "positional", description: "Domain to re-point", required: true },
|
|
@@ -1390,7 +2019,7 @@ var attach = defineCommand10({
|
|
|
1390
2019
|
console.log(`\u2713 ${args.domain} now points at ${targetApp}`);
|
|
1391
2020
|
}
|
|
1392
2021
|
});
|
|
1393
|
-
var detach =
|
|
2022
|
+
var detach = defineCommand11({
|
|
1394
2023
|
meta: {
|
|
1395
2024
|
name: "detach",
|
|
1396
2025
|
description: "Stop routing the domain (keeps the registration; auto-renew unchanged)"
|
|
@@ -1420,7 +2049,7 @@ var detach = defineCommand10({
|
|
|
1420
2049
|
console.log(`\u2713 ${args.domain} detached. Use \`deepspace domain attach\` to re-route, or \`renew --auto off\` to stop auto-renewal.`);
|
|
1421
2050
|
}
|
|
1422
2051
|
});
|
|
1423
|
-
var renew =
|
|
2052
|
+
var renew = defineCommand11({
|
|
1424
2053
|
meta: { name: "renew", description: "Toggle auto-renewal at the registrar" },
|
|
1425
2054
|
args: {
|
|
1426
2055
|
domain: { type: "positional", description: "Domain", required: true },
|
|
@@ -1454,13 +2083,13 @@ function openBrowser2(url) {
|
|
|
1454
2083
|
} catch {
|
|
1455
2084
|
}
|
|
1456
2085
|
}
|
|
1457
|
-
var domain_default =
|
|
2086
|
+
var domain_default = defineCommand11({
|
|
1458
2087
|
meta: { name: "domain", description: "Buy and manage custom domains" },
|
|
1459
2088
|
subCommands: { search, buy, list: list2, status, attach, detach, renew }
|
|
1460
2089
|
});
|
|
1461
2090
|
|
|
1462
2091
|
// src/cli/commands/integrations.ts
|
|
1463
|
-
import { defineCommand as
|
|
2092
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
1464
2093
|
|
|
1465
2094
|
// src/cli/commands/_invoke-impl.ts
|
|
1466
2095
|
import { readFileSync as readFileSync8 } from "fs";
|
|
@@ -1634,7 +2263,7 @@ async function runInvoke(args) {
|
|
|
1634
2263
|
}
|
|
1635
2264
|
|
|
1636
2265
|
// src/cli/commands/integrations.ts
|
|
1637
|
-
var list3 =
|
|
2266
|
+
var list3 = defineCommand12({
|
|
1638
2267
|
meta: {
|
|
1639
2268
|
name: "list",
|
|
1640
2269
|
description: "List all available integrations"
|
|
@@ -1655,7 +2284,7 @@ var list3 = defineCommand11({
|
|
|
1655
2284
|
}
|
|
1656
2285
|
}
|
|
1657
2286
|
});
|
|
1658
|
-
var info =
|
|
2287
|
+
var info = defineCommand12({
|
|
1659
2288
|
meta: {
|
|
1660
2289
|
name: "info",
|
|
1661
2290
|
description: "Print schema + example body for an integration endpoint"
|
|
@@ -1681,7 +2310,7 @@ var info = defineCommand11({
|
|
|
1681
2310
|
}
|
|
1682
2311
|
}
|
|
1683
2312
|
});
|
|
1684
|
-
var invoke =
|
|
2313
|
+
var invoke = defineCommand12({
|
|
1685
2314
|
meta: {
|
|
1686
2315
|
name: "invoke",
|
|
1687
2316
|
description: "Invoke a platform integration as the logged-in user"
|
|
@@ -1734,7 +2363,7 @@ var invoke = defineCommand11({
|
|
|
1734
2363
|
}
|
|
1735
2364
|
}
|
|
1736
2365
|
});
|
|
1737
|
-
var integrations_default =
|
|
2366
|
+
var integrations_default = defineCommand12({
|
|
1738
2367
|
meta: {
|
|
1739
2368
|
name: "integrations",
|
|
1740
2369
|
description: "List, inspect, and invoke platform integrations"
|
|
@@ -1747,8 +2376,8 @@ var integrations_default = defineCommand11({
|
|
|
1747
2376
|
});
|
|
1748
2377
|
|
|
1749
2378
|
// src/cli/commands/invoke.ts
|
|
1750
|
-
import { defineCommand as
|
|
1751
|
-
var invoke_default =
|
|
2379
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
2380
|
+
var invoke_default = defineCommand13({
|
|
1752
2381
|
meta: {
|
|
1753
2382
|
name: "invoke",
|
|
1754
2383
|
description: "Invoke a platform integration as the logged-in user"
|
|
@@ -1826,7 +2455,7 @@ var pkg = JSON.parse(readFileSync9(join12(__dirname, "..", "package.json"), "utf
|
|
|
1826
2455
|
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync11("/etc/ssl/certs/ca-certificates.crt")) {
|
|
1827
2456
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
1828
2457
|
}
|
|
1829
|
-
var create2 =
|
|
2458
|
+
var create2 = defineCommand14({
|
|
1830
2459
|
meta: {
|
|
1831
2460
|
name: "create",
|
|
1832
2461
|
description: "Create a new DeepSpace app"
|
|
@@ -1845,7 +2474,7 @@ var create2 = defineCommand13({
|
|
|
1845
2474
|
execSync5(`npm create deepspace@latest${name}`, { stdio: "inherit" });
|
|
1846
2475
|
}
|
|
1847
2476
|
});
|
|
1848
|
-
var main =
|
|
2477
|
+
var main = defineCommand14({
|
|
1849
2478
|
meta: {
|
|
1850
2479
|
name: "deepspace",
|
|
1851
2480
|
version: pkg.version,
|
|
@@ -1857,6 +2486,7 @@ var main = defineCommand13({
|
|
|
1857
2486
|
logout: logout_default,
|
|
1858
2487
|
whoami: whoami_default,
|
|
1859
2488
|
dev: dev_default,
|
|
2489
|
+
kill: kill_default,
|
|
1860
2490
|
test: test_default,
|
|
1861
2491
|
"test-accounts": test_accounts_default,
|
|
1862
2492
|
add: add_default,
|