deepspace 0.19.1 → 0.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # deepspace
2
2
 
3
+ ## 0.19.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Harden post-release upgrade and scaffold behavior: pin only real package
8
+ dependencies, expose PresenceRoom offline state, restrict fresh user rows to
9
+ their owners, wire feature roles and cron tasks correctly, and remove generated
10
+ build-preview secrets from deploy output while guiding existing Vite configs.
11
+
3
12
  ## 0.19.1
4
13
 
5
14
  ### Patch Changes
package/dist/cli.js CHANGED
@@ -3869,7 +3869,7 @@ function describeFilesFailure(status3, body) {
3869
3869
  import * as p6 from "@clack/prompts";
3870
3870
  import { execSync as execSync2 } from "child_process";
3871
3871
  import { createHash as createHash2 } from "crypto";
3872
- import { existsSync as existsSync14, readFileSync as readFileSync17, readdirSync as readdirSync4 } from "fs";
3872
+ import { existsSync as existsSync14, lstatSync as lstatSync2, readFileSync as readFileSync17, readdirSync as readdirSync4, unlinkSync as unlinkSync2 } from "fs";
3873
3873
  import { dirname as dirname7, join as join15, resolve as resolve11 } from "path";
3874
3874
 
3875
3875
  // src/documentation/deploy.ts
@@ -4409,6 +4409,16 @@ function findWorkerOwnedNotFoundBlockers(source, file) {
4409
4409
 
4410
4410
  // src/cli/commands/deploy/build.ts
4411
4411
  var RESERVED_RUN_WORKER_FIRST2 = new Set(RESERVED_RUN_WORKER_FIRST);
4412
+ function removeBuildDevVars(workerDir) {
4413
+ const path = join15(workerDir, ".dev.vars");
4414
+ if (!existsSync14(path)) return false;
4415
+ const stat = lstatSync2(path);
4416
+ if (!stat.isFile() || stat.isSymbolicLink()) {
4417
+ throw new Error(`Refusing unsafe build secret path: ${path}`);
4418
+ }
4419
+ unlinkSync2(path);
4420
+ return true;
4421
+ }
4412
4422
  function declaredCompatibilityDate(config) {
4413
4423
  const declared = config.compatibility_date;
4414
4424
  return typeof declared === "string" && /^\d{4}-\d{2}-\d{2}$/.test(declared) ? declared : null;
@@ -4465,6 +4475,11 @@ async function buildDeployBundle(options) {
4465
4475
  );
4466
4476
  }
4467
4477
  const workerDir = dirname7(outputWranglerPath);
4478
+ try {
4479
+ removeBuildDevVars(workerDir);
4480
+ } catch (error) {
4481
+ output.die(errorMessage(error), "build_output_unsafe");
4482
+ }
4468
4483
  const workerBundlePath = join15(workerDir, outputConfig.main);
4469
4484
  const clientDir = outputConfig.assets?.directory ? resolve11(workerDir, outputConfig.assets.directory) : null;
4470
4485
  if (!existsSync14(workerBundlePath)) {
@@ -7292,7 +7307,9 @@ function integrateCode(config, targetDir, emit) {
7292
7307
  if (insertion.import && !content.includes(insertion.import)) {
7293
7308
  const importIndex = content.search(/^import\s/m);
7294
7309
  content = `${content.slice(0, importIndex < 0 ? 0 : importIndex)}${insertion.import}
7295
- ${content.slice(importIndex < 0 ? 0 : importIndex)}`;
7310
+ ${content.slice(
7311
+ importIndex < 0 ? 0 : importIndex
7312
+ )}`;
7296
7313
  }
7297
7314
  const currentMarkerIndex = content.indexOf(insertion.marker);
7298
7315
  const insertAt = insertion.placement === "before" ? currentMarkerIndex : currentMarkerIndex + insertion.marker.length;
@@ -7446,15 +7463,22 @@ ${css}`;
7446
7463
  return unresolved;
7447
7464
  }
7448
7465
  function unresolvedRoute(route, config, reason, emit) {
7466
+ const roles = routeRolesSuffix(route);
7449
7467
  emit("");
7450
7468
  emit(" Add manually to src/nav.ts:");
7451
- emit(` { path: '${route.path}', label: '${config.name}' },`);
7469
+ emit(` { path: '${route.path}', label: '${config.name}'${roles} },`);
7452
7470
  return {
7453
7471
  area: "nav",
7454
7472
  reason,
7455
- steps: [`Add { path: '${route.path}', label: '${config.name}' } to the exported nav array.`]
7473
+ steps: [
7474
+ `Add { path: '${route.path}', label: '${config.name}'${roles} } to the exported nav array.`
7475
+ ]
7456
7476
  };
7457
7477
  }
7478
+ function routeRolesSuffix(route) {
7479
+ const roles = route.roles?.length ? route.roles : route.protected === false ? [] : ["member"];
7480
+ return roles.length ? `, roles: [${roles.map((role) => `'${role}' as Role`).join(", ")}]` : "";
7481
+ }
7458
7482
  function integrateRoute(config, targetDir, emit) {
7459
7483
  if (!config.route) return [];
7460
7484
  const navPath = join17(targetDir, "src", "nav.ts");
@@ -7478,7 +7502,7 @@ function integrateRoute(config, targetDir, emit) {
7478
7502
  )
7479
7503
  ];
7480
7504
  }
7481
- const roles = config.route.protected === false ? "" : ", roles: ['member' as Role]";
7505
+ const roles = routeRolesSuffix(config.route);
7482
7506
  const entry = ` { path: '${routePath}', label: '${config.name}'${roles} },`;
7483
7507
  content = content.replace(NAV_MARKER, `${NAV_MARKER}
7484
7508
  ${entry}`);
@@ -7674,7 +7698,7 @@ function installFeature(options) {
7674
7698
  );
7675
7699
  if (config.instructions?.length) {
7676
7700
  emit("");
7677
- emit("--- Manual wiring needed ---");
7701
+ emit("--- Next steps ---");
7678
7702
  emit("");
7679
7703
  config.instructions.forEach((instruction, index) => {
7680
7704
  emit(`${index + 1}. ${instruction}`);
@@ -8017,6 +8041,7 @@ Create one with: deepspace app create <name>`,
8017
8041
  }
8018
8042
  if (!outcome.ok) {
8019
8043
  throw new Refusal(outcome.error, outcome.code, {
8044
+ actionRequired: outcome.code === "manual_integration_required",
8020
8045
  ..."data" in outcome ? { extra: outcome.data } : {}
8021
8046
  });
8022
8047
  }
@@ -13603,7 +13628,7 @@ import { join as join23, resolve as resolve20 } from "path";
13603
13628
  // package.json
13604
13629
  var package_default = {
13605
13630
  name: "deepspace",
13606
- version: "0.19.1",
13631
+ version: "0.19.2",
13607
13632
  engines: {
13608
13633
  node: ">=22.15.0 <23 || >=24 <25 || >=26 <27"
13609
13634
  },
@@ -13755,6 +13780,8 @@ var package_default = {
13755
13780
  // src/cli/commands/update.ts
13756
13781
  var REGISTRY = "https://registry.npmjs.org/deepspace/latest";
13757
13782
  var DOCS_URL = "https://documentation.deep.space/cli-reference/commands";
13783
+ var BUILD_PREVIEW_SECRETS_GUIDE = "https://github.com/deepdotspace/deepspace-sdk/blob/main/docs/migrations/build-preview-secrets.md";
13784
+ var USERS_SCHEMA_VISIBILITY_GUIDE = "https://github.com/deepdotspace/deepspace-sdk/blob/main/docs/migrations/users-schema-member-visibility.md";
13758
13785
  var COMPATIBLE_AI_VERSION = package_default.dependencies.ai;
13759
13786
  var OLDEST_SUPPORTED_MINOR = 12;
13760
13787
  function parseVersion(raw) {
@@ -13780,18 +13807,45 @@ function readAppSdkVersion(appDir) {
13780
13807
  function pinSdkVersion(appDir, version) {
13781
13808
  const path = join23(appDir, "package.json");
13782
13809
  const source = readFileSync27(path, "utf8");
13783
- let updated = source.replace(
13784
- /("deepspace"\s*:\s*")[^"]+(")/,
13785
- (_match, head, tail) => `${head}^${version}${tail}`
13786
- );
13787
- updated = updated.replace(
13788
- /("ai"\s*:\s*")[^"]+(")/,
13789
- (_match, head, tail) => `${head}${COMPATIBLE_AI_VERSION}${tail}`
13790
- );
13791
- if (updated === source) return false;
13792
- writeFileSync8(path, updated);
13810
+ const manifest = JSON.parse(source);
13811
+ const dependencies = manifest.dependencies;
13812
+ if (!dependencies || typeof dependencies !== "object" || Array.isArray(dependencies)) return false;
13813
+ let changed = false;
13814
+ if (Object.prototype.hasOwnProperty.call(dependencies, "deepspace") && typeof dependencies.deepspace === "string" && dependencies.deepspace !== `^${version}`) {
13815
+ dependencies.deepspace = `^${version}`;
13816
+ changed = true;
13817
+ }
13818
+ if (Object.prototype.hasOwnProperty.call(dependencies, "ai") && typeof dependencies.ai === "string" && dependencies.ai !== COMPATIBLE_AI_VERSION) {
13819
+ dependencies.ai = COMPATIBLE_AI_VERSION;
13820
+ changed = true;
13821
+ }
13822
+ if (!changed) return false;
13823
+ const eol = source.includes("\r\n") ? "\r\n" : "\n";
13824
+ const indent = source.match(/\r?\n([\t ]+)"/)?.[1] ?? " ";
13825
+ const finalEol = source.endsWith("\n") ? eol : "";
13826
+ writeFileSync8(path, JSON.stringify(manifest, null, indent).replaceAll("\n", eol) + finalEol);
13793
13827
  return true;
13794
13828
  }
13829
+ function buildPreviewSecretsUpgradeInstruction(appDir) {
13830
+ const configName = [
13831
+ "vite.config.ts",
13832
+ "vite.config.mts",
13833
+ "vite.config.js",
13834
+ "vite.config.mjs"
13835
+ ].find((candidate) => existsSync25(join23(appDir, candidate)));
13836
+ if (!configName) return null;
13837
+ const source = readFileSync27(join23(appDir, configName), "utf8");
13838
+ if (source.includes("deepspace-remove-build-preview-secrets")) return null;
13839
+ return `${configName}: add the build-preview secret cleanup from ${BUILD_PREVIEW_SECRETS_GUIDE}; app update left this app-owned file unchanged.`;
13840
+ }
13841
+ function usersSchemaVisibilityUpgradeInstruction(appDir) {
13842
+ const schemaName = "src/schemas/users-schema.ts";
13843
+ const path = join23(appDir, schemaName);
13844
+ if (!existsSync25(path)) return null;
13845
+ const source = readFileSync27(path, "utf8");
13846
+ if (!/\bmember\s*:\s*\{[^}]*\bread\s*:\s*true\b/s.test(source)) return null;
13847
+ return `${schemaName}: review the member user-row visibility change at ${USERS_SCHEMA_VISIBILITY_GUIDE}; app update left this app-owned schema unchanged.`;
13848
+ }
13795
13849
  async function latestPublishedVersion() {
13796
13850
  const response = await fetch(REGISTRY, { signal: AbortSignal.timeout(15e3) }).catch(
13797
13851
  (error) => {
@@ -13881,27 +13935,36 @@ var update_default = defineDeepspaceCommand({
13881
13935
  }
13882
13936
  const dryRun = args["dry-run"] === true;
13883
13937
  const plan = planAppMigrations(appDir);
13938
+ const previewSecretsInstruction = buildPreviewSecretsUpgradeInstruction(appDir);
13939
+ const usersSchemaInstruction = usersSchemaVisibilityUpgradeInstruction(appDir);
13940
+ const manualInstructions = [previewSecretsInstruction, usersSchemaInstruction].filter(
13941
+ (instruction) => instruction !== null
13942
+ );
13884
13943
  const pinned = dryRun ? false : pinSdkVersion(appDir, targetRaw);
13885
13944
  if (!dryRun && plan.edits.length) applyAppMigrationPlan(appDir, plan);
13886
13945
  if (!args.json) {
13887
13946
  p34.log.info(`deepspace ${currentRaw} \u2192 ${targetRaw}`);
13888
13947
  if (pinned) p34.log.success("package.json now asks for the current SDK");
13948
+ for (const instruction of manualInstructions) p34.log.warn(instruction);
13889
13949
  if (!plan.pending.length && !plan.blockers.length) {
13890
- p34.log.success("No source changes required.");
13950
+ p34.log.success("No automatic source changes required.");
13891
13951
  }
13892
13952
  reportPlan(plan, !dryRun);
13893
13953
  }
13894
- if (plan.blockers.length) {
13954
+ if (plan.blockers.length || manualInstructions.length) {
13955
+ const remaining = plan.blockers.length + manualInstructions.length;
13895
13956
  throw new Refusal(
13896
- `${plan.blockers.length} change(s) need a human or agent edit; each is listed above with its file, line, and the change required.`,
13957
+ `${remaining} change(s) need a human or agent edit; follow the returned manual instructions and blockers.`,
13897
13958
  "manual_changes_required",
13898
13959
  {
13960
+ ...pinned ? { action: cliAction("npm", "install") } : {},
13899
13961
  actionRequired: true,
13900
13962
  extra: {
13901
13963
  currentVersion: currentRaw,
13902
13964
  targetVersion: targetRaw,
13903
13965
  applied: plan.pending.map((migration) => migration.id),
13904
- blockers: plan.blockers
13966
+ blockers: plan.blockers,
13967
+ manualInstructions
13905
13968
  }
13906
13969
  }
13907
13970
  );
@@ -13912,6 +13975,7 @@ var update_default = defineDeepspaceCommand({
13912
13975
  targetVersion: targetRaw,
13913
13976
  pinned,
13914
13977
  dryRun,
13978
+ manualInstructions,
13915
13979
  applied: plan.pending.map((migration) => ({
13916
13980
  id: migration.id,
13917
13981
  description: migration.description,