@sparkelf/dsh-plus 0.1.0-rc.34 → 0.1.0-rc.35

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/bin.js CHANGED
@@ -6,6 +6,7 @@ import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, rm
6
6
  import { dirname, join, posix, resolve, win32 } from "node:path";
7
7
  import { homedir } from "node:os";
8
8
  import semver from "semver";
9
+ import { parseDocument } from "yaml";
9
10
  import { fileURLToPath } from "node:url";
10
11
  import { createServer } from "node:net";
11
12
  //#region lib/types/registry-versions.js
@@ -319,11 +320,18 @@ function readDistributionProfile(distributionDirectory) {
319
320
  if (typeof allowed !== "boolean") throw new Error("dshPlus.profile.allowBuilds." + name + " must be a boolean");
320
321
  allowBuilds[name] = allowed;
321
322
  }
323
+ const overrides = {};
324
+ const rawOverrides = profile.overrides === void 0 ? {} : requireRecord(profile.overrides, "dshPlus.profile.overrides");
325
+ for (const [name, spec] of Object.entries(rawOverrides)) {
326
+ if (typeof spec !== "string" || spec === "") throw new Error("dshPlus.profile.overrides." + name + " must be a non-empty string");
327
+ overrides[name] = spec;
328
+ }
322
329
  return {
323
330
  name: String(manifest.name),
324
331
  bundles: requireStringArray(profile.bundles, "dshPlus.profile.bundles"),
325
332
  dependencies,
326
333
  allowBuilds,
334
+ overrides,
327
335
  version: String(manifest.version)
328
336
  };
329
337
  }
@@ -424,8 +432,30 @@ function ensureProfile(paths, consumerDirectory) {
424
432
  } }
425
433
  };
426
434
  writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
435
+ writeProfileOverrides(paths.profileDirectory, distribution.overrides);
427
436
  return true;
428
437
  }
438
+ /**
439
+ * Record the distribution's package substitutions in the profile workspace.
440
+ *
441
+ * pnpm reads \`overrides\` from \`pnpm-workspace.yaml\` since version 10 and ignores the
442
+ * same key in \`package.json\`, so a profile that carried it in the manifest would
443
+ * silently install the official package the override meant to replace.
444
+ *
445
+ * @param profileDirectory - the standalone profile directory.
446
+ * @param overrides - official package name to published replacement spec.
447
+ */
448
+ function writeProfileOverrides(profileDirectory, overrides) {
449
+ const workspacePath = join(profileDirectory, "pnpm-workspace.yaml");
450
+ const document = parseDocument(existsSync(workspacePath) ? readFileSync(workspacePath, "utf8") : "");
451
+ const [documentError] = document.errors;
452
+ if (documentError !== void 0) throw new Error("Plus profile workspace is not valid YAML", { cause: documentError });
453
+ if (document.get("packages") === void 0) document.set("packages", ["."]);
454
+ for (const [name, spec] of Object.entries(overrides)) document.setIn(["overrides", name], spec);
455
+ if (document.get("nodeLinker") === void 0) document.set("nodeLinker", "hoisted");
456
+ if (document.get("autoInstallPeers") === void 0) document.set("autoInstallPeers", false);
457
+ writeFileSync(workspacePath, String(document));
458
+ }
429
459
  /** Run git in one directory, returning undefined instead of throwing when asked to. */
430
460
  function git(root, args, acceptFailure = false) {
431
461
  const result = spawnSync("git", args, {
@@ -54,6 +54,7 @@ export declare function readDistributionProfile(distributionDirectory: string):
54
54
  readonly bundles: readonly string[];
55
55
  readonly dependencies: Readonly<Record<string, string>>;
56
56
  readonly allowBuilds: Readonly<Record<string, boolean>>;
57
+ readonly overrides: Readonly<Record<string, string>>;
57
58
  readonly version: string;
58
59
  };
59
60
  /**
@@ -13,6 +13,7 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, symlinkSync, writeFil
13
13
  import { createRequire } from 'node:module';
14
14
  import { homedir } from 'node:os';
15
15
  import { dirname, join, posix, resolve, win32 } from 'node:path';
16
+ import { parseDocument } from 'yaml';
16
17
  /** Profile name a standalone installation owns. */
17
18
  export const STANDALONE_PROFILE = 'plus';
18
19
  function requireRecord(value, label) {
@@ -105,11 +106,24 @@ export function readDistributionProfile(distributionDirectory) {
105
106
  throw new Error('dshPlus.profile.allowBuilds.' + name + ' must be a boolean');
106
107
  allowBuilds[name] = allowed;
107
108
  }
109
+ // An override substitutes our republished build for an official package by name: the
110
+ // built code imports the official specifier, so the installed location has to keep
111
+ // that name while its contents come from ours.
112
+ const overrides = {};
113
+ const rawOverrides = profile.overrides === undefined
114
+ ? {}
115
+ : requireRecord(profile.overrides, 'dshPlus.profile.overrides');
116
+ for (const [name, spec] of Object.entries(rawOverrides)) {
117
+ if (typeof spec !== 'string' || spec === '')
118
+ throw new Error('dshPlus.profile.overrides.' + name + ' must be a non-empty string');
119
+ overrides[name] = spec;
120
+ }
108
121
  return {
109
122
  name: String(manifest.name),
110
123
  bundles: requireStringArray(profile.bundles, 'dshPlus.profile.bundles'),
111
124
  dependencies,
112
125
  allowBuilds,
126
+ overrides,
113
127
  version: String(manifest.version),
114
128
  };
115
129
  }
@@ -222,8 +236,37 @@ export function ensureProfile(paths, consumerDirectory) {
222
236
  },
223
237
  };
224
238
  writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n');
239
+ writeProfileOverrides(paths.profileDirectory, distribution.overrides);
225
240
  return true;
226
241
  }
