deepspace 0.15.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 +118 -0
- package/dist/cli.js +562 -237
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +26 -157
- package/dist/index.js +209 -331
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +28 -154
- package/dist/server.js +38 -426
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +44 -227
- package/dist/worker.js +39 -433
- 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
|
|
@@ -3911,13 +3938,15 @@ function planUploadParts(totalBytes, partSize) {
|
|
|
3911
3938
|
}
|
|
3912
3939
|
return parts;
|
|
3913
3940
|
}
|
|
3914
|
-
var
|
|
3941
|
+
var GIB = 1024 * 1024 * 1024;
|
|
3942
|
+
var ACCOUNT_STORAGE_LIMIT_BYTES = {
|
|
3915
3943
|
test: 0,
|
|
3916
|
-
free:
|
|
3917
|
-
starter:
|
|
3918
|
-
premium:
|
|
3919
|
-
admin:
|
|
3944
|
+
free: 1 * GIB,
|
|
3945
|
+
starter: 10 * GIB,
|
|
3946
|
+
premium: 30 * GIB,
|
|
3947
|
+
admin: 100 * GIB
|
|
3920
3948
|
};
|
|
3949
|
+
var REPO_STORE_LIMIT_BYTES = 256 * 1024 * 1024;
|
|
3921
3950
|
var MAX_DEPLOY_ASSET_FILE_BYTES = 25 * 1024 * 1024;
|
|
3922
3951
|
var DANGEROUS_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
3923
3952
|
"text/html",
|
|
@@ -3968,11 +3997,11 @@ function describeFilesFailure(status3, body) {
|
|
|
3968
3997
|
import * as p6 from "@clack/prompts";
|
|
3969
3998
|
import { execSync as execSync2 } from "child_process";
|
|
3970
3999
|
import { createHash as createHash2 } from "crypto";
|
|
3971
|
-
import { existsSync as existsSync15, readFileSync as
|
|
3972
|
-
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";
|
|
3973
4002
|
|
|
3974
4003
|
// src/documentation/deploy.ts
|
|
3975
|
-
import { existsSync as existsSync13, readFileSync as
|
|
4004
|
+
import { existsSync as existsSync13, readFileSync as readFileSync16 } from "fs";
|
|
3976
4005
|
import { join as join14 } from "path";
|
|
3977
4006
|
function readDocumentationDeployManifest(appDir, clientDir) {
|
|
3978
4007
|
if (!existsSync13(join14(appDir, "documentation.json"))) return void 0;
|
|
@@ -3982,7 +4011,7 @@ function readDocumentationDeployManifest(appDir, clientDir) {
|
|
|
3982
4011
|
"documentation.json exists but the build produced no documentation manifest. Ensure vite.config.ts includes deepSpaceDocumentation() from deepspace/documentation."
|
|
3983
4012
|
);
|
|
3984
4013
|
}
|
|
3985
|
-
return JSON.parse(
|
|
4014
|
+
return JSON.parse(readFileSync16(manifestPath, "utf8"));
|
|
3986
4015
|
}
|
|
3987
4016
|
|
|
3988
4017
|
// src/cli/commands/update/app-migrations.ts
|
|
@@ -3994,7 +4023,7 @@ import {
|
|
|
3994
4023
|
ftruncateSync,
|
|
3995
4024
|
lstatSync,
|
|
3996
4025
|
openSync,
|
|
3997
|
-
readFileSync as
|
|
4026
|
+
readFileSync as readFileSync17,
|
|
3998
4027
|
writeSync
|
|
3999
4028
|
} from "fs";
|
|
4000
4029
|
import { join as join15 } from "path";
|
|
@@ -4139,7 +4168,7 @@ function readRegularFile(path) {
|
|
|
4139
4168
|
if (!opened.isFile() || opened.dev !== after.dev || opened.ino !== after.ino) {
|
|
4140
4169
|
throw new Error(`Migration input changed while opening: ${path}`);
|
|
4141
4170
|
}
|
|
4142
|
-
return
|
|
4171
|
+
return readFileSync17(fd, "utf-8");
|
|
4143
4172
|
} finally {
|
|
4144
4173
|
closeSync(fd);
|
|
4145
4174
|
}
|
|
@@ -4165,7 +4194,7 @@ function writeRegularFile(path, before, after) {
|
|
|
4165
4194
|
if (!opened.isFile() || opened.dev !== currentPath.dev || opened.ino !== currentPath.ino) {
|
|
4166
4195
|
throw new Error(`Migration input changed while opening: ${path}`);
|
|
4167
4196
|
}
|
|
4168
|
-
if (
|
|
4197
|
+
if (readFileSync17(fd, "utf-8") !== before) {
|
|
4169
4198
|
throw new Error(`Migration input changed after planning: ${path}`);
|
|
4170
4199
|
}
|
|
4171
4200
|
ftruncateSync(fd, 0);
|
|
@@ -4288,12 +4317,12 @@ async function buildDeployBundle(options) {
|
|
|
4288
4317
|
"build_output_missing"
|
|
4289
4318
|
);
|
|
4290
4319
|
}
|
|
4291
|
-
const deployConfig = JSON.parse(
|
|
4292
|
-
const outputWranglerPath =
|
|
4320
|
+
const deployConfig = JSON.parse(readFileSync18(deployConfigPath, "utf-8"));
|
|
4321
|
+
const outputWranglerPath = resolve11(dirname6(deployConfigPath), deployConfig.configPath);
|
|
4293
4322
|
if (!existsSync15(outputWranglerPath)) {
|
|
4294
4323
|
output.die(`Output wrangler.json not found at ${outputWranglerPath}`, "build_output_missing");
|
|
4295
4324
|
}
|
|
4296
|
-
const outputConfig = JSON.parse(
|
|
4325
|
+
const outputConfig = JSON.parse(readFileSync18(outputWranglerPath, "utf-8"));
|
|
4297
4326
|
if (outputConfig.name && outputConfig.name !== appName) {
|
|
4298
4327
|
const envHint = envName ? ` (--env ${envName})` : "";
|
|
4299
4328
|
output.die(
|
|
@@ -4301,9 +4330,9 @@ async function buildDeployBundle(options) {
|
|
|
4301
4330
|
"build_output_mismatch"
|
|
4302
4331
|
);
|
|
4303
4332
|
}
|
|
4304
|
-
const workerDir =
|
|
4333
|
+
const workerDir = dirname6(outputWranglerPath);
|
|
4305
4334
|
const workerBundlePath = join16(workerDir, outputConfig.main);
|
|
4306
|
-
const clientDir = outputConfig.assets?.directory ?
|
|
4335
|
+
const clientDir = outputConfig.assets?.directory ? resolve11(workerDir, outputConfig.assets.directory) : null;
|
|
4307
4336
|
if (!existsSync15(workerBundlePath)) {
|
|
4308
4337
|
output.die(`Worker bundle not found at ${workerBundlePath}`, "build_output_missing");
|
|
4309
4338
|
}
|
|
@@ -4320,7 +4349,7 @@ async function buildDeployBundle(options) {
|
|
|
4320
4349
|
const assets = collectAssets(clientDir);
|
|
4321
4350
|
const assetConfig = readDeployAssetConfig(clientDir);
|
|
4322
4351
|
spinner2.stop(`Collected ${assets.length} assets`);
|
|
4323
|
-
const workerJs =
|
|
4352
|
+
const workerJs = readFileSync18(workerBundlePath, "utf-8");
|
|
4324
4353
|
const doBindings = outputConfig.durable_objects?.bindings;
|
|
4325
4354
|
const sqliteClasses = new Set(
|
|
4326
4355
|
outputConfig.migrations?.flatMap((migration) => migration.new_sqlite_classes ?? []) ?? []
|
|
@@ -4399,7 +4428,7 @@ function collectAssets(dir) {
|
|
|
4399
4428
|
if (entry.isDirectory()) {
|
|
4400
4429
|
walk(fullPath, relativePath);
|
|
4401
4430
|
} else {
|
|
4402
|
-
const bytes =
|
|
4431
|
+
const bytes = readFileSync18(fullPath);
|
|
4403
4432
|
assets.push({
|
|
4404
4433
|
path: `/${relativePath}`,
|
|
4405
4434
|
hash: createHash2("sha256").update(bytes).digest("hex"),
|
|
@@ -4417,7 +4446,7 @@ function readDeployAssetConfig(clientDir) {
|
|
|
4417
4446
|
for (const [file, key] of [["_headers", "_headers"], ["_redirects", "_redirects"]]) {
|
|
4418
4447
|
const filePath = join16(clientDir, file);
|
|
4419
4448
|
if (!existsSync15(filePath)) continue;
|
|
4420
|
-
const content =
|
|
4449
|
+
const content = readFileSync18(filePath, "utf8");
|
|
4421
4450
|
if (content.trim()) config[key] = content;
|
|
4422
4451
|
}
|
|
4423
4452
|
return config;
|
|
@@ -4670,19 +4699,20 @@ function createDeployOutput(json) {
|
|
|
4670
4699
|
introShown = true;
|
|
4671
4700
|
},
|
|
4672
4701
|
die(message, code, opts = {}) {
|
|
4702
|
+
const action = opts.action ? executableAction(opts.action) : void 0;
|
|
4673
4703
|
if (json) {
|
|
4674
4704
|
emitJson({
|
|
4675
4705
|
ok: false,
|
|
4676
4706
|
code,
|
|
4677
4707
|
error: message,
|
|
4678
4708
|
...opts.actionRequired ? { actionRequired: true } : {},
|
|
4679
|
-
...
|
|
4709
|
+
...action ? { action } : {}
|
|
4680
4710
|
});
|
|
4681
4711
|
} else {
|
|
4682
4712
|
if (introShown && opts.actionRequired) p8.log.warn(withSlug(message, code));
|
|
4683
4713
|
else if (introShown) p8.cancel(withSlug(message, code));
|
|
4684
4714
|
else console.error(withSlug(message, code));
|
|
4685
|
-
if (
|
|
4715
|
+
if (action) printAction(action);
|
|
4686
4716
|
}
|
|
4687
4717
|
process.exit(opts.actionRequired ? 2 : 1);
|
|
4688
4718
|
}
|
|
@@ -4691,7 +4721,7 @@ function createDeployOutput(json) {
|
|
|
4691
4721
|
|
|
4692
4722
|
// src/cli/commands/deploy/request.ts
|
|
4693
4723
|
import * as p10 from "@clack/prompts";
|
|
4694
|
-
import { readFileSync as
|
|
4724
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
4695
4725
|
|
|
4696
4726
|
// src/cli/commands/deploy/repository.ts
|
|
4697
4727
|
import * as p9 from "@clack/prompts";
|
|
@@ -4884,7 +4914,7 @@ function repoApi(deployUrl, token, appId) {
|
|
|
4884
4914
|
// src/cli/lib/vc-remote.ts
|
|
4885
4915
|
import { existsSync as existsSync17 } from "fs";
|
|
4886
4916
|
import { tmpdir } from "os";
|
|
4887
|
-
import { isAbsolute as isAbsolute3, relative, resolve as
|
|
4917
|
+
import { isAbsolute as isAbsolute3, relative, resolve as resolve12 } from "path";
|
|
4888
4918
|
function spaceRemoteName(environment = DEEPSPACE_ENV) {
|
|
4889
4919
|
if (environment === "staging") return "space-staging";
|
|
4890
4920
|
if (environment === "production") return "space";
|
|
@@ -4930,7 +4960,7 @@ function entryIsTransient(cwd) {
|
|
|
4930
4960
|
const entry = process.argv[1];
|
|
4931
4961
|
if (!entry) return true;
|
|
4932
4962
|
if (/[\\/]_npx[\\/]/.test(entry) || entry.startsWith(tmpdir())) return true;
|
|
4933
|
-
const rel = relative(
|
|
4963
|
+
const rel = relative(resolve12(cwd), resolve12(entry));
|
|
4934
4964
|
return rel === "" || !rel.startsWith("..") && !isAbsolute3(rel);
|
|
4935
4965
|
}
|
|
4936
4966
|
function helperEntryUsable(command) {
|
|
@@ -5003,6 +5033,25 @@ function ensureSpaceRemote(cwd, appId, remote = SPACE_REMOTE) {
|
|
|
5003
5033
|
installCredentialHelper(cwd, url);
|
|
5004
5034
|
return url;
|
|
5005
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
|
+
}
|
|
5006
5055
|
function appIdFromRepoUrl(url) {
|
|
5007
5056
|
const match = /\/api\/repo\/([^/]+)\/?$/.exec(url);
|
|
5008
5057
|
return match ? decodeURIComponent(match[1]) : null;
|
|
@@ -5418,7 +5467,7 @@ async function pushWithTransientRetry(push) {
|
|
|
5418
5467
|
const message = errorMessage3(error);
|
|
5419
5468
|
const transient = /(?:HTTP |error: )(?:429|503)\b/i.test(message);
|
|
5420
5469
|
if (transient && attempt < backoffMs.length && Date.now() + backoffMs[attempt] < deadline) {
|
|
5421
|
-
await new Promise((
|
|
5470
|
+
await new Promise((resolve21) => setTimeout(resolve21, backoffMs[attempt]));
|
|
5422
5471
|
continue;
|
|
5423
5472
|
}
|
|
5424
5473
|
throw error;
|
|
@@ -5458,6 +5507,7 @@ async function deployBuiltBundle(options) {
|
|
|
5458
5507
|
appId,
|
|
5459
5508
|
appName,
|
|
5460
5509
|
token,
|
|
5510
|
+
claimReleased,
|
|
5461
5511
|
ignoreStale,
|
|
5462
5512
|
bundle,
|
|
5463
5513
|
secrets,
|
|
@@ -5475,7 +5525,8 @@ async function deployBuiltBundle(options) {
|
|
|
5475
5525
|
await uploadDeployAssets({ deployUrl, appId, token, assets: bundle.assets, output, spinner: spinner2 });
|
|
5476
5526
|
spinner2.message(`Deploying ${appName}...`);
|
|
5477
5527
|
let confirmRename = options.rename;
|
|
5478
|
-
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;
|
|
5479
5530
|
if (stopLabel !== null) spinner2.stop(stopLabel);
|
|
5480
5531
|
p10.cancel(code ? withSlug(message, code) : message);
|
|
5481
5532
|
if (action) printAction(action);
|
|
@@ -5521,6 +5572,7 @@ async function deployBuiltBundle(options) {
|
|
|
5521
5572
|
}
|
|
5522
5573
|
form.append("name", appName);
|
|
5523
5574
|
if (confirmRename) form.append("confirmRename", "true");
|
|
5575
|
+
if (claimReleased) form.append("claimReleased", "true");
|
|
5524
5576
|
if (shouldSendLineage(repository.commitOid, repository.recoverable)) {
|
|
5525
5577
|
form.append("commitOid", repository.commitOid);
|
|
5526
5578
|
}
|
|
@@ -5694,7 +5746,7 @@ async function uploadDeployAssets(options) {
|
|
|
5694
5746
|
// against the plan before it touches storage, and a stream body
|
|
5695
5747
|
// would be sent chunked with no length at all; a retry also needs a
|
|
5696
5748
|
// body it can send again.
|
|
5697
|
-
body:
|
|
5749
|
+
body: readFileSync19(asset.sourcePath)
|
|
5698
5750
|
})
|
|
5699
5751
|
);
|
|
5700
5752
|
if (!response.ok) {
|
|
@@ -5772,7 +5824,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5772
5824
|
lastError = error;
|
|
5773
5825
|
}
|
|
5774
5826
|
if (attempt < attempts) {
|
|
5775
|
-
await new Promise((
|
|
5827
|
+
await new Promise((resolve21) => setTimeout(resolve21, Math.min(8e3, 500 * 2 ** (attempt - 1))));
|
|
5776
5828
|
}
|
|
5777
5829
|
}
|
|
5778
5830
|
if (lastResponse) return lastResponse;
|
|
@@ -5781,7 +5833,7 @@ async function postWithRetry(url, makeInit, {
|
|
|
5781
5833
|
|
|
5782
5834
|
// src/cli/commands/deploy/secrets.ts
|
|
5783
5835
|
import * as p11 from "@clack/prompts";
|
|
5784
|
-
import { existsSync as existsSync18, readFileSync as
|
|
5836
|
+
import { existsSync as existsSync18, readFileSync as readFileSync20 } from "fs";
|
|
5785
5837
|
function classifyDevVarsSecrets(options) {
|
|
5786
5838
|
const store = new Set(options.storeSecretNames);
|
|
5787
5839
|
const strayKeys = options.handEditedDevVarKeys.filter((key) => !store.has(key));
|
|
@@ -5880,7 +5932,7 @@ function prepareDeploySecrets(options) {
|
|
|
5880
5932
|
}
|
|
5881
5933
|
function readCustomDevVars(path, output) {
|
|
5882
5934
|
if (!existsSync18(path)) return {};
|
|
5883
|
-
const section = extractCustomDevVars(stripGeneratedSecretsCache(
|
|
5935
|
+
const section = extractCustomDevVars(stripGeneratedSecretsCache(readFileSync20(path, "utf-8")));
|
|
5884
5936
|
if (!section) return {};
|
|
5885
5937
|
try {
|
|
5886
5938
|
return parseDevVars(section);
|
|
@@ -5920,6 +5972,11 @@ var deploy_default = defineCommand3({
|
|
|
5920
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.",
|
|
5921
5973
|
default: false
|
|
5922
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
|
+
},
|
|
5923
5980
|
"allow-missing-secrets": {
|
|
5924
5981
|
type: "boolean",
|
|
5925
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).",
|
|
@@ -5945,7 +6002,7 @@ var deploy_default = defineCommand3({
|
|
|
5945
6002
|
async run({ args }) {
|
|
5946
6003
|
const output = createDeployOutput(args.json === true);
|
|
5947
6004
|
preflightNodeVersion("deploy");
|
|
5948
|
-
const appDir =
|
|
6005
|
+
const appDir = resolve13(args.dir ?? ".");
|
|
5949
6006
|
const selectorRefusal = blankSelectorRefusal(args);
|
|
5950
6007
|
if (selectorRefusal) output.die(selectorRefusal.error, selectorRefusal.code);
|
|
5951
6008
|
const envName = typeof args.env === "string" && args.env.trim() ? args.env.trim() : void 0;
|
|
@@ -6033,6 +6090,7 @@ var deploy_default = defineCommand3({
|
|
|
6033
6090
|
appName,
|
|
6034
6091
|
token,
|
|
6035
6092
|
rename: args.rename === true,
|
|
6093
|
+
claimReleased: args["claim-released"] === true,
|
|
6036
6094
|
ignoreStale: Boolean(args["ignore-stale"]),
|
|
6037
6095
|
bundle,
|
|
6038
6096
|
secrets,
|
|
@@ -6061,10 +6119,7 @@ var deploy_default = defineCommand3({
|
|
|
6061
6119
|
url: body.url,
|
|
6062
6120
|
releaseId: body.releaseId ?? null,
|
|
6063
6121
|
bundleRetained: body.bundleRetained ?? null,
|
|
6064
|
-
// `serving` says what was actually established; `edgePropagating`
|
|
6065
|
-
// stays for callers written against the old shape.
|
|
6066
6122
|
serving,
|
|
6067
|
-
edgePropagating: serving === "unconfirmed",
|
|
6068
6123
|
recoverable: repository.recoverable,
|
|
6069
6124
|
...staleBaseGuardFields(body)
|
|
6070
6125
|
});
|
|
@@ -6083,7 +6138,7 @@ var deploy_default = defineCommand3({
|
|
|
6083
6138
|
appName,
|
|
6084
6139
|
url: body.url ?? null,
|
|
6085
6140
|
// Always present, so a caller branches on one field instead of
|
|
6086
|
-
// inferring success from
|
|
6141
|
+
// inferring success from an absent one.
|
|
6087
6142
|
serving,
|
|
6088
6143
|
releaseId: body.releaseId ?? null,
|
|
6089
6144
|
bundleRetained: body.bundleRetained ?? null,
|
|
@@ -6763,8 +6818,8 @@ var usage_default = defineDeepspaceCommand({
|
|
|
6763
6818
|
});
|
|
6764
6819
|
|
|
6765
6820
|
// src/cli/commands/add.ts
|
|
6766
|
-
import { existsSync as existsSync20, readFileSync as
|
|
6767
|
-
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";
|
|
6768
6823
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6769
6824
|
|
|
6770
6825
|
// src/cli/commands/feature-installer.ts
|
|
@@ -6776,7 +6831,7 @@ import {
|
|
|
6776
6831
|
mkdirSync as mkdirSync6,
|
|
6777
6832
|
mkdtempSync,
|
|
6778
6833
|
openSync as openSync2,
|
|
6779
|
-
readFileSync as
|
|
6834
|
+
readFileSync as readFileSync21,
|
|
6780
6835
|
readSync,
|
|
6781
6836
|
readdirSync as readdirSync5,
|
|
6782
6837
|
rmSync as rmSync4,
|
|
@@ -6784,21 +6839,21 @@ import {
|
|
|
6784
6839
|
} from "fs";
|
|
6785
6840
|
import { spawnSync as spawnSync6 } from "child_process";
|
|
6786
6841
|
import { tmpdir as tmpdir2 } from "os";
|
|
6787
|
-
import { dirname as
|
|
6842
|
+
import { dirname as dirname7, isAbsolute as isAbsolute4, join as join18, resolve as resolve14 } from "path";
|
|
6788
6843
|
import { fileURLToPath } from "url";
|
|
6789
6844
|
var NAV_MARKER = "// \u2500\u2500 Features add nav items below this line \u2500\u2500";
|
|
6790
6845
|
function featurePackageRoot(moduleUrl = import.meta.url) {
|
|
6791
|
-
let dir =
|
|
6846
|
+
let dir = dirname7(fileURLToPath(moduleUrl));
|
|
6792
6847
|
for (; ; ) {
|
|
6793
6848
|
const packagePath = join18(dir, "package.json");
|
|
6794
6849
|
if (existsSync19(packagePath)) {
|
|
6795
6850
|
try {
|
|
6796
|
-
const pkg2 = JSON.parse(
|
|
6851
|
+
const pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
|
|
6797
6852
|
if (pkg2.name === "deepspace") return dir;
|
|
6798
6853
|
} catch {
|
|
6799
6854
|
}
|
|
6800
6855
|
}
|
|
6801
|
-
const parent =
|
|
6856
|
+
const parent = dirname7(dir);
|
|
6802
6857
|
if (parent === dir) throw new Error("Could not locate the deepspace package root");
|
|
6803
6858
|
dir = parent;
|
|
6804
6859
|
}
|
|
@@ -6810,7 +6865,7 @@ function readFeatureConfig(id, packageRoot = featurePackageRoot()) {
|
|
|
6810
6865
|
const configPath = join18(packageRoot, "features", id, "feature.json");
|
|
6811
6866
|
if (!existsSync19(configPath)) return null;
|
|
6812
6867
|
try {
|
|
6813
|
-
const config = JSON.parse(
|
|
6868
|
+
const config = JSON.parse(readFileSync21(configPath, "utf-8"));
|
|
6814
6869
|
if (typeof config.id !== "string" || typeof config.name !== "string" || !Array.isArray(config.files)) {
|
|
6815
6870
|
return null;
|
|
6816
6871
|
}
|
|
@@ -6859,7 +6914,7 @@ function suggestFeature(featureId, packageRoot = featurePackageRoot()) {
|
|
|
6859
6914
|
return closest !== null && closestDistance <= threshold ? closest : null;
|
|
6860
6915
|
}
|
|
6861
6916
|
function resolveTargetDir(raw) {
|
|
6862
|
-
return isAbsolute4(raw) ? raw :
|
|
6917
|
+
return isAbsolute4(raw) ? raw : resolve14(raw);
|
|
6863
6918
|
}
|
|
6864
6919
|
function resolveFeatureDestPath(fileDest, route) {
|
|
6865
6920
|
const pages = "src/pages/";
|
|
@@ -6869,13 +6924,13 @@ function resolveFeatureDestPath(fileDest, route) {
|
|
|
6869
6924
|
return route?.protected === false ? `${appPages}${rest}` : `${appPages}(protected)/${rest}`;
|
|
6870
6925
|
}
|
|
6871
6926
|
function copyFile(src, dest) {
|
|
6872
|
-
mkdirSync6(
|
|
6927
|
+
mkdirSync6(dirname7(dest), { recursive: true });
|
|
6873
6928
|
copyFileSync(src, dest);
|
|
6874
6929
|
}
|
|
6875
6930
|
function copyFileWithImportShift(src, dest, levels) {
|
|
6876
|
-
mkdirSync6(
|
|
6931
|
+
mkdirSync6(dirname7(dest), { recursive: true });
|
|
6877
6932
|
const prefix = "../".repeat(levels);
|
|
6878
|
-
const shifted =
|
|
6933
|
+
const shifted = readFileSync21(src, "utf-8").replace(
|
|
6879
6934
|
/(from\s+|import\s+|import\()(['"])(\.\.\/)/g,
|
|
6880
6935
|
`$1$2${prefix}$3`
|
|
6881
6936
|
);
|
|
@@ -6934,7 +6989,7 @@ function integrateSchema(config, targetDir, emit) {
|
|
|
6934
6989
|
if (!existsSync19(schemasPath)) {
|
|
6935
6990
|
return [unresolvedSchema(config.schema, "src/schemas.ts was not found.", emit)];
|
|
6936
6991
|
}
|
|
6937
|
-
let content =
|
|
6992
|
+
let content = readFileSync21(schemasPath, "utf-8");
|
|
6938
6993
|
const { exportName, importPath, spreadOperator } = config.schema;
|
|
6939
6994
|
const importPattern = new RegExp(`^import\\s+\\{[^}]*\\b${exportName}\\b`, "m");
|
|
6940
6995
|
if (importPattern.test(content)) {
|
|
@@ -6991,7 +7046,7 @@ function integrateActions(config, targetDir, emit) {
|
|
|
6991
7046
|
if (!existsSync19(actionsPath)) {
|
|
6992
7047
|
return [unresolvedActions(config.actions, "src/actions/index.ts was not found.", emit)];
|
|
6993
7048
|
}
|
|
6994
|
-
let content =
|
|
7049
|
+
let content = readFileSync21(actionsPath, "utf-8");
|
|
6995
7050
|
const registryPattern = /export const actions:\s*Record<string,\s*ActionHandler(?:<[^>]*>)?>\s*=\s*\{/;
|
|
6996
7051
|
if (!registryPattern.test(content)) {
|
|
6997
7052
|
const reason = "src/actions/index.ts has an unexpected structure.";
|
|
@@ -7046,7 +7101,7 @@ function integrateCode(config, targetDir, emit) {
|
|
|
7046
7101
|
});
|
|
7047
7102
|
continue;
|
|
7048
7103
|
}
|
|
7049
|
-
const original =
|
|
7104
|
+
const original = readFileSync21(targetPath, "utf-8");
|
|
7050
7105
|
if (original.includes(insertion.insert.trim())) {
|
|
7051
7106
|
emit(` Integration already present: ${insertion.file}`);
|
|
7052
7107
|
continue;
|
|
@@ -7082,7 +7137,7 @@ ${content.slice(importIndex < 0 ? 0 : importIndex)}`;
|
|
|
7082
7137
|
function integrateIgnore(config, targetDir) {
|
|
7083
7138
|
if (!config.ignore?.length) return;
|
|
7084
7139
|
const targetPath = join18(targetDir, ".gitignore");
|
|
7085
|
-
const current = existsSync19(targetPath) ?
|
|
7140
|
+
const current = existsSync19(targetPath) ? readFileSync21(targetPath, "utf-8") : "";
|
|
7086
7141
|
const present = new Set(current.split(/\r?\n/).map((line) => line.trim()));
|
|
7087
7142
|
const missing = config.ignore.filter((pattern) => !present.has(pattern));
|
|
7088
7143
|
if (missing.length === 0) return;
|
|
@@ -7102,7 +7157,7 @@ function integrateWrangler(config, targetDir, emit) {
|
|
|
7102
7157
|
if (!existsSync19(targetPath)) {
|
|
7103
7158
|
return [{ area: "wrangler", reason: "wrangler.toml was not found.", steps }];
|
|
7104
7159
|
}
|
|
7105
|
-
let source =
|
|
7160
|
+
let source = readFileSync21(targetPath, "utf-8");
|
|
7106
7161
|
if (runWorkerFirst && !/^\[assets\]\s*$/m.test(source)) {
|
|
7107
7162
|
return [{ area: "wrangler", reason: "wrangler.toml has no [assets] section.", steps }];
|
|
7108
7163
|
}
|
|
@@ -7191,7 +7246,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
7191
7246
|
}
|
|
7192
7247
|
];
|
|
7193
7248
|
}
|
|
7194
|
-
let styles =
|
|
7249
|
+
let styles = readFileSync21(stylesPath, "utf-8");
|
|
7195
7250
|
let integrated = 0;
|
|
7196
7251
|
const unresolved = [];
|
|
7197
7252
|
for (const cssFile of config.css) {
|
|
@@ -7205,7 +7260,7 @@ function integrateCss(packageRoot, config, targetDir, emit) {
|
|
|
7205
7260
|
});
|
|
7206
7261
|
continue;
|
|
7207
7262
|
}
|
|
7208
|
-
const css =
|
|
7263
|
+
const css = readFileSync21(srcPath, "utf-8");
|
|
7209
7264
|
const fingerprint = css.match(/\.([\w-]+)\s*\{|@keyframes\s+([\w-]+)/);
|
|
7210
7265
|
const marker = fingerprint?.[1] ?? fingerprint?.[2];
|
|
7211
7266
|
if (marker && styles.includes(marker)) {
|
|
@@ -7236,7 +7291,7 @@ function integrateRoute(config, targetDir, emit) {
|
|
|
7236
7291
|
if (!existsSync19(navPath)) {
|
|
7237
7292
|
return [unresolvedRoute(config.route, config, "src/nav.ts was not found.", emit)];
|
|
7238
7293
|
}
|
|
7239
|
-
let content =
|
|
7294
|
+
let content = readFileSync21(navPath, "utf-8");
|
|
7240
7295
|
const routePath = config.route.path;
|
|
7241
7296
|
if (content.includes(`'${routePath}'`)) {
|
|
7242
7297
|
emit(` Nav already present: ${routePath}`);
|
|
@@ -7317,7 +7372,7 @@ function integrateDependencies(config, targetDir, runInstall, outputVisible, emi
|
|
|
7317
7372
|
}
|
|
7318
7373
|
let pkg2;
|
|
7319
7374
|
try {
|
|
7320
|
-
pkg2 = JSON.parse(
|
|
7375
|
+
pkg2 = JSON.parse(readFileSync21(packagePath, "utf-8"));
|
|
7321
7376
|
} catch (error) {
|
|
7322
7377
|
emit(
|
|
7323
7378
|
` Could not patch package.json (parse error: ${error instanceof Error ? error.message : String(error)})`
|
|
@@ -7377,7 +7432,7 @@ ${child.diagnosticTail}` : "";
|
|
|
7377
7432
|
}
|
|
7378
7433
|
function dependencySnapshot(targetDir) {
|
|
7379
7434
|
try {
|
|
7380
|
-
const pkg2 = JSON.parse(
|
|
7435
|
+
const pkg2 = JSON.parse(readFileSync21(join18(targetDir, "package.json"), "utf-8"));
|
|
7381
7436
|
return {
|
|
7382
7437
|
dependencies: pkg2.dependencies ?? {},
|
|
7383
7438
|
devDependencies: pkg2.devDependencies ?? {}
|
|
@@ -7626,7 +7681,7 @@ function isDeepSpaceApp(dir) {
|
|
|
7626
7681
|
const packagePath = join19(dir, "package.json");
|
|
7627
7682
|
if (!existsSync20(packagePath)) return false;
|
|
7628
7683
|
try {
|
|
7629
|
-
const pkg2 = JSON.parse(
|
|
7684
|
+
const pkg2 = JSON.parse(readFileSync22(packagePath, "utf-8"));
|
|
7630
7685
|
return Boolean(pkg2.dependencies?.deepspace || pkg2.devDependencies?.deepspace);
|
|
7631
7686
|
} catch {
|
|
7632
7687
|
return false;
|
|
@@ -7637,7 +7692,7 @@ function installedPackageRoot(fromDir) {
|
|
|
7637
7692
|
for (; ; ) {
|
|
7638
7693
|
const candidate = join19(dir, "node_modules", "deepspace");
|
|
7639
7694
|
if (existsSync20(join19(candidate, "package.json"))) return candidate;
|
|
7640
|
-
const parent =
|
|
7695
|
+
const parent = dirname8(dir);
|
|
7641
7696
|
if (parent === dir) return null;
|
|
7642
7697
|
dir = parent;
|
|
7643
7698
|
}
|
|
@@ -7650,7 +7705,7 @@ async function targetInstaller(appDir) {
|
|
|
7650
7705
|
"feature_installer_missing"
|
|
7651
7706
|
);
|
|
7652
7707
|
}
|
|
7653
|
-
if (
|
|
7708
|
+
if (realpathSync4(installedRoot) === realpathSync4(featurePackageRoot())) {
|
|
7654
7709
|
return { installFeature };
|
|
7655
7710
|
}
|
|
7656
7711
|
const entry = join19(installedRoot, "dist", "feature-installer.js");
|
|
@@ -7747,7 +7802,7 @@ var add_default = defineDeepspaceCommand({
|
|
|
7747
7802
|
}
|
|
7748
7803
|
return { data: { features: featureCatalog(root) } };
|
|
7749
7804
|
}
|
|
7750
|
-
const appDir =
|
|
7805
|
+
const appDir = resolve15(args.dir ?? ".");
|
|
7751
7806
|
if (!existsSync20(appDir)) {
|
|
7752
7807
|
throw new Refusal(
|
|
7753
7808
|
`Target directory not found: ${appDir}
|
|
@@ -7829,11 +7884,11 @@ function fmtDate(iso) {
|
|
|
7829
7884
|
}
|
|
7830
7885
|
async function confirm4(message) {
|
|
7831
7886
|
process.stdout.write(`${message} [y/N] `);
|
|
7832
|
-
return new Promise((
|
|
7887
|
+
return new Promise((resolve21) => {
|
|
7833
7888
|
process.stdin.setEncoding("utf-8");
|
|
7834
7889
|
process.stdin.once("data", (data) => {
|
|
7835
7890
|
const answer = data.toString().trim().toLowerCase();
|
|
7836
|
-
|
|
7891
|
+
resolve21(answer === "y" || answer === "yes");
|
|
7837
7892
|
});
|
|
7838
7893
|
});
|
|
7839
7894
|
}
|
|
@@ -8123,7 +8178,7 @@ var domain_default = defineCommand5({
|
|
|
8123
8178
|
|
|
8124
8179
|
// src/cli/commands/app-files.ts
|
|
8125
8180
|
import { defineCommand as defineCommand6 } from "citty";
|
|
8126
|
-
import { basename as basename4, resolve as
|
|
8181
|
+
import { basename as basename4, resolve as resolve16 } from "path";
|
|
8127
8182
|
import { existsSync as existsSync21, statSync as statSync2 } from "fs";
|
|
8128
8183
|
|
|
8129
8184
|
// src/cli/lib/app-files-api.ts
|
|
@@ -8324,7 +8379,7 @@ async function deleteAppFile(baseUrl, token, appId, key) {
|
|
|
8324
8379
|
const path = filesPath(appId, `/${encodeKeyPath(key)}`);
|
|
8325
8380
|
const res = await request(baseUrl, token, path, { method: "DELETE" });
|
|
8326
8381
|
const body = await readJson(res, path);
|
|
8327
|
-
return { existed: body.existed
|
|
8382
|
+
return { existed: body.existed };
|
|
8328
8383
|
}
|
|
8329
8384
|
async function downloadAppFile(baseUrl, token, appId, key, destination) {
|
|
8330
8385
|
const path = filesPath(appId, `/${encodeKeyPath(key)}`);
|
|
@@ -8394,7 +8449,7 @@ var put = defineDeepspaceCommand({
|
|
|
8394
8449
|
app: { type: "string", description: "App id or live name (defaults to ./wrangler.toml)" }
|
|
8395
8450
|
},
|
|
8396
8451
|
async run({ args }) {
|
|
8397
|
-
const localPath =
|
|
8452
|
+
const localPath = resolve16(String(args.file));
|
|
8398
8453
|
if (!existsSync21(localPath) || !statSync2(localPath).isFile()) {
|
|
8399
8454
|
throw new Refusal(`No such file: ${args.file}`, "file_not_found");
|
|
8400
8455
|
}
|
|
@@ -8495,7 +8550,7 @@ var get = defineDeepspaceCommand({
|
|
|
8495
8550
|
},
|
|
8496
8551
|
async run({ args }) {
|
|
8497
8552
|
const key = requireKey(String(args.key));
|
|
8498
|
-
const destination =
|
|
8553
|
+
const destination = resolve16(String(args.out ?? basename4(key)));
|
|
8499
8554
|
const { token, appId } = await target(args.app);
|
|
8500
8555
|
const result = await downloadAppFile(PLATFORM_URL, token, appId, key, destination);
|
|
8501
8556
|
if (!args.json) console.log(`\u2713 ${key} \u2192 ${destination} (${formatBytes(result.bytes)})`);
|
|
@@ -8865,7 +8920,7 @@ var transfer_default = defineCommand8({
|
|
|
8865
8920
|
import { defineCommand as defineCommand9 } from "citty";
|
|
8866
8921
|
|
|
8867
8922
|
// src/cli/commands/_invoke-impl.ts
|
|
8868
|
-
import { readFileSync as
|
|
8923
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
8869
8924
|
import * as p15 from "@clack/prompts";
|
|
8870
8925
|
var API_URL7 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
8871
8926
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
@@ -8906,7 +8961,7 @@ function resolveBody(opts) {
|
|
|
8906
8961
|
if (opts.body != null) {
|
|
8907
8962
|
raw = opts.body;
|
|
8908
8963
|
} else if (opts.bodyFile != null) {
|
|
8909
|
-
raw = opts.bodyFile === "-" ?
|
|
8964
|
+
raw = opts.bodyFile === "-" ? readFileSync23(0, "utf-8") : readFileSync23(opts.bodyFile, "utf-8");
|
|
8910
8965
|
} else {
|
|
8911
8966
|
return "{}";
|
|
8912
8967
|
}
|
|
@@ -9185,8 +9240,8 @@ var integrations_default = defineCommand9({
|
|
|
9185
9240
|
|
|
9186
9241
|
// src/cli/commands/feedback.ts
|
|
9187
9242
|
import * as p16 from "@clack/prompts";
|
|
9188
|
-
import { existsSync as existsSync22, readFileSync as
|
|
9189
|
-
import { dirname as
|
|
9243
|
+
import { existsSync as existsSync22, readFileSync as readFileSync24 } from "fs";
|
|
9244
|
+
import { dirname as dirname9, join as join20 } from "path";
|
|
9190
9245
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9191
9246
|
import { release } from "os";
|
|
9192
9247
|
var API_URL8 = process.env.DEEPSPACE_API_URL ?? PLATFORM_URLS.api;
|
|
@@ -9207,14 +9262,14 @@ function normalizeType(raw) {
|
|
|
9207
9262
|
}
|
|
9208
9263
|
function readCliVersion() {
|
|
9209
9264
|
try {
|
|
9210
|
-
const here =
|
|
9265
|
+
const here = dirname9(fileURLToPath2(import.meta.url));
|
|
9211
9266
|
const candidates = [
|
|
9212
9267
|
join20(here, "..", "package.json"),
|
|
9213
9268
|
join20(here, "..", "..", "..", "package.json")
|
|
9214
9269
|
];
|
|
9215
9270
|
for (const path of candidates) {
|
|
9216
9271
|
if (!existsSync22(path)) continue;
|
|
9217
|
-
const pkg2 = JSON.parse(
|
|
9272
|
+
const pkg2 = JSON.parse(readFileSync24(path, "utf-8"));
|
|
9218
9273
|
if (pkg2.name === "deepspace" && pkg2.version) return pkg2.version;
|
|
9219
9274
|
}
|
|
9220
9275
|
} catch {
|
|
@@ -9410,7 +9465,7 @@ Context: deepspace ${payload.cliVersion} \xB7 ${payload.nodeVersion} \xB7 ${payl
|
|
|
9410
9465
|
|
|
9411
9466
|
// src/cli/commands/secrets.ts
|
|
9412
9467
|
import { defineCommand as defineCommand10 } from "citty";
|
|
9413
|
-
import { readFileSync as
|
|
9468
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
9414
9469
|
|
|
9415
9470
|
// src/cli/lib/citty-args.ts
|
|
9416
9471
|
function dedupePositionals(bound, rest) {
|
|
@@ -9680,7 +9735,7 @@ var upload = defineCommand10({
|
|
|
9680
9735
|
async run({ args }) {
|
|
9681
9736
|
try {
|
|
9682
9737
|
const t = await resolveTarget(args);
|
|
9683
|
-
const content = args.file === "-" ?
|
|
9738
|
+
const content = args.file === "-" ? readFileSync25(0, "utf-8") : readFileSync25(args.file, "utf-8");
|
|
9684
9739
|
const secrets = parseSecretsUpload(content);
|
|
9685
9740
|
if (Object.keys(secrets).length === 0)
|
|
9686
9741
|
fail(new InputError("No secrets found in the input.", "empty_input"));
|
|
@@ -9936,7 +9991,7 @@ var init_default = defineDeepspaceCommand({
|
|
|
9936
9991
|
// src/cli/commands/status.ts
|
|
9937
9992
|
import { defineCommand as defineCommand11 } from "citty";
|
|
9938
9993
|
import * as p17 from "@clack/prompts";
|
|
9939
|
-
import { existsSync as existsSync23, readFileSync as
|
|
9994
|
+
import { existsSync as existsSync23, readFileSync as readFileSync26 } from "fs";
|
|
9940
9995
|
function timeAgo(iso) {
|
|
9941
9996
|
const ms = Date.now() - Date.parse(iso);
|
|
9942
9997
|
if (!Number.isFinite(ms) || ms < 0) return iso;
|
|
@@ -10030,7 +10085,7 @@ var status_default = defineCommand11({
|
|
|
10030
10085
|
let who = "logged in";
|
|
10031
10086
|
try {
|
|
10032
10087
|
const payload = decodeJwtPayload(
|
|
10033
|
-
|
|
10088
|
+
readFileSync26(TOKEN_PATH, "utf-8").trim()
|
|
10034
10089
|
);
|
|
10035
10090
|
if (payload.email) who = payload.email;
|
|
10036
10091
|
userId = payload.sub ?? null;
|
|
@@ -10182,21 +10237,24 @@ var status_default = defineCommand11({
|
|
|
10182
10237
|
}
|
|
10183
10238
|
const refs = refsResult.ok ? refsResult.value : void 0;
|
|
10184
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;
|
|
10185
10241
|
if (!facts.workspaceId && branch) {
|
|
10242
|
+
const isTrunk = defaultBranch === null ? null : branch === defaultBranch;
|
|
10243
|
+
const label = isTrunk === false ? "Branch sync" : "Trunk";
|
|
10186
10244
|
if (githubSource) {
|
|
10187
|
-
lines.push([
|
|
10188
|
-
json.trunk = { state: "external", provider: "github", branch };
|
|
10189
|
-
} 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);
|
|
10190
10248
|
else {
|
|
10191
10249
|
const remoteOid = trunkRef?.oid ?? null;
|
|
10192
10250
|
const localOid = resolveCommit(appDir, `refs/heads/${branch}`);
|
|
10193
10251
|
const remoteKnownLocally = remoteOid ? resolveCommit(appDir, remoteOid) !== null : false;
|
|
10194
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";
|
|
10195
10253
|
lines.push([
|
|
10196
|
-
|
|
10254
|
+
label,
|
|
10197
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)})`
|
|
10198
10256
|
]);
|
|
10199
|
-
json.trunk = { state: facts.trunkState, localOid, remoteOid };
|
|
10257
|
+
json.trunk = { state: facts.trunkState, localOid, remoteOid, branch, isTrunk };
|
|
10200
10258
|
}
|
|
10201
10259
|
}
|
|
10202
10260
|
if (!releaseResult.ok) reportRemoteFailure2("Live", "live", releaseResult.error);
|
|
@@ -10423,7 +10481,7 @@ var push_default = defineDeepspaceCommand({
|
|
|
10423
10481
|
|
|
10424
10482
|
// src/cli/commands/pull.ts
|
|
10425
10483
|
import * as p19 from "@clack/prompts";
|
|
10426
|
-
import { realpathSync as
|
|
10484
|
+
import { realpathSync as realpathSync5 } from "fs";
|
|
10427
10485
|
function targetedVcAction(command, cwd, appId, branch) {
|
|
10428
10486
|
return {
|
|
10429
10487
|
cwd,
|
|
@@ -10447,7 +10505,7 @@ function workspaceBranchPullRefusal(branch, trunkBranch) {
|
|
|
10447
10505
|
function worktreeHoldingBranch(worktrees, branch, selfPath) {
|
|
10448
10506
|
const real = (pth) => {
|
|
10449
10507
|
try {
|
|
10450
|
-
return
|
|
10508
|
+
return realpathSync5(pth);
|
|
10451
10509
|
} catch {
|
|
10452
10510
|
return pth;
|
|
10453
10511
|
}
|
|
@@ -10705,7 +10763,7 @@ var pull_default = defineDeepspaceCommand({
|
|
|
10705
10763
|
// src/cli/commands/clone.ts
|
|
10706
10764
|
import * as p20 from "@clack/prompts";
|
|
10707
10765
|
import { existsSync as existsSync24, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
|
|
10708
|
-
import { resolve as
|
|
10766
|
+
import { resolve as resolve17, basename as basename5, join as join21 } from "path";
|
|
10709
10767
|
function cleanFailedCloneDir(dir) {
|
|
10710
10768
|
let entries;
|
|
10711
10769
|
try {
|
|
@@ -10759,7 +10817,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10759
10817
|
async run({ args }) {
|
|
10760
10818
|
assertAppTargetResolvable(String(args.app));
|
|
10761
10819
|
const selector = String(args.app).trim();
|
|
10762
|
-
const dir =
|
|
10820
|
+
const dir = resolve17(String(args.dir ?? selector));
|
|
10763
10821
|
const dirPreexisted = validateCloneTarget(dir);
|
|
10764
10822
|
const spinner2 = args.json ? null : createSpinner();
|
|
10765
10823
|
spinner2?.start(`Resolving ${selector}\u2026`);
|
|
@@ -10799,6 +10857,7 @@ var clone_default = defineDeepspaceCommand({
|
|
|
10799
10857
|
throw err;
|
|
10800
10858
|
}
|
|
10801
10859
|
ensureSpaceRemote(dir, appId);
|
|
10860
|
+
ensureGitIdentity(dir, token);
|
|
10802
10861
|
const head = resolveCommit(dir, "HEAD");
|
|
10803
10862
|
const branch = currentBranch(dir);
|
|
10804
10863
|
spinner2?.stop(
|
|
@@ -11021,14 +11080,13 @@ Re-run with --allow-do-deletion to accept the data loss.`,
|
|
|
11021
11080
|
spinner2?.message("Waiting for the edge to serve this release...");
|
|
11022
11081
|
serving = await waitForLiveRelease(result.url, result.releaseStamp, 9e4);
|
|
11023
11082
|
}
|
|
11024
|
-
const edgePropagating = serving === "unconfirmed";
|
|
11025
11083
|
spinner2?.stop(
|
|
11026
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.`
|
|
11027
11085
|
);
|
|
11028
11086
|
const doClassGuard = result.doClassGuard === "unverified" ? "unverified" : void 0;
|
|
11029
11087
|
if (!args.json) {
|
|
11030
11088
|
if (result.url) {
|
|
11031
|
-
if (
|
|
11089
|
+
if (serving === "unconfirmed") p22.log.warn(`URL: ${result.url} (accepted; serving not yet verified)`);
|
|
11032
11090
|
else p22.log.success(`Live at: ${result.url}`);
|
|
11033
11091
|
}
|
|
11034
11092
|
if (result.bundleRetained === false) {
|
|
@@ -11056,7 +11114,6 @@ Re-run with --allow-do-deletion to accept the data loss.`,
|
|
|
11056
11114
|
wranglerEnv: wranglerEnv ?? null,
|
|
11057
11115
|
// Always present, matching `deploy`: one field to branch on.
|
|
11058
11116
|
serving,
|
|
11059
|
-
...edgePropagating ? { edgePropagating: true } : {},
|
|
11060
11117
|
...doClassGuard ? { doClassGuard } : {}
|
|
11061
11118
|
}
|
|
11062
11119
|
};
|
|
@@ -11068,7 +11125,7 @@ import { defineCommand as defineCommand12 } from "citty";
|
|
|
11068
11125
|
|
|
11069
11126
|
// src/cli/commands/workspace/new.ts
|
|
11070
11127
|
import * as p25 from "@clack/prompts";
|
|
11071
|
-
import { isAbsolute as isAbsolute6, resolve as
|
|
11128
|
+
import { isAbsolute as isAbsolute6, resolve as resolve18 } from "path";
|
|
11072
11129
|
|
|
11073
11130
|
// src/cli/commands/workspace/analysis.ts
|
|
11074
11131
|
import * as p23 from "@clack/prompts";
|
|
@@ -11077,6 +11134,14 @@ var PEER_REF_PREFIX = `${spacePrivateRef("peers")}/`;
|
|
|
11077
11134
|
function peerWorkspaceRef(workspaceId) {
|
|
11078
11135
|
return `${PEER_REF_PREFIX}${workspaceId}`;
|
|
11079
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
|
+
}
|
|
11080
11145
|
function formatCount(count) {
|
|
11081
11146
|
if (!count) return "?";
|
|
11082
11147
|
return count.capped ? `${count.count}+` : String(count.count);
|
|
@@ -11193,18 +11258,18 @@ function printOverlaps(overlaps, json) {
|
|
|
11193
11258
|
|
|
11194
11259
|
// src/cli/commands/workspace/local.ts
|
|
11195
11260
|
import * as p24 from "@clack/prompts";
|
|
11196
|
-
import { mkdirSync as mkdirSync7, readFileSync as
|
|
11197
|
-
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";
|
|
11198
11263
|
var WORKSPACE_MARKER = "deepspace-workspace.json";
|
|
11199
11264
|
function excludeWorktreeDir(appDir, dir) {
|
|
11200
11265
|
try {
|
|
11201
11266
|
ensureLocalExclude(appDir, ".deepspace/");
|
|
11202
|
-
const realDir =
|
|
11203
|
-
const rel = relative2(
|
|
11267
|
+
const realDir = realpathSync6(dir);
|
|
11268
|
+
const rel = relative2(realpathSync6(repoToplevel(appDir)), realDir);
|
|
11204
11269
|
if (!rel || rel === ".." || rel.startsWith(`..${sep2}`) || isAbsolute5(rel)) return;
|
|
11205
11270
|
const pattern = rel.split(sep2).join("/");
|
|
11206
11271
|
if (pattern === ".deepspace" || pattern.startsWith(".deepspace/")) return;
|
|
11207
|
-
const relApp = relative2(
|
|
11272
|
+
const relApp = relative2(realpathSync6(appDir), realDir).split(sep2).join("/");
|
|
11208
11273
|
if (relApp === ".deepspace" || relApp.startsWith(".deepspace/")) return;
|
|
11209
11274
|
ensureLocalExclude(appDir, `/${pattern}/`);
|
|
11210
11275
|
} catch {
|
|
@@ -11226,7 +11291,7 @@ function markManagedWorkspace(worktreeRoot, workspaceId) {
|
|
|
11226
11291
|
const marker = { version: 1, workspaceId, mode: "managed-linked" };
|
|
11227
11292
|
const tempPath = `${markerPath}.${process.pid}.tmp`;
|
|
11228
11293
|
try {
|
|
11229
|
-
mkdirSync7(
|
|
11294
|
+
mkdirSync7(dirname10(markerPath), { recursive: true });
|
|
11230
11295
|
writeFileSync9(tempPath, JSON.stringify(marker) + "\n");
|
|
11231
11296
|
renameSync2(tempPath, markerPath);
|
|
11232
11297
|
return true;
|
|
@@ -11251,7 +11316,7 @@ function isManagedWorkspaceWorktree(worktreeRoot, workspaceId) {
|
|
|
11251
11316
|
const markerPath = worktreeMarkerPath(worktreeRoot);
|
|
11252
11317
|
if (!markerPath) return false;
|
|
11253
11318
|
try {
|
|
11254
|
-
const marker = JSON.parse(
|
|
11319
|
+
const marker = JSON.parse(readFileSync27(markerPath, "utf-8"));
|
|
11255
11320
|
return marker.version === 1 && marker.workspaceId === workspaceId && marker.mode === "managed-linked";
|
|
11256
11321
|
} catch {
|
|
11257
11322
|
return false;
|
|
@@ -11263,7 +11328,7 @@ function defaultWorkspaceRoot(appDir, workspaceId) {
|
|
|
11263
11328
|
return join22(primary.path, ".deepspace", "ws", workspaceId.slice(3).toLowerCase());
|
|
11264
11329
|
}
|
|
11265
11330
|
function appDirInWorktree(appDir, worktreeRoot) {
|
|
11266
|
-
const appRelative = relative2(
|
|
11331
|
+
const appRelative = relative2(realpathSync6(repoToplevel(appDir)), realpathSync6(appDir));
|
|
11267
11332
|
return appRelative ? join22(worktreeRoot, appRelative) : worktreeRoot;
|
|
11268
11333
|
}
|
|
11269
11334
|
function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint, workspaceId, options = {}) {
|
|
@@ -11279,6 +11344,18 @@ function materializeWorkspaceWorktree(appDir, worktreeRoot, branch, startPoint,
|
|
|
11279
11344
|
}
|
|
11280
11345
|
excludeWorktreeDir(appDir, worktreeRoot);
|
|
11281
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
|
+
}
|
|
11282
11359
|
function inOwnLinkedWorktree(appDir, id) {
|
|
11283
11360
|
if (workspaceIdFromBranch(currentBranch(appDir)) !== id) return false;
|
|
11284
11361
|
try {
|
|
@@ -11387,7 +11464,7 @@ function cleanupWorkspaceLocal(appDir, id, trunkBranch, options = {}) {
|
|
|
11387
11464
|
}
|
|
11388
11465
|
let inside = false;
|
|
11389
11466
|
try {
|
|
11390
|
-
inside =
|
|
11467
|
+
inside = realpathSync6(repoToplevel(appDir)) === realpathSync6(linked.path);
|
|
11391
11468
|
} catch {
|
|
11392
11469
|
inside = false;
|
|
11393
11470
|
}
|
|
@@ -11483,7 +11560,7 @@ function inferWorkspaceId(appDir, explicit) {
|
|
|
11483
11560
|
const id = explicit?.trim() || workspaceIdFromBranch(currentBranch(appDir));
|
|
11484
11561
|
if (!id) {
|
|
11485
11562
|
throw new Refusal(
|
|
11486
|
-
'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"`.',
|
|
11487
11564
|
"not_in_workspace"
|
|
11488
11565
|
);
|
|
11489
11566
|
}
|
|
@@ -11492,17 +11569,28 @@ function inferWorkspaceId(appDir, explicit) {
|
|
|
11492
11569
|
}
|
|
11493
11570
|
return id;
|
|
11494
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
|
+
}
|
|
11495
11582
|
function assertSelectedWorkspaceCheckout(appDir, id, resumeArgv) {
|
|
11496
11583
|
const branch = currentBranch(appDir);
|
|
11497
11584
|
if (isSelectedWorkspaceCheckout(branch, id)) return;
|
|
11498
11585
|
const worktree = resolveWorkspaceWorktree(listWorktrees(appDir), id);
|
|
11499
|
-
const
|
|
11586
|
+
const worktreeAppDir = worktree ? appDirInWorktree(appDir, worktree) : null;
|
|
11587
|
+
const action = worktreeAppDir ? { cwd: worktreeAppDir, argv: resumeArgv } : { cwd: appDir, argv: ["deepspace", "workspace", "attach", id] };
|
|
11500
11588
|
throw new Refusal(
|
|
11501
|
-
`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."),
|
|
11502
11590
|
"workspace_checkout_mismatch",
|
|
11503
11591
|
{
|
|
11504
11592
|
action,
|
|
11505
|
-
extra:
|
|
11593
|
+
extra: worktreeAppDir ? { workspaceDir: worktreeAppDir } : void 0
|
|
11506
11594
|
}
|
|
11507
11595
|
);
|
|
11508
11596
|
}
|
|
@@ -11526,10 +11614,11 @@ function pushWorkspaceRef(appDir, token, ref, headOid) {
|
|
|
11526
11614
|
if (push.status === "committed" || push.status === "up_to_date") return;
|
|
11527
11615
|
if (push.status === "ref_conflict" || push.status === "non_fast_forward") {
|
|
11528
11616
|
throw new Refusal(
|
|
11529
|
-
`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.)`,
|
|
11530
11618
|
push.status,
|
|
11531
11619
|
{
|
|
11532
|
-
|
|
11620
|
+
actionRequired: true,
|
|
11621
|
+
action: { cwd: appDir, argv: ["git", "pull", "--no-rebase", SPACE_REMOTE, ref] }
|
|
11533
11622
|
}
|
|
11534
11623
|
);
|
|
11535
11624
|
}
|
|
@@ -11585,6 +11674,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11585
11674
|
);
|
|
11586
11675
|
spinner2?.message("Creating workspace\u2026");
|
|
11587
11676
|
ensureSpaceRemote(appDir, appId);
|
|
11677
|
+
ensureGitIdentity(appDir, token);
|
|
11588
11678
|
let baseOid = null;
|
|
11589
11679
|
const refs = await api4.getRefs();
|
|
11590
11680
|
if (baseArg) {
|
|
@@ -11628,7 +11718,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11628
11718
|
idempotencyKey: mintIdempotencyKey()
|
|
11629
11719
|
});
|
|
11630
11720
|
const dirInput = typeof args.dir === "string" ? args.dir.trim() : "";
|
|
11631
|
-
const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput :
|
|
11721
|
+
const worktreeRoot = dirInput ? isAbsolute6(dirInput) ? dirInput : resolve18(appDir, dirInput) : defaultWorkspaceRoot(appDir, id);
|
|
11632
11722
|
const dir = appDirInWorktree(appDir, worktreeRoot);
|
|
11633
11723
|
try {
|
|
11634
11724
|
materializeWorkspaceWorktree(appDir, worktreeRoot, branch, baseOid, id);
|
|
@@ -11666,8 +11756,18 @@ var newWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11666
11756
|
|
|
11667
11757
|
// src/cli/commands/workspace/attach.ts
|
|
11668
11758
|
import * as p26 from "@clack/prompts";
|
|
11669
|
-
import { existsSync as existsSync25, readdirSync as readdirSync7, rmSync as rmSync6 } from "fs";
|
|
11670
|
-
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
|
+
}
|
|
11671
11771
|
function finishedWorkspaceMessage(id, view) {
|
|
11672
11772
|
const workspace = view.workspace;
|
|
11673
11773
|
if (workspace.status === "landed") {
|
|
@@ -11736,6 +11836,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11736
11836
|
});
|
|
11737
11837
|
}
|
|
11738
11838
|
ensureSpaceRemote(appDir, appId2);
|
|
11839
|
+
ensureGitIdentity(appDir, token2);
|
|
11739
11840
|
const localWorkspaceRef = spacePrivateRef(`workspaces/${id}`);
|
|
11740
11841
|
runGitRemote(appDir, token2, [
|
|
11741
11842
|
"fetch",
|
|
@@ -11752,11 +11853,87 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11752
11853
|
);
|
|
11753
11854
|
}
|
|
11754
11855
|
const requestedDir = typeof args.dir === "string" ? args.dir.trim() : "";
|
|
11755
|
-
const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir :
|
|
11856
|
+
const worktreeRoot = requestedDir ? isAbsolute7(requestedDir) ? requestedDir : resolve19(appDir, requestedDir) : defaultWorkspaceRoot(appDir, id);
|
|
11756
11857
|
const dir2 = appDirInWorktree(appDir, worktreeRoot);
|
|
11757
|
-
|
|
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.");
|
|
11758
11935
|
throw new Refusal(
|
|
11759
|
-
`
|
|
11936
|
+
`Workspace ${id} is already checked out at ${existing} \u2014 continue there (or drop that worktree before attaching it elsewhere).`,
|
|
11760
11937
|
"branch_exists"
|
|
11761
11938
|
);
|
|
11762
11939
|
}
|
|
@@ -11775,6 +11952,10 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11775
11952
|
worktreeRoot,
|
|
11776
11953
|
branch,
|
|
11777
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",
|
|
11778
11959
|
task: view2.workspace.task
|
|
11779
11960
|
},
|
|
11780
11961
|
action: action2
|
|
@@ -11791,7 +11972,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11791
11972
|
extra: { status: view.workspace.status }
|
|
11792
11973
|
});
|
|
11793
11974
|
}
|
|
11794
|
-
const dir =
|
|
11975
|
+
const dir = resolve19(
|
|
11795
11976
|
process.cwd(),
|
|
11796
11977
|
(typeof args.dir === "string" ? args.dir.trim() : "") || `ws-${id.slice(3).toLowerCase()}`
|
|
11797
11978
|
);
|
|
@@ -11810,6 +11991,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11810
11991
|
try {
|
|
11811
11992
|
runGit(process.cwd(), ["init", "--quiet", dir]);
|
|
11812
11993
|
ensureSpaceRemote(dir, appId);
|
|
11994
|
+
ensureGitIdentity(dir, token);
|
|
11813
11995
|
const localWorkspaceRef = spacePrivateRef(`workspaces/${id}`);
|
|
11814
11996
|
runGitRemote(dir, token, [
|
|
11815
11997
|
"fetch",
|
|
@@ -11846,6 +12028,8 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11846
12028
|
dir,
|
|
11847
12029
|
branch,
|
|
11848
12030
|
tipOid: tip,
|
|
12031
|
+
remoteTip: tip,
|
|
12032
|
+
syncRelation: "in_sync",
|
|
11849
12033
|
task: view.workspace.task
|
|
11850
12034
|
},
|
|
11851
12035
|
action
|
|
@@ -11878,7 +12062,19 @@ var syncWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11878
12062
|
typeof args.app === "string" ? args.app : void 0
|
|
11879
12063
|
);
|
|
11880
12064
|
const id = inferWorkspaceId(appDir, workspaceArg);
|
|
11881
|
-
|
|
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
|
+
}
|
|
11882
12078
|
const headOid = resolveCommit(appDir, "HEAD");
|
|
11883
12079
|
if (!headOid) {
|
|
11884
12080
|
throw new Refusal("The workspace has no commits yet \u2014 commit first, then sync.", "no_commits");
|
|
@@ -11897,6 +12093,7 @@ var syncWorkspaceCommand = defineDeepspaceCommand({
|
|
|
11897
12093
|
);
|
|
11898
12094
|
}
|
|
11899
12095
|
ensureSpaceRemote(appDir, appId);
|
|
12096
|
+
ensureGitIdentity(appDir, token);
|
|
11900
12097
|
pushWorkspaceRef(appDir, token, before.workspace.ref, headOid);
|
|
11901
12098
|
try {
|
|
11902
12099
|
fetchTrunk(appDir, token, refs?.head ?? null);
|
|
@@ -12037,6 +12234,7 @@ var workspaceStatusCommand = defineDeepspaceCommand({
|
|
|
12037
12234
|
const aheadExact = headOid && baseLocal ? revListCount(appDir, workspace.baseOid, headOid) : null;
|
|
12038
12235
|
const unsynced = headOid !== null && view.tipOid !== headOid;
|
|
12039
12236
|
const dirty = workspaceDir ? statusFiles(workspaceDir) : [];
|
|
12237
|
+
const relation = !unsynced ? "in_sync" : workspace.status !== "active" || !workspaceDir ? "unknown" : workspaceSyncRelation(workspaceDir, headOid, view.tipOid);
|
|
12040
12238
|
const lines = await loadWorkspaceLines(appDir, token, api4, trunkOid);
|
|
12041
12239
|
const myTip = headOid ?? resolveCommit(appDir, peerWorkspaceRef(id)) ?? view.tipOid;
|
|
12042
12240
|
const line = myTip ? lineChangedPaths(appDir, workspace.baseOid, myTip, trunkOid) : null;
|
|
@@ -12056,6 +12254,10 @@ var workspaceStatusCommand = defineDeepspaceCommand({
|
|
|
12056
12254
|
...attached ? {
|
|
12057
12255
|
headOid,
|
|
12058
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,
|
|
12059
12261
|
uncommitted: dirty,
|
|
12060
12262
|
trunkOverlap
|
|
12061
12263
|
} : {},
|
|
@@ -12071,10 +12273,29 @@ var workspaceStatusCommand = defineDeepspaceCommand({
|
|
|
12071
12273
|
`Not checked out in this clone \u2014 showing the published state (local HEAD/uncommitted unavailable). Attach it with \`deepspace workspace attach ${id} <dir>\`.`
|
|
12072
12274
|
);
|
|
12073
12275
|
}
|
|
12074
|
-
if (unsynced)
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
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
|
+
}
|
|
12078
12299
|
if (dirty.length > 0) p29.log.warn(`${dirty.length} uncommitted file(s) in the worktree.`);
|
|
12079
12300
|
if (trunkOverlap.length > 0) {
|
|
12080
12301
|
p29.log.warn(
|
|
@@ -12092,13 +12313,13 @@ import * as p30 from "@clack/prompts";
|
|
|
12092
12313
|
|
|
12093
12314
|
// src/cli/lib/validation.ts
|
|
12094
12315
|
import { sync as spawnSync7 } from "cross-spawn";
|
|
12095
|
-
import { readFileSync as
|
|
12316
|
+
import { readFileSync as readFileSync28 } from "fs";
|
|
12096
12317
|
import { join as join23 } from "path";
|
|
12097
12318
|
var MAX_SUMMARY_CHARS = 4e3;
|
|
12098
12319
|
var MAX_OUTPUT_BUFFER = 64 * 1024 * 1024;
|
|
12099
12320
|
function configuredCommand(appDir) {
|
|
12100
12321
|
try {
|
|
12101
|
-
const pkg2 = JSON.parse(
|
|
12322
|
+
const pkg2 = JSON.parse(readFileSync28(join23(appDir, "package.json"), "utf-8"));
|
|
12102
12323
|
if (pkg2.scripts?.validate) return `${detectPackageManager(appDir)} run --silent validate`;
|
|
12103
12324
|
} catch {
|
|
12104
12325
|
}
|
|
@@ -12128,6 +12349,14 @@ ${res.stderr?.toString("utf-8") ?? ""}`.trim();
|
|
|
12128
12349
|
function hasLeftoverConflictMarkers(diffCheckOutput) {
|
|
12129
12350
|
return /leftover conflict marker/.test(diffCheckOutput);
|
|
12130
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
|
+
}
|
|
12131
12360
|
function landResumeArgv(args) {
|
|
12132
12361
|
const argv = ["deepspace", "workspace", "land"];
|
|
12133
12362
|
const workspace = args.workspace?.trim();
|
|
@@ -12193,7 +12422,20 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12193
12422
|
});
|
|
12194
12423
|
const recoveryAction = { cwd: appDir, argv: resumeArgv };
|
|
12195
12424
|
const resumeNext = humanCommand(resumeArgv);
|
|
12196
|
-
|
|
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
|
+
}
|
|
12197
12439
|
const headBefore = resolveCommit(appDir, "HEAD");
|
|
12198
12440
|
if (!headBefore) {
|
|
12199
12441
|
throw new Refusal("The workspace has no commits \u2014 nothing to land.", "no_commits");
|
|
@@ -12209,13 +12451,10 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12209
12451
|
const [{ view }, refs] = await Promise.all([api4.getWorkspace(id), api4.getRefs()]);
|
|
12210
12452
|
if (view.workspace.status !== "active") {
|
|
12211
12453
|
spinner2?.stop("Workspace finished.");
|
|
12212
|
-
throw
|
|
12213
|
-
`Workspace ${id} is already ${view.workspace.status}.`,
|
|
12214
|
-
"workspace_not_active",
|
|
12215
|
-
{ extra: { status: view.workspace.status } }
|
|
12216
|
-
);
|
|
12454
|
+
throw workspaceNotActiveRefusal(id, view.workspace.status, dropAction);
|
|
12217
12455
|
}
|
|
12218
12456
|
ensureSpaceRemote(appDir, appId);
|
|
12457
|
+
ensureGitIdentity(appDir, token);
|
|
12219
12458
|
const isResumedMerge = resolveCommit(appDir, "HEAD^2") !== null && view.tipOid !== null && resolveCommit(appDir, "HEAD^") === view.tipOid;
|
|
12220
12459
|
if (!isResumedMerge) {
|
|
12221
12460
|
pushWorkspaceRef(appDir, token, view.workspace.ref, headBefore);
|
|
@@ -12262,6 +12501,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12262
12501
|
"merge_conflict",
|
|
12263
12502
|
{
|
|
12264
12503
|
actionRequired: true,
|
|
12504
|
+
action: recoveryAction,
|
|
12265
12505
|
extra: { workspaceId: id, conflict: true }
|
|
12266
12506
|
}
|
|
12267
12507
|
);
|
|
@@ -12271,14 +12511,17 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12271
12511
|
const markerCheck = runGit(appDir, ["diff", "--check", "HEAD^", "HEAD"], {
|
|
12272
12512
|
allowFail: true
|
|
12273
12513
|
});
|
|
12274
|
-
|
|
12514
|
+
const markerOutput = markerCheck.stdout.toString("utf-8");
|
|
12515
|
+
if (hasLeftoverConflictMarkers(markerOutput)) {
|
|
12516
|
+
const files = conflictMarkerFiles(markerOutput);
|
|
12275
12517
|
spinner2?.stop("Conflict markers in merge.");
|
|
12276
12518
|
throw new Refusal(
|
|
12277
|
-
`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}.`,
|
|
12278
12520
|
"conflict_markers",
|
|
12279
12521
|
{
|
|
12280
12522
|
actionRequired: true,
|
|
12281
|
-
|
|
12523
|
+
action: recoveryAction,
|
|
12524
|
+
extra: { workspaceId: id, conflict: true, ...files.length ? { files } : {} }
|
|
12282
12525
|
}
|
|
12283
12526
|
);
|
|
12284
12527
|
}
|
|
@@ -12312,6 +12555,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12312
12555
|
"validation_failed",
|
|
12313
12556
|
{
|
|
12314
12557
|
actionRequired: true,
|
|
12558
|
+
action: recoveryAction,
|
|
12315
12559
|
extra: { workspaceId: id, passed: false, outputTail }
|
|
12316
12560
|
}
|
|
12317
12561
|
);
|
|
@@ -12323,6 +12567,7 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12323
12567
|
"validation_mutated_tree",
|
|
12324
12568
|
{
|
|
12325
12569
|
actionRequired: true,
|
|
12570
|
+
action: recoveryAction,
|
|
12326
12571
|
extra: { workspaceId: id }
|
|
12327
12572
|
}
|
|
12328
12573
|
);
|
|
@@ -12358,7 +12603,37 @@ var landWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12358
12603
|
"push_rejected"
|
|
12359
12604
|
);
|
|
12360
12605
|
}
|
|
12361
|
-
|
|
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
|
+
}
|
|
12362
12637
|
spinner2?.stop(`Landed ${id} into ${intoBranch} at ${landedOid.slice(0, 10)}.`);
|
|
12363
12638
|
const cleanup = keepWorktree ? null : cleanupWorkspaceLocal(appDir, id, intoBranch, { expectedBranchOid: landedOid });
|
|
12364
12639
|
const inOwnWorktree = !cleanup && inOwnLinkedWorktree(appDir, id);
|
|
@@ -12403,6 +12678,22 @@ function isWorkspaceTipPublished(appDir, localTip, publishedOids) {
|
|
|
12403
12678
|
);
|
|
12404
12679
|
}
|
|
12405
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
|
+
}
|
|
12406
12697
|
const syncArgv = ["deepspace", "workspace", "sync", "--app", args.appId, "--workspace", args.id];
|
|
12407
12698
|
const dropArgv = ["deepspace", "workspace", "drop", args.id, "--app", args.appId];
|
|
12408
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)}\`.`;
|
|
@@ -12410,11 +12701,25 @@ function workspaceUnsyncedRefusal(args) {
|
|
|
12410
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.`,
|
|
12411
12702
|
"workspace_unsynced",
|
|
12412
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.
|
|
12413
12706
|
...args.workspaceDir ? { action: { cwd: args.workspaceDir, argv: syncArgv } } : {},
|
|
12414
|
-
extra: { workspaceId: args.id }
|
|
12707
|
+
extra: { workspaceId: args.id, status: args.status }
|
|
12415
12708
|
}
|
|
12416
12709
|
);
|
|
12417
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
|
+
}
|
|
12418
12723
|
var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
12419
12724
|
meta: { name: "drop", description: "Abandon a workspace (ref retained briefly, then GC)" },
|
|
12420
12725
|
args: {
|
|
@@ -12439,32 +12744,47 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12439
12744
|
spinner2?.start(`Preparing to drop ${explicitId ?? "workspace"}\u2026`);
|
|
12440
12745
|
if (!findAppDir() && explicitId) {
|
|
12441
12746
|
const { api: api5 } = await resolveApiOnly(appArg);
|
|
12442
|
-
const
|
|
12747
|
+
const statusBefore = (await api5.getWorkspace(explicitId)).view.workspace.status;
|
|
12748
|
+
const { view: view2, remoteDropped: remoteDropped2 } = await dropRemoteTolerant(api5, explicitId, statusBefore);
|
|
12443
12749
|
spinner2?.stop();
|
|
12444
12750
|
if (!args.json) {
|
|
12445
12751
|
p31.log.success(
|
|
12446
|
-
`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.`
|
|
12447
12753
|
);
|
|
12448
12754
|
}
|
|
12449
|
-
return { data: { workspaceId: explicitId, status: view2.workspace.status } };
|
|
12755
|
+
return { data: { workspaceId: explicitId, status: view2.workspace.status, remoteDropped: remoteDropped2 } };
|
|
12450
12756
|
}
|
|
12451
|
-
const { appDir, appId, api: api4 } = await resolveTarget2(appArg);
|
|
12757
|
+
const { appDir, appId, token, api: api4 } = await resolveTarget2(appArg);
|
|
12452
12758
|
const id = inferWorkspaceId(appDir, explicitId);
|
|
12453
12759
|
const inspection = inspectWorkspaceCleanup(appDir, id);
|
|
12454
12760
|
let approvedBranchOid;
|
|
12761
|
+
const { view: before } = await api4.getWorkspace(id);
|
|
12455
12762
|
if (!keepWorktree && inspection.willDeleteBranch && inspection.branchOid) {
|
|
12456
|
-
const { view: before } = await api4.getWorkspace(id);
|
|
12457
12763
|
const publishedOids = [
|
|
12458
12764
|
before.tipOid,
|
|
12459
12765
|
before.workspace.landedOid,
|
|
12460
12766
|
before.workspace.baseOid
|
|
12461
12767
|
].filter((oid) => oid !== null);
|
|
12462
|
-
|
|
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) {
|
|
12463
12782
|
throw workspaceUnsyncedRefusal({
|
|
12464
12783
|
appId,
|
|
12465
12784
|
id,
|
|
12466
12785
|
branch: inspection.branch,
|
|
12467
|
-
workspaceDir: inspection.checkout.dir
|
|
12786
|
+
workspaceDir: inspection.checkout.dir,
|
|
12787
|
+
status: before.workspace.status
|
|
12468
12788
|
});
|
|
12469
12789
|
}
|
|
12470
12790
|
approvedBranchOid = inspection.branchOid;
|
|
@@ -12479,7 +12799,7 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12479
12799
|
{ extra: { workspaceId: id } }
|
|
12480
12800
|
);
|
|
12481
12801
|
}
|
|
12482
|
-
const { view } = await api4.
|
|
12802
|
+
const { view, remoteDropped } = await dropRemoteTolerant(api4, id, before.workspace.status);
|
|
12483
12803
|
spinner2?.message(`Cleaning up ${id} locally\u2026`);
|
|
12484
12804
|
const cleanup = keepWorktree ? null : cleanupWorkspaceLocal(appDir, id, null, {
|
|
12485
12805
|
expectedBranchOid: approvedBranchOid,
|
|
@@ -12489,12 +12809,15 @@ var dropWorkspaceCommand = defineDeepspaceCommand({
|
|
|
12489
12809
|
const data = {
|
|
12490
12810
|
workspaceId: id,
|
|
12491
12811
|
status: view.workspace.status,
|
|
12812
|
+
remoteDropped,
|
|
12492
12813
|
...retainedWorktree ? { worktree: retainedWorktree } : {},
|
|
12493
12814
|
...cleanup ? { cleanup: cleanupJson(cleanup) } : {}
|
|
12494
12815
|
};
|
|
12495
12816
|
spinner2?.stop();
|
|
12496
12817
|
if (!args.json) {
|
|
12497
|
-
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
|
+
);
|
|
12498
12821
|
if (cleanup && !cleanup.error) reportCleanupHuman(cleanup);
|
|
12499
12822
|
else if (retainedWorktree) p31.log.info(`Retained checkout: ${retainedWorktree}`);
|
|
12500
12823
|
}
|
|
@@ -12563,7 +12886,7 @@ function formatEvent2(e, lands, actors) {
|
|
|
12563
12886
|
detail = `"${String(s.task ?? "")}" from ${short(s.baseOid)}`;
|
|
12564
12887
|
break;
|
|
12565
12888
|
case "workspace.synced":
|
|
12566
|
-
detail = `\u2192 ${short(s.headOid)}
|
|
12889
|
+
detail = `\u2192 ${short(s.headOid)}`;
|
|
12567
12890
|
break;
|
|
12568
12891
|
case "workspace.landed":
|
|
12569
12892
|
detail = `"${String(s.task ?? "")}" \u2192 ${short(s.landedOid)} on ${String(s.into ?? "trunk")}`;
|
|
@@ -13061,8 +13384,8 @@ function sameRefs(left, right) {
|
|
|
13061
13384
|
|
|
13062
13385
|
// src/cli/commands/update.ts
|
|
13063
13386
|
import * as p34 from "@clack/prompts";
|
|
13064
|
-
import { existsSync as existsSync26, readFileSync as
|
|
13065
|
-
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";
|
|
13066
13389
|
var REGISTRY = "https://registry.npmjs.org/deepspace/latest";
|
|
13067
13390
|
var DOCS_URL = "https://documentation.deep.space/cli-reference/commands";
|
|
13068
13391
|
var OLDEST_SUPPORTED_MINOR = 12;
|
|
@@ -13078,17 +13401,17 @@ function gapIsTooWide(from, to) {
|
|
|
13078
13401
|
function readAppSdkVersion(appDir) {
|
|
13079
13402
|
const installed = join24(appDir, "node_modules", "deepspace", "package.json");
|
|
13080
13403
|
if (existsSync26(installed)) {
|
|
13081
|
-
const parsed2 = JSON.parse(
|
|
13404
|
+
const parsed2 = JSON.parse(readFileSync29(installed, "utf8"));
|
|
13082
13405
|
if (typeof parsed2.version === "string") return parsed2.version;
|
|
13083
13406
|
}
|
|
13084
13407
|
const manifest = join24(appDir, "package.json");
|
|
13085
13408
|
if (!existsSync26(manifest)) return null;
|
|
13086
|
-
const parsed = JSON.parse(
|
|
13409
|
+
const parsed = JSON.parse(readFileSync29(manifest, "utf8"));
|
|
13087
13410
|
return parsed.dependencies?.deepspace ?? null;
|
|
13088
13411
|
}
|
|
13089
13412
|
function pinSdkVersion(appDir, version) {
|
|
13090
13413
|
const path = join24(appDir, "package.json");
|
|
13091
|
-
const source =
|
|
13414
|
+
const source = readFileSync29(path, "utf8");
|
|
13092
13415
|
const updated = source.replace(
|
|
13093
13416
|
/("deepspace"\s*:\s*")[^"]+(")/,
|
|
13094
13417
|
(_match, head, tail) => `${head}^${version}${tail}`
|
|
@@ -13153,7 +13476,7 @@ var update_default = defineDeepspaceCommand({
|
|
|
13153
13476
|
}
|
|
13154
13477
|
},
|
|
13155
13478
|
async run({ args }) {
|
|
13156
|
-
const appDir =
|
|
13479
|
+
const appDir = resolve20(".");
|
|
13157
13480
|
if (!hasWranglerConfig(appDir)) {
|
|
13158
13481
|
throw new Refusal(
|
|
13159
13482
|
"No wrangler.toml found \u2014 run this from inside a DeepSpace app directory.",
|
|
@@ -13233,8 +13556,8 @@ var update_default = defineDeepspaceCommand({
|
|
|
13233
13556
|
});
|
|
13234
13557
|
|
|
13235
13558
|
// src/cli/cli.ts
|
|
13236
|
-
var __dirname =
|
|
13237
|
-
var pkg = JSON.parse(
|
|
13559
|
+
var __dirname = dirname11(fileURLToPath3(import.meta.url));
|
|
13560
|
+
var pkg = JSON.parse(readFileSync30(join25(__dirname, "..", "package.json"), "utf-8"));
|
|
13238
13561
|
if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync27("/etc/ssl/certs/ca-certificates.crt")) {
|
|
13239
13562
|
process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
13240
13563
|
}
|
|
@@ -13361,7 +13684,9 @@ function assertKnownCommandPath(argv) {
|
|
|
13361
13684
|
`${unknownCommandMessage(unknown)}
|
|
13362
13685
|
Run \`${unknown.helpPath.join(" ")} --help\` for the command list.`
|
|
13363
13686
|
);
|
|
13364
|
-
if (unknown.executable)
|
|
13687
|
+
if (unknown.executable) {
|
|
13688
|
+
printAction(executableAction({ cwd: process.cwd(), argv: unknown.suggestion }));
|
|
13689
|
+
}
|
|
13365
13690
|
process.exit(1);
|
|
13366
13691
|
}
|
|
13367
13692
|
var rawArgs = process.argv.slice(2);
|
|
@@ -13383,7 +13708,7 @@ if (rawArgs.includes("--json") && !wantsHelp) {
|
|
|
13383
13708
|
ok: false,
|
|
13384
13709
|
code: "unknown_command",
|
|
13385
13710
|
error: unknownCommandMessage(unknown),
|
|
13386
|
-
...unknown.executable ? { action: { cwd: process.cwd(), argv: unknown.suggestion } } : {}
|
|
13711
|
+
...unknown.executable ? { action: executableAction({ cwd: process.cwd(), argv: unknown.suggestion }) } : {}
|
|
13387
13712
|
})
|
|
13388
13713
|
);
|
|
13389
13714
|
process.exit(1);
|