@dsh-workbench/core 0.1.7 → 0.1.9

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.
Files changed (31) hide show
  1. package/client.js +858 -408
  2. package/dist/client/client.body.js +858 -408
  3. package/dist/client/index.js +858 -408
  4. package/dist/host/index.js +154 -6
  5. package/dist/types/app/client.d.ts +78 -15
  6. package/dist/types/app/layouts/env-gate/__tests__/gate-deadline.test.d.ts +1 -0
  7. package/dist/types/app/layouts/env-gate/gate-deadline.d.ts +4 -0
  8. package/dist/types/app/layouts/rightbar/ColumnSwitch.d.ts +10 -0
  9. package/dist/types/app/layouts/rightbar/MarketStates.d.ts +7 -0
  10. package/dist/types/app/layouts/rightbar/MarketView.d.ts +2 -1
  11. package/dist/types/app/layouts/rightbar/Rightbar.d.ts +3 -1
  12. package/dist/types/app/layouts/rightbar/SharedSection.d.ts +11 -0
  13. package/dist/types/app/layouts/rightbar/__tests__/market-change.test.d.ts +1 -0
  14. package/dist/types/app/layouts/rightbar/__tests__/market-live.test.d.ts +1 -0
  15. package/dist/types/app/layouts/rightbar/__tests__/market-settle.test.d.ts +1 -0
  16. package/dist/types/app/layouts/rightbar/dsh-column-source.d.ts +6 -0
  17. package/dist/types/app/layouts/rightbar/dsh-column-source.test.d.ts +1 -0
  18. package/dist/types/app/layouts/rightbar/market-change.d.ts +4 -0
  19. package/dist/types/app/layouts/rightbar/market-rows.d.ts +3 -1
  20. package/dist/types/app/layouts/rightbar/market-settle.d.ts +2 -0
  21. package/dist/types/app/layouts/rightbar/market-view-text.d.ts +10 -0
  22. package/dist/types/app/layouts/rightbar/presentation.d.ts +9 -0
  23. package/dist/types/app/layouts/rightbar/presentation.test.d.ts +1 -0
  24. package/dist/types/app/layouts/rightbar/store.d.ts +9 -0
  25. package/dist/types/modules/panels/__tests__/market-registries.test.d.ts +1 -0
  26. package/dist/types/modules/panels/model/market.d.ts +2 -0
  27. package/dist/types/shared/api/host/__tests__/profile-registries.test.d.ts +1 -0
  28. package/dist/types/shared/api/host/profile-registries.d.ts +21 -0
  29. package/docs/OPERATIONS.md +2 -0
  30. package/package.json +2 -2
  31. package/dist/types/app/layouts/rightbar/ExpandButton.d.ts +0 -9
@@ -1380,7 +1380,7 @@ function readBundleManager(ctx) {
1380
1380
  }
1381
1381
  //#endregion
1382
1382
  //#region src/shared/api/host/installed-module.ts
1383
- var PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
1383
+ var PACKAGE_NAME$1 = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
1384
1384
  function asRecord$1(value) {
1385
1385
  return typeof value === "object" && value !== null ? value : void 0;
1386
1386
  }
@@ -1388,7 +1388,7 @@ function asText$1(value) {
1388
1388
  return typeof value === "string" ? value : "";
1389
1389
  }
1390
1390
  function isPackageName(value) {
1391
- return value.length <= 214 && PACKAGE_NAME.test(value);
1391
+ return value.length <= 214 && PACKAGE_NAME$1.test(value);
1392
1392
  }
1393
1393
  function profileDirOf(ctx) {
1394
1394
  const profile = ctx.get("profileContext");
@@ -1477,6 +1477,118 @@ function readInstalledModule(profileDir, pkg) {
1477
1477
  };
1478
1478
  }
1479
1479
  //#endregion
