deepspace 0.16.0 → 0.17.0
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/CHANGELOG.md +102 -0
- package/dist/cli.js +555 -232
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -157
- package/dist/index.js +193 -326
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +4 -137
- package/dist/server.js +3 -412
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +5 -210
- package/dist/worker.js +3 -419
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// src/cli/cli.ts
|
|
4
4
|
import { defineCommand as defineCommand14, runMain, runCommand, renderUsage } from "citty";
|
|
5
5
|
import { sync as spawnSync8 } from "cross-spawn";
|
|
6
|
-
import { readFileSync as
|
|
7
|
-
import { dirname as
|
|
6
|
+
import { readFileSync as readFileSync30, existsSync as existsSync27 } from "fs";
|
|
7
|
+
import { dirname as dirname11, join as join25 } from "path";
|
|
8
8
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9
9
|
|
|
10
10
|
// src/cli/lib/spinner.ts
|
|
@@ -41,7 +41,8 @@ function stopActiveSpinner() {
|
|
|
41
41
|
|
|
42
42
|
// src/cli/lib/output.ts
|
|
43
43
|
import * as p2 from "@clack/prompts";
|
|
44
|
-
import {
|
|
44
|
+
import { readFileSync, realpathSync } from "fs";
|
|
45
|
+
import { dirname, isAbsolute, resolve } from "path";
|
|
45
46
|
|
|
46
47
|
// src/cli/lib/cli-format.ts
|
|
47
48
|
var ANSI_RE = /\[[0-9;]*m/g;
|
|
@@ -59,10 +60,35 @@ function humanCommand(argv) {
|
|
|
59
60
|
}
|
|
60
61
|
|
|
61
62
|
// src/cli/lib/output.ts
|
|
63
|
+
function resolveActionArgv(argv) {
|
|
64
|
+
if (argv[0] !== "deepspace") return argv;
|
|
65
|
+
const entry = cliEntryPath();
|
|
66
|
+
return entry ? [process.execPath, entry, ...argv.slice(1)] : argv;
|
|
67
|
+
}
|
|
68
|
+
function cliEntryPath() {
|
|
69
|
+
const entry = process.argv[1];
|
|
70
|
+
if (!entry || !isAbsolute(entry)) return null;
|
|
71
|
+
let real;
|
|
72
|
+
try {
|
|
73
|
+
real = realpathSync(entry);
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
if (!/(^|[\\/])cli\.[cm]?js$/.test(real)) return null;
|
|
78
|
+
try {
|
|
79
|
+
const pkg2 = JSON.parse(readFileSync(resolve(dirname(real), "..", "package.json"), "utf-8"));
|
|
80
|
+
return pkg2.name === "deepspace" ? real : null;
|
|
81
|
+
} catch {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function executableAction(action) {
|
|
86
|
+
const pinned = { ...action, argv: resolveActionArgv(action.argv) };
|
|
87
|
+
assertExecutableAction(pinned);
|
|
88
|
+
return pinned;
|
|
89
|
+
}
|
|
62
90
|
function cliAction(...argv) {
|
|
63
|
-
|
|
64
|
-
assertExecutableAction(action);
|
|
65
|
-
return action;
|
|
91
|
+
return executableAction({ cwd: process.cwd(), argv });
|
|
66
92
|
}
|
|
67
93
|
function assertExecutableAction(action) {
|
|
68
94
|
if (!isAbsolute(action.cwd)) throw new TypeError("CLI action cwd must be absolute");
|
|
@@ -78,7 +104,9 @@ function withSlug(msg, code) {
|
|
|
78
104
|
return msg.trimEnd().endsWith(tag) ? msg : `${msg.trimEnd()} ${tag}`;
|
|
79
105
|
}
|
|
80
106
|
function displayArg(arg) {
|
|
81
|
-
|
|
107
|
+
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(arg)) return arg;
|
|
108
|
+
if (process.platform === "win32") return `"${arg.replaceAll('"', '""')}"`;
|
|
109
|
+
return shQuote(arg);
|
|
82
110
|
}
|
|
83
111
|
function printAction(action) {
|
|
84
112
|
assertExecutableAction(action);
|
|
@@ -342,7 +370,7 @@ function effectivePlatformUrls(env = process.env) {
|
|
|
342
370
|
var DASHBOARD_URL = DEEPSPACE_ENV === "production" ? "https://dashboard.deep.space" : DEEPSPACE_ENV === "staging" ? "https://dashboard.deepspacesites.com" : "http://127.0.0.1:9";
|
|
343
371
|
|
|
344
372
|
// src/cli/auth.ts
|
|
345
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
373
|
+
import { readFileSync as readFileSync2, writeFileSync, existsSync, mkdirSync } from "fs";
|
|
346
374
|
import { join } from "path";
|
|
347
375
|
import { homedir } from "os";
|
|
348
376
|
|
|
@@ -382,8 +410,7 @@ var Refusal = class extends Error {
|
|
|
382
410
|
super(message);
|
|
383
411
|
this.name = "Refusal";
|
|
384
412
|
this.code = code;
|
|
385
|
-
|
|
386
|
-
this.action = opts.action;
|
|
413
|
+
this.action = opts.action ? executableAction(opts.action) : void 0;
|
|
387
414
|
this.actionRequired = opts.actionRequired ?? false;
|
|
388
415
|
this.extra = opts.extra ?? {};
|
|
389
416
|
}
|
|
@@ -428,7 +455,7 @@ function defineDeepspaceCommand(def) {
|
|
|
428
455
|
let succeeded = false;
|
|
429
456
|
try {
|
|
430
457
|
const out = await def.run({ args }) ?? {};
|
|
431
|
-
if (out.action)
|
|
458
|
+
if (out.action) out.action = executableAction(out.action);
|
|
432
459
|
if (json) {
|
|
433
460
|
console.log(
|
|
434
461
|
JSON.stringify({
|
|
@@ -492,7 +519,7 @@ function credentialPaths(authUrl = AUTH_URL) {
|
|
|
492
519
|
var { sessionPath: SESSION_PATH, tokenPath: TOKEN_PATH } = credentialPaths();
|
|
493
520
|
async function ensureToken() {
|
|
494
521
|
if (existsSync(TOKEN_PATH)) {
|
|
495
|
-
const existing =
|
|
522
|
+
const existing = readFileSync2(TOKEN_PATH, "utf-8").trim();
|
|
496
523
|
if (isTokenValid(existing)) {
|
|
497
524
|
return existing;
|
|
498
525
|
}
|
|
@@ -502,7 +529,7 @@ async function ensureToken() {
|
|
|
502
529
|
action: cliAction("deepspace", "auth", "login")
|
|
503
530
|
});
|
|
504
531
|
}
|
|
505
|
-
const sessionToken =
|
|
532
|
+
const sessionToken = readFileSync2(SESSION_PATH, "utf-8").trim();
|
|
506
533
|
const token = await exchangeSession(AUTH_URL, sessionToken);
|
|
507
534
|
if (!token) {
|
|
508
535
|
throw new Refusal(
|
|
@@ -526,7 +553,7 @@ function isTokenValid(jwt) {
|
|
|
526
553
|
registerAuthRefresh(async () => {
|
|
527
554
|
try {
|
|
528
555
|
if (!existsSync(SESSION_PATH)) return null;
|
|
529
|
-
const sessionToken =
|
|
556
|
+
const sessionToken = readFileSync2(SESSION_PATH, "utf-8").trim();
|
|
530
557
|
const token = await exchangeSession(AUTH_URL, sessionToken);
|
|
531
558
|
if (!token) return null;
|
|
532
559
|
mkdirSync(DIR, { recursive: true, mode: 448 });
|
|
@@ -538,7 +565,7 @@ registerAuthRefresh(async () => {
|
|
|
538
565
|
});
|
|
539
566
|
|
|
540
567
|
// src/cli/commands/login.ts
|
|
541
|
-
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, readFileSync as
|
|
568
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3 } from "fs";
|
|
542
569
|
import { join as join2 } from "path";
|
|
543
570
|
import { homedir as homedir2 } from "os";
|
|
544
571
|
import { randomBytes, createHash } from "crypto";
|
|
@@ -697,7 +724,7 @@ function readPasswordFromStdin() {
|
|
|
697
724
|
"password_stdin_needs_pipe"
|
|
698
725
|
);
|
|
699
726
|
}
|
|
700
|
-
return
|
|
727
|
+
return readFileSync3(0, "utf-8").replace(/\r?\n$/, "");
|
|
701
728
|
}
|
|
702
729
|
async function pollForCompletion(sessionId, codeVerifier) {
|
|
703
730
|
const maxAttempts = 120;
|
|
@@ -738,7 +765,7 @@ async function provisionProfile(jwt) {
|
|
|
738
765
|
}
|
|
739
766
|
}
|
|
740
767
|
function sleep(ms) {
|
|
741
|
-
return new Promise((
|
|
768
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
742
769
|
}
|
|
743
770
|
function base64url(bytes) {
|
|
744
771
|
return bytes.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
@@ -775,7 +802,7 @@ async function doEmailLogin(email, password) {
|
|
|
775
802
|
}
|
|
776
803
|
|
|
777
804
|
// src/cli/commands/logout.ts
|
|
778
|
-
import { existsSync as existsSync2, readFileSync as
|
|
805
|
+
import { existsSync as existsSync2, readFileSync as readFileSync4, rmSync } from "fs";
|
|
779
806
|
var AUTH_URL3 = process.env.DEEPSPACE_AUTH_URL ?? PLATFORM_URLS.auth;
|
|
780
807
|
var { sessionPath: SESSION_PATH2, tokenPath: TOKEN_PATH2 } = credentialPaths(AUTH_URL3);
|
|
781
808
|
var logout_default = defineDeepspaceCommand({
|
|
@@ -784,7 +811,7 @@ var logout_default = defineDeepspaceCommand({
|
|
|
784
811
|
description: "Sign out and remove cached credentials"
|
|
785
812
|
},
|
|
786
813
|
async run({ args }) {
|
|
787
|
-
const sessionToken = existsSync2(SESSION_PATH2) ?
|
|
814
|
+
const sessionToken = existsSync2(SESSION_PATH2) ? readFileSync4(SESSION_PATH2, "utf-8").trim() : null;
|
|
788
815
|
if (sessionToken) {
|
|
789
816
|
try {
|
|
790
817
|
await fetch(`${AUTH_URL3}/api/auth/sign-out`, {
|
|
@@ -810,8 +837,8 @@ var logout_default = defineDeepspaceCommand({
|
|
|
810
837
|
});
|
|
811
838
|
|
|
812
839
|
// src/cli/lib/app-identity.ts
|
|
813
|
-
import { existsSync as existsSync3, readFileSync as
|
|
814
|
-
import { join as join3, resolve } from "path";
|
|
840
|
+
import { existsSync as existsSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
841
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
815
842
|
import { parse as parseToml } from "smol-toml";
|
|
816
843
|
|
|
817
844
|
// src/server/utils/registry-client.ts
|
|
@@ -846,10 +873,10 @@ function mintAppId(now = Date.now()) {
|
|
|
846
873
|
return `app_${mintUlid(now)}`;
|
|
847
874
|
}
|
|
848
875
|
function readWranglerIdentityConfig(cwd) {
|
|
849
|
-
const wranglerPath = join3(
|
|
876
|
+
const wranglerPath = join3(resolve2(cwd), "wrangler.toml");
|
|
850
877
|
if (!existsSync3(wranglerPath)) return null;
|
|
851
878
|
try {
|
|
852
|
-
return parseToml(
|
|
879
|
+
return parseToml(readFileSync5(wranglerPath, "utf-8"));
|
|
853
880
|
} catch (err) {
|
|
854
881
|
throw new InputError(
|
|
855
882
|
`Could not parse ${wranglerPath}: ${err instanceof Error ? err.message : String(err)}`,
|
|
@@ -865,9 +892,9 @@ function readAppId(cwd = process.cwd(), wranglerEnv) {
|
|
|
865
892
|
return typeof id === "string" && APP_ID_RE.test(id) ? id : null;
|
|
866
893
|
}
|
|
867
894
|
function writeAppId(cwd, appId, opts = {}) {
|
|
868
|
-
const wranglerPath = join3(
|
|
895
|
+
const wranglerPath = join3(resolve2(cwd), "wrangler.toml");
|
|
869
896
|
if (!existsSync3(wranglerPath)) {
|
|
870
|
-
throw new Error(`No wrangler.toml in ${
|
|
897
|
+
throw new Error(`No wrangler.toml in ${resolve2(cwd)}`);
|
|
871
898
|
}
|
|
872
899
|
const existing = readAppId(cwd, opts.wranglerEnv);
|
|
873
900
|
if (existing && !opts.force) {
|
|
@@ -876,7 +903,7 @@ function writeAppId(cwd, appId, opts = {}) {
|
|
|
876
903
|
`wrangler.toml already carries ${existing}. The app id is immutable \u2014 use --new-id only to fork this repo as a separate app.`
|
|
877
904
|
);
|
|
878
905
|
}
|
|
879
|
-
let src =
|
|
906
|
+
let src = readFileSync5(wranglerPath, "utf-8");
|
|
880
907
|
const header = opts.wranglerEnv ? `[env.${opts.wranglerEnv}.vars]` : "[vars]";
|
|
881
908
|
const line = `DEEPSPACE_APP_ID = "${appId}"`;
|
|
882
909
|
const headerRe = new RegExp(`^\\${header.replace(/\./g, "\\.")}[ \\t]*$`, "m");
|
|
@@ -902,18 +929,18 @@ ${line}
|
|
|
902
929
|
}
|
|
903
930
|
|
|
904
931
|
// src/cli/commands/dev.ts
|
|
905
|
-
import { resolve as
|
|
932
|
+
import { resolve as resolve8, basename as basename2, join as join12 } from "path";
|
|
906
933
|
import spawn from "cross-spawn";
|
|
907
934
|
|
|
908
935
|
// src/cli/lib/app-context.ts
|
|
909
|
-
import { existsSync as existsSync4, readFileSync as
|
|
910
|
-
import { dirname, join as join4, resolve as
|
|
936
|
+
import { existsSync as existsSync4, readFileSync as readFileSync6, readdirSync } from "fs";
|
|
937
|
+
import { dirname as dirname2, join as join4, resolve as resolve3 } from "path";
|
|
911
938
|
import { parse as parseToml2 } from "smol-toml";
|
|
912
939
|
function detectAppName(cwd = process.cwd()) {
|
|
913
|
-
const wranglerPath = join4(
|
|
940
|
+
const wranglerPath = join4(resolve3(cwd), "wrangler.toml");
|
|
914
941
|
if (!existsSync4(wranglerPath)) return null;
|
|
915
942
|
try {
|
|
916
|
-
const config = parseToml2(
|
|
943
|
+
const config = parseToml2(readFileSync6(wranglerPath, "utf-8"));
|
|
917
944
|
return typeof config.name === "string" && config.name.length > 0 ? config.name : null;
|
|
918
945
|
} catch (error) {
|
|
919
946
|
throw new InputError(
|
|
@@ -923,10 +950,10 @@ function detectAppName(cwd = process.cwd()) {
|
|
|
923
950
|
}
|
|
924
951
|
}
|
|
925
952
|
function findAppDir(start = process.cwd()) {
|
|
926
|
-
let dir =
|
|
953
|
+
let dir = resolve3(start);
|
|
927
954
|
for (; ; ) {
|
|
928
955
|
if (existsSync4(join4(dir, "wrangler.toml"))) return dir;
|
|
929
|
-
const parent =
|
|
956
|
+
const parent = dirname2(dir);
|
|
930
957
|
if (parent === dir) return null;
|
|
931
958
|
dir = parent;
|
|
932
959
|
}
|
|
@@ -942,18 +969,18 @@ function findChildApps(dir) {
|
|
|
942
969
|
// src/cli/lib/launch-config.ts
|
|
943
970
|
import {
|
|
944
971
|
existsSync as existsSync5,
|
|
945
|
-
readFileSync as
|
|
946
|
-
realpathSync,
|
|
972
|
+
readFileSync as readFileSync8,
|
|
973
|
+
realpathSync as realpathSync2,
|
|
947
974
|
writeFileSync as writeFileSync4,
|
|
948
975
|
mkdirSync as mkdirSync4,
|
|
949
976
|
renameSync,
|
|
950
977
|
unlinkSync
|
|
951
978
|
} from "fs";
|
|
952
|
-
import { join as join6, resolve as
|
|
979
|
+
import { join as join6, resolve as resolve5, dirname as dirname4, basename, isAbsolute as isAbsolute2, sep } from "path";
|
|
953
980
|
|
|
954
981
|
// src/cli/lib/git/repository.ts
|
|
955
|
-
import { appendFileSync, mkdirSync as mkdirSync3, readFileSync as
|
|
956
|
-
import { dirname as
|
|
982
|
+
import { appendFileSync, mkdirSync as mkdirSync3, readFileSync as readFileSync7 } from "fs";
|
|
983
|
+
import { dirname as dirname3, join as join5, resolve as resolve4 } from "path";
|
|
957
984
|
|
|
958
985
|
// src/cli/lib/git/process.ts
|
|
959
986
|
import { sync as spawnSync } from "cross-spawn";
|
|
@@ -1156,16 +1183,16 @@ function listWorktrees(cwd) {
|
|
|
1156
1183
|
return worktrees;
|
|
1157
1184
|
}
|
|
1158
1185
|
function ensureLocalExclude(cwd, pattern) {
|
|
1159
|
-
const commonDir =
|
|
1186
|
+
const commonDir = resolve4(cwd, gitLine(cwd, ["rev-parse", "--git-common-dir"]));
|
|
1160
1187
|
const excludePath = join5(commonDir, "info", "exclude");
|
|
1161
1188
|
let current = "";
|
|
1162
1189
|
try {
|
|
1163
|
-
current =
|
|
1190
|
+
current = readFileSync7(excludePath, "utf-8");
|
|
1164
1191
|
} catch {
|
|
1165
1192
|
}
|
|
1166
1193
|
if (current.split("\n").some((line) => line.trim() === pattern)) return;
|
|
1167
1194
|
try {
|
|
1168
|
-
mkdirSync3(
|
|
1195
|
+
mkdirSync3(dirname3(excludePath), { recursive: true });
|
|
1169
1196
|
appendFileSync(
|
|
1170
1197
|
excludePath,
|
|
1171
1198
|
`${current.endsWith("\n") || current === "" ? "" : "\n"}${pattern}
|
|
@@ -1177,7 +1204,7 @@ function ensureLocalExclude(cwd, pattern) {
|
|
|
1177
1204
|
|
|
1178
1205
|
// src/cli/lib/launch-config.ts
|
|
1179
1206
|
function writeLaunchFile(launchPath, config) {
|
|
1180
|
-
mkdirSync4(
|
|
1207
|
+
mkdirSync4(dirname4(launchPath), { recursive: true });
|
|
1181
1208
|
const tmpPath = `${launchPath}.${process.pid}.tmp`;
|
|
1182
1209
|
writeFileSync4(tmpPath, JSON.stringify(config, null, 2) + "\n");
|
|
1183
1210
|
try {
|
|
@@ -1193,7 +1220,7 @@ function writeLaunchFile(launchPath, config) {
|
|
|
1193
1220
|
function readLaunchFile(launchPath) {
|
|
1194
1221
|
const empty = { version: "0.0.1", configurations: [] };
|
|
1195
1222
|
if (!existsSync5(launchPath)) return empty;
|
|
1196
|
-
const raw =
|
|
1223
|
+
const raw = readFileSync8(launchPath, "utf-8").trim();
|
|
1197
1224
|
if (!raw) return empty;
|
|
1198
1225
|
const parsed = JSON.parse(raw);
|
|
1199
1226
|
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.configurations)) return null;
|
|
@@ -1258,10 +1285,10 @@ function detectClaudeWorktree(appDir) {
|
|
|
1258
1285
|
listWorktrees(appDir).map((worktree) => canonicalPath(worktree.path))
|
|
1259
1286
|
);
|
|
1260
1287
|
if (!registered.has(worktreeRoot)) return null;
|
|
1261
|
-
const worktreesDir =
|
|
1262
|
-
const claudeDir =
|
|
1288
|
+
const worktreesDir = dirname4(worktreeRoot);
|
|
1289
|
+
const claudeDir = dirname4(worktreesDir);
|
|
1263
1290
|
if (basename(worktreesDir) !== "worktrees" || basename(claudeDir) !== ".claude") return null;
|
|
1264
|
-
const ownerRoot = canonicalPath(
|
|
1291
|
+
const ownerRoot = canonicalPath(dirname4(claudeDir));
|
|
1265
1292
|
if (!registered.has(ownerRoot)) return null;
|
|
1266
1293
|
return { mainRepoRoot: ownerRoot, worktreeName: basename(worktreeRoot) };
|
|
1267
1294
|
} catch {
|
|
@@ -1270,9 +1297,9 @@ function detectClaudeWorktree(appDir) {
|
|
|
1270
1297
|
}
|
|
1271
1298
|
function canonicalPath(path) {
|
|
1272
1299
|
try {
|
|
1273
|
-
return
|
|
1300
|
+
return realpathSync2(path);
|
|
1274
1301
|
} catch {
|
|
1275
|
-
return
|
|
1302
|
+
return resolve5(path);
|
|
1276
1303
|
}
|
|
1277
1304
|
}
|
|
1278
1305
|
function detectLinkedWorktree(appDir) {
|
|
@@ -1324,7 +1351,7 @@ function upsertWorktreeLaunchConfig(mainRepoRoot, worktreeName, appDir, opts) {
|
|
|
1324
1351
|
// the Claude Code desktop launch.json reference alongside `port`) and
|
|
1325
1352
|
// verified end-to-end: with it set, the preview server builds from the
|
|
1326
1353
|
// worktree instead of the session's main repo.
|
|
1327
|
-
cwd:
|
|
1354
|
+
cwd: resolve5(appDir)
|
|
1328
1355
|
});
|
|
1329
1356
|
writeLaunchFile(launchPath, config);
|
|
1330
1357
|
return { entryName, port };
|
|
@@ -1351,7 +1378,7 @@ function resolveWorktreePort(appDir) {
|
|
|
1351
1378
|
}
|
|
1352
1379
|
|
|
1353
1380
|
// src/cli/lib/dev-vars.ts
|
|
1354
|
-
import { existsSync as existsSync7, readFileSync as
|
|
1381
|
+
import { existsSync as existsSync7, readFileSync as readFileSync10 } from "fs";
|
|
1355
1382
|
|
|
1356
1383
|
// src/cli/lib/app-tokens.ts
|
|
1357
1384
|
async function fetchPublicKey(authUrl) {
|
|
@@ -1896,7 +1923,7 @@ function writeSecretFileSync(path, content) {
|
|
|
1896
1923
|
}
|
|
1897
1924
|
|
|
1898
1925
|
// src/cli/lib/wrangler-env.ts
|
|
1899
|
-
import { existsSync as existsSync6, readFileSync as
|
|
1926
|
+
import { existsSync as existsSync6, readFileSync as readFileSync9, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
1900
1927
|
import { join as join7 } from "path";
|
|
1901
1928
|
import { parse as parseToml3, stringify as stringifyToml } from "smol-toml";
|
|
1902
1929
|
|
|
@@ -2090,7 +2117,7 @@ var WranglerConfigError = class extends Error {
|
|
|
2090
2117
|
};
|
|
2091
2118
|
function readWranglerConfig(appDir) {
|
|
2092
2119
|
const path = join7(appDir, "wrangler.toml");
|
|
2093
|
-
const raw =
|
|
2120
|
+
const raw = readFileSync9(path, "utf-8");
|
|
2094
2121
|
try {
|
|
2095
2122
|
return parseToml3(raw);
|
|
2096
2123
|
} catch (err) {
|
|
@@ -2263,7 +2290,7 @@ async function writeDevVars(appDir, ownerId, callerJwt, wranglerEnv, opts = {})
|
|
|
2263
2290
|
const devVarsPath = devVarsPathFor(appDir, wranglerEnv, {
|
|
2264
2291
|
sharedDevVarsCache: useSharedDevVarsCache
|
|
2265
2292
|
});
|
|
2266
|
-
const existing = existsSync7(devVarsPath) ?
|
|
2293
|
+
const existing = existsSync7(devVarsPath) ? readFileSync10(devVarsPath, "utf-8") : "";
|
|
2267
2294
|
const custom = opts.generatedSecretsCache ?? extractCustomDevVars(stripGeneratedSecretsCache(existing).trimEnd());
|
|
2268
2295
|
let body;
|
|
2269
2296
|
if (!custom) {
|
|
@@ -2285,15 +2312,15 @@ ${custom}
|
|
|
2285
2312
|
}
|
|
2286
2313
|
|
|
2287
2314
|
// src/cli/lib/install-status.ts
|
|
2288
|
-
import { existsSync as existsSync9, readFileSync as
|
|
2289
|
-
import { dirname as
|
|
2315
|
+
import { existsSync as existsSync9, readFileSync as readFileSync12, realpathSync as realpathSync3 } from "fs";
|
|
2316
|
+
import { dirname as dirname5, join as join9, resolve as resolve6 } from "path";
|
|
2290
2317
|
|
|
2291
2318
|
// src/cli/lib/package-manager.ts
|
|
2292
|
-
import { existsSync as existsSync8, readFileSync as
|
|
2319
|
+
import { existsSync as existsSync8, readFileSync as readFileSync11 } from "fs";
|
|
2293
2320
|
import { join as join8 } from "path";
|
|
2294
2321
|
function detectPackageManager(appDir) {
|
|
2295
2322
|
try {
|
|
2296
|
-
const pkg2 = JSON.parse(
|
|
2323
|
+
const pkg2 = JSON.parse(readFileSync11(join8(appDir, "package.json"), "utf-8"));
|
|
2297
2324
|
const name = typeof pkg2.packageManager === "string" ? pkg2.packageManager.split("@")[0] : "";
|
|
2298
2325
|
if (name === "npm" || name === "pnpm" || name === "yarn" || name === "bun") return name;
|
|
2299
2326
|
} catch {
|
|
@@ -2331,7 +2358,7 @@ function ensureInstallReady(appDir) {
|
|
|
2331
2358
|
const donePath = join9(sentinelDir, "install.done");
|
|
2332
2359
|
const logPath = join9(sentinelDir, "install.log");
|
|
2333
2360
|
if (existsSync9(errPath)) {
|
|
2334
|
-
const detail =
|
|
2361
|
+
const detail = readFileSync12(errPath, "utf-8").trimEnd();
|
|
2335
2362
|
const log29 = existsSync9(logPath) ? ` Full log: ${logPath}.` : "";
|
|
2336
2363
|
throw new Refusal(
|
|
2337
2364
|
`Dependency install failed: ${detail}.${log29} Run \`npm install\` (or \`bun install\`) manually, then retry.`,
|
|
@@ -2372,22 +2399,22 @@ function resolvesDeepspace(fromDir) {
|
|
|
2372
2399
|
for (; ; ) {
|
|
2373
2400
|
if (existsSync9(join9(dir, "node_modules", "deepspace", "package.json"))) return true;
|
|
2374
2401
|
if (dir === checkoutRoot) return false;
|
|
2375
|
-
const parent =
|
|
2402
|
+
const parent = dirname5(dir);
|
|
2376
2403
|
if (parent === dir) return false;
|
|
2377
2404
|
dir = parent;
|
|
2378
2405
|
}
|
|
2379
2406
|
}
|
|
2380
2407
|
function canonicalPath2(path) {
|
|
2381
2408
|
try {
|
|
2382
|
-
return
|
|
2409
|
+
return realpathSync3(path);
|
|
2383
2410
|
} catch {
|
|
2384
|
-
return
|
|
2411
|
+
return resolve6(path);
|
|
2385
2412
|
}
|
|
2386
2413
|
}
|
|
2387
2414
|
function installWorkerAlive(sentinelDir) {
|
|
2388
2415
|
const pidPath = join9(sentinelDir, "install.pid");
|
|
2389
2416
|
if (!existsSync9(pidPath)) return false;
|
|
2390
|
-
const pid = Number(
|
|
2417
|
+
const pid = Number(readFileSync12(pidPath, "utf-8").trim());
|
|
2391
2418
|
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
2392
2419
|
try {
|
|
2393
2420
|
process.kill(pid, 0);
|
|
@@ -2401,7 +2428,7 @@ function installWorkerAlive(sentinelDir) {
|
|
|
2401
2428
|
import { execFileSync } from "child_process";
|
|
2402
2429
|
import { existsSync as existsSync10 } from "fs";
|
|
2403
2430
|
import * as nodeModule from "module";
|
|
2404
|
-
import { resolve as
|
|
2431
|
+
import { resolve as resolve7 } from "path";
|
|
2405
2432
|
function preflightNodeVersion(command, hasRegisterHooks = typeof nodeModule.registerHooks === "function") {
|
|
2406
2433
|
if (hasRegisterHooks) return;
|
|
2407
2434
|
throw new Refusal(
|
|
@@ -2412,7 +2439,7 @@ function preflightNodeVersion(command, hasRegisterHooks = typeof nodeModule.regi
|
|
|
2412
2439
|
var DLL_NOT_FOUND = -1073741515;
|
|
2413
2440
|
function preflightWindowsWorkerd(appDir) {
|
|
2414
2441
|
if (process.platform !== "win32") return;
|
|
2415
|
-
const workerdExe =
|
|
2442
|
+
const workerdExe = resolve7(
|
|
2416
2443
|
appDir,
|
|
2417
2444
|
"node_modules",
|
|
2418
2445
|
"@cloudflare",
|
|
@@ -2577,11 +2604,11 @@ import { createServer, Socket } from "net";
|
|
|
2577
2604
|
var DEFAULT_PORT = 5173;
|
|
2578
2605
|
function isPortListening(port, host, timeoutMs = 500) {
|
|
2579
2606
|
const target2 = host === "0.0.0.0" || host === "::" ? "127.0.0.1" : host;
|
|
2580
|
-
return new Promise((
|
|
2607
|
+
return new Promise((resolve21) => {
|
|
2581
2608
|
const socket = new Socket();
|
|
2582
2609
|
const done = (listening) => {
|
|
2583
2610
|
socket.destroy();
|
|
2584
|
-
|
|
2611
|
+
resolve21(listening);
|
|
2585
2612
|
};
|
|
2586
2613
|
socket.setTimeout(timeoutMs);
|
|
2587
2614
|
socket.once("connect", () => done(true));
|
|
@@ -2594,7 +2621,7 @@ async function waitForPortListening(port, host, timeoutMs) {
|
|
|
2594
2621
|
const deadline = Date.now() + timeoutMs;
|
|
2595
2622
|
while (Date.now() < deadline) {
|
|
2596
2623
|
if (await isPortListening(port, host)) return true;
|
|
2597
|
-
await new Promise((
|
|
2624
|
+
await new Promise((resolve21) => setTimeout(resolve21, 250));
|
|
2598
2625
|
}
|
|
2599
2626
|
return false;
|
|
2600
2627
|
}
|
|
@@ -2660,7 +2687,7 @@ var dev_default = defineDeepspaceCommand({
|
|
|
2660
2687
|
preflightNodeVersion("dev start");
|
|
2661
2688
|
const wranglerEnv = typeof args.env === "string" && args.env.trim() ? args.env.trim() : void 0;
|
|
2662
2689
|
const host = typeof args.host === "string" && args.host.trim() ? args.host.trim() : DEFAULT_DEV_HOST;
|
|
2663
|
-
const start =
|
|
2690
|
+
const start = resolve8(args.dir ?? ".");
|
|
2664
2691
|
const appDir = findAppDir(start);
|
|
2665
2692
|
if (!appDir) {
|
|
2666
2693
|
throw new Refusal(noAppDirMessage(start, findChildApps(start)), "no_app_dir");
|
|
@@ -2817,7 +2844,7 @@ Free it with \`${killCmd}\`, or start on another port: \`deepspace dev start --p
|
|
|
2817
2844
|
|
|
2818
2845
|
// src/cli/commands/kill.ts
|
|
2819
2846
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
2820
|
-
import { readFileSync as
|
|
2847
|
+
import { readFileSync as readFileSync13, readdirSync as readdirSync3, readlinkSync } from "fs";
|
|
2821
2848
|
import { setTimeout as wait } from "timers/promises";
|
|
2822
2849
|
var SIGTERM_GRACE_MS = 1500;
|
|
2823
2850
|
var IS_WIN = process.platform === "win32";
|
|
@@ -2968,7 +2995,7 @@ function listenerPidsViaProc(port) {
|
|
|
2968
2995
|
for (const f of ["/proc/net/tcp", "/proc/net/tcp6"]) {
|
|
2969
2996
|
let data;
|
|
2970
2997
|
try {
|
|
2971
|
-
data =
|
|
2998
|
+
data = readFileSync13(f, "utf-8");
|
|
2972
2999
|
} catch {
|
|
2973
3000
|
continue;
|
|
2974
3001
|
}
|
|
@@ -3098,7 +3125,7 @@ function isAlive(pid) {
|
|
|
3098
3125
|
}
|
|
3099
3126
|
|
|
3100
3127
|
// src/cli/commands/test.ts
|
|
3101
|
-
import { resolve as
|
|
3128
|
+
import { resolve as resolve9 } from "path";
|
|
3102
3129
|
import { sync as spawnSync4 } from "cross-spawn";
|
|
3103
3130
|
|
|
3104
3131
|
// src/cli/lib/playwright.ts
|
|
@@ -3127,10 +3154,10 @@ function ensurePlaywright(appDir) {
|
|
|
3127
3154
|
}
|
|
3128
3155
|
|
|
3129
3156
|
// src/cli/lib/test-account-service.ts
|
|
3130
|
-
import { readFileSync as
|
|
3157
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
3131
3158
|
|
|
3132
3159
|
// src/testing/accounts.ts
|
|
3133
|
-
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as
|
|
3160
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
|
|
3134
3161
|
import { homedir as homedir3 } from "os";
|
|
3135
3162
|
import { join as join13 } from "path";
|
|
3136
3163
|
var TEST_ACCOUNTS_PATH = join13(homedir3(), ".deepspace", "test-accounts.json");
|
|
@@ -3206,7 +3233,7 @@ function removeTestAccounts(ids, emails = [], scope = currentTestAccountScope())
|
|
|
3206
3233
|
function readTestAccountStore() {
|
|
3207
3234
|
if (!existsSync12(TEST_ACCOUNTS_PATH)) return { version: 2, scopes: {}, unscoped: [] };
|
|
3208
3235
|
try {
|
|
3209
|
-
const raw = JSON.parse(
|
|
3236
|
+
const raw = JSON.parse(readFileSync14(TEST_ACCOUNTS_PATH, "utf-8"));
|
|
3210
3237
|
if (Array.isArray(raw)) return { version: 2, scopes: {}, unscoped: validTestAccounts(raw) };
|
|
3211
3238
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
3212
3239
|
return { version: 2, scopes: {}, unscoped: [] };
|
|
@@ -3244,7 +3271,7 @@ function saveTestAccountStore(store) {
|
|
|
3244
3271
|
var SESSION_COOKIE2 = "__Secure-better-auth.session_token";
|
|
3245
3272
|
var AUTH_URL4 = process.env.DEEPSPACE_AUTH_URL ?? PLATFORM_URLS.auth;
|
|
3246
3273
|
function sessionCookie() {
|
|
3247
|
-
const token =
|
|
3274
|
+
const token = readFileSync15(SESSION_PATH, "utf-8").trim();
|
|
3248
3275
|
return `${SESSION_COOKIE2}=${encodeURIComponent(token)}`;
|
|
3249
3276
|
}
|
|
3250
3277
|
async function fetchRemoteTestAccounts() {
|
|
@@ -3321,7 +3348,7 @@ var test_default = defineDeepspaceCommand({
|
|
|
3321
3348
|
preflightNodeVersion("test run");
|
|
3322
3349
|
const suite = args.suite ?? "default";
|
|
3323
3350
|
const wranglerEnv = typeof args.env === "string" && args.env.trim() ? args.env.trim() : void 0;
|
|
3324
|
-
const start =
|
|
3351
|
+
const start = resolve9(".");
|
|
3325
3352
|
const appDir = findAppDir(start);
|
|
3326
3353
|
if (!appDir) {
|
|
3327
3354
|
throw new Refusal(noAppDirMessage(start, findChildApps(start)), "no_app_dir");
|
|
@@ -3468,7 +3495,7 @@ function runVitest(appDir) {
|
|
|
3468
3495
|
|
|
3469
3496
|
// src/cli/commands/screenshot.ts
|
|
3470
3497
|
import { sync as spawnSync5 } from "cross-spawn";
|
|
3471
|
-
import { resolve as
|
|
3498
|
+
import { resolve as resolve10 } from "path";
|
|
3472
3499
|
var screenshot_default = defineDeepspaceCommand({
|
|
3473
3500
|
meta: {
|
|
3474
3501
|
name: "screenshot",
|
|
@@ -3497,7 +3524,7 @@ var screenshot_default = defineDeepspaceCommand({
|
|
|
3497
3524
|
}
|
|
3498
3525
|
},
|
|
3499
3526
|
async run({ args }) {
|
|
3500
|
-
const appDir =
|
|
3527
|
+
const appDir = resolve10(".");
|
|
3501
3528
|
ensurePlaywright(appDir);
|
|
3502
3529
|
const url = String(args.url);
|
|
3503
3530
|
const output = String(args.output);
|
|
@@ -3798,7 +3825,7 @@ var test_accounts_default = defineCommand2({
|
|
|
3798
3825
|
// src/cli/commands/deploy.ts
|
|
3799
3826
|
import * as p12 from "@clack/prompts";
|
|
3800
3827
|
import { defineCommand as defineCommand3 } from "citty";
|
|
3801
|
-
import { resolve as
|
|
3828
|
+
import { resolve as resolve13 } from "path";
|
|
3802
3829
|
|
|
3803
3830
|
// src/cli/lib/edge-propagation.ts
|
|
3804
3831
|
import { request as httpRequest } from "http";
|
|
@@ -3863,14 +3890,14 @@ async function servesRelease(probe, releaseStamp) {
|
|
|
3863
3890
|
}
|
|
3864
3891
|
function getOnFreshConnection(url, timeoutMs = 5e3) {
|
|
3865
3892
|
const send = url.protocol === "http:" ? httpRequest : httpsRequest;
|
|
3866
|
-
return new Promise((
|
|
3893
|
+
return new Promise((resolve21) => {
|
|
3867
3894
|
const request2 = send(
|
|
3868
3895
|
url,
|
|
3869
3896
|
{ method: "GET", agent: false, timeout: timeoutMs, headers: { "cache-control": "no-cache" } },
|
|
3870
3897
|
(response) => {
|
|
3871
3898
|
if (response.statusCode !== 200) {
|
|
3872
3899
|
response.resume();
|
|
3873
|
-
|
|
3900
|
+
resolve21(null);
|
|
3874
3901
|
return;
|
|
3875
3902
|
}
|
|
3876
3903
|
let body = "";
|
|
@@ -3878,20 +3905,20 @@ function getOnFreshConnection(url, timeoutMs = 5e3) {
|
|
|
3878
3905
|
response.on("data", (chunk) => {
|
|
3879
3906
|
if (body.length < 4096) body += chunk;
|
|
3880
3907
|
});
|
|
3881
|
-
response.on("end", () =>
|
|
3882
|
-
response.on("error", () =>
|
|
3908
|
+
response.on("end", () => resolve21(body));
|
|
3909
|
+
response.on("error", () => resolve21(null));
|
|
3883
3910
|
}
|
|
3884
3911
|
);
|
|
3885
3912
|
request2.on("timeout", () => {
|
|
3886
3913
|
request2.destroy();
|
|
3887
|
-
|
|
3914
|
+
resolve21(null);
|
|
3888
3915
|
});
|
|
3889
|
-
request2.on("error", () =>
|
|
3916
|
+
request2.on("error", () => resolve21(null));
|
|
3890
3917
|
request2.end();
|
|
3891
3918
|
});
|
|
3892
3919
|
}
|
|
3893
3920
|
function sleep2(ms) {
|
|
3894
|
-
return new Promise((
|
|
3921
|
+
return new Promise((resolve21) => setTimeout(resolve21, ms));
|
|
3895
3922
|
}
|
|
3896
3923
|
|
|
3897
3924
|
// src/shared/app-files.ts
|
|
@@ -3970,11 +3997,11 @@ function describeFilesFailure(status3, body) {
|
|
|
3970
3997
|
import * as p6 from "@clack/prompts";
|
|
3971
3998
|
import { execSync as execSync2 } from "child_process";
|
|
3972
3999
|
import { createHash as createHash2 } from "crypto";
|
|
3973
|
-
import { existsSync as existsSync15, readFileSync as
|
|
3974
|
-
import { dirname as
|
|
4000
|
+
import { existsSync as existsSync15, readFileSync as readFileSync18, readdirSync as readdirSync4 } from "fs";
|
|
4001
|
+
import { dirname as dirname6, join as join16, resolve as resolve11 } from "path";
|
|
3975
4002
|
|
|
3976
4003
|
// src/documentation/deploy.ts
|
|
3977
|
-
import { existsSync as existsSync13, readFileSync as
|
|
4004
|
+
import { existsSync as existsSync13, readFileSync as readFileSync16 } from "fs";
|
|
3978
4005
|
import { join as join14 } from "path";
|
|
3979
4006
|
function readDocumentationDeployManifest(appDir, clientDir) {
|
|
3980
4007
|
if (!existsSync13(join14(appDir, "documentation.json"))) return void 0;
|
|
@@ -3984,7 +4011,7 @@ function readDocumentationDeployManifest(appDir, clientDir) {
|
|
|
3984
4011
|
"documentation.json exists but the build produced no documentation manifest. Ensure vite.config.ts includes deepSpaceDocumentation() from deepspace/documentation."
|
|
3985
4012
|
);
|
|
3986
4013
|
}
|
|
3987
|
-
return JSON.parse(
|
|
4014
|
+
return JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
3988
4015
|
}
|
|
3989
4016
|
|
|
3990
4017
|
// src/cli/commands/update/app-migrations.ts
|
|
@@ -3996,7 +4023,7 @@ import {
|
|
|
3996
4023
|
ftruncateSync,
|
|
3997
4024
|
lstatSync,
|
|
3998
4025
|
openSync,
|
|
3999
|
-
readFileSync as
|
|
4026
|
+
readFileSync as readFileSync17,
|
|
4000
4027
|
writeSync
|
|
4001
4028
|
} from "fs";
|
|
4002
4029
|
import { join as join15 } from "path";
|
|
@@ -4141,7 +4168,7 @@ function readRegularFile(path) {
|
|
|
4141
4168
|
if (!opened.isFile() || opened.dev !== after.dev || opened.ino !== after.ino) {
|
|
4142
4169
|
throw new Error(`Migration input changed while opening: ${path}`);
|
|
4143
4170
|
}
|
|
4144
|
-
return
|
|
4171
|
+
return readFileSync17(fd, "utf-8");
|
|
4145
4172
|
} finally {
|
|
4146
4173
|
closeSync(fd);
|
|
4147
4174
|
}
|
|
@@ -4167,7 +4194,7 @@ function writeRegularFile(path, before, after) {
|
|
|
4167
4194
|
if (!opened.isFile() || opened.dev !== currentPath.dev || opened.ino !== currentPath.ino) {
|
|
4168
4195
|
throw new Error(`Migration input changed while opening: ${path}`);
|
|
4169
4196
|
}
|
|
4170
|
-
if (
|
|
4197
|
+
if (readFileSync17(fd, "utf-8") !== before) {
|
|
4171
4198
|
throw new Error(`Migration input changed after planning: ${path}`);
|
|
4172
4199
|
}
|
|
4173
4200
|
ftruncateSync(fd, 0);
|
|
@@ -4290,12 +4317,12 @@ async function buildDeployBundle(options) {
|
|
|
4290
4317
|
"build_output_missing"
|
|
4291
4318
|
);
|
|
4292
4319
|
}
|
|
4293
|
-
const deployConfig = JSON.parse(
|
|
4294
|
-
const outputWranglerPath =
|
|
4320
|
+
const deployConfig = JSON.parse(readFileSync18(deployConfigPath, "utf-8"));
|
|
4321
|
+
const outputWranglerPath = resolve11(dirname6(deployConfigPath), deployConfig.configPath);
|
|
4295
4322
|
if (!existsSync15(outputWranglerPath)) {
|
|
4296
4323
|
output.die(`Output wrangler.json not found at ${outputWranglerPath}`, "build_output_missing");
|
|
4297
4324
|
}
|
|
4298
|
-
const outputConfig = JSON.parse(
|
|
4325
|
+
const outputConfig = JSON.parse(readFileSync18(outputWranglerPath, "utf-8"));
|
|
4299
4326
|
if (outputConfig.name && outputConfig.name !== appName) {
|
|
4300
4327
|
const envHint = envName ? ` (--env ${envName})` : "";
|
|
4301
4328
|
output.die(
|
|
@@ -4303,9 +4330,9 @@ async function buildDeployBundle(options) {
|
|
|
4303
4330
|
"build_output_mismatch"
|
|
4304
4331
|
);
|
|
4305
4332
|
}
|
|
4306
|
-
const workerDir =
|
|
4333
|
+
const workerDir = dirname6(outputWranglerPath);
|
|
4307
4334
|
const workerBundlePath = join16(workerDir, outputConfig.main);
|
|
4308
|
-
const clientDir = outputConfig.assets?.directory ?
|
|
4335
|
+
const clientDir = outputConfig.assets?.directory ? resolve11(workerDir, outputConfig.assets.directory) : null;
|
|
4309
4336
|
if (!existsSync15(workerBundlePath)) {
|
|
4310
4337
|
output.die(`Worker bundle not found at ${workerBundlePath}`, "build_output_missing");
|
|
4311
4338
|
}
|
|
@@ -4322,7 +4349,7 @@ async function buildDeployBundle(options) {
|
|
|
4322
4349
|
const assets = collectAssets(clientDir);
|
|
4323
4350
|
const assetConfig = readDeployAssetConfig(clientDir);
|
|
4324
4351
|
spinner2.stop(`Collected ${assets.length} assets`);
|
|
4325
|
-
const workerJs =
|
|
4352
|
+
const workerJs = readFileSync18(workerBundlePath, "utf-8");
|
|
4326
4353
|
const doBindings = outputConfig.durable_objects?.bindings;
|
|
4327
4354
|
const sqliteClasses = new Set(
|
|
4328
4355
|
outputConfig.migrations?.flatMap((migration) => migration.new_sqlite_classes ?? []) ?? []
|
|
@@ -4401,7 +4428,7 @@ function collectAssets(dir) {
|
|
|
4401
4428
|
if (entry.isDirectory()) {
|
|
4402
4429
|
walk(fullPath, relativePath);
|
|
4403
4430
|
} else {
|
|
4404
|
-
const bytes =
|
|
4431
|
+
const bytes = readFileSync18(fullPath);
|
|
4405
4432
|
assets.push({
|
|
4406
4433
|
path: `/${relativePath}`,
|
|
4407
4434
|
hash: createHash2("sha256").update(bytes).digest("hex"),
|
|
@@ -4419,7 +4446,7 @@ function readDeployAssetConfig(clientDir) {
|
|
|
4419
4446
|
for (const [file, key] of [["_headers", "_headers"], ["_redirects", "_redirects"]]) {
|
|
4420
4447
|
const filePath = join16(clientDir, file);
|
|
4421
4448
|
if (!existsSync15(filePath)) continue;
|
|
4422
|
-
const content =
|
|
4449
|
+
const content = readFileSync18(filePath, "utf8");
|
|
4423
4450
|
if (content.trim()) config[key] = content;
|
|
4424
4451
|
}
|
|
4425
4452
|
return config;
|
|
@@ -4672,19 +4699,20 @@ function createDeployOutput(json) {
|
|
|
4672
4699
|
introShown = true;
|
|
4673
4700
|
},
|
|
4674
4701
|
die(message, code, opts = {}) {
|
|
4702
|
+
const action = opts.action ? executableAction(opts.action) : void 0;
|
|
4675
4703
|
if (json) {
|
|
4676
4704
|
emitJson({
|
|
4677
4705
|
ok: false,
|
|
4678
4706
|
code,
|
|
4679
4707
|
error: message,
|
|
4680
4708
|
...opts.actionRequired ? { actionRequired: true } : {},
|
|
4681
|
-
...
|
|
4709
|
+
...action ? { action } : {}
|
|
4682
4710
|
});
|
|
4683
4711
|
} else {
|
|
4684
4712
|
if (introShown && opts.actionRequired) p8.log.warn(withSlug(message, code));
|
|
4685
4713
|
else if (introShown) p8.cancel(withSlug(message, code));
|
|
4686
4714
|
else console.error(withSlug(message, code));
|
|
4687
|
-
if (
|
|
4715
|
+
if (action) printAction(action);
|
|
4688
4716
|
}
|
|
4689
4717
|
process.exit(opts.actionRequired ? 2 : 1);
|
|
4690
4718
|
}
|
|
@@ -4693,7 +4721,7 @@ function createDeployOutput(json) {
|
|
|
4693
4721
|
|
|
4694
4722
|
// src/cli/commands/deploy/request.ts
|
|
4695
4723
|
import * as p10 from "@clack/prompts";
|
|
4696
|
-
import { readFileSync as
|
|
4724
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
4697
4725
|
|
|
4698
4726
|
// src/cli/commands/deploy/repository.ts
|
|
4699
4727
|
import * as p9 from "@clack/prompts";
|
|
@@ -4886,7 +4914,7 @@ function repoApi(deployUrl, token, appId) {
|
|
|
4886
4914
|
// src/cli/lib/vc-remote.ts
|
|
4887
4915
|
import { existsSync as existsSync17 } from "fs";
|
|
4888
4916
|
import { tmpdir } from "os";
|
|
4889
|
-
import { isAbsolute as isAbsolute3, relative, resolve as
|
|
4917
|
+
import { isAbsolute as isAbsolute3, relative, resolve as resolve12 } from "path";
|
|
4890
4918
|
function spaceRemoteName(environment = DEEPSPACE_ENV) {
|
|
4891
4919
|
if (environment === "staging") return "space-staging";
|
|
4892
4920
|
if (environment === "production") return "space";
|
|
@@ -4932,7 +4960,7 @@ function entryIsTransient(cwd) {
|
|
|
4932
4960
|
const entry = process.argv[1];
|
|
4933
4961
|
if (!entry) return true;
|
|
4934
4962
|
if (/[\\/]_npx[\\/]/.test(entry) || entry.startsWith(tmpdir())) return true;
|
|
4935
|
-
const rel = relative(
|
|
4963
|
+
const rel = relative(resolve12(cwd), resolve12(entry));
|
|
4936
4964
|
return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
|
|
4937
4965
|
}
|
|
4938
4966
|
function helperEntryUsable(command) {
|
|
@@ -5005,6 +5033,25 @@ function ensureSpaceRemote(cwd, appId, remote = SPACE_REMOTE) {
|
|
|
5005
5033
|
installCredentialHelper(cwd, url);
|
|
5006
5034
|
return url;
|
|
5007
5035
|
}
|
|
5036
|
+
function ensureGitIdentity(cwd, token) {
|
|
5037
|
+
try {
|
|
5038
|
+
const configured = (key) => runGit(cwd, ["config", "--get", key], { allowFail: true }).stdout.toString("utf-8").trim() !== "";
|
|
5039
|
+
const missingName = !configured("user.name");
|
|
5040
|
+
const missingEmail = !configured("user.email");
|
|
5041
|
+
if (!missingName && !missingEmail) return;
|
|
5042
|
+
const payload = decodeJwtPayload(token);
|
|
5043
|
+
if (!payload.email) return;
|
|
5044
|
+
if (missingName) {
|
|
5045
|
+
runGit(cwd, ["config", "--local", "user.name", payload.name || payload.email], {
|
|
5046
|
+
allowFail: true
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
if (missingEmail) {
|
|
5050
|
+
runGit(cwd, ["config", "--local", "user.email", payload.email], { allowFail: true });
|
|
5051
|
+
}
|
|
5052
|
+
} catch {
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5008
5055
|
function appIdFromRepoUrl(url) {
|
|
5009
5056
|
const match = /\/api\/repo\/([^/]+)\/?$/.exec(url);
|
|
5010
5057
|
return match ? decodeURIComponent(match[1]) : null;
|
|
@@ -5420,7 +5467,7 @@ async function pushWithTransientRetry(push) {
|
|
|
5420
5467
|
const message = errorMessage3(error);
|
|
5421
5468
|
const transient = /(?:HTTP |error: )(?:429|503)\b/i.test(message);
|
|
5422
5469
|
if (transient && attempt < backoffMs.length && Date.now() + backoffMs[attempt] < deadline) {
|
|
5423
|
-
await new Promise((
|
|
5470
|
+
await new Promise((resolve21) => setTimeout(resolve21, backoffMs[attempt]));
|
|
5424
5471
|
continue;
|
|
5425
5472
|
}
|
|
5426
5473
|
throw error;
|
|
@@ -5460,6 +5507,7 @@ async function deployBuiltBundle(options) {
|
|
|
5460
5507
|
appId,
|
|
5461
5508
|
appName,
|
|
5462
5509
|
token,
|
|
5510
|
+
claimReleased,
|
|
5463
5511
|
ignoreStale,
|
|
5464
5512
|
bundle,
|
|
5465
5513
|
secrets,
|
|
@@ -5477,7 +5525,8 @@ async function deployBuiltBundle(options) {
|
|
|
5477
5525
|
await uploadDeployAssets({ deployUrl, appId, token, assets: bundle.assets, output, spinner: spinner2 });
|
|
5478
5526
|
spinner2.message(`Deploying ${appName}...`);
|
|
5479
5527
|
let confirmRename = options.rename;
|
|
5480
|
-
const bail = async (message, stopLabel = "Deploy failed", code, actionRequired = false,
|
|
5528
|
+
const bail = async (message, stopLabel = "Deploy failed", code, actionRequired = false, rawAction) => {
|
|
5529
|
+
const action = rawAction ? executableAction(rawAction) : void 0;
|
|
5481
5530
|
if (stopLabel !== null) spinner2.stop(stopLabel);
|
|
5482
5531
|
p10.cancel(code ? withSlug(message, code) : message);
|
|
5483
5532
|
if (action) printAction(action);
|
|
@@ -5523,6 +5572,7 @@ async function deployBuiltBundle(options) {
|
|
|
5523
5572
|
}
|
|
5524
5573
|
form.append("name", appName);
|
|
5525
5574
|
if (confirmRename) form.append("confirmRename", "true");
|
|
5575
|
+
if (claimReleased) form.append("claimReleased", "true");
|
|
5526
5576
|
if (shouldSendLineage(repository.commitOid, repository.recoverable)) {
|
|
5527
5577
|
form.append("commitOid", repository.commitOid);
|
|
5528
5578
|
}
|
|
@@ -5696,7 +5746,7 @@ async function uploadDeployAssets(options) {
|
|
|
5696
5746
|
// against the plan before it touches storage, and a stream body
|
|
5697
5747
|
// would be sent chunked with no length at all; a retry also needs a
|
|
5698
5748
|
// body it can send again.
|
|
5699
|
-
body:
|
|
5749
|
+
body: readFileSync19(asset.sourcePath)
|
|
5700
5750
|
})
|
|
5701
5751
|
);
|
|
5702
5752
|
if (!response.ok) {
|
|
@@ -5774,7 +5824,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5774
5824
|
lastError = error;
|
|
5775
5825
|
}
|
|
5776
5826
|
if (attempt < attempts) {
|
|
5777
|
-
await new Promise((
|
|
5827
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(8e3, 500 * 2 ** (attempt - 1))));
|
|
5778
5828
|
}
|
|
5779
5829
|
}
|
|
5780
5830
|
if (lastResponse) return lastResponse;
|
|
@@ -5783,7 +5833,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5783
5833
|
|
|
5784
5834
|
// src/cli/commands/deploy/secrets.ts
|
|
5785
5835
|
import * as p11 from "@clack/prompts";
|
|
5786
|
-
import { existsSync as existsSync18, readFileSync as
|
|
5836
|
+
import { existsSync as existsSync18, readFileSync as readFileSync20 } from "fs";
|
|
5787
5837
|
function classifyDevVarsSecrets(options) {
|
|
5788
5838
|
const store = new Set(options.storeSecretNames);
|
|
5789
5839
|
const strayKeys = options.handEditedDevVarKeys.filter((key) => !store.has(key));
|
|
@@ -5882,7 +5932,7 @@ function prepareDeploySecrets(options) {
|
|
|
5882
5932
|
}
|
|
5883
5933
|
function readCustomDevVars(path, output) {
|
|
5884
5934
|
if (!existsSync18(path)) return {};
|
|
5885
|
-
const section = extractCustomDevVars(stripGeneratedSecretsCache(
|
|
5935
|
+
const section = extractCustomDevVars(stripGeneratedSecretsCache(readFileSync20(path, "utf-8")));
|
|
5886
5936
|
if (!section) return {};
|
|
5887
5937
|
try {
|
|
5888
5938
|
return parseDevVars(section);
|
|
@@ -5922,6 +5972,11 @@ var deploy_default = defineCommand3({
|
|
|
5922
5972
|
description: "Confirm that a changed wrangler `name` renames this app (its URL moves; data, secrets, and collaborators travel). Without this flag an interactive prompt asks.",
|
|
5923
5973
|
default: false
|
|
5924
5974
|
},
|
|
5975
|
+
"claim-released": {
|
|
5976
|
+
type: "boolean",
|
|
5977
|
+
description: "Platform admins only: claim an app name still inside its 30-day release cooldown. The previous owner permanently loses their reserved reclaim. Non-admin accounts are refused.",
|
|
5978
|
+
default: false
|
|
5979
|
+
},
|
|
5925
5980
|
"allow-missing-secrets": {
|
|
5926
5981
|
type: "boolean",
|
|
5927
5982
|
description: "Deploy even though hand-edited .dev.vars secrets are absent from the store (they will NOT be deployed, and any a previous deploy set are dropped).",
|
|
@@ -5947,7 +6002,7 @@ var deploy_default = defineCommand3({
|
|
|
5947
6002
|
async run({ args }) {
|
|
5948
6003
|
const output = createDeployOutput(args.json === true);
|
|
5949
6004
|
preflightNodeVersion("deploy");
|
|
5950
|
-
const appDir =
|
|
6005
|
+
const appDir = resolve13(args.dir ?? ".");
|
|
5951
6006
|
const selectorRefusal = blankSelectorRefusal(args);
|
|
5952
6007
|
if (selectorRefusal) output.die(selectorRefusal.error, selectorRefusal.code);
|
|
5953
6008
|
const envName = typeof args.env === "string" && args.env.trim() ? args.env.trim() : void 0;
|
|
@@ -6035,6 +6090,7 @@ var deploy_default = defineCommand3({
|
|
|
6035
6090
|
appName,
|
|
6036
6091
|
token,
|
|
6037
6092
|
rename: args.rename === true,
|
|
6093
|
+
claimReleased: args["claim-released"] === true,
|
|
6038
6094
|
ignoreStale: Boolean(args["ignore-stale"]),
|
|
6039
6095
|
bundle,
|
|
6040
6096
|
secrets,
|
|
@@ -6063,10 +6119,7 @@ var deploy_default = defineCommand3({
|
|
|
6063
6119
|
url: body.url,
|
|
6064
6120
|
releaseId: body.releaseId ?? null,
|
|
6065
6121
|
bundleRetained: body.bundleRetained ?? null,
|
|
6066
|
-
// `serving` says what was actually established; `edgePropagating`
|
|
6067
|
-
// stays for callers written against the old shape.
|
|
6068
6122
|
serving,
|
|
6069
|
-
edgePropagating: serving === "unconfirmed",
|
|
6070
6123
|
recoverable: repository.recoverable,
|
|
6071
6124
|
...staleBaseGuardFields(body)
|
|
6072
6125
|
});
|
|
@@ -6085,7 +6138,7 @@ var deploy_default = defineCommand3({
|
|
|
6085
6138
|
appName,
|
|
6086
6139
|
url: body.url ?? null,
|
|
6087
6140
|
// Always present, so a caller branches on one field instead of
|
|
6088
|
-
// inferring success from
|
|
6141
|
+
// inferring success from an absent one.
|
|
6089
6142
|
serving,
|
|
6090
6143
|
releaseId: body.releaseId ?? null,
|
|
6091
6144
|
bundleRetained: body.bundleRetained ?? null,
|
|
@@ -6765,8 +6818,8 @@ var usage_default = defineDeepspaceCommand({
|
|
|
6765
6818
|
});
|
|
6766
6819
|
|
|
6767
6820
|
// src/cli/commands/add.ts
|
|
6768
|
-
import { existsSync as existsSync20, readFileSync as
|
|
6769
|
-
import { dirname as
|
|
6821
|
+
import { existsSync as existsSync20, readFileSync as readFileSync22, realpathSync as realpathSync4 } from "fs";
|
|
6822
|
+
import { dirname as dirname8, join as join19, resolve as resolve15 } from "path";
|
|
6770
6823
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6771
6824
|
|
|
6772
6825
|
// src/cli/commands/feature-installer.ts
|
|
@@ -6778,7 +6831,7 @@ import {
|
|
|
6778
6831
|
mkdirSync as mkdirSync6,
|
|
6779
6832
|
mkdtempSync,
|
|
6780
6833
|
openSync as openSync2,
|
|
6781
|
-
readFileSync as
|
|
6834
|
+
readFileSync as readFileSync21,
|
|
6782
6835
|
readSync,
|
|
6783
6836
|
readdirSync as readdirSync5,
|
|
6784
6837
|
rmSync as rmSync4,
|
|
@@ -6786,21 +6839,21 @@ import {
|
|
|
6786
6839
|
} from "fs";
|
|
6787
6840
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
6788
6841
|
import { tmpdir as tmpdir2 } from "os";
|
|
6789
|
-
import { dirname as
|
|
6842
|
+
import { dirname as dirname7, isAbsolute as isAbsolute4, join as join18, resolve as resolve14 } from "path";
|
|
6790
6843
|
import { fileURLToPath } from "url";
|
|
6791
6844
|
var NAV_MARKER = "// \u2500\u2500 Features add nav items below this line \u2500\u2500";
|
|
6792
6845
|
function featurePackageRoot(moduleUrl = import.meta.url) {
|
|
6793
|
-
let dir =
|
|
6846
|
+
let dir = dirname7(fileURLToPath(moduleUrl));
|
|
6794
6847
|
for (; ; ) {
|
|
6795
6848
|
const packagePath = join18(dir, "package.json");
|
|
6796
6849
|
if (existsSync19(packagePath)) {
|
|
6797
6850
|
try {
|
|
6798
|
-
const pkg2 = JSON.parse(
|
|
6851
|
+
const pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
|
|
6799
6852
|
if (pkg2.name === "deepspace") return dir;
|
|
6800
6853
|
} catch {
|
|
6801
6854
|
}
|
|
6802
6855
|
}
|
|
6803
|
-
const parent =
|
|
6856
|
+
const parent = dirname7(dir);
|
|
6804
6857
|
if (parent === dir) throw new Error("Could not locate the deepspace package root");
|
|
6805
6858
|
dir = parent;
|
|
6806
6859
|
}
|
|
@@ -6812,7 +6865,7 @@ function readFeatureConfig(id, packageRoot = featurePackageRoot()) {
|
|
|
6812
6865
|
const configPath = join18(packageRoot, "features", id, "feature.json");
|
|
6813
6866
|
if (!existsSync19(configPath)) return null;
|
|
6814
6867
|
try {
|
|
6815
|
-
const config = JSON.parse(
|
|
6868
|
+
const config = JSON.parse(readFileSync21(configPath, "utf-8"));
|
|
6816
6869
|
if (typeof config.id !== "string" || typeof config.name !== "string" || !Array.isArray(config.files)) {
|
|
6817
6870
|
return null;
|
|
6818
6871
|
}
|
|
@@ -6861,7 +6914,7 @@ function suggestFeature(featureId, packageRoot = featurePackageRoot()) {
|
|
|
6861
6914
|
return closest !== null && closestDistance <= threshold ? closest : null;
|
|
6862
6915
|
}
|
|
6863
6916
|
function resolveTargetDir(raw) {
|
|
6864
|
-
return isAbsolute4(raw) ? raw :
|
|
6917
|
+
return isAbsolute4(raw) ? raw : resolve14(raw);
|
|
6865
6918
|
}
|
|
6866
6919
|
function resolveFeatureDestPath(fileDest, route) {
|
|
6867
6920
|
const pages = "src/pages/";
|
|
@@ -6871,13 +6924,13 @@ function resolveFeatureDestPath(fileDest, route) {
|
|
|
6871
6924
|
return route?.protected === false ? `${appPages}${rest}` : `${appPages}(protected)/${rest}`;
|
|
6872
6925
|
}
|
|
6873
6926
|
function copyFile(src, dest) {
|
|
6874
|
-
mkdirSync6(
|
|
6927
|
+
mkdirSync6(dirname7(dest), { recursive: true });
|
|
6875
6928
|
copyFileSync(src, dest);
|
|
6876
6929
|
}
|
|
6877
6930
|
function copyFileWithImportShift(src, dest, levels) {
|
|
6878
|
-
mkdirSync6(
|
|
6931
|
+
mkdirSync6(dirname7(dest), { recursive: true });
|
|
6879
6932
|
const prefix = "../".repeat(levels);
|
|
6880
|
-
const shifted =
|
|
6933
|
+
const shifted = readFileSync21(src, "utf-8").replace(
|
|
6881
6934
|
/(from\s+|import\s+|import\()(['"])(\.\.\/)/g,
|
|
6882
6935
|
`$1$2${prefix}$3`
|
|
6883
6936
|
);
|
|
@@ -6936,7 +6989,7 @@ function integrateSchema(config, targetDir, emit) {
|
|
|
6936
6989
|
if (!existsSync19(schemasPath)) {
|
|
6937
6990
|
return [unresolvedSchema(config.schema, "src/schemas.ts was not found.", emit)];
|
|
6938
6991
|
}
|
|
6939
|
-
let content =
|
|
6992
|
+
let content = readFileSync21(schemasPath, "utf-8");
|
|
6940
6993
|
const { exportName, importPath, spreadOperator } = config.schema;
|
|
6941
6994
|
const importPattern = new RegExp(`^import\\s+\\{[^}]*\\b${exportName}\\b`, "m");
|
|
6942
6995
|
if (importPattern.test(content)) {
|
|
@@ -6993,7 +7046,7 @@ function integrateActions(config, targetDir, emit) {
|
|
|
6993
7046
|
if (!existsSync19(actionsPath)) {
|
|
6994
7047
|
return [unresolvedActions(config.actions, "src/actions/index.ts was not found.", emit)];
|
|
6995
7048
|
}
|
|
6996
|
-
let content =
|
|
7049
|
+
let content = readFileSync21(actionsPath, "utf-8");
|
|
6997
7050
|
const registryPattern = /export const actions:\s*Record<string,\s*ActionHandler(?:<[^>]*>)?>\s*=\s*\{/;
|
|
6998
7051
|
if (!registryPattern.test(content)) {
|
|
6999
7052
|
const reason = "src/actions/index.ts has an unexpected structure.";
|
|
@@ -7048,7 +7101,7 @@ function integrateCode(config, targetDir, emit) {
|
|
|
7048
7101
|
});
|
|
7049
7102
|
continue;
|
|
7050
7103
|
}
|
|
7051
|
-
const original =
|
|
7104
|
+
const original = readFileSync21(targetPath, "utf-8");
|
|
7052
7105
|
if (original.includes(insertion.insert.trim())) {
|
|
7053
7106
|
emit(` Integration already present: ${insertion.file}`);
|
|
7054
7107
|
continue;
|
|
@@ -7084,7 +7137,7 @@ ${content.slice(importIndex < 0 ? 0 : importIndex)}`;
|
|
|
7084
7137
|
function integrateIgnore(config, targetDir) {
|
|
7085
7138
|
if (!config.ignore?.length) return;
|
|
7086
7139
|
const targetPath = join18(targetDir, ".gitignore");
|
|
7087
|
-
const current = existsSync19(targetPath) ?
|
|
7140
|
+
const current = existsSync19(targetPath) ? readFileSync21(targetPath, "utf-8") : "";
|
|
7088
7141
|
const present = new Set(current.split(/\r?\n/).map((line) => line.trim()));
|
|
7089
7142
|
const missing = config.ignore.filter((pattern) => !present.has(pattern));
|
|
7090
7143
|
if (missing.length === 0) return;
|
|
@@ -7104,7 +7157,7 @@ function integrateWrangler(config, targetDir, emit) {
|
|
|
7104
7157
|
if (!existsSync19(targetPath)) {
|
|
7105
7158
|
return [{ area: "wrangler", reason: "wrangler.toml was not found.", steps }];
|
|
7106
7159
|
}
|
|
7107
|
-
let source =
|
|
7160
|
+
let source = readFileSync21(targetPath, "utf-8");
|
|
7108
7161
|
if (runWorkerFirst && !/^\[assets\]\s*$/m.test(source)) {
|
|
7109
7162
|
return [{ area: "wrangler", reason: "wrangler.toml has no [assets] section.", steps }];
|
|
7110
7163
|
}
|
|
@@ -7193,7 +7246,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
7193
7246
|
}
|
|
7194
7247
|
];
|
|
7195
7248
|
}
|
|
7196
|
-
let styles =
|
|
7249
|
+
let styles = readFileSync21(stylesPath, "utf-8");
|
|
7197
7250
|
let integrated = 0;
|
|
7198
7251
|
const unresolved = [];
|
|
7199
7252
|
for (const cssFile of config.css) {
|
|
@@ -7207,7 +7260,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
7207
7260
|
});
|
|
7208
7261
|
continue;
|
|
7209
7262
|
}
|
|
7210
|
-
const css =
|
|
7263
|
+
const css = readFileSync21(srcPath, "utf-8");
|
|
7211
7264
|
const fingerprint = css.match(/\.([\w-]+)\s*\{|@keyframes\s+([\w-]+)/);
|
|
7212
7265
|
const marker = fingerprint?.[1] ?? fingerprint?.[2];
|
|
7213
7266
|
if (marker && styles.includes(marker)) {
|
|
@@ -7238,7 +7291,7 @@ function integrateRoute(config, targetDir, emit) {
|
|
|
7238
7291
|
if (!existsSync19(navPath)) {
|
|
7239
7292
|
return [unresolvedRoute(config.route, config, "src/nav.ts was not found.", emit)];
|
|
7240
7293
|
}
|
|
7241
|
-
let content =
|
|
7294
|
+
let content = readFileSync21(navPath, "utf-8");
|
|
7242
7295
|
const routePath = config.route.path;
|
|
7243
7296
|
if (content.includes(`'${routePath}'`)) {
|
|
7244
7297
|
emit(` Nav already present: ${routePath}`);
|
|
@@ -7319,7 +7372,7 @@ function integrateDependencies(config, targetDir, runInstall, outputVisible, emi
|
|
|
7319
7372
|
}
|
|
7320
7373
|
let pkg2;
|
|
7321
7374
|
try {
|
|
7322
|
-
pkg2 = JSON.parse(
|
|
7375
|
+
pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
|
|
7323
7376
|
} catch (error) {
|
|
7324
7377
|
emit(
|
|
7325
7378
|
` Could not patch package.json (parse error: ${error instanceof Error ? error.message : String(error)})`
|
|
@@ -7379,7 +7432,7 @@ ${child.diagnosticTail}` : "";
|
|
|
7379
7432
|
}
|
|
7380
7433
|
function dependencySnapshot(targetDir) {
|
|
7381
7434
|
try {
|
|
7382
|
-
const pkg2 = JSON.parse(
|
|
7435
|
+
const pkg2 = JSON.parse(readFileSync21(join18(targetDir, "package.json"), "utf-8"));
|
|
7383
7436
|
return {
|
|
7384
7437
|
dependencies: pkg2.dependencies ?? {},
|
|
7385
7438
|
devDependencies: pkg2.devDependencies ?? {}
|
|
@@ -7628,7 +7681,7 @@ function isDeepSpaceApp(dir) {
|
|
|
7628
7681
|
const packagePath = join19(dir, "package.json");
|
|
7629
7682
|
if (!existsSync20(packagePath)) return false;
|
|
7630
7683
|
try {
|
|
7631
|
-
const pkg2 = JSON.parse(
|
|
7684
|
+
const pkg2 = JSON.parse(readFileSync22(packagePath, "utf-8"));
|
|
7632
7685
|
return Boolean(pkg2.dependencies?.deepspace || pkg2.devDependencies?.deepspace);
|
|
7633
7686
|
} catch {
|
|
7634
7687
|
return false;
|
|
@@ -7639,7 +7692,7 @@ function installedPackageRoot(fromDir) {
|
|
|
7639
7692
|
for (; ; ) {
|
|
7640
7693
|
const candidate = join19(dir, "node_modules", "deepspace");
|
|
7641
7694
|
if (existsSync20(join19(candidate, "package.json"))) return candidate;
|
|
7642
|
-
const parent =
|
|
7695
|
+
const parent = dirname8(dir);
|
|
7643
7696
|
if (parent === dir) return null;
|
|
7644
7697
|
dir = parent;
|
|
7645
7698
|
}
|
|
@@ -7652,7 +7705,7 @@ async function targetInstaller(appDir) {
|
|
|
7652
7705
|
"feature_installer_missing"
|
|
7653
7706
|
);
|
|
7654
7707
|
}
|
|
7655
|
-
if (
|
|
7708
|
+
if (realpathSync4(installedRoot) === realpathSync4(featurePackageRoot())) {
|
|
7656
7709
|
return { installFeature };
|
|
7657
7710
|
}
|
|
7658
7711
|
const entry = join19(installedRoot, "dist", "feature-installer.js");
|
|
@@ -7749,7 +7802,7 @@ var add_default = defineDeepspaceCommand({
|
|
|
7749
7802
|
}
|
|
7750
7803
|
return { data: { features: featureCatalog(root) } };
|
|
7751
7804
|
}
|
|
7752
|
-
const appDir =
|
|
7805
|
+
const appDir = resolve15(args.dir ?? ".");
|
|
7753
7806
|
if (!existsSync20(appDir)) {
|
|
7754
7807
|
throw new Refusal(
|
|
7755
7808
|
`Target directory not found: ${appDir}
|
|
@@ -7831,11 +7884,11 @@ function fmtDate(iso) {
|
|
|
7831
7884
|
}
|
|
7832
7885
|
async function confirm4(message) {
|
|
7833
7886
|
process.stdout.write(`${message} [y/N] `);
|
|
7834
|
-
return new Promise((
|
|
7887
|
+
return new Promise((resolve21) => {
|
|
7835
7888
|
process.stdin.setEncoding("utf-8");
|
|
7836
7889
|
process.stdin.once("data", (data) => {
|
|
7837
7890
|
const answer = data.toString().trim().toLowerCase();
|
|
7838
|
-
|
|
7891
|
+
resolve21(answer === "y" || answer === "yes");
|
|
7839
7892
|
});
|
|
7840
7893
|
});
|
|
7841
7894
|
}
|
|
@@ -8125,7 +8178,7 @@ var domain_default = defineCommand5({
|
|
|
8125
8178
|
|
|
8126
8179
|
// src/cli/commands/app-files.ts
|
|
8127
8180
|
import { defineCommand as defineCommand6 } from "citty";
|
|
8128
|
-
import { basename as basename4, resolve as
|
|
8181
|
+
import { basename as basename4, resolve as resolve16 } from "path";
|
|
8129
8182
|
import { existsSync as existsSync21, statSync as statSync2 } from "fs";
|
|
8130
8183
|
|
|
8131
8184
|
// src/cli/lib/app-files-api.ts
|
|
@@ -8326,7 +8379,7 @@ async function deleteAppFile(baseUrl, token, appId, key) {
|
|
|
8326
8379
|
const path = filesPath(appId, `/${encodeKeyPath(key)}`);
|
|
8327
8380
|
const res = await request(baseUrl, token, path, { method: "DELETE" });
|
|
8328
8381
|
const body = await readJson(res, path);
|
|
8329
|
-
return { existed: body.existed
|
|
8382
|
+
return { existed: body.existed };
|
|
8330
8383
|
}
|
|
8331
8384
|
async function downloadAppFile(baseUrl, token, appId, key, destination) {
|
|
8332
8385
|
const path = filesPath(appId, `/${encodeKeyPath(key)}`);
|
|
@@ -8396,7 +8449,7 @@ var put = defineDeepspaceCommand({
|
|
|
8396
8449
|
app: { type: "string", description: "App id or live name (defaults to ./wrangler.toml)" }
|
|
8397
8450
|
},
|
|
8398
8451
|
async run({ args }) {
|
|
8399
|
-
const localPath =
|
|
8452
|
+
const localPath = resolve16(String(args.file));
|
|
8400
8453
|
if (!existsSync21(localPath) || !statSync2(localPath).isFile()) {
|
|
8401
8454
|
throw new Refusal(`No such file: ${args.file}`, "file_not_found");
|
|
8402
8455
|
}
|
|
@@ -8497,7 +8550,7 @@ var get = defineDeepspaceCommand({
|
|
|
8497
8550
|
},
|
|
8498
8551
|
async run({ args }) {
|
|
8499
8552
|
const key = requireKey(String(args.key));
|
|
8500
|
-
const destination =
|
|
8553
|
+
const destination = resolve16(String(args.out ?? basename4(key)));
|
|
8501
8554
|
const { token, appId } = await target(args.app);
|
|
8502
8555
|
const result = await downloadAppFile(PLATFORM_URL, token, appId, key, destination);
|
|
8503
8556
|
if (!args.json) console.log(`\u2713 ${key} \u2192 ${destination} (${formatBytes(result.bytes)})`);
|
|
@@ -8867,7 +8920,7 @@ var transfer_default = defineCommand8({
|
|
|
8867
8920
|
import { defineCommand as defineCommand9 } from "citty";
|
|
8868
8921
|
|
|
8869
8922
|
// src/cli/commands/_invoke-impl.ts
|
|
8870
|
-
import { readFileSync as
|
|
8923
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
8871
8924
|
import * as p15 from "@clack/prompts";
|
|
8872
8925
|
var API_URL7 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
8873
8926
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -8908,7 +8961,7 @@ function resolveBody(opts) {
|
|
|
8908
8961
|
if (opts.body != null) {
|
|
8909
8962
|
raw = opts.body;
|
|
8910
8963
|
} else if (opts.bodyFile != null) {
|
|
8911
|
-
raw = opts.bodyFile === "-" ?
|
|
8964
|
+
raw = opts.bodyFile === "-" ? readFileSync23(0, "utf-8") : readFileSync23(opts.bodyFile, "utf-8");
|
|
8912
8965
|
} else {
|
|
8913
8966
|
return "{}";
|
|
8914
8967
|
}
|
|
@@ -9187,8 +9240,8 @@ var integrations_default = defineCommand9({
|
|
|
9187
9240
|
|
|
9188
9241
|
// src/cli/commands/feedback.ts
|
|
9189
9242
|
import * as p16 from "@clack/prompts";
|
|
9190
|
-
import { existsSync as existsSync22, readFileSync as
|
|
9191
|
-
import { dirname as
|
|
9243
|
+
import { existsSync as existsSync22, readFileSync as readFileSync24 } from "fs";
|
|
9244
|
+
import { dirname as dirname9, join as join20 } from "path";
|
|
9192
9245
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9193
9246
|
import { release } from "os";
|
|
9194
9247
|
var API_URL8 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
@@ -9209,14 +9262,14 @@ function normalizeType(raw) {
|
|
|
9209
9262
|
}
|
|
9210
9263
|
function readCliVersion() {
|
|
9211
9264
|
try {
|
|
9212
|
-
const here =
|
|
9265
|
+
const here = dirname9(fileURLToPath2(import.meta.url));
|
|
9213
9266
|
const candidates = [
|
|
9214
9267
|
join20(here, "..", "package.json"),
|
|
9215
9268
|
join20(here, "..", "..", "..", "package.json")
|
|
9216
9269
|
];
|
|
9217
9270
|
for (const path of candidates) {
|
|
9218
9271
|
if (!existsSync22(path)) continue;
|
|
9219
|
-
const pkg2 = JSON.parse(
|
|
9272
|
+
const pkg2 = JSON.parse(readFileSync24(path, "utf-8"));
|
|
9220
9273
|
if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
|
|
9221
9274
|
}
|
|
9222
9275
|
} catch {
|
|
@@ -9412,7 +9465,7 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
|
|
|
9412
9465
|
|
|
9413
9466
|
// src/cli/commands/secrets.ts
|
|
9414
9467
|
import { defineCommand as defineCommand10 } from "citty";
|
|
9415
|
-
import { readFileSync as
|
|
9468
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
9416
9469
|
|
|
9417
9470
|
// src/cli/lib/citty-args.ts
|
|
9418
9471
|
function dedupePositionals(bound, rest) {
|
|
@@ -9682,7 +9735,7 @@ var upload = defineCommand10({
|
|
|
9682
9735
|
async run({ args }) {
|
|
9683
9736
|
try {
|
|
9684
9737
|
const t = await resolveTarget(args);
|
|
9685
|
-
const content = args.file === "-" ?
|
|
9738
|
+
const content = args.file === "-" ? readFileSync25(0, "utf-8") : readFileSync25(args.file, "utf-8");
|
|
9686
9739
|
const secrets = parseSecretsUpload(content);
|
|
9687
9740
|
if (Object.keys(secrets).length === 0)
|
|
9688
9741
|
fail(new InputError("No secrets found in the input.", "empty_input"));
|
|
@@ -9938,7 +9991,7 @@ var init_default = defineDeepspaceCommand({
|
|
|
9938
9991
|
// src/cli/commands/status.ts
|
|
9939
9992
|
import { defineCommand as defineCommand11 } from "citty";
|
|
9940
9993
|
import * as p17 from "@clack/prompts";
|
|
9941
|
-
import { existsSync as existsSync23, readFileSync as
|
|
9994
|
+
import { existsSync as existsSync23, readFileSync as readFileSync26 } from "fs";
|
|
9942
9995
|
function timeAgo(iso) {
|
|
9943
9996
|
const ms = Date.now() - Date.parse(iso);
|
|
9944
9997
|
if (!Number.isFinite(ms) || ms < 0) return iso;
|
|
@@ -10032,7 +10085,7 @@ var status_default = defineCommand11({
|
|
|
10032
10085
|
let who = "logged in";
|
|
10033
10086
|
try {
|
|
10034
10087
|
const payload = decodeJwtPayload(
|
|
10035
|
-
|
|
10088
|
+
readFileSync26(TOKEN_PATH, "utf-8").trim()
|
|
10036
10089
|
);
|
|
10037
10090
|
if (payload.email) who = payload.email;
|
|
10038
10091
|
userId = payload.sub ?? null;
|
|
@@ -10184,21 +10237,24 @@ var status_default = defineCommand11({
|
|
|
10184
10237
|
}
|
|
10185
10238
|
const refs = refsResult.ok ? refsResult.value : void 0;
|
|
10186
10239
|
const trunkRef = refs?.refs.find((r) => `refs/heads/${branch}` === r.name);
|
|
10240
|
+
const defaultBranch = refs?.head && refs.head.startsWith("refs/heads/") ? refs.head.slice("refs/heads/".length) : null;
|
|
10187
10241
|
if (!facts.workspaceId && branch) {
|
|
10242
|
+
const isTrunk = defaultBranch === null ? null : branch === defaultBranch;
|
|
10243
|
+
const label = isTrunk === false ? "Branch sync" : "Trunk";
|
|
10188
10244
|
if (githubSource) {
|
|
10189
|
-
lines.push([
|
|
10190
|
-
json.trunk = { state: "external", provider: "github", branch };
|
|
10191
|
-
} else if (!refsResult.ok) reportRemoteFailure2(
|
|
10245
|
+
lines.push([label, `${branch} is owned through normal Git/GitHub`]);
|
|
10246
|
+
json.trunk = { state: "external", provider: "github", branch, isTrunk };
|
|
10247
|
+
} else if (!refsResult.ok) reportRemoteFailure2(label, "trunk", refsResult.error);
|
|
10192
10248
|
else {
|
|
10193
10249
|
const remoteOid = trunkRef?.oid ?? null;
|
|
10194
10250
|
const localOid = resolveCommit(appDir, `refs/heads/${branch}`);
|
|
10195
10251
|
const remoteKnownLocally = remoteOid ? resolveCommit(appDir, remoteOid) !== null : false;
|
|
10196
10252
|
facts.trunkState = remoteOid === null && localOid === null ? "unknown" : remoteOid === localOid ? "in_sync" : remoteOid && localOid && remoteKnownLocally && isAncestor(appDir, remoteOid, localOid) ? "local_ahead" : remoteOid && localOid && remoteKnownLocally && isAncestor(appDir, localOid, remoteOid) ? "local_behind" : remoteOid && localOid && remoteKnownLocally ? "diverged" : "differs";
|
|
10197
10253
|
lines.push([
|
|
10198
|
-
|
|
10254
|
+
label,
|
|
10199
10255
|
remoteOid === null ? `cloud repo has no ${branch} yet` : facts.trunkState === "in_sync" ? `${branch} in sync with the cloud repo (${remoteOid.slice(0, 10)})` : `${branch} ${facts.trunkState.replace("_", " ")} relative to the cloud repo (local ${localOid?.slice(0, 10) ?? "none"}, cloud ${remoteOid.slice(0, 10)})`
|
|
10200
10256
|
]);
|
|
10201
|
-
json.trunk = { state: facts.trunkState, localOid, remoteOid };
|
|
10257
|
+
json.trunk = { state: facts.trunkState, localOid, remoteOid, branch, isTrunk };
|
|
10202
10258
|
}
|
|
10203
10259
|
}
|
|
10204
10260
|
if (!releaseResult.ok) reportRemoteFailure2("Live", "live", releaseResult.error);
|
|
@@ -10425,7 +10481,7 @@ var push_default = defineDeepspaceCommand({
|
|
|
10425
10481
|
|
|
10426
10482
|
// src/cli/commands/pull.ts
|
|
10427
10483
|
import * as p19 from "@clack/prompts";
|
|
10428
|
-
import { realpathSync as
|
|
10484
|
+
import { realpathSync as realpathSync5 } from "fs";
|
|
10429
10485
|
function targetedVcAction(command, cwd, appId, branch) {
|
|
10430
10486
|
return {
|
|
10431
10487
|
cwd,
|
|
@@ -10449,7 +10505,7 @@ function workspaceBranchPullRefusal(branch, trunkBranch) {
|
|
|
10449
10505
|
function worktreeHoldingBranch(worktrees, branch, selfPath) {
|
|
10450
10506
|
const real = (pth) => {
|
|
10451
10507
|
try {
|
|
10452
|
-
return
|
|
10508
|
+
return realpathSync5(pth);
|
|
10453
10509
|
} catch {
|
|
10454
10510
|
return pth;
|
|
10455
10511
|
}
|
|
@@ -10707,7 +10763,7 @@ var pull_default = defineDeepspaceCommand({
|
|
|
10707
10763
|
// src/cli/commands/clone.ts
|
|
10708
10764
|
import * as p20 from "@clack/prompts";
|
|
10709
10765
|
import { existsSync as existsSync24, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
|
|
10710
|
-
import { resolve as
|
|
10766
|
+
import { resolve as resolve17, basename as basename5, join as join21 } from "path";
|
|
10711
10767
|
function cleanFailedCloneDir(dir) {
|
|
10712
10768
|
let entries;
|
|
10713
10769
|
try {
|
|
@@ -10761,7 +10817,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10761
10817
|
async run({ args }) {
|
|
10762
10818
|
assertAppTargetResolvable(String(args.app));
|
|
10763
10819
|
const selector = String(args.app).trim();
|
|
10764
|
-
const dir =
|
|
10820
|
+
const dir = resolve17(String(args.dir ?? selector));
|
|
10765
10821
|
const dirPreexisted = validateCloneTarget(dir);
|
|
10766
10822
|
const spinner2 = args.json ? null : createSpinner();
|
|
10767
10823
|
spinner2?.start(`Resolving ${selector}\u2026`);
|
|
@@ -10801,6 +10857,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10801
10857
|
throw err;
|
|
10802
10858
|
}
|
|
10803
10859
|
ensureSpaceRemote(dir, appId);
|
|
10860
|
+
ensureGitIdentity(dir, token);
|
|
10804
10861
|
const head = resolveCommit(dir, "HEAD");
|
|
10805
10862
|
const branch = currentBranch(dir);
|
|
10806
10863
|
spinner2?.stop(
|
|
@@ -11023,14 +11080,13 @@ Re-run with --allow-do-deletion to accept the data loss.`,
|
|
|
11023
11080
|
spinner2?.message("Waiting for the edge to serve this release...");
|
|
11024
11081
|
serving = await waitForLiveRelease(result.url, result.releaseStamp, 9e4);
|
|
11025
11082
|
}
|
|
11026
|
-
const edgePropagating = serving === "unconfirmed";
|
|
11027
11083
|
spinner2?.stop(
|
|
11028
11084
|
serving === "confirmed" ? `Rolled back to ${result.rolledBackTo ?? releaseId}.` : serving === "unconfirmed" ? `Rolled back to ${result.rolledBackTo ?? releaseId} \u2014 the edge is still rolling it out.` : `Rolled back to ${result.rolledBackTo ?? releaseId} \u2014 serving could not be verified from here.`
|
|
11029
11085
|
);
|
|
11030
11086
|
const doClassGuard = result.doClassGuard === "unverified" ? "unverified" : void 0;
|
|
11031
11087
|
if (!args.json) {
|
|
11032
11088
|
if (result.url) {
|
|
11033
|
-
if (
|
|
11089
|
+
if (serving === "unconfirmed") p22.log.warn(`URL: ${result.url} (accepted; serving not yet verified)`);
|
|
11034
11090
|
else p22.log.success(`Live at: ${result.url}`);
|
|
11035
11091
|
}
|
|
11036
11092
|
if (result.bundleRetained === false) {
|
|
@@ -11058,7 +11114,6 @@ Re-run with --allow-do-deletion to accept the data loss.`,
|
|
|
11058
11114
|
wranglerEnv: wranglerEnv ?? null,
|
|
11059
11115
|
// Always present, matching `deploy`: one field to branch on.
|
|
11060
11116
|
serving,
|
|
11061
|
-
...edgePropagating ? { edgePropagating: true } : {},
|
|
11062
11117
|
...doClassGuard ? { doClassGuard } : {}
|
|
11063
11118
|
}
|
|
11064
11119
|
};
|
|
@@ -11070,7 +11125,7 @@ import { defineCommand as defineCommand12 } from "citty";
|
|
|
11070
11125
|
|
|
11071
11126
|
// src/cli/commands/workspace/new.ts
|
|
11072
11127
|
import * as p25 from "@clack/prompts";
|
|
11073
|
-
import { isAbsolute as isAbsolute6, resolve as
|
|
11128
|
+
import { isAbsolute as isAbsolute6, resolve as resolve18 } from "path";
|
|
11074
11129
|
|
|
11075
11130
|
// src/cli/commands/workspace/analysis.ts
|
|
11076
11131
|
import * as p23 from "@clack/prompts";
|
|
@@ -11079,6 +11134,14 @@ var PEER_REF_PREFIX = `${spacePrivateRef("peers")}/`;
|
|
|
11079
11134
|
function peerWorkspaceRef(workspaceId) {
|
|
11080
11135
|
return `${PEER_REF_PREFIX}${workspaceId}`;
|
|
11081
11136
|
}
|
|
11137
|
+
function workspaceSyncRelation(dir, localOid, publishedOid) {
|
|
11138
|
+
if (localOid !== null && localOid === publishedOid) return "in_sync";
|
|
11139
|
+
if (localOid === null || publishedOid === null) return "unknown";
|
|
11140
|
+
if (resolveCommit(dir, publishedOid) === null) return "unknown";
|
|
11141
|
+
if (isAncestor(dir, localOid, publishedOid)) return "behind";
|
|
11142
|
+
if (isAncestor(dir, publishedOid, localOid)) return "ahead";
|
|
11143
|
+
return "diverged";
|
|
11144
|
+
}
|
|
11082
11145
|
function formatCount(count) {
|
|
11083
11146
|
if (!count) return "?";
|
|
11084
11147
|
return count.capped ? `${count.count}+` : String(count.count);
|
|
@@ -11195,18 +11258,18 @@ function printOverlaps(overlaps, json) {
|
|
|
11195
11258
|
|
|
11196
11259
|
// src/cli/commands/workspace/local.ts
|
|
11197
11260
|
import * as p24 from "@clack/prompts";
|
|
11198
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
11199
|
-
import { dirname as
|
|
11261
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync27, realpathSync as realpathSync6, renameSync as renameSync2, statSync as statSync3, writeFileSync as writeFileSync9 } from "fs";
|
|
11262
|
+
import { dirname as dirname10, isAbsolute as isAbsolute5, join as join22, relative as relative2, sep as sep2 } from "path";
|
|
11200
11263
|
var WORKSPACE_MARKER = "deepspace-workspace.json";
|
|
11201
11264
|
function excludeWorktreeDir(appDir, dir) {
|
|
11202
11265
|
try {
|
|
11203
11266
|
ensureLocalExclude(appDir, ".deepspace/");
|
|
11204
|
-
const realDir =
|
|
11205
|
-
const rel = relative2(
|
|
11267
|
+
const realDir = realpathSync6(dir);
|
|
11268
|
+
const rel = relative2(realpathSync6(repoToplevel(appDir)), realDir);
|
|
11206
11269
|
if (!rel || rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute5(rel)) return;
|
|
11207
11270
|
const pattern = rel.split(sep2).join("/");
|
|
11208
11271
|
if (pattern === ".deepspace" || pattern.startsWith(".deepspace/")) return;
|
|
11209
|
-
const relApp = relative2(
|
|
11272
|
+
const relApp = relative2(realpathSync6(appDir), realDir).split(sep2).join("/");
|
|
11210
11273
|
if (relApp === ".deepspace" || relApp.startsWith(".deepspace/")) return;
|
|
11211
11274
|
ensureLocalExclude(appDir, `/${pattern}/`);
|
|
11212
11275
|
} catch {
|
|
@@ -11228,7 +11291,7 @@ function markManagedWorkspace(worktreeRoot, workspaceId) {
|
|
|
11228
11291
|
const marker = { version: 1, workspaceId, mode: "managed-linked" };
|
|
11229
11292
|
const tempPath = `${markerPath}.${process.pid}.tmp`;
|
|
11230
11293
|
try {
|
|
11231
|
-
mkdirSync7(
|
|
11294
|
+
mkdirSync7(dirname10(markerPath), { recursive: true });
|
|
11232
11295
|
writeFileSync9(tempPath, JSON.stringify(marker) + "\n");
|
|
11233
11296
|
renameSync2(tempPath, markerPath);
|
|
11234
11297
|
return true;
|
|
@@ -11253,7 +11316,7 @@ function isManagedWorkspaceWorktree(worktreeRoot, workspaceId) {
|
|
|
11253
11316
|
const markerPath = worktreeMarkerPath(worktreeRoot);
|
|
11254
11317
|
if (!markerPath) return false;
|
|
11255
11318
|
try {
|
|
11256
|
-
const marker = JSON.parse(
|
|
11319
|
+
const marker = JSON.parse(readFileSync27(markerPath, "utf-8"));
|
|
11257
11320
|
return marker.version === 1 && marker.workspaceId === workspaceId && marker.mode === "managed-linked";
|
|
11258
11321
|
} catch {
|
|
11259
11322
|
return false;
|
|
@@ -11265,7 +11328,7 @@ function defaultWorkspaceRoot(appDir, workspaceId) {
|
|
|
11265
11328
|
return join22(primary.path, ".deepspace", "ws", workspaceId.slice(3).toLowerCase());
|
|
11266
11329
|
}
|
|
11267
11330
|
function appDirInWorktree(appDir, worktreeRoot) {
|
|
11268
|
-
const appRelative = relative2(
|
|
11331
|
+
const appRelative = relative2(realpathSync6(repoToplevel(appDir)), realpathSync6(appDir));
|
|
11269
11332
|
return appRelative ? join22(worktreeRoot, appRelative) : worktreeRoot;
|
|
11270
11333
|
}
|
|
11271
11334
|
function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint, workspaceId, options = {}) {
|
|
@@ -11281,6 +11344,18 @@ function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint,
|
|
|
11281
11344
|
}
|
|
11282
11345
|
excludeWorktreeDir(appDir, worktreeRoot);
|
|
11283
11346
|
}
|
|
11347
|
+
function rematerializeWorkspaceWorktree(appDir, worktreeRoot, branch, workspaceId, options = {}) {
|
|
11348
|
+
const added = runGit(appDir, ["worktree", "add", worktreeRoot, branch], { allowFail: true });
|
|
11349
|
+
if (added.status !== 0) {
|
|
11350
|
+
return added.stderr.toString("utf-8").trim() || "unknown git error";
|
|
11351
|
+
}
|
|
11352
|
+
if (!(options.markManaged ?? markManagedWorkspace)(worktreeRoot, workspaceId)) {
|
|
11353
|
+
runGit(appDir, ["worktree", "remove", worktreeRoot], { allowFail: true });
|
|
11354
|
+
return `could not record DeepSpace ownership for ${worktreeRoot}`;
|
|
11355
|
+
}
|
|
11356
|
+
excludeWorktreeDir(appDir, worktreeRoot);
|
|
11357
|
+
return null;
|
|
11358
|
+
}
|
|
11284
11359
|
function inOwnLinkedWorktree(appDir, id) {
|
|
11285
11360
|
if (workspaceIdFromBranch(currentBranch(appDir)) !== id) return false;
|
|
11286
11361
|
try {
|
|
@@ -11389,7 +11464,7 @@ function cleanupWorkspaceLocal(appDir, id, trunkBranch, options = {}) {
|
|
|
11389
11464
|
}
|
|
11390
11465
|
let inside = false;
|
|
11391
11466
|
try {
|
|
11392
|
-
inside =
|
|
11467
|
+
inside = realpathSync6(repoToplevel(appDir)) === realpathSync6(linked.path);
|
|
11393
11468
|
} catch {
|
|
11394
11469
|
inside = false;
|
|
11395
11470
|
}
|
|
@@ -11485,7 +11560,7 @@ function inferWorkspaceId(appDir, explicit) {
|
|
|
11485
11560
|
const id = explicit?.trim() || workspaceIdFromBranch(currentBranch(appDir));
|
|
11486
11561
|
if (!id) {
|
|
11487
11562
|
throw new Refusal(
|
|
11488
|
-
'Not inside a workspace worktree (the branch is not ws/<id>).
|
|
11563
|
+
'Not inside a workspace worktree (the branch is not ws/<id>). Select one with `-w ws_\u2026` (for `workspace drop`, pass the id as the argument), or create one with `deepspace workspace new -t "\u2026"`.',
|
|
11489
11564
|
"not_in_workspace"
|
|
11490
11565
|
);
|
|
11491
11566
|
}
|
|
@@ -11494,17 +11569,28 @@ function inferWorkspaceId(appDir, explicit) {
|
|
|
11494
11569
|
}
|
|
11495
11570
|
return id;
|
|
11496
11571
|
}
|
|
11572
|
+
function workspaceNotActiveRefusal(id, status3, dropAction) {
|
|
11573
|
+
return new Refusal(
|
|
11574
|
+
`Workspace ${id} is already ${status3}.` + (dropAction ? " This checkout is a leftover \u2014 `deepspace workspace drop` cleans it up." : ""),
|
|
11575
|
+
"workspace_not_active",
|
|
11576
|
+
{
|
|
11577
|
+
...dropAction ? { action: dropAction } : {},
|
|
11578
|
+
extra: { workspaceId: id, status: status3 }
|
|
11579
|
+
}
|
|
11580
|
+
);
|
|
11581
|
+
}
|
|
11497
11582
|
function assertSelectedWorkspaceCheckout(appDir, id, resumeArgv) {
|
|
11498
11583
|
const branch = currentBranch(appDir);
|
|
11499
11584
|
if (isSelectedWorkspaceCheckout(branch, id)) return;
|
|
11500
11585
|
const worktree = resolveWorkspaceWorktree(listWorktrees(appDir), id);
|
|
11501
|
-
const
|
|
11586
|
+
const worktreeAppDir = worktree ? appDirInWorktree(appDir, worktree) : null;
|
|
11587
|
+
const action = worktreeAppDir ? { cwd: worktreeAppDir, argv: resumeArgv } : { cwd: appDir, argv: ["deepspace", "workspace", "attach", id] };
|
|
11502
11588
|
throw new Refusal(
|
|
11503
|
-
`Workspace ${id} is not checked out here (current branch: ${branch ?? "detached"}). ` + (
|
|
11589
|
+
`Workspace ${id} is not checked out here (current branch: ${branch ?? "detached"}). ` + (worktreeAppDir ? `Run this command from its checkout at ${worktreeAppDir}.` : "Attach it in this clone before mutating its published line."),
|
|
11504
11590
|
"workspace_checkout_mismatch",
|
|
11505
11591
|
{
|
|
11506
11592
|
action,
|
|
11507
|
-
extra:
|
|
11593
|
+
extra: worktreeAppDir ? { workspaceDir: worktreeAppDir } : void 0
|
|
11508
11594
|
}
|
|
11509
11595
|
);
|
|
11510
11596
|
}
|
|
@@ -11528,10 +11614,11 @@ function pushWorkspaceRef(appDir, token, ref, headOid) {
|
|
|
11528
11614
|
if (push.status === "committed" || push.status === "up_to_date") return;
|
|
11529
11615
|
if (push.status === "ref_conflict" || push.status === "non_fast_forward") {
|
|
11530
11616
|
throw new Refusal(
|
|
11531
|
-
`Another checkout advanced this workspace's line, so publishing yours is not a fast-forward \u2014 the push was refused rather than drop that work. Integrate its tip (\`git pull ${SPACE_REMOTE} ${ref}\`, or re-attach the workspace in a fresh dir), resolve any conflicts, then re-run the command. (Amended or rebased your own commits? Same refusal \u2014 merge your old tip back in.)`,
|
|
11617
|
+
`Another checkout advanced this workspace's line, so publishing yours is not a fast-forward \u2014 the push was refused rather than drop that work. Integrate its tip (\`git pull --no-rebase ${SPACE_REMOTE} ${ref}\`, or re-attach the workspace in a fresh dir), resolve any conflicts, then re-run the command. (Amended or rebased your own commits? Same refusal \u2014 merge your old tip back in.)`,
|
|
11532
11618
|
push.status,
|
|
11533
11619
|
{
|
|
11534
|
-
|
|
11620
|
+
actionRequired: true,
|
|
11621
|
+
action: { cwd: appDir, argv: ["git", "pull", "--no-rebase", SPACE_REMOTE, ref] }
|
|
11535
11622
|
}
|
|
11536
11623
|
);
|
|
11537
11624
|
}
|
|
@@ -11587,6 +11674,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11587
11674
|
);
|
|
11588
11675
|
spinner2?.message("Creating workspace\u2026");
|
|
11589
11676
|
ensureSpaceRemote(appDir, appId);
|
|
11677
|
+
ensureGitIdentity(appDir, token);
|
|
11590
11678
|
let baseOid = null;
|
|
11591
11679
|
const refs = await api4.getRefs();
|
|
11592
11680
|
if (baseArg) {
|
|
@@ -11630,7 +11718,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11630
11718
|
idempotencyKey: mintIdempotencyKey()
|
|
11631
11719
|
});
|
|
11632
11720
|
const dirInput = typeof args.dir === "string" ? args.dir.trim() : "";
|
|
11633
|
-
const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput :
|
|
11721
|
+
const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput : resolve18(appDir, dirInput) : defaultWorkspaceRoot(appDir, id);
|
|
11634
11722
|
const dir = appDirInWorktree(appDir, worktreeRoot);
|
|
11635
11723
|
try {
|
|
11636
11724
|
materializeWorkspaceWorktree(appDir, worktreeRoot, branch, baseOid, id);
|
|
@@ -11668,8 +11756,18 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11668
11756
|
|
|
11669
11757
|
// src/cli/commands/workspace/attach.ts
|
|
11670
11758
|
import * as p26 from "@clack/prompts";
|
|
11671
|
-
import { existsSync as existsSync25, readdirSync as readdirSync7, rmSync as rmSync6 } from "fs";
|
|
11672
|
-
import { isAbsolute as isAbsolute7, resolve as
|
|
11759
|
+
import { existsSync as existsSync25, readdirSync as readdirSync7, realpathSync as realpathSync7, rmSync as rmSync6 } from "fs";
|
|
11760
|
+
import { isAbsolute as isAbsolute7, resolve as resolve19 } from "path";
|
|
11761
|
+
function samePath(a, b) {
|
|
11762
|
+
const real = (p35) => {
|
|
11763
|
+
try {
|
|
11764
|
+
return realpathSync7(p35);
|
|
11765
|
+
} catch {
|
|
11766
|
+
return resolve19(p35);
|
|
11767
|
+
}
|
|
11768
|
+
};
|
|
11769
|
+
return real(a) === real(b);
|
|
11770
|
+
}
|
|
11673
11771
|
function finishedWorkspaceMessage(id, view) {
|
|
11674
11772
|
const workspace = view.workspace;
|
|
11675
11773
|
if (workspace.status === "landed") {
|
|
@@ -11738,6 +11836,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11738
11836
|
});
|
|
11739
11837
|
}
|
|
11740
11838
|
ensureSpaceRemote(appDir, appId2);
|
|
11839
|
+
ensureGitIdentity(appDir, token2);
|
|
11741
11840
|
const localWorkspaceRef = spacePrivateRef(`workspaces/${id}`);
|
|
11742
11841
|
runGitRemote(appDir, token2, [
|
|
11743
11842
|
"fetch",
|
|
@@ -11754,11 +11853,87 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11754
11853
|
);
|
|
11755
11854
|
}
|
|
11756
11855
|
const requestedDir = typeof args.dir === "string" ? args.dir.trim() : "";
|
|
11757
|
-
const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir :
|
|
11856
|
+
const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir : resolve19(appDir, requestedDir) : defaultWorkspaceRoot(appDir, id);
|
|
11758
11857
|
const dir2 = appDirInWorktree(appDir, worktreeRoot);
|
|
11759
|
-
|
|
11858
|
+
const localTip = resolveCommit(appDir, `refs/heads/${branch}`);
|
|
11859
|
+
if (localTip) {
|
|
11860
|
+
let existing = resolveWorkspaceWorktree(listWorktrees(appDir), id);
|
|
11861
|
+
if (existing && !existsSync25(existing)) {
|
|
11862
|
+
runGit(appDir, ["worktree", "prune"], { allowFail: true });
|
|
11863
|
+
existing = null;
|
|
11864
|
+
}
|
|
11865
|
+
const relation = workspaceSyncRelation(appDir, localTip, tip2);
|
|
11866
|
+
const inSync = relation === "in_sync";
|
|
11867
|
+
const behindOrDiverged = relation === "behind" || relation === "diverged";
|
|
11868
|
+
const syncAdvice = behindOrDiverged ? `integrate the published tip first (\`git pull --no-rebase ${SPACE_REMOTE} ${view2.workspace.ref}\`)` : `run \`deepspace workspace sync\` from it`;
|
|
11869
|
+
const syncAction = (cwd) => behindOrDiverged ? { cwd, argv: ["git", "pull", "--no-rebase", SPACE_REMOTE, view2.workspace.ref] } : { cwd, argv: ["deepspace", "workspace", "sync"] };
|
|
11870
|
+
if (existing && (!requestedDir || samePath(existing, worktreeRoot))) {
|
|
11871
|
+
const existingDir = appDirInWorktree(appDir, existing);
|
|
11872
|
+
spinner2?.stop(`Already attached: ${id}.`);
|
|
11873
|
+
if (!args.json) {
|
|
11874
|
+
p26.log.info(`Task: ${view2.workspace.task}`);
|
|
11875
|
+
p26.log.info(`Work in: cd ${existingDir}`);
|
|
11876
|
+
if (!inSync) {
|
|
11877
|
+
p26.log.warn(
|
|
11878
|
+
`The checkout is at ${localTip.slice(0, 10)} but the workspace's published tip is ${tip2.slice(0, 10)} \u2014 ${syncAdvice}.`
|
|
11879
|
+
);
|
|
11880
|
+
}
|
|
11881
|
+
}
|
|
11882
|
+
return {
|
|
11883
|
+
data: {
|
|
11884
|
+
workspaceId: id,
|
|
11885
|
+
mode: "worktree",
|
|
11886
|
+
dir: existingDir,
|
|
11887
|
+
worktreeRoot: existing,
|
|
11888
|
+
branch,
|
|
11889
|
+
tipOid: localTip,
|
|
11890
|
+
remoteTip: tip2,
|
|
11891
|
+
syncRelation: relation,
|
|
11892
|
+
task: view2.workspace.task,
|
|
11893
|
+
alreadyAttached: true
|
|
11894
|
+
},
|
|
11895
|
+
...inSync ? {} : { action: syncAction(existingDir) }
|
|
11896
|
+
};
|
|
11897
|
+
}
|
|
11898
|
+
if (!existing) {
|
|
11899
|
+
const failure = rematerializeWorkspaceWorktree(appDir, worktreeRoot, branch, id);
|
|
11900
|
+
if (failure) {
|
|
11901
|
+
spinner2?.stop("Branch exists.");
|
|
11902
|
+
throw new Refusal(
|
|
11903
|
+
`Branch ${branch} exists locally with no worktree, and re-materializing it failed: ${failure}. Inspect it (\`git log ${branch}\`) and check it out yourself.`,
|
|
11904
|
+
"branch_exists"
|
|
11905
|
+
);
|
|
11906
|
+
}
|
|
11907
|
+
spinner2?.stop(`Re-attached ${id}.`);
|
|
11908
|
+
if (!args.json) {
|
|
11909
|
+
p26.log.info(`Task: ${view2.workspace.task}`);
|
|
11910
|
+
p26.log.info(`Work in: cd ${dir2}`);
|
|
11911
|
+
if (!inSync) {
|
|
11912
|
+
p26.log.warn(
|
|
11913
|
+
`The re-materialized checkout is at ${localTip.slice(0, 10)} but the workspace's published tip is ${tip2.slice(0, 10)} \u2014 after installing, ${syncAdvice}.`
|
|
11914
|
+
);
|
|
11915
|
+
}
|
|
11916
|
+
}
|
|
11917
|
+
const action3 = { cwd: dir2, argv: [detectPackageManager(dir2), "install"] };
|
|
11918
|
+
return {
|
|
11919
|
+
data: {
|
|
11920
|
+
workspaceId: id,
|
|
11921
|
+
mode: "worktree",
|
|
11922
|
+
dir: dir2,
|
|
11923
|
+
worktreeRoot,
|
|
11924
|
+
branch,
|
|
11925
|
+
tipOid: localTip,
|
|
11926
|
+
remoteTip: tip2,
|
|
11927
|
+
syncRelation: relation,
|
|
11928
|
+
task: view2.workspace.task,
|
|
11929
|
+
rematerialized: true
|
|
11930
|
+
},
|
|
11931
|
+
action: action3
|
|
11932
|
+
};
|
|
11933
|
+
}
|
|
11934
|
+
spinner2?.stop("Branch exists.");
|
|
11760
11935
|
throw new Refusal(
|
|
11761
|
-
`
|
|
11936
|
+
`Workspace ${id} is already checked out at ${existing} \u2014 continue there (or drop that worktree before attaching it elsewhere).`,
|
|
11762
11937
|
"branch_exists"
|
|
11763
11938
|
);
|
|
11764
11939
|
}
|
|
@@ -11777,6 +11952,10 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11777
11952
|
worktreeRoot,
|
|
11778
11953
|
branch,
|
|
11779
11954
|
tipOid: tip2,
|
|
11955
|
+
remoteTip: tip2,
|
|
11956
|
+
// Freshly materialized at the published tip — trivially in sync;
|
|
11957
|
+
// every attach outcome carries the same shape.
|
|
11958
|
+
syncRelation: "in_sync",
|
|
11780
11959
|
task: view2.workspace.task
|
|
11781
11960
|
},
|
|
11782
11961
|
action: action2
|
|
@@ -11793,7 +11972,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11793
11972
|
extra: { status: view.workspace.status }
|
|
11794
11973
|
});
|
|
11795
11974
|
}
|
|
11796
|
-
const dir =
|
|
11975
|
+
const dir = resolve19(
|
|
11797
11976
|
process.cwd(),
|
|
11798
11977
|
(typeof args.dir === "string" ? args.dir.trim() : "") || `ws-${id.slice(3).toLowerCase()}`
|
|
11799
11978
|
);
|
|
@@ -11812,6 +11991,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11812
11991
|
try {
|
|
11813
11992
|
runGit(process.cwd(), ["init", "--quiet", dir]);
|
|
11814
11993
|
ensureSpaceRemote(dir, appId);
|
|
11994
|
+
ensureGitIdentity(dir, token);
|
|
11815
11995
|
const localWorkspaceRef = spacePrivateRef(`workspaces/${id}`);
|
|
11816
11996
|
runGitRemote(dir, token, [
|
|
11817
11997
|
"fetch",
|
|
@@ -11848,6 +12028,8 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11848
12028
|
dir,
|
|
11849
12029
|
branch,
|
|
11850
12030
|
tipOid: tip,
|
|
12031
|
+
remoteTip: tip,
|
|
12032
|
+
syncRelation: "in_sync",
|
|
11851
12033
|
task: view.workspace.task
|
|
11852
12034
|
},
|
|
11853
12035
|
action
|
|
@@ -11880,7 +12062,19 @@ var syncWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11880
12062
|
typeof args.app === "string" ? args.app : void 0
|
|
11881
12063
|
);
|
|
11882
12064
|
const id = inferWorkspaceId(appDir, workspaceArg);
|
|
11883
|
-
|
|
12065
|
+
try {
|
|
12066
|
+
assertSelectedWorkspaceCheckout(appDir, id, ["deepspace", "workspace", "sync"]);
|
|
12067
|
+
} catch (mismatch) {
|
|
12068
|
+
const current = await api4.getWorkspace(id).then((r) => r.view).catch(() => null);
|
|
12069
|
+
if (current && current.workspace.status !== "active") {
|
|
12070
|
+
spinner2?.stop("Workspace finished.");
|
|
12071
|
+
throw workspaceNotActiveRefusal(id, current.workspace.status, {
|
|
12072
|
+
cwd: appDir,
|
|
12073
|
+
argv: ["deepspace", "workspace", "drop", id, "--app", appId]
|
|
12074
|
+
});
|
|
12075
|
+
}
|
|
12076
|
+
throw mismatch;
|
|
12077
|
+
}
|
|
11884
12078
|
const headOid = resolveCommit(appDir, "HEAD");
|
|
11885
12079
|
if (!headOid) {
|
|
11886
12080
|
throw new Refusal("The workspace has no commits yet \u2014 commit first, then sync.", "no_commits");
|
|
@@ -11899,6 +12093,7 @@ var syncWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11899
12093
|
);
|
|
11900
12094
|
}
|
|
11901
12095
|
ensureSpaceRemote(appDir, appId);
|
|
12096
|
+
ensureGitIdentity(appDir, token);
|
|
11902
12097
|
pushWorkspaceRef(appDir, token, before.workspace.ref, headOid);
|
|
11903
12098
|
try {
|
|
11904
12099
|
fetchTrunk(appDir, token, refs?.head ?? null);
|
|
@@ -12039,6 +12234,7 @@ var workspaceStatusCommand = defineDeepspaceCommand({
|
|
|
12039
12234
|
const aheadExact = headOid && baseLocal ? revListCount(appDir, workspace.baseOid, headOid) : null;
|
|
12040
12235
|
const unsynced = headOid !== null && view.tipOid !== headOid;
|
|
12041
12236
|
const dirty = workspaceDir ? statusFiles(workspaceDir) : [];
|
|
12237
|
+
const relation = !unsynced ? "in_sync" : workspace.status !== "active" || !workspaceDir ? "unknown" : workspaceSyncRelation(workspaceDir, headOid, view.tipOid);
|
|
12042
12238
|
const lines = await loadWorkspaceLines(appDir, token, api4, trunkOid);
|
|
12043
12239
|
const myTip = headOid ?? resolveCommit(appDir, peerWorkspaceRef(id)) ?? view.tipOid;
|
|
12044
12240
|
const line = myTip ? lineChangedPaths(appDir, workspace.baseOid, myTip, trunkOid) : null;
|
|
@@ -12058,6 +12254,10 @@ var workspaceStatusCommand = defineDeepspaceCommand({
|
|
|
12058
12254
|
...attached ? {
|
|
12059
12255
|
headOid,
|
|
12060
12256
|
unsynced,
|
|
12257
|
+
// The human line distinguishes behind/diverged/ahead; the machine
|
|
12258
|
+
// mirror must too, or a JSON caller can't tell a fast-forward from
|
|
12259
|
+
// a real divergence.
|
|
12260
|
+
syncRelation: relation,
|
|
12061
12261
|
uncommitted: dirty,
|
|
12062
12262
|
trunkOverlap
|
|
12063
12263
|
} : {},
|
|
@@ -12073,10 +12273,29 @@ var workspaceStatusCommand = defineDeepspaceCommand({
|
|
|
12073
12273
|
`Not checked out in this clone \u2014 showing the published state (local HEAD/uncommitted unavailable). Attach it with \`deepspace workspace attach ${id} <dir>\`.`
|
|
12074
12274
|
);
|
|
12075
12275
|
}
|
|
12076
|
-
if (unsynced)
|
|
12077
|
-
|
|
12078
|
-
|
|
12079
|
-
|
|
12276
|
+
if (unsynced) {
|
|
12277
|
+
if (workspace.status === "landed") {
|
|
12278
|
+
p29.log.info(
|
|
12279
|
+
`Already landed${workspace.landedOid ? ` at ${workspace.landedOid.slice(0, 10)}` : ""} \u2014 this checkout is a leftover; \`deepspace workspace drop ${id}\` cleans it up.`
|
|
12280
|
+
);
|
|
12281
|
+
} else if (workspace.status === "dropped") {
|
|
12282
|
+
p29.log.info(
|
|
12283
|
+
`Already dropped \u2014 this checkout is a leftover; \`deepspace workspace drop ${id}\` cleans it up.`
|
|
12284
|
+
);
|
|
12285
|
+
} else if (relation === "behind") {
|
|
12286
|
+
p29.log.warn(
|
|
12287
|
+
`Local HEAD ${headOid?.slice(0, 10)} is BEHIND the published tip ${view.tipOid?.slice(0, 10)} (another checkout synced ahead) \u2014 fast-forward first (\`git pull --no-rebase ${SPACE_REMOTE} ${workspace.ref}\`).`
|
|
12288
|
+
);
|
|
12289
|
+
} else if (relation === "diverged") {
|
|
12290
|
+
p29.log.warn(
|
|
12291
|
+
`Local HEAD ${headOid?.slice(0, 10)} has DIVERGED from the published tip ${view.tipOid?.slice(0, 10)} \u2014 integrate it first (\`git pull --no-rebase ${SPACE_REMOTE} ${workspace.ref}\`), then \`deepspace workspace sync\`.`
|
|
12292
|
+
);
|
|
12293
|
+
} else {
|
|
12294
|
+
p29.log.warn(
|
|
12295
|
+
`Local HEAD ${headOid?.slice(0, 10)} is not synced (server has ${view.tipOid?.slice(0, 10) ?? "nothing"}) \u2014 run \`deepspace workspace sync\`.`
|
|
12296
|
+
);
|
|
12297
|
+
}
|
|
12298
|
+
}
|
|
12080
12299
|
if (dirty.length > 0) p29.log.warn(`${dirty.length} uncommitted file(s) in the worktree.`);
|
|
12081
12300
|
if (trunkOverlap.length > 0) {
|
|
12082
12301
|
p29.log.warn(
|
|
@@ -12094,13 +12313,13 @@ import * as p30 from "@clack/prompts";
|
|
|
12094
12313
|
|
|
12095
12314
|
// src/cli/lib/validation.ts
|
|
12096
12315
|
import { sync as spawnSync7 } from "cross-spawn";
|
|
12097
|
-
import { readFileSync as
|
|
12316
|
+
import { readFileSync as readFileSync28 } from "fs";
|
|
12098
12317
|
import { join as join23 } from "path";
|
|
12099
12318
|
var MAX_SUMMARY_CHARS = 4e3;
|
|
12100
12319
|
var MAX_OUTPUT_BUFFER = 64 * 1024 * 1024;
|
|
12101
12320
|
function configuredCommand(appDir) {
|
|
12102
12321
|
try {
|
|
12103
|
-
const pkg2 = JSON.parse(
|
|
12322
|
+
const pkg2 = JSON.parse(readFileSync28(join23(appDir, "package.json"), "utf-8"));
|
|
12104
12323
|
if (pkg2.scripts?.validate) return `${detectPackageManager(appDir)} run --silent validate`;
|
|
12105
12324
|
} catch {
|
|
12106
12325
|
}
|
|
@@ -12130,6 +12349,14 @@ ${res.stderr?.toString("utf-8") ?? ""}`.trim();
|
|
|
12130
12349
|
function hasLeftoverConflictMarkers(diffCheckOutput) {
|
|
12131
12350
|
return /leftover conflict marker/.test(diffCheckOutput);
|
|
12132
12351
|
}
|
|
12352
|
+
function conflictMarkerFiles(diffCheckOutput) {
|
|
12353
|
+
const files = /* @__PURE__ */ new Set();
|
|
12354
|
+
for (const line of diffCheckOutput.split("\n")) {
|
|
12355
|
+
const match = /^(.+?):\d+: leftover conflict marker/.exec(line);
|
|
12356
|
+
if (match) files.add(match[1]);
|
|
12357
|
+
}
|
|
12358
|
+
return [...files];
|
|
12359
|
+
}
|
|
12133
12360
|
function landResumeArgv(args) {
|
|
12134
12361
|
const argv = ["deepspace", "workspace", "land"];
|
|
12135
12362
|
const workspace = args.workspace?.trim();
|
|
@@ -12195,7 +12422,20 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12195
12422
|
});
|
|
12196
12423
|
const recoveryAction = { cwd: appDir, argv: resumeArgv };
|
|
12197
12424
|
const resumeNext = humanCommand(resumeArgv);
|
|
12198
|
-
|
|
12425
|
+
const dropAction = {
|
|
12426
|
+
cwd: appDir,
|
|
12427
|
+
argv: ["deepspace", "workspace", "drop", id, "--app", appId]
|
|
12428
|
+
};
|
|
12429
|
+
try {
|
|
12430
|
+
assertSelectedWorkspaceCheckout(appDir, id, resumeArgv);
|
|
12431
|
+
} catch (mismatch) {
|
|
12432
|
+
const current = await api4.getWorkspace(id).then((r) => r.view).catch(() => null);
|
|
12433
|
+
if (current && current.workspace.status !== "active") {
|
|
12434
|
+
spinner2?.stop("Workspace finished.");
|
|
12435
|
+
throw workspaceNotActiveRefusal(id, current.workspace.status, dropAction);
|
|
12436
|
+
}
|
|
12437
|
+
throw mismatch;
|
|
12438
|
+
}
|
|
12199
12439
|
const headBefore = resolveCommit(appDir, "HEAD");
|
|
12200
12440
|
if (!headBefore) {
|
|
12201
12441
|
throw new Refusal("The workspace has no commits \u2014 nothing to land.", "no_commits");
|
|
@@ -12211,13 +12451,10 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12211
12451
|
const [{ view }, refs] = await Promise.all([api4.getWorkspace(id), api4.getRefs()]);
|
|
12212
12452
|
if (view.workspace.status !== "active") {
|
|
12213
12453
|
spinner2?.stop("Workspace finished.");
|
|
12214
|
-
throw
|
|
12215
|
-
`Workspace ${id} is already ${view.workspace.status}.`,
|
|
12216
|
-
"workspace_not_active",
|
|
12217
|
-
{ extra: { status: view.workspace.status } }
|
|
12218
|
-
);
|
|
12454
|
+
throw workspaceNotActiveRefusal(id, view.workspace.status, dropAction);
|
|
12219
12455
|
}
|
|
12220
12456
|
ensureSpaceRemote(appDir, appId);
|
|
12457
|
+
ensureGitIdentity(appDir, token);
|
|
12221
12458
|
const isResumedMerge = resolveCommit(appDir, "HEAD^2") !== null && view.tipOid !== null && resolveCommit(appDir, "HEAD^") === view.tipOid;
|
|
12222
12459
|
if (!isResumedMerge) {
|
|
12223
12460
|
pushWorkspaceRef(appDir, token, view.workspace.ref, headBefore);
|
|
@@ -12264,6 +12501,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12264
12501
|
"merge_conflict",
|
|
12265
12502
|
{
|
|
12266
12503
|
actionRequired: true,
|
|
12504
|
+
action: recoveryAction,
|
|
12267
12505
|
extra: { workspaceId: id, conflict: true }
|
|
12268
12506
|
}
|
|
12269
12507
|
);
|
|
@@ -12273,14 +12511,17 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12273
12511
|
const markerCheck = runGit(appDir, ["diff", "--check", "HEAD^", "HEAD"], {
|
|
12274
12512
|
allowFail: true
|
|
12275
12513
|
});
|
|
12276
|
-
|
|
12514
|
+
const markerOutput = markerCheck.stdout.toString("utf-8");
|
|
12515
|
+
if (hasLeftoverConflictMarkers(markerOutput)) {
|
|
12516
|
+
const files = conflictMarkerFiles(markerOutput);
|
|
12277
12517
|
spinner2?.stop("Conflict markers in merge.");
|
|
12278
12518
|
throw new Refusal(
|
|
12279
|
-
`The merge commit still contains unresolved conflict markers (<<<<<<< / ======= / >>>>>>>). Fix the marked files, commit the correction, then re-run \`${resumeNext}\`. Nothing was pushed to ${intoBranch}.`,
|
|
12519
|
+
`The merge commit still contains unresolved conflict markers (<<<<<<< / ======= / >>>>>>>)${files.length ? ` in ${files.join(", ")}` : ""}. Fix the marked files, commit the correction, then re-run \`${resumeNext}\`. Nothing was pushed to ${intoBranch}.`,
|
|
12280
12520
|
"conflict_markers",
|
|
12281
12521
|
{
|
|
12282
12522
|
actionRequired: true,
|
|
12283
|
-
|
|
12523
|
+
action: recoveryAction,
|
|
12524
|
+
extra: { workspaceId: id, conflict: true, ...files.length ? { files } : {} }
|
|
12284
12525
|
}
|
|
12285
12526
|
);
|
|
12286
12527
|
}
|
|
@@ -12314,6 +12555,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12314
12555
|
"validation_failed",
|
|
12315
12556
|
{
|
|
12316
12557
|
actionRequired: true,
|
|
12558
|
+
action: recoveryAction,
|
|
12317
12559
|
extra: { workspaceId: id, passed: false, outputTail }
|
|
12318
12560
|
}
|
|
12319
12561
|
);
|
|
@@ -12325,6 +12567,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12325
12567
|
"validation_mutated_tree",
|
|
12326
12568
|
{
|
|
12327
12569
|
actionRequired: true,
|
|
12570
|
+
action: recoveryAction,
|
|
12328
12571
|
extra: { workspaceId: id }
|
|
12329
12572
|
}
|
|
12330
12573
|
);
|
|
@@ -12360,7 +12603,37 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12360
12603
|
"push_rejected"
|
|
12361
12604
|
);
|
|
12362
12605
|
}
|
|
12363
|
-
|
|
12606
|
+
try {
|
|
12607
|
+
await api4.landWorkspace(id, { landedOid, intoRef });
|
|
12608
|
+
} catch (err) {
|
|
12609
|
+
const code = errorCode(err);
|
|
12610
|
+
if (code === "workspace_not_active") {
|
|
12611
|
+
const status3 = await api4.getWorkspace(id).then((r) => r.view.workspace.status).catch(() => null);
|
|
12612
|
+
if (status3 && status3 !== "active") {
|
|
12613
|
+
spinner2?.stop("Workspace finished.");
|
|
12614
|
+
throw new Refusal(
|
|
12615
|
+
`${intoBranch} took the land push (${landedOid.slice(0, 10)}), and the workspace is already ${status3} \u2014 a concurrent land or drop finished first, so there is nothing left to record. This checkout is a leftover; \`deepspace workspace drop ${id}\` cleans it up.`,
|
|
12616
|
+
"workspace_not_active",
|
|
12617
|
+
{
|
|
12618
|
+
actionRequired: true,
|
|
12619
|
+
action: dropAction,
|
|
12620
|
+
extra: { workspaceId: id, into: intoBranch, landedOid, pushed: true, status: status3 }
|
|
12621
|
+
}
|
|
12622
|
+
);
|
|
12623
|
+
}
|
|
12624
|
+
}
|
|
12625
|
+
spinner2?.stop("Landed; not recorded.");
|
|
12626
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
12627
|
+
throw new Refusal(
|
|
12628
|
+
`The land push succeeded (${intoBranch} was at ${landedOid.slice(0, 10)}), but recording the land failed (${detail}). Resolve that, then re-run \`${resumeNext}\` \u2014 it re-checks the merge (a no-op when already pushed) and records it.`,
|
|
12629
|
+
"land_unrecorded",
|
|
12630
|
+
{
|
|
12631
|
+
actionRequired: true,
|
|
12632
|
+
action: recoveryAction,
|
|
12633
|
+
extra: { workspaceId: id, into: intoBranch, landedOid, pushed: true }
|
|
12634
|
+
}
|
|
12635
|
+
);
|
|
12636
|
+
}
|
|
12364
12637
|
spinner2?.stop(`Landed ${id} into ${intoBranch} at ${landedOid.slice(0, 10)}.`);
|
|
12365
12638
|
const cleanup = keepWorktree ? null : cleanupWorkspaceLocal(appDir, id, intoBranch, { expectedBranchOid: landedOid });
|
|
12366
12639
|
const inOwnWorktree = !cleanup && inOwnLinkedWorktree(appDir, id);
|
|
@@ -12405,6 +12678,22 @@ function isWorkspaceTipPublished(appDir, localTip, publishedOids) {
|
|
|
12405
12678
|
);
|
|
12406
12679
|
}
|
|
12407
12680
|
function workspaceUnsyncedRefusal(args) {
|
|
12681
|
+
const dropKeepArgv = [
|
|
12682
|
+
"deepspace",
|
|
12683
|
+
"workspace",
|
|
12684
|
+
"drop",
|
|
12685
|
+
args.id,
|
|
12686
|
+
"--app",
|
|
12687
|
+
args.appId,
|
|
12688
|
+
"--keep-worktree"
|
|
12689
|
+
];
|
|
12690
|
+
if (args.status !== "active") {
|
|
12691
|
+
return new Refusal(
|
|
12692
|
+
`${args.id} is already ${args.status} on the server, and this checkout has committed work that was never published \u2014 nothing can publish it now. Keep it with \`${humanCommand(dropKeepArgv)}\` (retains the branch/worktree for manual disposal), or delete the branch yourself. Nothing was dropped.`,
|
|
12693
|
+
"workspace_unsynced",
|
|
12694
|
+
{ extra: { workspaceId: args.id, status: args.status } }
|
|
12695
|
+
);
|
|
12696
|
+
}
|
|
12408
12697
|
const syncArgv = ["deepspace", "workspace", "sync", "--app", args.appId, "--workspace", args.id];
|
|
12409
12698
|
const dropArgv = ["deepspace", "workspace", "drop", args.id, "--app", args.appId];
|
|
12410
12699
|
const publish = args.workspaceDir ? `Publish them first with \`${humanCommand(syncArgv)}\`, then re-run \`${humanCommand(dropArgv)}\`.` : `Recreate a worktree from the branch (\`git worktree add <dir> ${args.branch}\`), publish from there with \`${humanCommand(syncArgv)}\`, then re-run \`${humanCommand(dropArgv)}\`.`;
|
|
@@ -12412,11 +12701,25 @@ function workspaceUnsyncedRefusal(args) {
|
|
|
12412
12701
|
`${args.id} has committed work that isn't published yet. ${publish} Alternatively, pass \`--keep-worktree\` to drop the cloud workspace while retaining the local branch/worktree for manual disposal. Nothing was dropped.`,
|
|
12413
12702
|
"workspace_unsynced",
|
|
12414
12703
|
{
|
|
12704
|
+
// Exit 1 with an unblock action, deliberately: drop is destructive and
|
|
12705
|
+
// refusing it is a hard stop, not the "your turn" hand-off exit 2 means.
|
|
12415
12706
|
...args.workspaceDir ? { action: { cwd: args.workspaceDir, argv: syncArgv } } : {},
|
|
12416
|
-
extra: { workspaceId: args.id }
|
|
12707
|
+
extra: { workspaceId: args.id, status: args.status }
|
|
12417
12708
|
}
|
|
12418
12709
|
);
|
|
12419
12710
|
}
|
|
12711
|
+
async function dropRemoteTolerant(api4, id, statusBefore) {
|
|
12712
|
+
try {
|
|
12713
|
+
const view = (await api4.dropWorkspace(id)).view;
|
|
12714
|
+
return { view, remoteDropped: statusBefore === "active" && view.workspace.status === "dropped" };
|
|
12715
|
+
} catch (err) {
|
|
12716
|
+
const code = errorCode(err);
|
|
12717
|
+
if (code !== "workspace_not_active") throw err;
|
|
12718
|
+
const current = await api4.getWorkspace(id).catch(() => null);
|
|
12719
|
+
if (!current || current.view.workspace.status === "active") throw err;
|
|
12720
|
+
return { view: current.view, remoteDropped: false };
|
|
12721
|
+
}
|
|
12722
|
+
}
|
|
12420
12723
|
var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
12421
12724
|
meta: { name: "drop", description: "Abandon a workspace (ref retained briefly, then GC)" },
|
|
12422
12725
|
args: {
|
|
@@ -12441,32 +12744,47 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12441
12744
|
spinner2?.start(`Preparing to drop ${explicitId ?? "workspace"}\u2026`);
|
|
12442
12745
|
if (!findAppDir() && explicitId) {
|
|
12443
12746
|
const { api: api5 } = await resolveApiOnly(appArg);
|
|
12444
|
-
const
|
|
12747
|
+
const statusBefore = (await api5.getWorkspace(explicitId)).view.workspace.status;
|
|
12748
|
+
const { view: view2, remoteDropped: remoteDropped2 } = await dropRemoteTolerant(api5, explicitId, statusBefore);
|
|
12445
12749
|
spinner2?.stop();
|
|
12446
12750
|
if (!args.json) {
|
|
12447
12751
|
p31.log.success(
|
|
12448
|
-
`Dropped ${explicitId}. Its ref sticks around briefly for undo, then is reaped.`
|
|
12752
|
+
remoteDropped2 ? `Dropped ${explicitId}. Its ref sticks around briefly for undo, then is reaped.` : `Workspace ${explicitId} was already ${view2.workspace.status} on the server \u2014 nothing to drop remotely.`
|
|
12449
12753
|
);
|
|
12450
12754
|
}
|
|
12451
|
-
return { data: { workspaceId: explicitId, status: view2.workspace.status } };
|
|
12755
|
+
return { data: { workspaceId: explicitId, status: view2.workspace.status, remoteDropped: remoteDropped2 } };
|
|
12452
12756
|
}
|
|
12453
|
-
const { appDir, appId, api: api4 } = await resolveTarget2(appArg);
|
|
12757
|
+
const { appDir, appId, token, api: api4 } = await resolveTarget2(appArg);
|
|
12454
12758
|
const id = inferWorkspaceId(appDir, explicitId);
|
|
12455
12759
|
const inspection = inspectWorkspaceCleanup(appDir, id);
|
|
12456
12760
|
let approvedBranchOid;
|
|
12761
|
+
const { view: before } = await api4.getWorkspace(id);
|
|
12457
12762
|
if (!keepWorktree && inspection.willDeleteBranch && inspection.branchOid) {
|
|
12458
|
-
const { view: before } = await api4.getWorkspace(id);
|
|
12459
12763
|
const publishedOids = [
|
|
12460
12764
|
before.tipOid,
|
|
12461
12765
|
before.workspace.landedOid,
|
|
12462
12766
|
before.workspace.baseOid
|
|
12463
12767
|
].filter((oid) => oid !== null);
|
|
12464
|
-
|
|
12768
|
+
let published = isWorkspaceTipPublished(appDir, inspection.branchOid, publishedOids);
|
|
12769
|
+
if (!published && before.workspace.status !== "active") {
|
|
12770
|
+
ensureSpaceRemote(appDir, appId);
|
|
12771
|
+
const refs = await api4.getRefs();
|
|
12772
|
+
const trunkRef = refs?.head?.startsWith("refs/heads/") ? refs.head : null;
|
|
12773
|
+
if (trunkRef) {
|
|
12774
|
+
runGitRemote(appDir, token, ["fetch", "--quiet", "--refmap=", SPACE_REMOTE, trunkRef], {
|
|
12775
|
+
allowFail: true
|
|
12776
|
+
});
|
|
12777
|
+
const trunkTip = resolveCommit(appDir, "FETCH_HEAD");
|
|
12778
|
+
published = trunkTip !== null && isWorkspaceTipPublished(appDir, inspection.branchOid, [trunkTip]);
|
|
12779
|
+
}
|
|
12780
|
+
}
|
|
12781
|
+
if (!published) {
|
|
12465
12782
|
throw workspaceUnsyncedRefusal({
|
|
12466
12783
|
appId,
|
|
12467
12784
|
id,
|
|
12468
12785
|
branch: inspection.branch,
|
|
12469
|
-
workspaceDir: inspection.checkout.dir
|
|
12786
|
+
workspaceDir: inspection.checkout.dir,
|
|
12787
|
+
status: before.workspace.status
|
|
12470
12788
|
});
|
|
12471
12789
|
}
|
|
12472
12790
|
approvedBranchOid = inspection.branchOid;
|
|
@@ -12481,7 +12799,7 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12481
12799
|
{ extra: { workspaceId: id } }
|
|
12482
12800
|
);
|
|
12483
12801
|
}
|
|
12484
|
-
const { view } = await api4.
|
|
12802
|
+
const { view, remoteDropped } = await dropRemoteTolerant(api4, id, before.workspace.status);
|
|
12485
12803
|
spinner2?.message(`Cleaning up ${id} locally\u2026`);
|
|
12486
12804
|
const cleanup = keepWorktree ? null : cleanupWorkspaceLocal(appDir, id, null, {
|
|
12487
12805
|
expectedBranchOid: approvedBranchOid,
|
|
@@ -12491,12 +12809,15 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12491
12809
|
const data = {
|
|
12492
12810
|
workspaceId: id,
|
|
12493
12811
|
status: view.workspace.status,
|
|
12812
|
+
remoteDropped,
|
|
12494
12813
|
...retainedWorktree ? { worktree: retainedWorktree } : {},
|
|
12495
12814
|
...cleanup ? { cleanup: cleanupJson(cleanup) } : {}
|
|
12496
12815
|
};
|
|
12497
12816
|
spinner2?.stop();
|
|
12498
12817
|
if (!args.json) {
|
|
12499
|
-
p31.log.success(
|
|
12818
|
+
p31.log.success(
|
|
12819
|
+
remoteDropped ? `Dropped ${id}. Its ref sticks around briefly for undo, then is reaped.` : `Workspace ${id} was already ${view.workspace.status} on the server \u2014 nothing to drop remotely.`
|
|
12820
|
+
);
|
|
12500
12821
|
if (cleanup && !cleanup.error) reportCleanupHuman(cleanup);
|
|
12501
12822
|
else if (retainedWorktree) p31.log.info(`Retained checkout: ${retainedWorktree}`);
|
|
12502
12823
|
}
|
|
@@ -12565,7 +12886,7 @@ function formatEvent2(e, lands, actors) {
|
|
|
12565
12886
|
detail = `"${String(s.task ?? "")}" from ${short(s.baseOid)}`;
|
|
12566
12887
|
break;
|
|
12567
12888
|
case "workspace.synced":
|
|
12568
|
-
detail = `\u2192 ${short(s.headOid)}
|
|
12889
|
+
detail = `\u2192 ${short(s.headOid)}`;
|
|
12569
12890
|
break;
|
|
12570
12891
|
case "workspace.landed":
|
|
12571
12892
|
detail = `"${String(s.task ?? "")}" \u2192 ${short(s.landedOid)} on ${String(s.into ?? "trunk")}`;
|
|
@@ -13063,8 +13384,8 @@ function sameRefs(left, right) {
|
|
|
13063
13384
|
|
|
13064
13385
|
// src/cli/commands/update.ts
|
|
13065
13386
|
import * as p34 from "@clack/prompts";
|
|
13066
|
-
import { existsSync as existsSync26, readFileSync as
|
|
13067
|
-
import { join as join24, resolve as
|
|
13387
|
+
import { existsSync as existsSync26, readFileSync as readFileSync29, writeFileSync as writeFileSync10 } from "fs";
|
|
13388
|
+
import { join as join24, resolve as resolve20 } from "path";
|
|
13068
13389
|
var REGISTRY = "https://registry.npmjs.org/deepspace/latest";
|
|
13069
13390
|
var DOCS_URL = "https://documentation.deep.space/cli-reference/commands";
|
|
13070
13391
|
var OLDEST_SUPPORTED_MINOR = 12;
|
|
@@ -13080,17 +13401,17 @@ function gapIsTooWide(from, to) {
|
|
|
13080
13401
|
function readAppSdkVersion(appDir) {
|
|
13081
13402
|
const installed = join24(appDir, "node_modules", "deepspace", "package.json");
|
|
13082
13403
|
if (existsSync26(installed)) {
|
|
13083
|
-
const parsed2 = JSON.parse(
|
|
13404
|
+
const parsed2 = JSON.parse(readFileSync29(installed, "utf8"));
|
|
13084
13405
|
if (typeof parsed2.version === "string") return parsed2.version;
|
|
13085
13406
|
}
|
|
13086
13407
|
const manifest = join24(appDir, "package.json");
|
|
13087
13408
|
if (!existsSync26(manifest)) return null;
|
|
13088
|
-
const parsed = JSON.parse(
|
|
13409
|
+
const parsed = JSON.parse(readFileSync29(manifest, "utf8"));
|
|
13089
13410
|
return parsed.dependencies?.deepspace ?? null;
|
|
13090
13411
|
}
|
|
13091
13412
|
function pinSdkVersion(appDir, version) {
|
|
13092
13413
|
const path = join24(appDir, "package.json");
|
|
13093
|
-
const source =
|
|
13414
|
+
const source = readFileSync29(path, "utf8");
|
|
13094
13415
|
const updated = source.replace(
|
|
13095
13416
|
/("deepspace"\s*:\s*")[^"]+(")/,
|
|
13096
13417
|
(_match, head, tail) => `${head}^${version}${tail}`
|
|
@@ -13155,7 +13476,7 @@ var update_default = defineDeepspaceCommand({
|
|
|
13155
13476
|
}
|
|
13156
13477
|
},
|
|
13157
13478
|
async run({ args }) {
|
|
13158
|
-
const appDir =
|
|
13479
|
+
const appDir = resolve20(".");
|
|
13159
13480
|
if (!hasWranglerConfig(appDir)) {
|
|
13160
13481
|
throw new Refusal(
|
|
13161
13482
|
"No wrangler.toml found \u2014 run this from inside a DeepSpace app directory.",
|
|
@@ -13235,8 +13556,8 @@ var update_default = defineDeepspaceCommand({
|
|
|
13235
13556
|
});
|
|
13236
13557
|
|
|
13237
13558
|
// src/cli/cli.ts
|
|
13238
|
-
var __dirname =
|
|
13239
|
-
var pkg = JSON.parse(
|
|
13559
|
+
var __dirname = dirname11(fileURLToPath3(import.meta.url));
|
|
13560
|
+
var pkg = JSON.parse(readFileSync30(join25(__dirname, "..", "package.json"), "utf-8"));
|
|
13240
13561
|
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync27("/etc/ssl/certs/ca-certificates.crt")) {
|
|
13241
13562
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
13242
13563
|
}
|
|
@@ -13363,7 +13684,9 @@ function assertKnownCommandPath(argv) {
|
|
|
13363
13684
|
`${unknownCommandMessage(unknown)}
|
|
13364
13685
|
Run \`${unknown.helpPath.join(" ")} --help\` for the command list.`
|
|
13365
13686
|
);
|
|
13366
|
-
if (unknown.executable)
|
|
13687
|
+
if (unknown.executable) {
|
|
13688
|
+
printAction(executableAction({ cwd: process.cwd(), argv: unknown.suggestion }));
|
|
13689
|
+
}
|
|
13367
13690
|
process.exit(1);
|
|
13368
13691
|
}
|
|
13369
13692
|
var rawArgs = process.argv.slice(2);
|
|
@@ -13385,7 +13708,7 @@ if (rawArgs.includes("--json") && !wantsHelp) {
|
|
|
13385
13708
|
ok: false,
|
|
13386
13709
|
code: "unknown_command",
|
|
13387
13710
|
error: unknownCommandMessage(unknown),
|
|
13388
|
-
...unknown.executable ? { action: { cwd: process.cwd(), argv: unknown.suggestion } } : {}
|
|
13711
|
+
...unknown.executable ? { action: executableAction({ cwd: process.cwd(), argv: unknown.suggestion }) } : {}
|
|
13389
13712
|
})
|
|
13390
13713
|
);
|
|
13391
13714
|
process.exit(1);
|