@sparkelf/dsh-plus 0.2.2-alpha.2.29 → 0.2.2-alpha.2.30

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/lib/apply.js CHANGED
@@ -1,2 +1,2 @@
1
- import { n as parseOfficialWorkspacePackages, r as runApply, t as materializeOfficialPackageScope } from "./apply-08huHfLG.js";
1
+ import { n as parseOfficialWorkspacePackages, r as runApply, t as materializeOfficialPackageScope } from "./apply-e0aMC4B4.js";
2
2
  export { materializeOfficialPackageScope, parseOfficialWorkspacePackages, runApply };
package/lib/bin.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { i as readPatchSet, r as runApply } from "./apply-08huHfLG.js";
2
+ import { r as runApply } from "./apply-e0aMC4B4.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { execFileSync, spawn, spawnSync } from "node:child_process";
5
5
  import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
6
- import { dirname, join, posix, resolve, win32 } from "node:path";
6
+ import { dirname, isAbsolute, join, posix, relative, resolve, win32 } from "node:path";
7
7
  import { homedir } from "node:os";
8
- import semver from "semver";
8
+ import semver, { validRange } from "semver";
9
9
  import { parseDocument } from "yaml";
10
10
  import { fileURLToPath } from "node:url";
11
11
  import { createServer } from "node:net";
@@ -790,6 +790,125 @@ async function waitForAuthenticatedUrl(logPath, timeoutMilliseconds) {
790
790
  }
791
791
  }
792
792
  //#endregion