1480
+ //#region src/shared/api/host/profile-registries.ts
1481
+ var REGISTRY_MARKER = "# dsh-workbench 写的:这一行的包只在这个源上(dsh 卸载没有源参数,pnpm 得问得到)";
1482
+ function scopeOf(pkg) {
1483
+ const slash = pkg.indexOf("/");
1484
+ return pkg.startsWith("@") && slash > 1 ? pkg.slice(0, slash) : null;
1485
+ }
1486
+ function normalizeRegistry(url) {
1487
+ const trimmed = url.trim();
1488
+ return trimmed.endsWith("/") ? trimmed : `${trimmed}/`;
1489
+ }
1490
+ function sameRegistry(a, b) {
1491
+ if (a === null || a === void 0 || b === null || b === void 0) return false;
1492
+ if (a.trim() === "" || b.trim() === "") return false;
1493
+ return normalizeRegistry(a) === normalizeRegistry(b);
1494
+ }
1495
+ function registryRootOf(name, tarball) {
1496
+ const at = tarball.indexOf(`/${name}/-/`);
1497
+ if (at > 0) return normalizeRegistry(tarball.slice(0, at));
1498
+ try {
1499
+ return normalizeRegistry(new URL(tarball).origin);
1500
+ } catch {
1501
+ return null;
1502
+ }
1503
+ }
1504
+ var PACKAGE_KEY = /^ {2}'?(\S+)'?:\s*$/;
1505
+ var PACKAGE_NAME = /^(?:@[^/\s]+\/)?[^/\s@]+$/;
1506
+ var TARBALL = /tarball:\s*(\S+?)\}?\s*$/;
1507
+ function sourcesFromLockfile(text) {
1508
+ const found = /* @__PURE__ */ new Map();
1509
+ let name = null;
1510
+ for (const line of text.split("\n")) {
1511
+ const key = PACKAGE_KEY.exec(line);
1512
+ if (key !== null) {
1513
+ const raw = key[1] ?? "";
1514
+ const at = raw.lastIndexOf("@");
1515
+ const candidate = at > 0 ? raw.slice(0, at) : "";
1516
+ name = PACKAGE_NAME.test(candidate) ? candidate : null;
1517
+ continue;
1518
+ }
1519
+ if (name === null) continue;
1520
+ const tarball = TARBALL.exec(line);
1521
+ if (tarball === null) continue;
1522
+ const scope = scopeOf(name);
1523
+ const root = registryRootOf(name, tarball[1] ?? "");
1524
+ name = null;
1525
+ if (scope === null || root === null) continue;
1526
+ const seen = found.get(scope);
1527
+ if (seen === void 0) found.set(scope, root);
1528
+ else if (!sameRegistry(seen, root)) found.set(scope, null);
1529
+ }
1530
+ return [...found.entries()].filter((entry) => entry[1] !== null).map(([scope, registry]) => ({
1531
+ scope,
1532
+ registry
1533
+ }));
1534
+ }
1535
+ function mergeRegistryConfig(text, entries) {
1536
+ const lines = text.split("\n");
1537
+ const present = (key) => lines.some((line) => line.trim().startsWith(`${key}=`));
1538
+ const appended = [];
1539
+ const added = [];
1540
+ for (const entry of entries) {
1541
+ const key = `${entry.scope}:registry`;
1542
+ if (entry.registry.trim() === "" || present(key)) continue;
1543
+ lines.push(`${key}=${normalizeRegistry(entry.registry)}`);
1544
+ appended.push(`${key}=${normalizeRegistry(entry.registry)}`);
1545
+ added.push(key);
1546
+ }
1547
+ if (appended.length === 0) return {
1548
+ text,
1549
+ added: []
1550
+ };
1551
+ const base = text === "" ? "" : text.endsWith("\n") ? text : `${text}\n`;
1552
+ return {
1553
+ text: `${base}${base.includes("# dsh-workbench 写的:这一行的包只在这个源上(dsh 卸载没有源参数,pnpm 得问得到)") ? "" : `${REGISTRY_MARKER}\n`}${appended.join("\n")}\n`,
1554
+ added
1555
+ };
1556
+ }
1557
+ function registryFailure(change) {
1558
+ if (change.application !== "failed") return false;
1559
+ if (change.packageResult?.kind === "not-found") return true;
1560
+ const output = change.packageResult?.output ?? change.errorDetail ?? "";
1561
+ return /ERR_PNPM_[A-Z_]*FETCH/.test(output);
1562
+ }
1563
+ function createRegistryNotebook(dir) {
1564
+ return {
1565
+ sources() {
1566
+ if (dir === null) return [];
1567
+ try {
1568
+ return sourcesFromLockfile(fs.readFileSync(path.join(dir, "pnpm-lock.yaml"), "utf8"));
1569
+ } catch {
1570
+ return [];
1571
+ }
1572
+ },
1573
+ remember(entries) {
1574
+ if (dir === null || entries.length === 0) return [];
1575
+ const file = path.join(dir, ".npmrc");
1576
+ let before;
1577
+ try {
1578
+ before = fs.readFileSync(file, "utf8");
1579
+ } catch {
1580
+ before = "";
1581
+ }
1582
+ const merged = mergeRegistryConfig(before, entries);
1583
+ if (merged.added.length === 0) return [];
1584
+ const temp = `${file}.dsh-workbench.tmp`;
1585
+ fs.writeFileSync(temp, merged.text, { mode: 384 });
1586
+ fs.renameSync(temp, file);
1587
+ return merged.added;
1588
+ }
1589
+ };
1590
+ }
1591
+ //#endregion
1480
1592
  //#region src/shared/api/host/release.ts
