deepspace 0.21.0 → 0.22.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/dist/cli.js CHANGED
@@ -8,8 +8,8 @@ import {
8
8
  renderUsage
9
9
  } from "citty";
10
10
  import { sync as spawnSync8 } from "cross-spawn";
11
- import { readFileSync as readFileSync28, existsSync as existsSync26 } from "fs";
12
- import { dirname as dirname12, join as join24 } from "path";
11
+ import { readFileSync as readFileSync28, existsSync as existsSync27 } from "fs";
12
+ import { dirname as dirname12, join as join25 } from "path";
13
13
  import { fileURLToPath as fileURLToPath3 } from "url";
14
14
 
15
15
  // src/cli/lib/spinner.ts
@@ -913,8 +913,6 @@ import { parse as parseToml } from "smol-toml";
913
913
  // src/server/utils/registry-client.ts
914
914
  var APP_ID_RE = /^app_[0-9A-HJKMNP-TV-Z]{26}$/;
915
915
  var STRICT_APP_ID_RE = APP_ID_RE;
916
-
917
- // src/cli/lib/app-identity.ts
918
916
  var CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
919
917
  function mintUlid(now = Date.now()) {
920
918
  let ts = "";
@@ -938,9 +936,8 @@ function mintUlid(now = Date.now()) {
938
936
  }
939
937
  return `${ts}${rs}`.slice(0, 26);
940
938
  }
941
- function mintAppId(now = Date.now()) {
942
- return `app_${mintUlid(now)}`;
943
- }
939
+
940
+ // src/cli/lib/app-identity.ts
944
941
  function readWranglerIdentityConfig(cwd) {
945
942
  const wranglerPath = join2(resolve2(cwd), "wrangler.toml");
946
943
  if (!existsSync3(wranglerPath)) return null;
@@ -996,6 +993,18 @@ ${line}
996
993
  }
997
994
  writeFileSync2(wranglerPath, src);
998
995
  }
996
+ var APP_ID_PLACEHOLDER = "__APP_ID__";
997
+ function stampAppIdInSources(cwd, appId, previousAppId) {
998
+ const constantsPath = join2(resolve2(cwd), "src", "constants.ts");
999
+ if (!existsSync3(constantsPath)) return false;
1000
+ const needles = [APP_ID_PLACEHOLDER, ...previousAppId ? [previousAppId] : []];
1001
+ const content = readFileSync5(constantsPath, "utf-8");
1002
+ let next = content;
1003
+ for (const needle of needles) next = next.replaceAll(needle, appId);
1004
+ if (next === content) return false;
1005
+ writeFileSync2(constantsPath, next);
1006
+ return true;
1007
+ }
999
1008
 
1000
1009
  // src/cli/commands/dev.ts
1001
1010
  import { resolve as resolve8, basename as basename2, join as join11 } from "path";