242
+ /**
243
+ * Record the distribution's package substitutions in the profile workspace.
244
+ *
245
+ * pnpm reads \`overrides\` from \`pnpm-workspace.yaml\` since version 10 and ignores the
246
+ * same key in \`package.json\`, so a profile that carried it in the manifest would
247
+ * silently install the official package the override meant to replace.
248
+ *
249
+ * @param profileDirectory - the standalone profile directory.
250
+ * @param overrides - official package name to published replacement spec.
251
+ */
252
+ function writeProfileOverrides(profileDirectory, overrides) {
253
+ const workspacePath = join(profileDirectory, 'pnpm-workspace.yaml');
254
+ const document = parseDocument(existsSync(workspacePath) ? readFileSync(workspacePath, 'utf8') : '');
255
+ const [documentError] = document.errors;
256
+ if (documentError !== undefined)
257
+ throw new Error('Plus profile workspace is not valid YAML', { cause: documentError });
258
+ if (document.get('packages') === undefined)
259
+ document.set('packages', ['.']);
260
+ for (const [name, spec] of Object.entries(overrides))
261
+ document.setIn(['overrides', name], spec);
262
+ // The profile resolves bundles from this directory, so peers the official tree would
263
+ // supply have to come from what the consumer installed.
264
+ if (document.get('nodeLinker') === undefined)
265
+ document.set('nodeLinker', 'hoisted');
266
+ if (document.get('autoInstallPeers') === undefined)
267
+ document.set('autoInstallPeers', false);
268
+ writeFileSync(workspacePath, String(document));
269
+ }
227
270
  /** Run git in one directory, returning undefined instead of throwing when asked to. */
228
271
  function git(root, args, acceptFailure = false) {
229
272
  const result = spawnSync('git', args, { cwd: root, encoding: 'utf8' });
package/package.json CHANGED
@@ -98,6 +98,28 @@
98
98
  "dsh-better-sidebar": "0.19.1",
99
99
  "dsh-sql-workbench": "0.5.1",
100
100
  "dsh-video-preview": "0.1.4"
101
+ },
102
+ "overrides": {
103
+ "@deepseek-ai/dsh-agent-presets": "npm:@sparkelf/dsh-agent-presets@0.1.5-rc.2",
104
+ "@deepseek-ai/dsh-api-gateway": "npm:@sparkelf/dsh-api-gateway@0.1.5-rc.2",
105
+ "@deepseek-ai/dsh-api-session-controller": "npm:@sparkelf/dsh-api-session-controller@0.1.5-rc.2",
106
+ "@deepseek-ai/dsh-client-connection": "npm:@sparkelf/dsh-client-connection@0.1.5-rc.2",
107
+ "@deepseek-ai/dsh-client-ui-agent-preset": "npm:@sparkelf/dsh-client-ui-agent-preset@0.1.5-rc.2",
108
+ "@deepseek-ai/dsh-client-ui-conversation": "npm:@sparkelf/dsh-client-ui-conversation@0.1.5-rc.2",
109
+ "@deepseek-ai/dsh-client-ui-deliverables": "npm:@sparkelf/dsh-client-ui-deliverables@0.1.5-rc.2",
110
+ "@deepseek-ai/dsh-client-ui-layout": "npm:@sparkelf/dsh-client-ui-layout@0.1.5-rc.2",
111
+ "@deepseek-ai/dsh-client-ui-model-selection": "npm:@sparkelf/dsh-client-ui-model-selection@0.1.5-rc.2",
112
+ "@deepseek-ai/dsh-client-ui-primitives": "npm:@sparkelf/dsh-client-ui-primitives@0.1.5-rc.2",
113
+ "@deepseek-ai/dsh-client-ui-settings-models": "npm:@sparkelf/dsh-client-ui-settings-models@0.1.5-rc.2",
114
+ "@deepseek-ai/dsh-client-ui-trajectory": "npm:@sparkelf/dsh-client-ui-trajectory@0.1.5-rc.2",
115
+ "@deepseek-ai/dsh-host-frontend-static": "npm:@sparkelf/dsh-host-frontend-static@0.1.5-rc.2",
116
+ "@deepseek-ai/dsh-host-webserver": "npm:@sparkelf/dsh-host-webserver@0.1.5-rc.2",
117
+ "@deepseek-ai/dsh-llm-pi-ai": "npm:@sparkelf/dsh-llm-pi-ai@0.1.5-rc.2",
118
+ "@deepseek-ai/dsh-session-log-export": "npm:@sparkelf/dsh-session-log-export@0.1.5-rc.2",
119
+ "@deepseek-ai/dsh-tools": "npm:@sparkelf/dsh-tools@0.1.5-rc.2",
120
+ "@deepseek-ai/dsh-web-app": "npm:@sparkelf/dsh-web-app@0.1.5-rc.2",
121
+ "@deepseek-ai/dsh-web-frontend": "npm:@sparkelf/dsh-web-frontend@0.1.5-rc.2",
122
+ "@deepseek-ai/dsh-workspace": "npm:@sparkelf/dsh-workspace@0.1.5-rc.2"
101
123
  }
102
124
  },
103
125
  "sourceBase": {
@@ -140,5 +162,5 @@
140
162
  },
141
163
  "type": "module",
142
164
  "types": "lib/types/index.d.ts",
143
- "version": "0.1.0-rc.34"
165
+ "version": "0.1.0-rc.35"
144
166
  }