1481
1593
  function parseLedgerVersion(stdout, name) {
1482
1594
  const parsed = parseJsonLoose(stdout);
@@ -1703,7 +1815,7 @@ function bundleNameOf(change, spec) {
1703
1815
  return at > 0 ? spec.slice(0, at) : spec;
1704
1816
  }
1705
1817
  function createMarketService(options) {
1706
- const { manifests, manifestsNow, probe, shell, logger, onInstalled, onUninstalled, isReleased, bundles, installed, modules } = options;
1818
+ const { manifests, manifestsNow, probe, shell, logger, onInstalled, onUninstalled, isReleased, bundles, installed, modules, registries } = options;
1707
1819
  const command = options.command ?? "opencli";
1708
1820
  const catalog = () => (manifestsNow?.() ?? manifests).filter((manifest) => (manifest.env?.plugins ?? []).length > 0 || (manifest.env?.libs ?? []).length > 0);
1709
1821
  function requireEntry(unit) {
@@ -1850,6 +1962,38 @@ function createMarketService(options) {
1850
1962
  };
1851
1963
  }
1852
1964
  }
1965
+ async function rememberInstalledSource(manager, pkg, registry) {
1966
+ if (registries === void 0 || registry === void 0) return;
1967
+ const scope = scopeOf(pkg);
1968
+ if (scope === null) return;
1969
+ const known = await manager.registries().catch(() => null);
1970
+ if (known !== null && sameRegistry(known.resolved, registry)) return;
1971
+ try {
1972
+ const added = registries.remember([{
1973
+ scope,
1974
+ registry
1975
+ }]);
1976
+ if (added.length > 0) logger?.info?.(`[dsh-workbench] 把 ${added.join("、")} 记进 profile 的 .npmrc(卸载只认 pnpm 的配置)`);
1977
+ } catch (error) {
1978
+ logger?.warn?.(`[dsh-workbench] 记这个 scope 的源失败:${String(error)}`);
1979
+ }
1980
+ }
1981
+ async function retryAfterRegistryFix(manager, pkg, change) {
1982
+ if (registries === void 0 || !registryFailure(change)) return change;
1983
+ const known = await manager.registries().catch(() => null);
1984
+ const missing = registries.sources().filter((entry) => !sameRegistry(entry.registry, known?.resolved ?? null));
1985
+ if (missing.length === 0) return change;
1986
+ let added;
1987
+ try {
1988
+ added = registries.remember(missing);
1989
+ } catch (error) {
1990
+ logger?.warn?.(`[dsh-workbench] 卸 ${pkg} 撞上源,但补配置失败:${String(error)}`);
1991
+ return change;
1992
+ }
1993
+ if (added.length === 0) return change;
1994
+ logger?.warn?.(`[dsh-workbench] 卸 ${pkg} 撞上源:补 ${added.join("、")} 后重试一次`);
1995
+ return await manager.remove(pkg).catch(() => null) ?? change;
1996
+ }
1853
1997
  const service = {
1854
1998
  async list() {
1855
1999
  return snapshot();
@@ -1955,7 +2099,8 @@ function createMarketService(options) {
1955
2099
  };
1956
2100
  },
1957
2101
  async installBundle(spec, options) {
1958
- const change = await requireBundles().install({
2102
+ const manager = requireBundles();
2103
+ const change = await manager.install({
1959
2104
  spec,
1960
2105
  ...options?.registry === void 0 ? {} : { registry: options.registry },
1961
2106
  ...options?.requestId === void 0 ? {} : { requestId: options.requestId },
@@ -1967,6 +2112,7 @@ function createMarketService(options) {
1967
2112
  kind: "unknown",
1968
2113
  pkg
1969
2114
  };
2115
+ await rememberInstalledSource(manager, pkg, options?.registry);
1970
2116
  return {
1971
2117
  change,
1972
2118
  module,
@@ -1982,8 +2128,9 @@ function createMarketService(options) {
1982
2128
  const unit = module.kind === "module" ? module.unit : void 0;
1983
2129
  const manifest = unit === void 0 ? void 0 : catalog().find((item) => item.id === unit);
1984
2130
  const before = unit === void 0 ? void 0 : await capabilityOf(unit, true);
1985
- const change = await manager.remove(pkg);
1986
- if (change === null) throw new Error("插件管理器回的卸载结果看不懂。");
2131
+ const first = await manager.remove(pkg);
2132
+ if (first === null) throw new Error("插件管理器回的卸载结果看不懂。");
2133
+ const change = await retryAfterRegistryFix(manager, pkg, first);
1987
2134
  if (change.application !== "applied" || unit === void 0) return {
1988
2135
  change,
1989
2136
  keptFor: []
@@ -2682,6 +2829,7 @@ var HOST_UNITS = [{
2682
2829
  bundles: readBundleManager(ctx),
2683
2830
  installed: (pkg) => readInstalledModule(profileDir, pkg),
2684
2831
  modules: () => profileModules(profileDir),
2832
+ registries: createRegistryNotebook(profileDir),
2685
2833
  onUninstalled: (unit) => {
2686
2834
  panels.release(unit);
2687
2835
  },