@dsh-workbench/core 1.1.3 → 1.1.4
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/client.js +686 -505
- package/dist/client/client.body.js +686 -505
- package/dist/client/index.js +541 -360
- package/dist/host/index.js +244 -6
- package/dist/types/app/layouts/market/discover-confirm.d.ts +3 -2
- package/dist/types/app/layouts/market/market-check.d.ts +10 -0
- package/dist/types/app/layouts/market/market-header.d.ts +1 -3
- package/dist/types/app/layouts/market/use-discover.d.ts +2 -1
- package/dist/types/app/layouts/market/use-git-transport.d.ts +2 -2
- package/dist/types/app/layouts/market/use-module-versions.d.ts +3 -0
- package/dist/types/app/layouts/market/use-settling-modules.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/MarketView.d.ts +3 -1
- package/dist/types/app/layouts/rightbar/market-freshness.d.ts +1 -0
- package/dist/types/app/layouts/rightbar/market-row-types.d.ts +4 -1
- package/dist/types/app/layouts/rightbar/market-rows.d.ts +2 -0
- package/dist/types/app/layouts/rightbar/market-section.d.ts +4 -2
- package/dist/types/app/layouts/rightbar/use-market-default.d.ts +12 -0
- package/dist/types/kernel/contract/market-index.d.ts +2 -2
- package/dist/types/modules/panels/model/market-installed.d.ts +19 -0
- package/dist/types/modules/panels/model/market-installed.test.d.ts +1 -0
- package/dist/types/modules/panels/model/market-route.d.ts +1 -0
- package/dist/types/shared/api/host/git-probe.d.ts +3 -0
- package/dist/types/shared/api/host/market-sources-store.d.ts +2 -1
- package/dist/types/shared/api/host/profile-dependencies.d.ts +1 -0
- package/dist/types/shared/hooks/market-queries.d.ts +2 -1
- package/package.json +3 -3
package/dist/host/index.js
CHANGED
|
@@ -388,6 +388,99 @@ function boardSituation(probe, workshop) {
|
|
|
388
388
|
if (probe.where !== "" && !insideWorkshop(workshop, probe.where)) return "off-workspace";
|
|
389
389
|
return "panel-closed";
|
|
390
390
|
}
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region ../shared/dist/lib/git-address.js
|
|
393
|
+
var SCP = /^(?:([A-Za-z0-9._-]+)@)?([A-Za-z0-9.-]+):(?!\/)(\S+)$/;
|
|
394
|
+
function bare(url) {
|
|
395
|
+
return url.trim().replace(/^git\+/, "");
|
|
396
|
+
}
|
|
397
|
+
function pathOf(pathname) {
|
|
398
|
+
return pathname.replace(/^\/+/, "").replace(/\/+$/, "");
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* 把一个 git 地址拆成「哪台主机 + 哪个路径」,不管发布者当初用的是 https、ssh 还是
|
|
402
|
+
* scp 那种 `git@host:path` 写法;认不出来给 undefined。
|
|
403
|
+
*/
|
|
404
|
+
function gitAddressOf(url) {
|
|
405
|
+
const text = bare(url);
|
|
406
|
+
if (text === "") return void 0;
|
|
407
|
+
if (text.includes("://")) {
|
|
408
|
+
let parsed;
|
|
409
|
+
try {
|
|
410
|
+
parsed = new URL(text);
|
|
411
|
+
} catch {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:" && parsed.protocol !== "ssh:") return;
|
|
415
|
+
const path = pathOf(parsed.pathname);
|
|
416
|
+
if (path === "") return void 0;
|
|
417
|
+
const port = parsed.port === "" ? void 0 : Number(parsed.port);
|
|
418
|
+
const shared = {
|
|
419
|
+
host: parsed.hostname,
|
|
420
|
+
path,
|
|
421
|
+
...port === void 0 ? {} : { port }
|
|
422
|
+
};
|
|
423
|
+
if (parsed.protocol !== "ssh:") return {
|
|
424
|
+
kind: "https",
|
|
425
|
+
...shared
|
|
426
|
+
};
|
|
427
|
+
return {
|
|
428
|
+
kind: "ssh",
|
|
429
|
+
...shared,
|
|
430
|
+
...parsed.username === "" ? {} : { user: parsed.username }
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
const scp = SCP.exec(text);
|
|
434
|
+
if (scp === null) return void 0;
|
|
435
|
+
const path = pathOf(scp[3] ?? "");
|
|
436
|
+
if (path === "") return void 0;
|
|
437
|
+
return {
|
|
438
|
+
kind: "ssh",
|
|
439
|
+
host: scp[2] ?? "",
|
|
440
|
+
path,
|
|
441
|
+
...scp[1] === void 0 ? {} : { user: scp[1] }
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
/** 一份地址的规范写法:ssh 一律成 `ssh://user@host/path`(pnpm 认这个),https 原样。 */
|
|
445
|
+
function gitAddressText(address) {
|
|
446
|
+
const port = address.port === void 0 ? "" : `:${String(address.port)}`;
|
|
447
|
+
if (address.kind === "ssh") return `ssh://${address.user === void 0 || address.user === "" ? "git" : address.user}@${address.host}${port}/${address.path}`;
|
|
448
|
+
return `https://${address.host}${port}/${address.path}`;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* 同一个仓库的两种读法,发布者用的那种排前面。ssh 那条一律规范成 `ssh://` 形式,
|
|
452
|
+
* 因为 `git@host:path` 拼进安装 spec 时 pnpm 不认;https 那条保留发布者的原样(含 http)。
|
|
453
|
+
*/
|
|
454
|
+
function gitTransportCandidates(url) {
|
|
455
|
+
const address = gitAddressOf(url);
|
|
456
|
+
if (address === void 0) {
|
|
457
|
+
const only = bare(url);
|
|
458
|
+
return only === "" ? [] : [{
|
|
459
|
+
kind: only.startsWith("ssh") ? "ssh" : "https",
|
|
460
|
+
url: only
|
|
461
|
+
}];
|
|
462
|
+
}
|
|
463
|
+
const primary = {
|
|
464
|
+
kind: address.kind,
|
|
465
|
+
url: address.kind === "ssh" ? gitAddressText(address) : bare(url)
|
|
466
|
+
};
|
|
467
|
+
const other = address.kind === "https" ? {
|
|
468
|
+
kind: "ssh",
|
|
469
|
+
url: gitAddressText({
|
|
470
|
+
kind: "ssh",
|
|
471
|
+
host: address.host,
|
|
472
|
+
path: address.path
|
|
473
|
+
})
|
|
474
|
+
} : {
|
|
475
|
+
kind: "https",
|
|
476
|
+
url: gitAddressText({
|
|
477
|
+
kind: "https",
|
|
478
|
+
host: address.host,
|
|
479
|
+
path: address.path
|
|
480
|
+
})
|
|
481
|
+
};
|
|
482
|
+
return other.url === primary.url ? [primary] : [primary, other];
|
|
483
|
+
}
|
|
391
484
|
/**
|
|
392
485
|
* 外壳愿意认的协议版本;不在表里的模块当场被拒,不猜语义。
|
|
393
486
|
*/
|
|
@@ -4546,6 +4639,7 @@ function checkVersionRange(contract, version) {
|
|
|
4546
4639
|
var MARKET_DISCOVER_ROUTE = "panels/market-discover";
|
|
4547
4640
|
var MARKET_DOC_ROUTE = "panels/market-doc";
|
|
4548
4641
|
var MARKET_GIT_PROBE_ROUTE = "panels/git-probe";
|
|
4642
|
+
var MARKET_INSTALLED_ROUTE = "panels/market-installed";
|
|
4549
4643
|
var MARKET_PUBLISH_PREVIEW_ROUTE = "panels/market-publish-preview";
|
|
4550
4644
|
var MARKET_SOURCES_RESOURCE = "market-sources";
|
|
4551
4645
|
var MARKET_SOURCES_ROUTE = "panels/market-sources";
|
|
@@ -5581,6 +5675,18 @@ async function probeGitAddress(shell, url, options = {}) {
|
|
|
5581
5675
|
...detail === "" ? {} : { detail }
|
|
5582
5676
|
};
|
|
5583
5677
|
}
|
|
5678
|
+
var PROBE_CACHE_MS = 6e4;
|
|
5679
|
+
var probeCache = /* @__PURE__ */ new Map();
|
|
5680
|
+
async function probeGitAddressCached(shell, url, options = {}) {
|
|
5681
|
+
const hit = probeCache.get(url);
|
|
5682
|
+
if (hit !== void 0 && Date.now() - hit.at < PROBE_CACHE_MS) return hit.payload;
|
|
5683
|
+
const payload = await probeGitAddress(shell, url, options);
|
|
5684
|
+
probeCache.set(url, {
|
|
5685
|
+
at: Date.now(),
|
|
5686
|
+
payload
|
|
5687
|
+
});
|
|
5688
|
+
return payload;
|
|
5689
|
+
}
|
|
5584
5690
|
//#endregion
|
|
5585
5691
|
//#region src/shared/api/host/git-routes.ts
|
|
5586
5692
|
function gitProbeHandler(ctx) {
|
|
@@ -11749,10 +11855,22 @@ function pluginNameOf(entry) {
|
|
|
11749
11855
|
}
|
|
11750
11856
|
//#endregion
|
|
11751
11857
|
//#region src/modules/panels/model/market-route.ts
|
|
11858
|
+
function packageNameInPath(path) {
|
|
11859
|
+
const parts = path.split("/").filter((part) => part !== "");
|
|
11860
|
+
const last = parts[parts.length - 1];
|
|
11861
|
+
if (last === void 0 || last === "") return void 0;
|
|
11862
|
+
const parent = parts[parts.length - 2];
|
|
11863
|
+
return parent !== void 0 && parent.startsWith("@") ? `${parent}/${last}` : last;
|
|
11864
|
+
}
|
|
11752
11865
|
function bundleNameOf(change, spec) {
|
|
11753
11866
|
if (change.bundle !== void 0 && change.bundle !== "") return change.bundle;
|
|
11754
|
-
const at = spec.
|
|
11755
|
-
|
|
11867
|
+
const at = spec.indexOf("&path:");
|
|
11868
|
+
if (at !== -1) {
|
|
11869
|
+
const inPath = packageNameInPath(spec.slice(at + 6));
|
|
11870
|
+
if (inPath !== void 0) return inPath;
|
|
11871
|
+
}
|
|
11872
|
+
const version = spec.lastIndexOf("@");
|
|
11873
|
+
return version > 0 ? spec.slice(0, version) : spec;
|
|
11756
11874
|
}
|
|
11757
11875
|
function installedPluginName(spec, pkg) {
|
|
11758
11876
|
const local = localDirOf(spec);
|
|
@@ -12994,6 +13112,85 @@ function marketDiscoverRoutes(discover) {
|
|
|
12994
13112
|
};
|
|
12995
13113
|
}
|
|
12996
13114
|
//#endregion
|
|
13115
|
+
//#region src/modules/panels/model/market-installed.ts
|
|
13116
|
+
async function transportOf(source, spec, probe, preferred) {
|
|
13117
|
+
if (source.type !== "git" || probe === void 0) return source;
|
|
13118
|
+
const candidates = gitTransportCandidates(source.url);
|
|
13119
|
+
if (candidates.length === 0) return source;
|
|
13120
|
+
const installed = spec === void 0 ? void 0 : gitAddressOf(spec);
|
|
13121
|
+
const first = preferred ?? installed?.kind;
|
|
13122
|
+
const ordered = first === void 0 ? candidates : [...candidates].sort((left, right) => Number(right.kind === first) - Number(left.kind === first));
|
|
13123
|
+
for (const candidate of ordered) if (await probe(candidate.url).catch(() => "unreachable") === "ok") return {
|
|
13124
|
+
...source,
|
|
13125
|
+
url: candidate.url
|
|
13126
|
+
};
|
|
13127
|
+
return {
|
|
13128
|
+
...source,
|
|
13129
|
+
url: ordered[0]?.url ?? source.url
|
|
13130
|
+
};
|
|
13131
|
+
}
|
|
13132
|
+
async function installedFromIndexes(input) {
|
|
13133
|
+
const modules = new Map(input.modules.map((module) => [module.pkg, module]));
|
|
13134
|
+
const rows = [];
|
|
13135
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13136
|
+
for (const source of input.sources) {
|
|
13137
|
+
const index = input.cached(source);
|
|
13138
|
+
if (index === void 0) continue;
|
|
13139
|
+
for (const entry of index.plugins) {
|
|
13140
|
+
const module = modules.get(entry.name);
|
|
13141
|
+
const newest = entry.versions[0];
|
|
13142
|
+
if (module === void 0 || newest === void 0 || seen.has(entry.name)) continue;
|
|
13143
|
+
if (!input.isNewer(newest.version, module.version)) continue;
|
|
13144
|
+
seen.add(entry.name);
|
|
13145
|
+
rows.push({
|
|
13146
|
+
pkg: entry.name,
|
|
13147
|
+
unit: module.unit,
|
|
13148
|
+
version: newest.version,
|
|
13149
|
+
sourceId: source.id,
|
|
13150
|
+
sourceLabel: source.label,
|
|
13151
|
+
source: newest.source
|
|
13152
|
+
});
|
|
13153
|
+
const wanted = input.dependencyOf(entry.name);
|
|
13154
|
+
const host = gitAddressOf(source.url)?.host;
|
|
13155
|
+
const resolved = await transportOf(newest.source, wanted, input.probe, host === void 0 ? void 0 : input.preferred?.(host));
|
|
13156
|
+
rows[rows.length - 1] = {
|
|
13157
|
+
...rows[rows.length - 1],
|
|
13158
|
+
source: resolved
|
|
13159
|
+
};
|
|
13160
|
+
}
|
|
13161
|
+
}
|
|
13162
|
+
return rows;
|
|
13163
|
+
}
|
|
13164
|
+
function marketInstalledRoutes(read) {
|
|
13165
|
+
return { [MARKET_INSTALLED_ROUTE]: async () => ({
|
|
13166
|
+
ok: true,
|
|
13167
|
+
...await read()
|
|
13168
|
+
}) };
|
|
13169
|
+
}
|
|
13170
|
+
function transportOfSpec(spec) {
|
|
13171
|
+
const address = gitAddressOf(spec);
|
|
13172
|
+
return address === void 0 ? void 0 : {
|
|
13173
|
+
host: address.host,
|
|
13174
|
+
kind: address.kind
|
|
13175
|
+
};
|
|
13176
|
+
}
|
|
13177
|
+
//#endregion
|
|
13178
|
+
//#region src/shared/api/host/profile-dependencies.ts
|
|
13179
|
+
function dependencyReader(profileDir) {
|
|
13180
|
+
if (profileDir === null) return () => void 0;
|
|
13181
|
+
let dependencies;
|
|
13182
|
+
return (pkg) => {
|
|
13183
|
+
if (dependencies === void 0) try {
|
|
13184
|
+
const raw = JSON.parse(readFileSync(join(profileDir, "package.json"), "utf8")).dependencies;
|
|
13185
|
+
dependencies = typeof raw === "object" && raw !== null ? raw : {};
|
|
13186
|
+
} catch {
|
|
13187
|
+
dependencies = {};
|
|
13188
|
+
}
|
|
13189
|
+
const value = dependencies[pkg];
|
|
13190
|
+
return typeof value === "string" ? value : void 0;
|
|
13191
|
+
};
|
|
13192
|
+
}
|
|
13193
|
+
//#endregion
|
|
12997
13194
|
//#region src/modules/panels/model/market-sources-act.ts
|
|
12998
13195
|
function marketSourcesRoutes(store) {
|
|
12999
13196
|
return { [MARKET_SOURCES_ROUTE]: async () => ({
|
|
@@ -13581,6 +13778,15 @@ function createMarketDocReader(options) {
|
|
|
13581
13778
|
function fileOf(root) {
|
|
13582
13779
|
return join(root, "market-index", "sources.json");
|
|
13583
13780
|
}
|
|
13781
|
+
function transportsOf(raw) {
|
|
13782
|
+
const record = typeof raw === "object" && raw !== null ? raw : {};
|
|
13783
|
+
const found = {};
|
|
13784
|
+
for (const [host, kind] of Object.entries(record)) {
|
|
13785
|
+
if (host === "" || kind !== "https" && kind !== "ssh") continue;
|
|
13786
|
+
found[host] = kind;
|
|
13787
|
+
}
|
|
13788
|
+
return found;
|
|
13789
|
+
}
|
|
13584
13790
|
function readPayload(path, logger) {
|
|
13585
13791
|
let raw;
|
|
13586
13792
|
try {
|
|
@@ -13588,7 +13794,8 @@ function readPayload(path, logger) {
|
|
|
13588
13794
|
} catch {
|
|
13589
13795
|
return {
|
|
13590
13796
|
sources: [],
|
|
13591
|
-
selected: null
|
|
13797
|
+
selected: null,
|
|
13798
|
+
transports: {}
|
|
13592
13799
|
};
|
|
13593
13800
|
}
|
|
13594
13801
|
const record = typeof raw === "object" && raw !== null ? raw : {};
|
|
@@ -13605,7 +13812,8 @@ function readPayload(path, logger) {
|
|
|
13605
13812
|
const selectedRaw = record["selected"];
|
|
13606
13813
|
return {
|
|
13607
13814
|
sources,
|
|
13608
|
-
selected: typeof selectedRaw === "string" && sources.some((source) => source.id === selectedRaw) ? selectedRaw : sources[0]?.id ?? null
|
|
13815
|
+
selected: typeof selectedRaw === "string" && sources.some((source) => source.id === selectedRaw) ? selectedRaw : sources[0]?.id ?? null,
|
|
13816
|
+
transports: transportsOf(record["transports"])
|
|
13609
13817
|
};
|
|
13610
13818
|
}
|
|
13611
13819
|
async function writePayload(path, payload) {
|
|
@@ -13624,6 +13832,18 @@ function createMarketSourcesStore(options) {
|
|
|
13624
13832
|
function read() {
|
|
13625
13833
|
return readPayload(path, options.logger);
|
|
13626
13834
|
}
|
|
13835
|
+
async function rememberTransport(host, kind) {
|
|
13836
|
+
if (host === "") return;
|
|
13837
|
+
const current = read();
|
|
13838
|
+
const transports = {
|
|
13839
|
+
...current.transports ?? {},
|
|
13840
|
+
[host]: kind
|
|
13841
|
+
};
|
|
13842
|
+
await writePayload(path, {
|
|
13843
|
+
...current,
|
|
13844
|
+
transports
|
|
13845
|
+
});
|
|
13846
|
+
}
|
|
13627
13847
|
async function apply(action) {
|
|
13628
13848
|
const current = read();
|
|
13629
13849
|
if (action.action === "save") {
|
|
@@ -13655,7 +13875,8 @@ function createMarketSourcesStore(options) {
|
|
|
13655
13875
|
}
|
|
13656
13876
|
return {
|
|
13657
13877
|
read,
|
|
13658
|
-
apply
|
|
13878
|
+
apply,
|
|
13879
|
+
rememberTransport
|
|
13659
13880
|
};
|
|
13660
13881
|
}
|
|
13661
13882
|
//#endregion
|
|
@@ -15190,6 +15411,15 @@ var OWNED = [{
|
|
|
15190
15411
|
...diyRecordRoutes(record),
|
|
15191
15412
|
...marketDiscoverRoutes(discover),
|
|
15192
15413
|
...marketSourcesRoutes(marketSources),
|
|
15414
|
+
...marketInstalledRoutes(async () => ({ modules: await installedFromIndexes({
|
|
15415
|
+
sources: marketSources.read().sources,
|
|
15416
|
+
cached: (source) => marketIndex.cached(source)?.index,
|
|
15417
|
+
modules: supply.profileModules(profileDir),
|
|
15418
|
+
dependencyOf: dependencyReader(profileDir),
|
|
15419
|
+
isNewer: supply.isNewerVersion,
|
|
15420
|
+
preferred: (host) => marketSources.read().transports?.[host],
|
|
15421
|
+
...shell === void 0 ? {} : { probe: (url) => probeGitAddressCached(shell, url, { timeoutMs: 4e3 }).then((one) => one.status) }
|
|
15422
|
+
}) })),
|
|
15193
15423
|
...publishPreviewRoutes(workshopPathOf(ctx), (unit) => inferredAuthorOf(workshopPathOf(ctx), unit, shell))
|
|
15194
15424
|
},
|
|
15195
15425
|
registerTools: () => [
|
|
@@ -15227,7 +15457,15 @@ var OWNED = [{
|
|
|
15227
15457
|
handle: (payload) => applyPanelsPref(panels, payload)
|
|
15228
15458
|
},
|
|
15229
15459
|
provision: {
|
|
15230
|
-
handle: (request) =>
|
|
15460
|
+
handle: async (request) => {
|
|
15461
|
+
const result = await dispatchMarket(market, request);
|
|
15462
|
+
const application = result.change?.application;
|
|
15463
|
+
if (request.spec !== void 0 && (application === "applied" || application === "restart-required" || application === "overridden")) {
|
|
15464
|
+
const used = transportOfSpec(request.spec);
|
|
15465
|
+
if (used !== void 0) await marketSources.rememberTransport(used.host, used.kind);
|
|
15466
|
+
}
|
|
15467
|
+
return result;
|
|
15468
|
+
},
|
|
15231
15469
|
affectedUnits: (request) => affectedUnitsOf(manifests(), request)
|
|
15232
15470
|
}
|
|
15233
15471
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Translate } from '@dsh-workbench/shared';
|
|
2
|
-
import type { DiscoverEntry, DiscoverVersionRow } from '../../../kernel/contract/market-index';
|
|
2
|
+
import type { DiscoverEntry, DiscoverVersionRow, GitTransportKind } from '../../../kernel/contract/market-index';
|
|
3
3
|
export interface DiscoverChoice {
|
|
4
4
|
readonly entry: DiscoverEntry;
|
|
5
5
|
readonly version: DiscoverVersionRow;
|
|
@@ -8,7 +8,8 @@ export interface DiscoverConfirmProps {
|
|
|
8
8
|
readonly t: Translate;
|
|
9
9
|
readonly locale: string;
|
|
10
10
|
readonly choice: DiscoverChoice | null;
|
|
11
|
+
readonly transports: Readonly<Record<string, GitTransportKind>>;
|
|
11
12
|
readonly onCancel: () => void;
|
|
12
13
|
readonly onConfirm: (url?: string) => void;
|
|
13
14
|
}
|
|
14
|
-
export declare function DiscoverConfirm({ t, locale, choice, onCancel, onConfirm }: DiscoverConfirmProps): JSX.Element | null;
|
|
15
|
+
export declare function DiscoverConfirm({ t, locale, choice, transports, onCancel, onConfirm }: DiscoverConfirmProps): JSX.Element | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Translate } from '@dsh-workbench/shared';
|
|
2
|
+
export interface MarketCheckProps {
|
|
3
|
+
readonly t: Translate;
|
|
4
|
+
readonly checkedAt: number | null;
|
|
5
|
+
readonly checking: boolean;
|
|
6
|
+
readonly failed: boolean;
|
|
7
|
+
readonly disabled: boolean;
|
|
8
|
+
readonly onCheck: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function MarketCheck({ t, checkedAt, checking, failed, disabled, onCheck }: MarketCheckProps): JSX.Element;
|
|
@@ -5,9 +5,7 @@ export interface MarketHeaderProps {
|
|
|
5
5
|
readonly idPrefix: string;
|
|
6
6
|
readonly tab: MarketTab;
|
|
7
7
|
readonly busy: boolean;
|
|
8
|
-
readonly checking: boolean;
|
|
9
8
|
readonly onTab: (tab: MarketTab) => void;
|
|
10
|
-
readonly onReload: () => void;
|
|
11
9
|
readonly onAdd: () => void;
|
|
12
10
|
}
|
|
13
|
-
export declare function MarketHeader({ t, idPrefix, tab, busy,
|
|
11
|
+
export declare function MarketHeader({ t, idPrefix, tab, busy, onTab, onAdd }: MarketHeaderProps): JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Translate } from '@dsh-workbench/shared';
|
|
2
|
-
import type { DiscoverEntry, DiscoverPayload, DiscoverVersionRow, MarketSourceConfig } from '../../../kernel/contract/market-index';
|
|
2
|
+
import type { DiscoverEntry, DiscoverPayload, DiscoverVersionRow, GitTransportKind, MarketSourceConfig } from '../../../kernel/contract/market-index';
|
|
3
3
|
import { type DiscoverSort } from './discover-view';
|
|
4
4
|
interface InstallTarget {
|
|
5
5
|
readonly entry: DiscoverEntry;
|
|
@@ -25,6 +25,7 @@ export interface DiscoverController {
|
|
|
25
25
|
readonly failure: string | null;
|
|
26
26
|
readonly sources: DiscoverPayload['sources'];
|
|
27
27
|
readonly selected: string | null;
|
|
28
|
+
readonly transports: Readonly<Record<string, GitTransportKind>>;
|
|
28
29
|
readonly entries: readonly DiscoverEntry[];
|
|
29
30
|
readonly shown: readonly DiscoverEntry[];
|
|
30
31
|
readonly total: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GitProbeStatus, MarketIndexGitSource } from '../../../kernel/contract/market-index';
|
|
1
|
+
import type { GitProbeStatus, GitTransportKind, MarketIndexGitSource } from '../../../kernel/contract/market-index';
|
|
2
2
|
export type TransportProbe = GitProbeStatus | 'checking' | 'unknown';
|
|
3
3
|
export interface GitTransportRow {
|
|
4
4
|
readonly kind: 'https' | 'ssh';
|
|
@@ -16,4 +16,4 @@ export interface GitTransportState {
|
|
|
16
16
|
setCustom(value: string): void;
|
|
17
17
|
checkCustom(): void;
|
|
18
18
|
}
|
|
19
|
-
export declare function useGitTransport(source: MarketIndexGitSource | null): GitTransportState;
|
|
19
|
+
export declare function useGitTransport(source: MarketIndexGitSource | null, preferredKind?: GitTransportKind | undefined): GitTransportState;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ModuleVersion, WorkbenchSelfUpdate, WorkbenchVersion } from '../../../kernel/contract/bundle-install';
|
|
2
|
+
import type { MarketInstalledModule } from '../../../kernel/contract/market-index';
|
|
2
3
|
import type { InstalledPlugin } from '../../../shared/api/installed-plugins';
|
|
3
4
|
export interface ModuleVersionsState {
|
|
4
5
|
readonly modules: readonly ModuleVersion[] | null;
|
|
@@ -7,6 +8,7 @@ export interface ModuleVersionsState {
|
|
|
7
8
|
readonly selfUpdate: WorkbenchSelfUpdate | null;
|
|
8
9
|
readonly read: boolean;
|
|
9
10
|
readonly checking: boolean;
|
|
11
|
+
readonly failed: boolean;
|
|
10
12
|
readonly checkedAt: number | null;
|
|
11
13
|
}
|
|
12
14
|
export interface ModuleVersionsView extends ModuleVersionsState {
|
|
@@ -19,5 +21,6 @@ export declare function bumpModuleVersionsEpoch(): void;
|
|
|
19
21
|
export declare function moduleVersionsValue(): ModuleVersionsState;
|
|
20
22
|
export declare function resetModuleVersions(): void;
|
|
21
23
|
export declare function subscribeModuleVersions(listener: () => void): () => void;
|
|
24
|
+
export declare function withMarketUpdates(modules: readonly ModuleVersion[], rows: readonly MarketInstalledModule[]): readonly ModuleVersion[];
|
|
22
25
|
export declare function runModuleVersionsRead(force?: boolean, fresh?: boolean): Promise<void>;
|
|
23
26
|
export declare function useModuleVersions(): ModuleVersionsView;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useSettlingModules(installedKey: string, rosterKey: string, activeKey: string): ReadonlySet<string>;
|
|
@@ -20,6 +20,8 @@ export interface MarketViewProps {
|
|
|
20
20
|
}) => void;
|
|
21
21
|
readonly onPending?: ((pending: boolean) => void) | undefined;
|
|
22
22
|
readonly updates?: ModuleUpdateMap | undefined;
|
|
23
|
+
readonly updatesCheckedAt?: number | null | undefined;
|
|
24
|
+
readonly updatesFailed?: boolean | undefined;
|
|
23
25
|
readonly installed?: readonly InstalledWorkbenchModule[] | undefined;
|
|
24
26
|
readonly installedRead?: boolean | undefined;
|
|
25
27
|
readonly workbench?: WorkbenchVersion | null | undefined;
|
|
@@ -30,4 +32,4 @@ export interface MarketViewProps {
|
|
|
30
32
|
readonly defaults?: readonly string[] | undefined;
|
|
31
33
|
readonly changed?: Readonly<Record<string, number>> | undefined;
|
|
32
34
|
}
|
|
33
|
-
export declare function MarketView({ t, titleOf, manifests, installable, capabilities, freshness, onChanged, onPending, updates, installed, installedRead, workbench, selfUpdate, plugins, settling, mock, defaults, changed, }: MarketViewProps): JSX.Element;
|
|
35
|
+
export declare function MarketView({ t, titleOf, manifests, installable, capabilities, freshness, onChanged, onPending, updates, updatesCheckedAt, updatesFailed, installed, installedRead, workbench, selfUpdate, plugins, settling, mock, defaults, changed, }: MarketViewProps): JSX.Element;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Translate } from '@dsh-workbench/shared';
|
|
2
2
|
export declare const MARKET_STALE_MS = 600000;
|
|
3
3
|
export declare function checkedAgoText(at: number, now: number, t: Translate): string;
|
|
4
|
+
export declare function checkedAgo(at: number, t: Translate): string;
|
|
4
5
|
export interface MarketFreshness {
|
|
5
6
|
readonly loaded: boolean;
|
|
6
7
|
readonly checking: boolean;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ModuleUpdateBlock } from '../../../kernel/contract/bundle-install';
|
|
2
|
-
|
|
2
|
+
import type { MarketInstalledModule } from '../../../kernel/contract/market-index';
|
|
3
|
+
export type MarketRowAction = 'install' | 'update' | 'update-bundle' | 'install-version' | 'remove-bundle' | 'uninstall' | 'update-dependency' | 'update-plugin' | 'uninstall-plugin' | 'update-workbench' | 'migrate-workbench' | 'dismiss-followup';
|
|
3
4
|
export type MarketState = 'checking' | 'installed' | 'inactive' | 'unusable' | 'broken' | 'outdated' | 'pending-restart' | 'pending-followup' | 'missing' | 'unchecked' | 'unknown';
|
|
4
5
|
export interface MarketNote {
|
|
5
6
|
readonly key: 'panels.market.needEnv' | 'panels.market.noSource' | 'panels.market.badSource' | 'panels.market.needCommands' | 'panels.market.needBinary' | 'panels.market.needLib' | 'panels.market.moduleRefused' | 'panels.market.moduleRestartHint' | 'panels.market.pluginAlsoKnownAs' | 'panels.market.pluginBroken';
|
|
@@ -12,6 +13,7 @@ export interface ModuleUpdate {
|
|
|
12
13
|
readonly latest?: string;
|
|
13
14
|
readonly local?: boolean;
|
|
14
15
|
readonly blocked?: ModuleUpdateBlock;
|
|
16
|
+
readonly market?: MarketInstalledModule;
|
|
15
17
|
}
|
|
16
18
|
export interface MarketFollowUp {
|
|
17
19
|
readonly id: string;
|
|
@@ -35,6 +37,7 @@ export interface MarketRow {
|
|
|
35
37
|
readonly latest?: string;
|
|
36
38
|
};
|
|
37
39
|
readonly moduleUpdate?: ModuleUpdate;
|
|
40
|
+
readonly market?: MarketInstalledModule;
|
|
38
41
|
readonly pkg?: string;
|
|
39
42
|
readonly local?: boolean;
|
|
40
43
|
readonly versionLabel?: string;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ModuleUpdateBlock, ModuleVersion } from '../../../kernel/contract/bundle-install';
|
|
2
|
+
import type { MarketInstalledModule } from '../../../kernel/contract/market-index';
|
|
2
3
|
import type { Translate, UnitManifest, UnitTitle } from '@dsh-workbench/shared';
|
|
3
4
|
import type { MarketNameMap } from './market-names';
|
|
4
5
|
import type { MarketRow, MarketRowAction, MarketState, ModuleUpdate } from './market-row-types';
|
|
@@ -21,6 +22,7 @@ export interface InstalledWorkbenchModule {
|
|
|
21
22
|
readonly local?: boolean | undefined;
|
|
22
23
|
readonly refused?: readonly string[] | undefined;
|
|
23
24
|
readonly clientRefused?: readonly string[] | undefined;
|
|
25
|
+
readonly market?: MarketInstalledModule | undefined;
|
|
24
26
|
}
|
|
25
27
|
export declare function withClientRefusals(modules: readonly InstalledWorkbenchModule[], refusals: readonly {
|
|
26
28
|
readonly unit: string;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { Translate } from '@dsh-workbench/shared';
|
|
1
|
+
import type { ReactNode, Translate } from '@dsh-workbench/shared';
|
|
2
2
|
import type { MarketRow } from './market-row-types';
|
|
3
3
|
import { type MarketRowAction } from './market-rows';
|
|
4
4
|
import type { MarketSectionIcon } from './market-section-icon';
|
|
5
5
|
import { type Pending } from './market-view-text';
|
|
6
|
-
export declare function MarketSection({ t, titleKey, icon, rows, pending, failureOf, act, confirmActions, onConfirming, onDefault, boardBusy, }: {
|
|
6
|
+
export declare function MarketSection({ t, titleKey, icon, rows, pending, failureOf, act, confirmActions, onConfirming, onDefault, boardBusy, headAction, keepHead, }: {
|
|
7
7
|
readonly t: Translate;
|
|
8
8
|
readonly titleKey?: string;
|
|
9
9
|
readonly icon?: MarketSectionIcon;
|
|
@@ -15,4 +15,6 @@ export declare function MarketSection({ t, titleKey, icon, rows, pending, failur
|
|
|
15
15
|
readonly boardBusy?: boolean | undefined;
|
|
16
16
|
readonly confirmActions: readonly MarketRowAction[];
|
|
17
17
|
readonly onConfirming: (id: string | null) => void;
|
|
18
|
+
readonly headAction?: ReactNode;
|
|
19
|
+
readonly keepHead?: boolean;
|
|
18
20
|
}): JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Translate } from '@dsh-workbench/shared';
|
|
2
|
+
export interface MarketDefaultSeat {
|
|
3
|
+
readonly pending: boolean;
|
|
4
|
+
setDefault(id: string, next: boolean): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export declare function useMarketDefault(input: {
|
|
7
|
+
readonly t: Translate;
|
|
8
|
+
readonly mocked: boolean;
|
|
9
|
+
readonly defaults: readonly string[];
|
|
10
|
+
readonly changed: Readonly<Record<string, number>>;
|
|
11
|
+
readonly setNotice: (next: string | null) => void;
|
|
12
|
+
}): MarketDefaultSeat;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { MARKET_DISCOVER_ROUTE, MARKET_DOC_ROUTE, MARKET_GIT_PROBE_ROUTE, MARKET_INDEX_FORMAT, MARKET_INDEX_PATH, MARKET_PUBLISH_PREVIEW_ROUTE, MARKET_SOURCES_RESOURCE, MARKET_SOURCES_ROUTE, MARKET_WORKBENCH_LABEL, } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
2
|
-
export type { DiscoverCompat, DiscoverDoc, DiscoverDocKind, DiscoverEntry, DiscoverFilter, DiscoverInstallState, DiscoverPayload, DiscoverProblem, DiscoverSourceRow, DiscoverState, DiscoverVersionRow, GitProbePayload, GitProbeStatus, IndexSourceSpec, MarketClaim, MarketIndex, MarketIndexCategory, MarketIndexEngines, MarketIndexEntry, MarketIndexEntryMetadata, MarketIndexGitSource, MarketIndexLabel, MarketIndexMetadata, MarketIndexNpmSource, MarketIndexParse, MarketIndexProblem, MarketIndexProblemKind, MarketIndexSortKey, MarketIndexSource, MarketIndexVersion, MarketLocalizedText, MarketPublishDestination, MarketSourceConfig, MarketSourceKind, MarketSourcePolicy, MarketSourcesAction, MarketSourcesPayload, PublishChangelog, PublishPreview, } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
1
|
+
export { MARKET_DISCOVER_ROUTE, MARKET_DOC_ROUTE, MARKET_GIT_PROBE_ROUTE, MARKET_INSTALLED_ROUTE, MARKET_INDEX_FORMAT, MARKET_INDEX_PATH, MARKET_PUBLISH_PREVIEW_ROUTE, MARKET_SOURCES_RESOURCE, MARKET_SOURCES_ROUTE, MARKET_WORKBENCH_LABEL, } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
2
|
+
export type { DiscoverCompat, DiscoverDoc, DiscoverDocKind, DiscoverEntry, DiscoverFilter, DiscoverInstallState, DiscoverPayload, DiscoverProblem, DiscoverSourceRow, DiscoverState, DiscoverVersionRow, GitProbePayload, GitProbeStatus, GitTransportKind, MarketInstalledModule, MarketInstalledPayload, IndexSourceSpec, MarketClaim, MarketIndex, MarketIndexCategory, MarketIndexEngines, MarketIndexEntry, MarketIndexEntryMetadata, MarketIndexGitSource, MarketIndexLabel, MarketIndexMetadata, MarketIndexNpmSource, MarketIndexParse, MarketIndexProblem, MarketIndexProblemKind, MarketIndexSortKey, MarketIndexSource, MarketIndexVersion, MarketLocalizedText, MarketPublishDestination, MarketSourceConfig, MarketSourceKind, MarketSourcePolicy, MarketSourcesAction, MarketSourcesPayload, PublishChangelog, PublishPreview, } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { GitTransportKind, MarketIndex, MarketInstalledModule, MarketInstalledPayload, MarketSourceConfig } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
2
|
+
import type { RouteTable } from '@dsh-workbench/shared/host';
|
|
3
|
+
import type { ProfileModule } from '@dsh-workbench/shared/host';
|
|
4
|
+
import type { GitProbeStatus } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
5
|
+
export interface InstalledIndexInput {
|
|
6
|
+
readonly sources: readonly MarketSourceConfig[];
|
|
7
|
+
readonly cached: (source: MarketSourceConfig) => MarketIndex | undefined;
|
|
8
|
+
readonly modules: readonly ProfileModule[];
|
|
9
|
+
readonly dependencyOf: (pkg: string) => string | undefined;
|
|
10
|
+
readonly isNewer: (latest: string, installed: string) => boolean;
|
|
11
|
+
readonly probe?: ((url: string) => Promise<GitProbeStatus>) | undefined;
|
|
12
|
+
readonly preferred?: ((host: string) => GitTransportKind | undefined) | undefined;
|
|
13
|
+
}
|
|
14
|
+
export declare function installedFromIndexes(input: InstalledIndexInput): Promise<readonly MarketInstalledModule[]>;
|
|
15
|
+
export declare function marketInstalledRoutes(read: () => MarketInstalledPayload | Promise<MarketInstalledPayload>): RouteTable;
|
|
16
|
+
export declare function transportOfSpec(spec: string): {
|
|
17
|
+
readonly host: string;
|
|
18
|
+
readonly kind: GitTransportKind;
|
|
19
|
+
} | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -25,6 +25,7 @@ export interface BundleInstallDeps {
|
|
|
25
25
|
readonly rememberSource: (manager: BundleManager, pkg: string, registry: string | undefined) => Promise<void>;
|
|
26
26
|
readonly remove?: ((pkg: string) => Promise<BundleChange>) | undefined;
|
|
27
27
|
}
|
|
28
|
+
export declare function bundleNameOf(change: BundleChange, spec: string): string;
|
|
28
29
|
export declare function installDshBundle(deps: Omit<BundleInstallDeps, 'spec' | 'options'>, spec: string, options?: BundleInstallOptions): Promise<BundleInstallOutcome>;
|
|
29
30
|
export type ReplaceBundleDeps = Omit<BundleInstallDeps, 'spec' | 'options' | 'remove'> & {
|
|
30
31
|
readonly remove: (pkg: string) => Promise<BundleChange>;
|
|
@@ -4,3 +4,6 @@ export declare function classifyGitProbe(stderr: string, timedOut: boolean): Git
|
|
|
4
4
|
export declare function probeGitAddress(shell: DshShell, url: string, options?: {
|
|
5
5
|
readonly timeoutMs?: number;
|
|
6
6
|
}): Promise<GitProbePayload>;
|
|
7
|
+
export declare function probeGitAddressCached(shell: DshShell, url: string, options?: {
|
|
8
|
+
readonly timeoutMs?: number;
|
|
9
|
+
}): Promise<GitProbePayload>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MarketSourcesAction, MarketSourcesPayload } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
1
|
+
import type { GitTransportKind, MarketSourcesAction, MarketSourcesPayload } from '@dsh-workbench/shared/contract/protocol/market-index';
|
|
2
2
|
export type MarketSourcesWrite = Exclude<MarketSourcesAction, {
|
|
3
3
|
readonly action: 'init';
|
|
4
4
|
} | {
|
|
@@ -7,6 +7,7 @@ export type MarketSourcesWrite = Exclude<MarketSourcesAction, {
|
|
|
7
7
|
export interface MarketSourcesStore {
|
|
8
8
|
read(): MarketSourcesPayload;
|
|
9
9
|
apply(action: MarketSourcesWrite): Promise<MarketSourcesPayload>;
|
|
10
|
+
rememberTransport(host: string, kind: GitTransportKind): Promise<void>;
|
|
10
11
|
}
|
|
11
12
|
export interface MarketSourcesStoreOptions {
|
|
12
13
|
readonly root: string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function dependencyReader(profileDir: string | null): (pkg: string) => string | undefined;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ApiResponse } from '@dsh-workbench/shared';
|
|
2
|
-
import { type DiscoverDoc, type DiscoverDocKind, type DiscoverPayload, type GitProbePayload, type MarketSourcesPayload, type PublishPreview } from '../../kernel/contract/market-index';
|
|
2
|
+
import { type DiscoverDoc, type DiscoverDocKind, type DiscoverPayload, type GitProbePayload, type MarketInstalledPayload, type MarketSourcesPayload, type PublishPreview } from '../../kernel/contract/market-index';
|
|
3
3
|
export declare function readMarketDiscover(options?: {
|
|
4
4
|
readonly force?: boolean;
|
|
5
5
|
}): Promise<ApiResponse<DiscoverPayload>>;
|
|
6
6
|
export declare function readMarketSources(): Promise<ApiResponse<MarketSourcesPayload>>;
|
|
7
7
|
export declare function readGitProbe(url: string): Promise<ApiResponse<GitProbePayload>>;
|
|
8
|
+
export declare function readMarketInstalled(): Promise<ApiResponse<MarketInstalledPayload>>;
|
|
8
9
|
export declare function readMarketDoc(name: string, version: string, kind: DiscoverDocKind): Promise<ApiResponse<{
|
|
9
10
|
readonly doc: DiscoverDoc;
|
|
10
11
|
}>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "个人工作台:Agent 工作台(左栏 + 常驻对话 + 自研右侧数据面板)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"icon": "./icon.svg",
|
|
@@ -100,8 +100,8 @@
|
|
|
100
100
|
"proper-lockfile": "^4.1.2",
|
|
101
101
|
"which": "^7.0.0",
|
|
102
102
|
"write-file-atomic": "^8.0.0",
|
|
103
|
-
"@dsh-workbench/shared": "1.1.
|
|
104
|
-
"@dsh-workbench/adapters-default": "1.1.
|
|
103
|
+
"@dsh-workbench/shared": "1.1.4",
|
|
104
|
+
"@dsh-workbench/adapters-default": "1.1.4"
|
|
105
105
|
},
|
|
106
106
|
"license": "MIT",
|
|
107
107
|
"repository": {
|