@@ -5618,7 +5627,7 @@ async function syncDeployRepository(options) {
5618
5627
  p9.log.info(`Workspace ${workspaceBranchId} is synced at ${tip.slice(0, 10)}.`);
5619
5628
  } else if (secretFiles.length > 0) {
5620
5629
  p9.log.warn(
5621
- `Skipping cloud-repo push \u2014 the branch tracks secret file(s): ${secretFiles.join(", ")}. Untrack with \`git rm --cached ${secretFiles[0]}\` (add to .gitignore), re-commit, then \`deepspace push\`. Deploy continues; this release's source isn't recoverable until then.`
5630
+ `Skipping cloud-repo push \u2014 the branch tracks secret file(s): ${secretFiles.join(", ")}. Untrack with \`git rm --cached ${secretFiles[0]}\` (add to .gitignore), re-commit, then \`deepspace push\`. Without the push this deploy carries no source lineage: if the live release has one, the server refuses it as stale (--ignore-stale replaces it anyway), and this release's source isn't recoverable until the push works.`
5622
5631
  );
5623
5632
  } else {
5624
5633
  const pushResult = await pushWithTransientRetry(
@@ -6252,13 +6261,14 @@ var deploy_default = defineCommand3({
6252
6261
  );
6253
6262
  }
6254
6263
  const appName = nameResult.name;
6255
- let appId = readAppId(appDir, envName);
6264
+ const appId = readAppId(appDir, envName);
6256
6265
  p12.log.info(envName ? `App: ${appName} (env: ${envName})` : `App: ${appName}`);
6257
6266
  const { token, ownerId } = await authenticate(appDir, output);
6258
6267
  if (!appId) {
6259
- appId = mintAppId();
6260
- writeAppId(appDir, appId, { wranglerEnv: envName });
6261
- p12.log.info(`Minted app id ${appId} \u2014 commit wrangler.toml.`);
6268
+ return output.die(
6269
+ `No app id in wrangler.toml${envName ? ` for [env.${envName}]` : ""}. Run \`deepspace app init${envName ? ` --env ${envName}` : ""}\` to register this app, then re-deploy.`,
6270
+ "app_not_initialized"
6271
+ );
6262
6272
  }
6263
6273
  p12.log.info(`Id: ${appId}`);
6264
6274
  const secretsCache = await loadDeploySecrets({
@@ -10233,10 +10243,29 @@ var secrets_default = defineCommand10({
10233
10243
  });
10234
10244
 
10235
10245
  // src/cli/commands/init.ts
10246
+ import { existsSync as existsSync21 } from "fs";
10247
+ import { join as join20 } from "path";
10248
+ var DEPLOY_URL12 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
10249
+ function commitScaffoldIfUnborn(appDir, token) {
10250
+ try {
10251
+ if (!existsSync21(join20(appDir, ".git"))) return false;
10252
+ if (runGit(appDir, ["rev-parse", "--verify", "HEAD"], { allowFail: true }).status === 0) {
10253
+ return false;
10254
+ }
10255
+ ensureGitIdentity(appDir, token);
10256
+ if (runGit(appDir, ["add", "-A"], { allowFail: true }).status !== 0) return false;
10257
+ const commit = runGit(appDir, ["commit", "-m", "Initial DeepSpace scaffold", "--no-verify"], {
10258
+ allowFail: true
10259
+ });
10260
+ return commit.status === 0;
10261
+ } catch {
10262
+ return false;
10263
+ }
10264
+ }
10236
10265
  var init_default = defineDeepspaceCommand({
10237
10266
  meta: {
10238
10267
  name: "init",
10239
- description: "Mint this app\u2019s immutable DEEPSPACE_APP_ID into wrangler.toml"
10268
+ description: "Register this app: mint its immutable DEEPSPACE_APP_ID into wrangler.toml"
10240
10269
  },
10241
10270
  args: {
10242
10271
  "new-id": {
@@ -10270,23 +10299,31 @@ var init_default = defineDeepspaceCommand({
10270
10299
  data: { status: "already_initialized", appId: existing, appDir, env: envName ?? null }
10271
10300
  };
10272
10301
  }
10273
- const appId = mintAppId();
10302
+ const token = await ensureToken();
10303
+ const { appId } = await apiFetch(DEPLOY_URL12, token, "/api/apps/mint", {
10304
+ method: "POST"
10305
+ });
10274
10306
  writeAppId(appDir, appId, { wranglerEnv: envName, force: Boolean(args["new-id"]) });
10307
+ if (!envName) stampAppIdInSources(appDir, appId, existing);
10308
+ const committedScaffold = commitScaffoldIfUnborn(appDir, token);
10275
10309
  if (!args.json) {
10276
10310
  if (existing) {
10277
10311
  console.log(`Forked: ${existing} \u2192 ${appId}${envName ? ` (env: ${envName})` : ""}`);
10278
- console.log("The next deploy registers this as a NEW app; the original is untouched.");
10312
+ console.log("Registered as a NEW app under your account; the original is untouched.");
10279
10313
  } else {
10280
- console.log(`Minted ${appId}${envName ? ` (env: ${envName})` : ""} \u2014 commit wrangler.toml.`);
10281
- console.log("The first deploy registers it and claims the `name` subdomain.");
10314
+ console.log(
10315
+ `Registered ${appId}${envName ? ` (env: ${envName})` : ""} to your account` + (committedScaffold ? " \u2014 initial scaffold commit created." : " \u2014 commit wrangler.toml.")
10316
+ );
10317
+ console.log("The first deploy claims the `name` subdomain.");
10282
10318
  }
10283
10319
  console.log(`App dir: ${appDir}`);
10284
10320
  }
10285
10321
  return {
10286
10322
  data: {
10287
- status: existing ? "forked" : "minted",
10323
+ status: existing ? "forked" : "registered",
10288
10324
  appId,
10289
10325
  ...existing ? { previousAppId: existing } : {},
10326
+ committedScaffold,
10290
10327
  appDir,
10291
10328
  env: envName ?? null
10292
10329
  }
@@ -10297,7 +10334,7 @@ var init_default = defineDeepspaceCommand({
10297
10334
  // src/cli/commands/status.ts
10298
10335
  import { defineCommand as defineCommand11 } from "citty";
10299
10336
  import * as p17 from "@clack/prompts";
10300
- import { existsSync as existsSync21, readFileSync as readFileSync24 } from "fs";
10337
+ import { existsSync as existsSync22, readFileSync as readFileSync24 } from "fs";
10301
10338
  function timeAgo(iso) {
10302
10339
  const ms = Date.now() - Date.parse(iso);
10303
10340
  if (!Number.isFinite(ms) || ms < 0) return iso;
@@ -10382,7 +10419,7 @@ var status_default = defineCommand11({
10382
10419
  json.services = urls;
10383
10420
  if (urlOverrides.length > 0) json.urlOverrides = urlOverrides;
10384
10421
  }
10385
- facts.loggedIn = existsSync21(SESSION_PATH);
10422
+ facts.loggedIn = existsSync22(SESSION_PATH);
10386
10423
  let userId = null;
10387
10424
  if (!facts.loggedIn) {
10388
10425
  lines.push(["Session", "not logged in"]);
@@ -11071,18 +11108,18 @@ var pull_default = defineDeepspaceCommand({
11071
11108
 
11072
11109
  // src/cli/commands/clone.ts
11073
11110
  import * as p20 from "@clack/prompts";
11074
- import { existsSync as existsSync22, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
11075
- import { resolve as resolve17, basename as basename5, join as join20 } from "path";
11111
+ import { existsSync as existsSync23, readdirSync as readdirSync6, rmSync as rmSync5 } from "fs";
11112
+ import { resolve as resolve17, basename as basename5, join as join21 } from "path";
11076
11113
  function cleanFailedCloneDir(dir) {
11077
11114
  let entries;
11078
11115
  try {
11079
11116
  entries = readdirSync6(dir);
11080
11117
  } catch {
11081
- return existsSync22(dir) ? ["<unreadable>"] : [];
11118
+ return existsSync23(dir) ? ["<unreadable>"] : [];
11082
11119
  }
11083
11120
  if (entries.length === 1 && entries[0] === ".git") {
11084
11121
  try {
11085
- rmSync5(join20(dir, ".git"), { recursive: true, force: true });
11122
+ rmSync5(join21(dir, ".git"), { recursive: true, force: true });
11086
11123
  return [];
11087
11124
  } catch {
11088
11125
  return entries;
@@ -11091,7 +11128,7 @@ function cleanFailedCloneDir(dir) {
11091
11128
  return entries;
11092
11129
  }
11093
11130
  function validateCloneTarget(dir) {
11094
- if (!existsSync22(dir)) return false;
11131
+ if (!existsSync23(dir)) return false;
11095
11132
  let entries;
11096
11133
  try {
11097
11134
  entries = readdirSync6(dir);
@@ -11214,7 +11251,7 @@ async function actorLabels(token, appId) {
11214
11251
  }
11215
11252
 
11216
11253
  // src/cli/commands/releases.ts
11217
- var DEPLOY_URL12 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
11254
+ var DEPLOY_URL13 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
11218
11255
  var releases_default = defineDeepspaceCommand({
11219
11256
  meta: {
11220
11257
  name: "releases",
@@ -11249,8 +11286,8 @@ var releases_default = defineDeepspaceCommand({
11249
11286
  const spinner2 = args.json ? null : createSpinner();
11250
11287
  spinner2?.start("Loading release history\u2026");
11251
11288
  const token = await ensureToken();
11252
- const appId = await resolveAppTarget(DEPLOY_URL12, token, appArg, { wranglerEnv: envArg });
11253
- const { releases } = await repoApi(DEPLOY_URL12, token, appId).listReleases(limit);
11289
+ const appId = await resolveAppTarget(DEPLOY_URL13, token, appArg, { wranglerEnv: envArg });
11290
+ const { releases } = await repoApi(DEPLOY_URL13, token, appId).listReleases(limit);
11254
11291
  spinner2?.stop(`Loaded ${releases.length} ${releases.length === 1 ? "release" : "releases"}.`);
11255
11292
  if (!args.json) {
11256
11293
  if (releases.length === 0) {
@@ -11283,7 +11320,7 @@ Retry in a moment, or re-run with --allow-do-deletion to accept the risk.`,
11283
11320
  "do_guard_unavailable"
11284
11321
  );
11285
11322
  }
11286
- var DEPLOY_URL13 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
11323
+ var DEPLOY_URL14 = process.env.DEEPSPACE_DEPLOY_URL ?? PLATFORM_URLS.deploy;
11287
11324
  function pickPreviousRelease(releases) {
11288
11325
  if (releases.length === 0) {
11289
11326
  return { error: "No releases recorded yet \u2014 nothing to roll back to.", code: "no_releases" };
@@ -11345,8 +11382,8 @@ var rollback_default = defineDeepspaceCommand({
11345
11382
  const spinner2 = args.json ? null : createSpinner();
11346
11383
  spinner2?.start("Preparing rollback\u2026");
11347
11384
  const token = await ensureToken();
11348
- const appId = await resolveAppTarget(DEPLOY_URL13, token, appArg, { wranglerEnv: envArg });
11349
- const api4 = repoApi(DEPLOY_URL13, token, appId);
11385
+ const appId = await resolveAppTarget(DEPLOY_URL14, token, appArg, { wranglerEnv: envArg });
11386
+ const api4 = repoApi(DEPLOY_URL14, token, appId);
11350
11387
  let releaseId = args.release ? String(args.release).trim() : "";
11351
11388
  if (!releaseId) {
11352
11389
  const { releases } = await api4.listReleases(2);
@@ -11357,7 +11394,7 @@ var rollback_default = defineDeepspaceCommand({
11357
11394
  spinner2?.message(`Rolling back to ${releaseId}\u2026`);
11358
11395
  let result;
11359
11396
  try {
11360
- result = await apiFetch(DEPLOY_URL13, token, `/api/deploy/${appId}/rollback`, {
11397
+ result = await apiFetch(DEPLOY_URL14, token, `/api/deploy/${appId}/rollback`, {
11361
11398
  method: "POST",
11362
11399
  body: JSON.stringify({
11363
11400
  releaseId,
@@ -11568,7 +11605,7 @@ function printOverlaps(overlaps, json) {
11568
11605
  // src/cli/commands/workspace/local.ts
11569
11606
  import * as p24 from "@clack/prompts";
11570
11607
  import {
11571
- existsSync as existsSync23,
11608
+ existsSync as existsSync24,
11572
11609
  mkdirSync as mkdirSync7,
11573
11610
  readFileSync as readFileSync25,
11574
11611
  realpathSync as realpathSync6,
@@ -11576,7 +11613,7 @@ import {
11576
11613
  statSync as statSync3,
11577
11614
  writeFileSync as writeFileSync7
11578
11615
  } from "fs";
11579
- import { dirname as dirname11, isAbsolute as isAbsolute5, join as join21, relative as relative2, sep as sep2 } from "path";
11616
+ import { dirname as dirname11, isAbsolute as isAbsolute5, join as join22, relative as relative2, sep as sep2 } from "path";
11580
11617
  var WORKSPACE_MARKER = "deepspace-workspace.json";
11581
11618
  function excludeWorktreeDir(appDir, dir) {
11582
11619
  try {
@@ -11597,7 +11634,7 @@ function worktreeMarkerPath(worktreeRoot) {
11597
11634
  const result = runGit(worktreeRoot, ["rev-parse", "--absolute-git-dir"], { allowFail: true });
11598
11635
  if (result.status !== 0) return null;
11599
11636
  const gitDir = result.stdout.toString("utf-8").trim();
11600
- return isAbsolute5(gitDir) ? join21(gitDir, WORKSPACE_MARKER) : null;
11637
+ return isAbsolute5(gitDir) ? join22(gitDir, WORKSPACE_MARKER) : null;
11601
11638
  } catch {
11602
11639
  return null;
11603
11640
  }
@@ -11642,11 +11679,11 @@ function isManagedWorkspaceWorktree(worktreeRoot, workspaceId) {
11642
11679
  function defaultWorkspaceRoot(appDir, workspaceId) {
11643
11680
  const primary = listWorktrees(appDir)[0];
11644
11681
  if (!primary) throw new Error("Git did not report a primary worktree");
11645
- return join21(primary.path, ".deepspace", "ws", workspaceId.slice(3).toLowerCase());
11682
+ return join22(primary.path, ".deepspace", "ws", workspaceId.slice(3).toLowerCase());
11646
11683
  }
11647
11684
  function appDirInWorktree(appDir, worktreeRoot) {
11648
11685
  const appRelative = relative2(realpathSync6(repoToplevel(appDir)), realpathSync6(appDir));
11649
- return appRelative ? join21(worktreeRoot, appRelative) : worktreeRoot;
11686
+ return appRelative ? join22(worktreeRoot, appRelative) : worktreeRoot;
11650
11687
  }
11651
11688
  function primaryAppDir(appDir) {
11652
11689
  const primary = listWorktrees(appDir)[0];
@@ -11681,7 +11718,7 @@ function rematerializeWorkspaceWorktree(appDir, worktreeRoot, branch, workspaceI
11681
11718
  function inOwnLinkedWorktree(appDir, id) {
11682
11719
  if (workspaceIdFromBranch(currentBranch(appDir)) !== id) return false;
11683
11720
  try {
11684
- return statSync3(join21(repoToplevel(appDir), ".git")).isFile();
11721
+ return statSync3(join22(repoToplevel(appDir), ".git")).isFile();
11685
11722
  } catch {
11686
11723
  return false;
11687
11724
  }
@@ -11806,7 +11843,7 @@ function cleanupWorkspaceLocal(appDir, id, trunkBranch, options = {}) {
11806
11843
  }
11807
11844
  runGit(mainDir, ["worktree", "prune"], { allowFail: true });
11808
11845
  out.worktreeDir = null;
11809
- const leftover = existsSync23(linked.path);
11846
+ const leftover = existsSync24(linked.path);
11810
11847
  if (leftover) out.leftoverDir = linked.path;
11811
11848
  else out.worktreeRemoved = linked.path;
11812
11849
  deleteWsBranch(mainDir, branch, expectedBranchOid, out);
@@ -12104,7 +12141,7 @@ var newWorkspaceCommand = defineDeepspaceCommand({
12104
12141
 
12105
12142
  // src/cli/commands/workspace/attach.ts
12106
12143
  import * as p26 from "@clack/prompts";
12107
- import { existsSync as existsSync24, readdirSync as readdirSync7, realpathSync as realpathSync7, rmSync as rmSync6 } from "fs";
12144
+ import { existsSync as existsSync25, readdirSync as readdirSync7, realpathSync as realpathSync7, rmSync as rmSync6 } from "fs";
12108
12145
  import { isAbsolute as isAbsolute7, resolve as resolve19 } from "path";
12109
12146
  function samePath(a, b) {
12110
12147
  const real = (p35) => {
@@ -12124,7 +12161,7 @@ function finishedWorkspaceMessage(id, view) {
12124
12161
  return `Workspace ${id} is ${workspace.status} \u2014 its ref is retained briefly (fetch ${workspace.ref} to inspect), but attach only works on active workspaces.`;
12125
12162
  }
12126
12163
  function cleanFailedFreshAttachDir(dir) {
12127
- if (!existsSync24(dir)) return [];
12164
+ if (!existsSync25(dir)) return [];
12128
12165
  let entries;
12129
12166
  try {
12130
12167
  entries = readdirSync7(dir);
@@ -12206,7 +12243,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
12206
12243
  const localTip = resolveCommit(appDir, `refs/heads/${branch}`);
12207
12244
  if (localTip) {
12208
12245
  let existing = resolveWorkspaceWorktree(listWorktrees(appDir), id);
12209
- if (existing && !existsSync24(existing)) {
12246
+ if (existing && !existsSync25(existing)) {
12210
12247
  runGit(appDir, ["worktree", "prune"], { allowFail: true });
12211
12248
  existing = null;
12212
12249
  }
@@ -12324,7 +12361,7 @@ var attachWorkspaceCommand = defineDeepspaceCommand({
12324
12361
  process.cwd(),
12325
12362
  (typeof args.dir === "string" ? args.dir.trim() : "") || `ws-${id.slice(3).toLowerCase()}`
12326
12363
  );
12327
- if (existsSync24(dir)) {
12364
+ if (existsSync25(dir)) {
12328
12365
  spinner2?.stop("Target exists.");
12329
12366
  throw new Refusal(`${dir} already exists \u2014 pass a different directory.`, "dir_exists");
12330
12367
  }
@@ -12662,12 +12699,12 @@ import * as p30 from "@clack/prompts";
12662
12699
  // src/cli/lib/validation.ts
12663
12700
  import { sync as spawnSync7 } from "cross-spawn";
12664
12701
  import { readFileSync as readFileSync26 } from "fs";
12665
- import { join as join22 } from "path";
12702
+ import { join as join23 } from "path";
12666
12703
  var MAX_SUMMARY_CHARS = 4e3;
12667
12704
  var MAX_OUTPUT_BUFFER = 64 * 1024 * 1024;
12668
12705
  function configuredCommand(appDir) {
12669
12706
  try {
12670
- const pkg2 = JSON.parse(readFileSync26(join22(appDir, "package.json"), "utf-8"));
12707
+ const pkg2 = JSON.parse(readFileSync26(join23(appDir, "package.json"), "utf-8"));
12671
12708
  if (pkg2.scripts?.validate) return `${detectPackageManager(appDir)} run --silent validate`;
12672
12709
  } catch {
12673
12710
  }
@@ -13743,13 +13780,13 @@ function sameRefs(left, right) {
13743
13780
 
13744
13781
  // src/cli/commands/update.ts
13745
13782
  import * as p34 from "@clack/prompts";
13746
- import { existsSync as existsSync25, readFileSync as readFileSync27, writeFileSync as writeFileSync8 } from "fs";
13747
- import { join as join23, resolve as resolve20 } from "path";
13783
+ import { existsSync as existsSync26, readFileSync as readFileSync27, writeFileSync as writeFileSync8 } from "fs";
13784
+ import { join as join24, resolve as resolve20 } from "path";
13748
13785
 
13749
13786
  // package.json
13750
13787
  var package_default = {
13751
13788
  name: "deepspace",
13752
- version: "0.21.0",
13789
+ version: "0.22.0",
13753
13790
  engines: {
13754
13791
  node: ">=22.15.0 <23 || >=24 <25 || >=26 <27"
13755
13792
  },
@@ -13920,18 +13957,18 @@ function gapIsTooWide(from, to) {
13920
13957
  return from.major === 0 && from.minor < OLDEST_SUPPORTED_MINOR;
13921
13958
  }
13922
13959
  function readAppSdkVersion(appDir) {
13923
- const installed = join23(appDir, "node_modules", "deepspace", "package.json");
13924
- if (existsSync25(installed)) {
13960
+ const installed = join24(appDir, "node_modules", "deepspace", "package.json");
13961
+ if (existsSync26(installed)) {
13925
13962
  const parsed2 = JSON.parse(readFileSync27(installed, "utf8"));
13926
13963
  if (typeof parsed2.version === "string") return parsed2.version;
13927
13964
  }
13928
- const manifest = join23(appDir, "package.json");
13929
- if (!existsSync25(manifest)) return null;
13965
+ const manifest = join24(appDir, "package.json");
13966
+ if (!existsSync26(manifest)) return null;
13930
13967
  const parsed = JSON.parse(readFileSync27(manifest, "utf8"));
13931
13968
  return parsed.dependencies?.deepspace ?? null;
13932
13969
  }
13933
13970
  function pinSdkVersion(appDir, version) {
13934
- const path = join23(appDir, "package.json");
13971
+ const path = join24(appDir, "package.json");
13935
13972
  const source = readFileSync27(path, "utf8");
13936
13973
  const manifest = JSON.parse(source);
13937
13974
  const dependencies = manifest.dependencies;
@@ -13958,16 +13995,16 @@ function buildPreviewSecretsUpgradeInstruction(appDir) {
13958
13995
  "vite.config.mts",
13959
13996
  "vite.config.js",
13960
13997
  "vite.config.mjs"
13961
- ].find((candidate) => existsSync25(join23(appDir, candidate)));
13998
+ ].find((candidate) => existsSync26(join24(appDir, candidate)));
13962
13999
  if (!configName) return null;
13963
- const source = readFileSync27(join23(appDir, configName), "utf8");
14000
+ const source = readFileSync27(join24(appDir, configName), "utf8");
13964
14001
  if (source.includes("deepspace-remove-build-preview-secrets")) return null;
13965
14002
  return `${configName}: add the build-preview secret cleanup from ${BUILD_PREVIEW_SECRETS_GUIDE}; app update left this app-owned file unchanged.`;
13966
14003
  }
13967
14004
  function usersSchemaVisibilityUpgradeInstruction(appDir) {
13968
14005
  const schemaName = "src/schemas/users-schema.ts";
13969
- const path = join23(appDir, schemaName);
13970
- if (!existsSync25(path)) return null;
14006
+ const path = join24(appDir, schemaName);
14007
+ if (!existsSync26(path)) return null;
13971
14008
  const source = readFileSync27(path, "utf8");
13972
14009
  if (!/\bmember\s*:\s*\{[^}]*\bread\s*:\s*true\b/s.test(source)) return null;
13973
14010
  return `${schemaName}: review the member user-row visibility change at ${USERS_SCHEMA_VISIBILITY_GUIDE}; app update left this app-owned schema unchanged.`;
@@ -14119,8 +14156,8 @@ var update_default = defineDeepspaceCommand({
14119
14156
 
14120
14157
  // src/cli/cli.ts
14121
14158
  var __dirname = dirname12(fileURLToPath3(import.meta.url));
14122
- var pkg = JSON.parse(readFileSync28(join24(__dirname, "..", "package.json"), "utf-8"));
14123
- if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync26("/etc/ssl/certs/ca-certificates.crt")) {
14159
+ var pkg = JSON.parse(readFileSync28(join25(__dirname, "..", "package.json"), "utf-8"));
14160
+ if (process.platform === "linux" && !process.env.SSL_CERT_FILE && existsSync27("/etc/ssl/certs/ca-certificates.crt")) {
14124
14161
  process.env.SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
14125
14162
  }
14126
14163
  var create2 = defineCommand14({