793
+ //#region lib/types/patch-set.js
794
+ /**
795
+ * Read the Plus distribution's embedded patch set.
796
+ *
797
+ * The distribution owns one patch set for official DSH and, separately, the patches it
798
+ * carries for third-party packages. Both live inside the distribution package: the
799
+ * manifest declares entries, and each entry's payload is a file under `patches/`. A
800
+ * consumer resolves no independently published patch package.
801
+ *
802
+ * The two lists are governed differently. A Plus entry must target an official package
803
+ * that the profile republishes and overrides; a third-party entry must name its upstream
804
+ * and a retirement condition, and never becomes part of the official patch set.
805
+ */
806
+ function object(value, label) {
807
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error(label + " must be an object");
808
+ return value;
809
+ }
810
+ function string(value, label) {
811
+ if (typeof value !== "string" || value === "") throw new Error(label + " must be a non-empty string");
812
+ return value;
813
+ }
814
+ function range(value, label) {
815
+ const text = string(value, label);
816
+ if (validRange(text) === null) throw new Error(label + " is not a semantic-version range: " + text);
817
+ return text;
818
+ }
819
+ /** A payload stays inside the distribution package it is declared by. */
820
+ function patchFile(distributionDirectory, declared, label) {
821
+ const absolute = resolve(distributionDirectory, declared);
822
+ const local = relative(distributionDirectory, absolute);
823
+ if (local === "" || isAbsolute(local) || local === ".." || local.startsWith("../")) throw new Error(label + " must stay inside the distribution package: " + declared);
824
+ if (!existsSync(absolute)) throw new Error(label + " does not exist: " + absolute);
825
+ return local.replaceAll("\\", "/");
826
+ }
827
+ function sourceTarget(value, sourceBaseRevision, label) {
828
+ const target = object(value, label);
829
+ if (target.kind !== "dsh-source") throw new Error(label + ".kind must be dsh-source");
830
+ if (!Array.isArray(target.paths) || target.paths.length === 0) throw new Error(label + ".paths must be a non-empty array");
831
+ const paths = target.paths.map((entry, index) => {
832
+ const path = string(entry, label + ".paths[" + String(index) + "]");
833
+ if (!path.endsWith("/")) throw new Error(label + ".paths entries must be repository directory prefixes");
834
+ return path;
835
+ });
836
+ if (!Array.isArray(target.packages) || target.packages.length === 0) throw new Error(label + ".packages must be a non-empty array");
837
+ return {
838
+ kind: "dsh-source",
839
+ baseRevision: sourceBaseRevision,
840
+ packages: target.packages.map((entry, index) => {
841
+ const name = string(entry, label + ".packages[" + String(index) + "]");
842
+ if (!name.startsWith("@deepseek-ai/")) throw new Error(label + ".packages entries must be official package names");
843
+ return name;
844
+ }),
845
+ paths
846
+ };
847
+ }
848
+ function npmTarget(value, label) {
849
+ const target = object(value, label);
850
+ if (target.kind !== "npm") throw new Error(label + ".kind must be npm");
851
+ return {
852
+ kind: "npm",
853
+ name: string(target.name, label + ".name"),
854
+ range: range(target.range, label + ".range")
855
+ };
856
+ }
857
+ function entry(value, scope, sourceBaseRevision, distributionDirectory, label) {
858
+ const record = object(value, label);
859
+ const id = string(record.id, label + ".id");
860
+ const dsh = range(record.dsh, label + ".dsh");
861
+ const file = patchFile(distributionDirectory, string(record.file, label + ".file"), label + ".file");
862
+ const retireWhen = string(record.retireWhen, label + ".retireWhen");
863
+ const targetLabel = label + ".target";
864
+ const target = scope === "plus" ? object(record.target, targetLabel).kind === "dsh-source" ? sourceTarget(record.target, sourceBaseRevision, targetLabel) : npmTarget(record.target, targetLabel) : npmTarget(record.target, targetLabel);
865
+ if (scope === "third-party") return {
866
+ id,
867
+ scope,
868
+ dsh,
869
+ file,
870
+ retireWhen,
871
+ upstreamUrl: string(record.upstreamUrl, label + ".upstreamUrl"),
872
+ target
873
+ };
874
+ return {
875
+ id,
876
+ scope,
877
+ dsh,
878
+ file,
879
+ retireWhen,
880
+ target
881
+ };
882
+ }
883
+ /**
884
+ * Read and validate the embedded patch set from an installed distribution.
885
+ * @param distributionDirectory - installed `@sparkelf/dsh-plus` directory.
886
+ * @param manifest - its parsed package manifest.
887
+ * @returns the ordered Plus entries, third-party entries, and the exact source base.
888
+ */
889
+ function readPatchSet(distributionDirectory, manifest) {
890
+ const plus = object(manifest.dshPlus, "dshPlus");
891
+ const sourceBaseRevision = string(object(plus.sourceBase, "dshPlus.sourceBase").revision, "dshPlus.sourceBase.revision");
892
+ const declaration = object(plus.patchSet, "dshPlus.patchSet");
893
+ if (declaration.formatVersion !== 1) throw new Error("dshPlus.patchSet.formatVersion must be 1");
894
+ if (!Array.isArray(declaration.entries) || declaration.entries.length === 0) throw new Error("dshPlus.patchSet.entries must be a non-empty array");
895
+ const entries = declaration.entries.map((value, index) => entry(value, "plus", sourceBaseRevision, distributionDirectory, "dshPlus.patchSet.entries[" + String(index) + "]"));
896
+ const thirdPartyRaw = plus.thirdPartyPatches;
897
+ const thirdParty = thirdPartyRaw === void 0 ? [] : Array.isArray(thirdPartyRaw) ? thirdPartyRaw.map((value, index) => entry(value, "third-party", sourceBaseRevision, distributionDirectory, "dshPlus.thirdPartyPatches[" + String(index) + "]")) : (() => {
898
+ throw new Error("dshPlus.thirdPartyPatches must be an array");
899
+ })();
900
+ const ids = /* @__PURE__ */ new Set();
901
+ for (const item of [...entries, ...thirdParty]) {
902
+ if (ids.has(item.id)) throw new Error("duplicate patch entry id: " + item.id);
903
+ ids.add(item.id);
904
+ }
905
+ return {
906
+ entries,
907
+ thirdPartyPatches: thirdParty,
908
+ sourceBaseRevision
909
+ };
910
+ }
911
+ //#endregion
793
912
  //#region lib/types/standalone-profile.js
794
913
  /**
795
914
  * Runtime paths and profile composition for a standalone Plus installation.
@@ -858,11 +977,6 @@ function requireStringArray(value, label) {
858
977
  if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) throw new Error(label + " must be a string array");
859
978
  return value;
860
979
  }
861
- /** Read one non-empty string field. */
862
- function requireString(value, label) {
863
- if (typeof value !== "string" || value.trim() === "") throw new Error(label + " must be a non-empty string");
864
- return value;
865
- }
866
980
  /** Resolve the DSH home, honouring the environment override the launcher itself reads. */
867
981
  function resolveHome(env = process.env) {
868
982
  const configured = env.DSH_HOME;
@@ -900,12 +1014,11 @@ function isWithin(candidate, parent, platform = process.platform) {
900
1014
  * @returns absolute path to the installed distribution.
901
1015
  */
902
1016
  function resolveDistributionDirectory(anchor) {
903
- const ownDirectory = dirname(dirname(fileURLToPath(import.meta.url)));
904
1017
  let resolved;
905
1018
  try {
906
1019
  resolved = dirname(createRequire(anchor).resolve("@sparkelf/dsh-plus/package.json"));
907
1020
  } catch {
908
- return ownDirectory;
1021
+ throw new Error("@sparkelf/dsh-plus is not installed in " + dirname(anchor) + "; run this command from the directory that installed it");
909
1022
  }
910
1023
  let current = resolve(dirname(anchor));
911
1024
  for (;;) {
@@ -914,14 +1027,20 @@ function resolveDistributionDirectory(anchor) {
914
1027
  if (parent === current) break;
915
1028
  current = parent;
916
1029
  }
917
- return ownDirectory;
1030
+ throw new Error("@sparkelf/dsh-plus resolved outside " + resolve(dirname(anchor)) + " (found " + resolved + "); run this command from the directory that installed it");
918
1031
  }
1032
+ /** The reviewed bundle order and pins the installed distribution declares. */
919
1033
  function readDistributionProfile(distributionDirectory) {
920
1034
  const manifest = requireRecord(JSON.parse(readFileSync(join(distributionDirectory, "package.json"), "utf8")), "Plus distribution manifest");
921
1035
  const plus = requireRecord(manifest.dshPlus, "dshPlus");
922
1036
  const profile = requireRecord(plus.profile, "dshPlus.profile");
923
- const dependencies = requireDependencyMap(requireRecord(profile.dependencies, "dshPlus.profile.dependencies"), "dshPlus.profile.dependencies");
1037
+ const rawDependencies = requireRecord(profile.dependencies, "dshPlus.profile.dependencies");
924
1038
  const rawAllowBuilds = requireRecord(profile.allowBuilds, "dshPlus.profile.allowBuilds");
1039
+ const dependencies = {};
1040
+ for (const [name, spec] of Object.entries(rawDependencies)) {
1041
+ if (typeof spec !== "string" || spec === "") throw new Error("dshPlus.profile.dependencies." + name + " must be a non-empty string");
1042
+ dependencies[name] = spec;
1043
+ }
925
1044
  const allowBuilds = {};
926
1045
  for (const [name, allowed] of Object.entries(rawAllowBuilds)) {
927
1046
  if (typeof allowed !== "boolean") throw new Error("dshPlus.profile.allowBuilds." + name + " must be a boolean");
@@ -933,16 +1052,6 @@ function readDistributionProfile(distributionDirectory) {
933
1052
  if (typeof spec !== "string" || spec === "") throw new Error("dshPlus.profile.overrides." + name + " must be a non-empty string");
934
1053
  overrides[name] = spec;
935
1054
  }
936
- const editions = {};
937
- const rawEditions = plus.editions === void 0 ? {} : requireRecord(plus.editions, "dshPlus.editions");
938
- for (const [id, value] of Object.entries(rawEditions)) {
939
- const edition = requireRecord(value, "dshPlus.editions." + id);
940
- editions[id] = {
941
- label: requireString(edition.label, "dshPlus.editions." + id + ".label"),
942
- bundles: requireStringArray(edition.bundles, "dshPlus.editions." + id + ".bundles"),
943
- packages: requireDependencyMap(requireRecord(edition.packages, "dshPlus.editions." + id + ".packages"), "dshPlus.editions." + id + ".packages")
944
- };
945
- }
946
1055
  const compatibility = requireRecord(plus.compatibility, "dshPlus.compatibility");
947
1056
  return {
948
1057
  name: String(manifest.name),
@@ -950,20 +1059,10 @@ function readDistributionProfile(distributionDirectory) {
950
1059
  dependencies,
951
1060
  allowBuilds,
952
1061
  overrides,
953
- editions,
954
1062
  dshRange: String(compatibility.dsh),
955
1063
  version: String(manifest.version)
956
1064
  };
957
1065
  }
958
- /** Read one package-name-to-spec map, rejecting empty entries. */
959
- function requireDependencyMap(value, label) {
960
- const dependencies = {};
961
- for (const [name, spec] of Object.entries(value)) {
962
- if (typeof spec !== "string" || spec === "") throw new Error(label + "." + name + " must be a non-empty string");
963
- dependencies[name] = spec;
964
- }
965
- return dependencies;
966
- }
967
1066
  /**
968
1067
  * Give the profile its own installed tree, built from the distribution's declarations.
969
1068
  *
@@ -983,11 +1082,7 @@ function requireDependencyMap(value, label) {
983
1082
  * @param consumerDirectory - directory whose `node_modules` holds the installation.
984
1083
  */
985
1084
  function installProfilePackages(paths, consumerDirectory) {
986
- if (!existsSync(join(consumerDirectory, "node_modules"))) {
987
- installWithRegistryFallback(paths);
988
- alignReplacedPackageNames(join(paths.profileDirectory, "node_modules"));
989
- return;
990
- }
1085
+ if (!existsSync(join(consumerDirectory, "node_modules"))) throw new Error("no node_modules in " + consumerDirectory + "; run npm install there first");
991
1086
  const profileModules = join(paths.profileDirectory, "node_modules");
992
1087
  if (existsSync(profileModules)) {
993
1088
  linkNestedBundles(paths, profileModules);
@@ -1009,7 +1104,6 @@ function installProfilePackages(paths, consumerDirectory) {
1009
1104
  function installWithRegistryFallback(paths) {
1010
1105
  const registries = registryOrder();
1011
1106
  for (const [index, registry] of registries.entries()) {
1012
- if (index > 0) rmSync(join(paths.profileDirectory, "pnpm-lock.yaml"), { force: true });
1013
1107
  const result = spawnSync("pnpm", [
1014
1108
  "install",
1015
1109
  "--no-frozen-lockfile",
@@ -1018,8 +1112,7 @@ function installWithRegistryFallback(paths) {
1018
1112
  ], {
1019
1113
  cwd: paths.profileDirectory,
1020
1114
  stdio: "inherit",
1021
- shell: process.platform === "win32",
1022
- timeout: 5 * 6e4
1115
+ shell: process.platform === "win32"
1023
1116
  });
1024
1117
  if (result.error !== void 0) throw result.error;
1025
1118
  if (result.status === 0) return;
@@ -1078,7 +1171,7 @@ const MAINLAND_REGISTRY = "https://registry.npmmirror.com";
1078
1171
  */
1079
1172
  function registryOrder() {
1080
1173
  const configured = process.env.DSH_PLUS_INSTALL_REGISTRY;
1081
- if (configured !== void 0 && configured !== "") return [configured, configured === MAINLAND_REGISTRY ? OFFICIAL_REGISTRY : MAINLAND_REGISTRY];
1174
+ if (configured !== void 0 && configured !== "") return [configured, MAINLAND_REGISTRY];
1082
1175
  const locale = [
1083
1176
  process.env.LANG,
1084
1177
  process.env.LC_ALL,
@@ -1179,85 +1272,12 @@ function resolvePaths(anchor, env = process.env) {
1179
1272
  *
1180
1273
  * @param paths - resolved standalone paths.
1181
1274
  * @param consumerDirectory - directory whose `node_modules` holds the installed packages.
1182
- * @param edition - edition id whose package list to install, or undefined for the default.
1183
1275
  * @returns whether this call created the manifest.
1184
1276
  */
1185
- function ensureProfile(paths, consumerDirectory, edition) {
1277
+ function ensureProfile(paths, consumerDirectory) {
1186
1278
  const manifestPath = join(paths.profileDirectory, "package.json");
1187
1279
  const distribution = readDistributionProfile(paths.distributionDirectory);
1188
- const composition = edition === void 0 ? void 0 : distribution.editions[edition];
1189
- if (edition !== void 0 && composition === void 0) {
1190
- const offered = Object.keys(distribution.editions);
1191
- throw new Error("unknown edition \"" + edition + "\"; this release offers " + (offered.length === 0 ? "(none)" : offered.join(", ")));
1192
- }
1193
- for (const name of Object.keys(composition?.packages ?? {})) if (name.startsWith("@deepseek-ai/")) throw new Error("edition \"" + String(edition) + "\" lists the official package " + name + "; editions contain only third-party or self-developed plugins");
1194
- const runtime = distribution.dshRange.replace(/^>=?/u, "");
1195
- const baseBundles = composition === void 0 ? distribution.bundles : distribution.bundles.filter((bundle) => bundle.startsWith("@deepseek-ai/") || bundle === "@sparkelf/dsh-plus");
1196
- const basePackages = composition === void 0 ? distribution.dependencies : {
1197
- "@deepseek-ai/dsh": distribution.dshRange,
1198
- "@sparkelf/dsh-plus": distribution.version,
1199
- "@deepseek-ai/cordis": "^4.0.6-alpha.1",
1200
- "@deepseek-ai/cordis-plugin-group": "^1.0.6-alpha.1",
1201
- "@deepseek-ai/cordis-plugin-include": "^1.0.11-alpha.1",
1202
- "@deepseek-ai/cordis-plugin-loader": "^1.0.7-alpha.1",
1203
- "@deepseek-ai/dsh-home-paths": runtime,
1204
- "@deepseek-ai/dsh-launch-environment": runtime,
1205
- "@deepseek-ai/dsh-agent": runtime,
1206
- "@deepseek-ai/dsh-llm": runtime,
1207
- "@deepseek-ai/dsh-scope": runtime,
1208
- "@deepseek-ai/dsh-session": runtime,
1209
- "@deepseek-ai/dsh-system-prompt": runtime,
1210
- "@deepseek-ai/dsh-user-approval": runtime,
1211
- "@deepseek-ai/dsh-attachment": runtime,
1212
- "@deepseek-ai/dsh-compaction": runtime,
1213
- "@deepseek-ai/dsh-fs": runtime,
1214
- "@deepseek-ai/dsh-shell": runtime,
1215
- "@deepseek-ai/dsh-spill": runtime,
1216
- "@deepseek-ai/dsh-sandbox": runtime,
1217
- "@deepseek-ai/dsh-ptc-runtime": runtime,
1218
- "@deepseek-ai/dsh-llm-deepseek": runtime,
1219
- "@deepseek-ai/dsh-deepseek-account": runtime,
1220
- "@deepseek-ai/dsh-anonymous-user-id": runtime,
1221
- "@deepseek-ai/dsh-bash-local": runtime,
1222
- "@deepseek-ai/dsh-client-store": runtime,
1223
- "@deepseek-ai/dsh-jobs": runtime,
1224
- "@deepseek-ai/dsh-sdk-protocol": runtime,
1225
- "@deepseek-ai/dsh-session-persistence": runtime,
1226
- "@deepseek-ai/dsh-session-telemetry": runtime,
1227
- "@deepseek-ai/dsh-session-title-llm": runtime,
1228
- "@deepseek-ai/dsh-util-workspace-path": runtime,
1229
- "@deepseek-ai/dsh-workflow": runtime,
1230
- ...Object.fromEntries(baseBundles.filter((bundle) => bundle.startsWith("@deepseek-ai/dsh-")).map((bundle) => [bundle, runtime]))
1231
- };
1232
- const compositionPackages = composition === void 0 ? basePackages : {
1233
- ...basePackages,
1234
- ...composition.packages
1235
- };
1236
- for (const [alias, target] of Object.entries({
1237
- "dsh-better-sidebar": "@sparkelf/dsh-better-sidebar",
1238
- "dsh-sql-workbench": "@sparkelf/dsh-sql-workbench"
1239
- })) {
1240
- const spec = compositionPackages[target];
1241
- if (spec !== void 0 && compositionPackages[alias] === void 0) compositionPackages[alias] = "npm:" + target + "@" + spec;
1242
- }
1243
- const compositionBundles = composition === void 0 ? baseBundles : [...baseBundles, ...composition.bundles];
1244
1280
  if (existsSync(manifestPath)) {
1245
- if (composition !== void 0) {
1246
- const manifest = requireRecord(JSON.parse(readFileSync(manifestPath, "utf8")), "Plus profile manifest");
1247
- manifest.dependencies = {
1248
- ...manifest.dependencies,
1249
- ...compositionPackages
1250
- };
1251
- manifest.dsh = {
1252
- ...manifest.dsh,
1253
- profile: {
1254
- ...manifest.dsh?.profile,
1255
- bundles: [...compositionBundles],
1256
- ...edition === void 0 ? {} : { plusEdition: edition }
1257
- }
1258
- };
1259
- writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
1260
- }
1261
1281
  writeProfileOverrides(paths.profileDirectory, distribution.overrides, distribution.allowBuilds, paths.omittedPackages);
1262
1282
  installProfilePackages(paths, consumerDirectory);
1263
1283
  return false;
@@ -1267,11 +1287,14 @@ function ensureProfile(paths, consumerDirectory, edition) {
1267
1287
  name: "dsh-profile-plus",
1268
1288
  private: true,
1269
1289
  type: "module",
1270
- dependencies: compositionPackages,
1290
+ dependencies: {
1291
+ "@sparkelf/dsh-plus": distribution.version,
1292
+ "@deepseek-ai/dsh": distribution.dshRange,
1293
+ ...distribution.dependencies
1294
+ },
1271
1295
  dsh: { profile: {
1272
- bundles: [...compositionBundles],
1273
- patchReload: "live",
1274
- ...edition === void 0 ? {} : { plusEdition: edition }
1296
+ bundles: distribution.bundles,
1297
+ patchReload: "live"
1275
1298
  } }
1276
1299
  };
1277
1300
  writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
@@ -1299,7 +1322,7 @@ function writeProfileOverrides(profileDirectory, overrides, allowBuilds, omitted
1299
1322
  for (const [name, spec] of Object.entries(omittedPackages)) document.setIn(["overrides", name], spec);
1300
1323
  for (const [name, allowed] of Object.entries(allowBuilds)) document.setIn(["allowBuilds", name], allowed);
1301
1324
  if (document.get("nodeLinker") === void 0) document.set("nodeLinker", "hoisted");
1302
- if (document.get("autoInstallPeers") === void 0) document.set("autoInstallPeers", true);
1325
+ if (document.get("autoInstallPeers") === void 0) document.set("autoInstallPeers", false);
1303
1326
  writeFileSync(workspacePath, String(document));
1304
1327
  }
1305
1328
  /** Run git in one directory, returning undefined instead of throwing when asked to. */
@@ -1355,18 +1378,7 @@ function resolveInstalledPackage(from, packageName) {
1355
1378
  try {
1356
1379
  manifestPath = requireFrom.resolve(packageName + "/package.json");
1357
1380
  } catch {
1358
- let directory;
1359
- try {
1360
- directory = dirname(requireFrom.resolve(packageName));
1361
- } catch {
1362
- throw new Error(packageName + " is not installed under " + from);
1363
- }
1364
- while (!existsSync(resolve(directory, "package.json"))) {
1365
- const parent = dirname(directory);
1366
- if (parent === directory) throw new Error(packageName + " has no resolvable package manifest under " + from);
1367
- directory = parent;
1368
- }
1369
- manifestPath = resolve(directory, "package.json");
1381
+ throw new Error(packageName + " is not installed under " + from);
1370
1382
  }
1371
1383
  const manifest = requireRecord(JSON.parse(readFileSync(manifestPath, "utf8")), packageName + " manifest");
1372
1384
  return {
@@ -1396,7 +1408,6 @@ function parseStartOptions(argv) {
1396
1408
  let host = "127.0.0.1";
1397
1409
  let open = true;
1398
1410
  let foreground = false;
1399
- let edition;
1400
1411
  let capabilities;
1401
1412
  for (let index = 0; index < argv.length; index += 1) {
1402
1413
  const token = argv[index];
@@ -1422,13 +1433,6 @@ function parseStartOptions(argv) {
1422
1433
  foreground = true;
1423
1434
  continue;
1424
1435
  }
1425
- if (token === "--edition") {
1426
- const value = argv[index + 1];
1427
- if (value === void 0 || value === "") throw new Error("--edition requires a value");
1428
- edition = value;
1429
- index += 1;
1430
- continue;
1431
- }
1432
1436
  if (token === "--capabilities") {
1433
1437
  const value = argv[index + 1];
1434
1438
  if (value === void 0) throw new Error("--capabilities requires a comma-separated list, or an empty string for none");
@@ -1446,7 +1450,6 @@ function parseStartOptions(argv) {
1446
1450
  host,
1447
1451
  open,
1448
1452
  foreground,
1449
- edition,
1450
1453
  capabilities
1451
1454
  };
1452
1455
  }
@@ -1532,56 +1535,6 @@ function runForeground(entry, profileName, port, host, open) {
1532
1535
  if (!open) args.push("--no-open");
1533
1536
  return spawnSync(process.execPath, args, { stdio: "inherit" }).status ?? 1;
1534
1537
  }
1535
- /** Parse the install command's edition selection. */
1536
- function parseInstallOptions(argv) {
1537
- let edition;
1538
- let profile;
1539
- for (let index = 0; index < argv.length; index += 1) {
1540
- const token = argv[index];
1541
- if (token === "--edition") {
1542
- const value = argv[index + 1];
1543
- if (value === void 0 || value === "") throw new Error("--edition requires a value");
1544
- edition = value;
1545
- index += 1;
1546
- continue;
1547
- }
1548
- if (token === "--profile") {
1549
- const value = argv[index + 1];
1550
- if (value === void 0 || value === "") throw new Error("--profile requires a value");
1551
- profile = value;
1552
- index += 1;
1553
- continue;
1554
- }
1555
- throw new Error("unknown option: " + String(token));
1556
- }
1557
- if (edition === void 0) throw new Error("install requires --edition personal or --edition team");
1558
- return {
1559
- edition,
1560
- profile
1561
- };
1562
- }
1563
- /**
1564
- * Install one edition's package manifest into the profile.
1565
- *
1566
- * The profile's `package.json` is the install artifact; there is no separate standalone
1567
- * package. A later `start` uses the same manifest, so changing the edition is a new
1568
- * install rather than a second product.
1569
- *
1570
- * @param argv - arguments after `install`.
1571
- * @returns the process exit code.
1572
- */
1573
- function install(argv) {
1574
- const { edition, profile } = parseInstallOptions(argv);
1575
- const base = resolvePaths(declarationAnchor());
1576
- const paths = profile === void 0 ? base : {
1577
- ...base,
1578
- profileName: profile,
1579
- profileDirectory: join(base.home, "profiles", profile)
1580
- };
1581
- ensureProfile(paths, installationRoot(), edition);
1582
- console.log("Installed the " + edition + " edition into " + paths.profileDirectory);
1583
- return 0;
1584
- }
1585
1538
  async function start(argv) {
1586
1539
  const options = parseStartOptions(argv);
1587
1540
  const anchor = installationAnchor();
@@ -1615,9 +1568,8 @@ async function start(argv) {
1615
1568
  }
1616
1569
  console.log("pnpm installed.");
1617
1570
  }
1618
- const created = ensureProfile(paths, installationRoot(), options.edition);
1571
+ const created = ensureProfile(paths, installationRoot());
1619
1572
  console.log(created ? "Created the " + paths.profileName + " profile at " + paths.profileDirectory : "Using the existing " + paths.profileName + " profile");
1620
- if (options.edition !== void 0) console.log("Edition: " + options.edition);
1621
1573
  for (const label of applyProfileNpmPatches(paths.distributionDirectory, paths.profileDirectory)) console.log("Applied the reviewed patch " + label);
1622
1574
  const answers = created || !existsSync(join(paths.home, "capabilities.json")) ? options.capabilities === void 0 ? await interviewCapabilities(true) : selectCapabilities(options.capabilities) : void 0;
1623
1575
  if (answers !== void 0) {
@@ -1960,23 +1912,6 @@ async function doctor() {
1960
1912
  const record = readCapabilityRecord(paths.home);
1961
1913
  const drifted = record === void 0 ? [] : CAPABILITIES.filter((capability) => record.enabled.includes(capability.id) !== actual.mounted.includes(capability.id));
1962
1914
  check(drifted.length === 0, drifted.length === 0 ? "capabilities: " + (actual.mounted.length === 0 ? "(none enabled)" : actual.mounted.join(", ")) : "capabilities disagree with capabilities.json: " + drifted.map((capability) => capability.id).join(", ") + " (run dsh-plus capabilities)");
1963
- const profileManifestPath = join(paths.profileDirectory, "package.json");
1964
- if (existsSync(profileManifestPath)) {
1965
- const profileManifest = JSON.parse(readFileSync(profileManifestPath, "utf8"));
1966
- const editionId = profileManifest.dsh?.profile?.plusEdition;
1967
- if (editionId !== void 0) {
1968
- const edition = readDistributionProfile(paths.distributionDirectory).editions[editionId];
1969
- if (edition === void 0) check(false, "edition \"" + editionId + "\" is not declared by this distribution");
1970
- else {
1971
- const bundles = new Set(profileManifest.dsh?.profile?.bundles ?? []);
1972
- const missingBundles = edition.bundles.filter((bundle) => !bundles.has(bundle));
1973
- const packageNames = Object.keys(edition.packages);
1974
- const missingPackages = packageNames.filter((name) => !existsSync(join(paths.profileDirectory, "node_modules", ...name.split("/"), "package.json")));
1975
- check(missingBundles.length === 0, "edition " + editionId + ": " + String(edition.bundles.length - missingBundles.length) + "/" + String(edition.bundles.length) + " bundles mounted" + (missingBundles.length === 0 ? "" : " (missing " + missingBundles.join(", ") + ")"));
1976
- check(missingPackages.length === 0, "edition " + editionId + ": " + String(packageNames.length - missingPackages.length) + "/" + String(packageNames.length) + " packages installed" + (missingPackages.length === 0 ? "" : " (missing " + missingPackages.join(", ") + ")"));
1977
- }
1978
- }
1979
- }
1980
1915
  console.log(failures === 0 ? "No problems found." : String(failures) + " problem(s) found.");
1981
1916
  return failures === 0 ? 0 : 1;
1982
1917
  }
@@ -1984,7 +1919,6 @@ const USAGE = [
1984
1919
  "Usage: dsh-plus <command> [options]",
1985
1920
  "",
1986
1921
  "Commands:",
1987
- " install install an edition package manifest into the profile",
1988
1922
  " start start the server (first run creates the profile)",
1989
1923
  " stop stop the server",
1990
1924
  " status report whether the server is running",
@@ -1997,11 +1931,6 @@ const USAGE = [
1997
1931
  " --host <h> interface to bind (default 127.0.0.1)",
1998
1932
  " --no-open do not open a browser",
1999
1933
  " --foreground run in this terminal instead of in the background",
2000
- " --edition <id> install the named edition manifest (personal or team)",
2001
- "",
2002
- "install options:",
2003
- " --edition <id> package manifest to install (personal or team)",
2004
- " --profile <n> profile name to install into (default: this installation)",
2005
1934
  "",
2006
1935
  "capabilities options:",
2007
1936
  " --enable <ids> enable the comma-separated capability ids",
@@ -2024,7 +1953,6 @@ async function runStandaloneCli(argv) {
2024
1953
  console.log(USAGE);
2025
1954
  return 0;
2026
1955
  }
2027
- if (command === "install") return install(rest);
2028
1956
  if (command === "start") return await start(rest);
2029
1957
  if (command === "stop") return stop();
2030
1958
  if (command === "status") return status();
@@ -1,4 +1,4 @@
1
- /** Materialize the Plus distribution's embedded patch set without Desktop. */
1
+ /** Materialize the Plus distribution's independent patch packages without Desktop. */
2
2
  /** One official workspace package available as a profile peer dependency. */
3
3
  export interface OfficialWorkspacePackage {
4
4
  name: string;