dsh-plugin-upgrader 1.6.2 → 1.7.0
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 +84 -0
- package/README.en.md +45 -2
- package/README.md +35 -1
- package/assets/icon-180.png +0 -0
- package/lib/client.js +258 -7
- package/lib/host/hostinfo.d.ts +82 -0
- package/lib/host/hostinfo.d.ts.map +1 -0
- package/lib/host/hostinfo.js +92 -0
- package/lib/host/hostinfo.js.map +1 -0
- package/lib/host/install.d.ts +19 -1
- package/lib/host/install.d.ts.map +1 -1
- package/lib/host/install.js +166 -8
- package/lib/host/install.js.map +1 -1
- package/lib/host/overview.d.ts +19 -0
- package/lib/host/overview.d.ts.map +1 -1
- package/lib/host/overview.js +27 -3
- package/lib/host/overview.js.map +1 -1
- package/lib/host/registry.d.ts +50 -1
- package/lib/host/registry.d.ts.map +1 -1
- package/lib/host/registry.js +63 -2
- package/lib/host/registry.js.map +1 -1
- package/lib/host/runtime.d.ts +13 -0
- package/lib/host/runtime.d.ts.map +1 -0
- package/lib/host/runtime.js +114 -0
- package/lib/host/runtime.js.map +1 -0
- package/lib/host/version.d.ts +22 -3
- package/lib/host/version.d.ts.map +1 -1
- package/lib/host/version.js +278 -3
- package/lib/host/version.js.map +1 -1
- package/lib/index.d.ts +78 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +109 -14
- package/lib/index.js.map +1 -1
- package/package.json +2 -1
package/lib/client.js
CHANGED
|
@@ -87,6 +87,11 @@ window.__ModuleLoader__.load({
|
|
|
87
87
|
noHistoryWhy: "\u8FD9\u4E2A\u5305\u4E0D\u662F\u4ECE npm \u6CE8\u518C\u8868\u5B89\u88C5\u7684\uFF0C\u6CA1\u6709\u53D1\u5E03\u5386\u53F2\u3002",
|
|
88
88
|
historyFailed: "\u7248\u672C\u5217\u8868\u8BFB\u53D6\u5931\u8D25\uFF0C\u70B9\u300C\u68C0\u67E5\u66F4\u65B0\u300D\u53EF\u91CD\u8BD5",
|
|
89
89
|
mirrorBehind: "\u955C\u50CF\u6E90\u5C1A\u672A\u540C\u6B65\u8FD9\u4E9B\u5DF2\u53D1\u5E03\u7248\u672C\uFF0C\u88C5\u4E0D\u4E86",
|
|
90
|
+
incompatible: "\u4E0D\u652F\u6301\u5F53\u524D DSH",
|
|
91
|
+
incompatibleWhy: (range) => `\u8FD9\u4E2A\u7248\u672C\u8981\u6C42 DSH ${range}\uFF0C\u800C\u5F53\u524D\u5BBF\u4E3B\u4E0D\u6EE1\u8DB3\u3002\u88C5\u4E0A\u53BB\u4F1A\u88AB\u5BBF\u4E3B\u62D2\u7EDD\u3002`,
|
|
92
|
+
incompatibleLatest: (version, range) => `\u6700\u65B0\u7248 ${version} \u8981\u6C42 DSH ${range}\uFF0C\u5F53\u524D\u5BBF\u4E3B\u4E0D\u6EE1\u8DB3\uFF0C\u6240\u4EE5\u4E0D\u80FD\u5347\u4E0A\u53BB\u3002\u53EF\u4EE5\u5148\u628A DSH \u5347\u5230\u90A3\u4E2A\u8303\u56F4\uFF0C\u6216\u6362\u4E00\u4E2A\u517C\u5BB9\u7684\u7248\u672C\u3002`,
|
|
93
|
+
runtimeUnknown: "\u8BFB\u4E0D\u5230\u5F53\u524D DSH \u7248\u672C\uFF0C\u65E0\u6CD5\u5224\u65AD\u517C\u5BB9\u6027",
|
|
94
|
+
requiresDsh: (range) => `\u8981\u6C42 DSH ${range}`,
|
|
90
95
|
versions: (n) => `${n} \u4E2A\u7248\u672C`,
|
|
91
96
|
showingNewest: (n) => `\u5217\u51FA\u6700\u65B0 ${n} \u4E2A`,
|
|
92
97
|
progress: (done, total) => `\u6B63\u5728\u5904\u7406 ${done}/${total}`,
|
|
@@ -105,6 +110,21 @@ window.__ModuleLoader__.load({
|
|
|
105
110
|
cancelling: "\u6B63\u5728\u53D6\u6D88\u2026",
|
|
106
111
|
restart: "\u9700\u8981\u91CD\u542F DSH \u624D\u4F1A\u751F\u6548\u3002",
|
|
107
112
|
restartHint: "\u5DF2\u4FDD\u5B58\u7684\u6539\u52A8\u5728\u4E0B\u6B21\u542F\u52A8\u65F6\u751F\u6548\u3002",
|
|
113
|
+
restartOpen: "\u91CD\u542F DSH",
|
|
114
|
+
restartTitle: "\u91CD\u542F DSH",
|
|
115
|
+
restartBody: "\u5DF2\u4FDD\u5B58\u7684\u6539\u52A8\u8981\u7B49 DSH \u91CD\u65B0\u542F\u52A8\u624D\u4F1A\u751F\u6548\u3002\u8FD9\u4E00\u9875\u4E0D\u80FD\u66FF\u4F60\u91CD\u542F\u5B83\u2014\u2014\u684C\u9762\u7248\u7531\u5E94\u7528\u5916\u58F3\u638C\u63E1\u91CD\u542F\uFF0C\u4ECE\u7EC8\u7AEF\u542F\u52A8\u7684\u5BBF\u4E3B\u4E5F\u6CA1\u4EBA\u66FF\u5B83\u62C9\u8D77\u3002",
|
|
116
|
+
restartDesktopHint: "\u5B8C\u5168\u9000\u51FA DeepSeek Harness\uFF08\u4E0D\u662F\u5173\u7A97\u53E3\uFF0C\u800C\u662F\u9000\u51FA\u5E94\u7528\uFF09\uFF0C\u518D\u91CD\u65B0\u6253\u5F00\u5B83\u3002",
|
|
117
|
+
restartCommandHint: "\u5728\u539F\u6765\u7684\u7EC8\u7AEF\u91CC\u505C\u6389\u5B83\uFF0C\u518D\u8FD0\u884C\u540C\u4E00\u6761\u547D\u4EE4\uFF1A",
|
|
118
|
+
restartCopy: "\u590D\u5236\u547D\u4EE4",
|
|
119
|
+
restartCopied: "\u5DF2\u590D\u5236",
|
|
120
|
+
restartPid: (pid, profile) => `\u5F53\u524D\u5BBF\u4E3B\u8FDB\u7A0B ${pid}\uFF0Cprofile\uFF1A${profile}`,
|
|
121
|
+
restartRefresh: "\u91CD\u542F\u597D\u4E86\uFF0C\u5237\u65B0\u9875\u9762",
|
|
122
|
+
restartWaiting: "\u6B63\u5728\u7B49\u5BBF\u4E3B\u56DE\u6765\u2026",
|
|
123
|
+
restartStillOld: "\u5BBF\u4E3B\u8FD8\u6CA1\u6362\u65B0\u8FDB\u7A0B\u3002\u786E\u8BA4\u65E7\u8FDB\u7A0B\u5DF2\u7ECF\u9000\u51FA\uFF0C\u518D\u8BD5\u4E00\u6B21\u3002",
|
|
124
|
+
restartReloadBlocked: "\u5BBF\u4E3B\u5DF2\u7ECF\u91CD\u542F\uFF0C\u4F46\u8FD9\u4E00\u9875\u7684\u63D2\u4EF6\u6E05\u5355\u8FC7\u671F\u4E86\uFF0C\u76F4\u63A5\u5237\u65B0\u4F1A\u542F\u52A8\u5931\u8D25\u3002\u8BF7\u518D\u91CD\u542F\u4E00\u6B21 DSH\u3002",
|
|
125
|
+
restartReloadRefused: "\u5BBF\u4E3B\u5DF2\u7ECF\u91CD\u542F\uFF0C\u4F46\u8FD9\u4E00\u9875\u6CA1\u6CD5\u81EA\u5DF1\u5237\u65B0\u3002\u624B\u52A8\u5237\u65B0\u4E00\u4E0B\uFF0C\u6216\u8005\u91CD\u542F DSH \u5B8C\u6210\u5347\u7EA7\u3002",
|
|
126
|
+
restartLoading: "\u6B63\u5728\u8BFB\u53D6\u5BBF\u4E3B\u4FE1\u606F\u2026",
|
|
127
|
+
restartLoadFailed: (detail) => `\u8BFB\u4E0D\u5230\u5BBF\u4E3B\u4FE1\u606F\uFF1A${detail}`,
|
|
108
128
|
reloadForAppearance: "\u4E3B\u9898\u63D2\u4EF6\u5DF2\u66F4\u65B0\uFF0C\u6B63\u5728\u91CD\u65B0\u52A0\u8F7D\u9875\u9762\u4EE5\u6062\u590D\u4E3B\u9898\u5916\u89C2\uFF08\u4E3B\u9898\u914D\u7F6E\u4FDD\u5B58\u5728\u78C1\u76D8\u4E0A\uFF0C\u4E0D\u4F1A\u4E22\u5931\uFF09\u3002",
|
|
109
129
|
reloadBlocked: "\u5916\u89C2\u5DF2\u6062\u590D\uFF0C\u4F46\u8FD9\u4E00\u9875\u7684\u63D2\u4EF6\u6E05\u5355\u5DF2\u7ECF\u8FC7\u671F\uFF0C\u91CD\u65B0\u52A0\u8F7D\u4F1A\u542F\u52A8\u5931\u8D25\u3002\u8BF7\u91CD\u542F DSH \u5B8C\u6210\u8FD9\u6B21\u5347\u7EA7\u3002",
|
|
110
130
|
done: "\u5B8C\u6210",
|
|
@@ -206,6 +226,11 @@ window.__ModuleLoader__.load({
|
|
|
206
226
|
noHistoryWhy: "This package was not installed from an npm registry, so it has no published history.",
|
|
207
227
|
historyFailed: 'Could not read the version list; "Check for updates" retries it',
|
|
208
228
|
mirrorBehind: "Your mirror has not synced these published versions yet, so they cannot be installed",
|
|
229
|
+
incompatible: "Not for this DSH",
|
|
230
|
+
incompatibleWhy: (range) => `This version requires DSH ${range}, which this host does not satisfy. Installing it would be rejected.`,
|
|
231
|
+
incompatibleLatest: (version, range) => `The newest release ${version} requires DSH ${range}, which this host does not satisfy, so the upgrade is not offered. Upgrade DSH into that range, or pick a compatible version.`,
|
|
232
|
+
runtimeUnknown: "Could not read the running DSH version, so compatibility cannot be judged",
|
|
233
|
+
requiresDsh: (range) => `requires DSH ${range}`,
|
|
209
234
|
versions: (n) => `${n} versions`,
|
|
210
235
|
showingNewest: (n) => `showing newest ${n}`,
|
|
211
236
|
progress: (done, total) => `Working on ${done}/${total}`,
|
|
@@ -224,6 +249,21 @@ window.__ModuleLoader__.load({
|
|
|
224
249
|
cancelling: "Cancelling\u2026",
|
|
225
250
|
restart: "Restart DSH to finish.",
|
|
226
251
|
restartHint: "Saved changes take effect on the next start.",
|
|
252
|
+
restartOpen: "Restart DSH",
|
|
253
|
+
restartTitle: "Restart DSH",
|
|
254
|
+
restartBody: "The saved change only takes effect once DSH starts again. This page cannot do that for you \u2014 the desktop app keeps the restart in its own shell, and a host started from a terminal has nobody to start it again.",
|
|
255
|
+
restartDesktopHint: "Quit DeepSeek Harness completely (quit the app, not just the window), then open it again.",
|
|
256
|
+
restartCommandHint: "Stop it in the terminal it was started from, then run the same command:",
|
|
257
|
+
restartCopy: "Copy command",
|
|
258
|
+
restartCopied: "Copied",
|
|
259
|
+
restartPid: (pid, profile) => `Host process ${pid}, profile ${profile}`,
|
|
260
|
+
restartRefresh: "Restarted \u2014 reload the page",
|
|
261
|
+
restartWaiting: "Waiting for the host to come back\u2026",
|
|
262
|
+
restartStillOld: "The host has not been replaced yet. Check that the old process exited, then try again.",
|
|
263
|
+
restartReloadBlocked: "The host restarted, but this page's plugin list is out of date and reloading it would fail to start. Restart DSH once more.",
|
|
264
|
+
restartReloadRefused: "The host restarted, but this page could not reload itself. Reload it by hand, or restart DSH to finish the upgrade.",
|
|
265
|
+
restartLoading: "Reading host information\u2026",
|
|
266
|
+
restartLoadFailed: (detail) => `Could not read host information: ${detail}`,
|
|
227
267
|
reloadForAppearance: "The theme plugin was updated; reloading the page to restore its look (its settings are on disk and are not lost).",
|
|
228
268
|
reloadBlocked: "The look is restored, but this page's plugin list is out of date and reloading it would fail to start. Restart DSH to finish this upgrade.",
|
|
229
269
|
done: "done",
|
|
@@ -393,15 +433,23 @@ window.__ModuleLoader__.load({
|
|
|
393
433
|
const started = await readJson(response);
|
|
394
434
|
return started.id;
|
|
395
435
|
}
|
|
436
|
+
var WATCH_MISS_LIMIT = 4;
|
|
396
437
|
async function watchJob(id, options) {
|
|
438
|
+
const wait = options.delay ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
439
|
+
let missed = 0;
|
|
397
440
|
for (; ; ) {
|
|
398
441
|
if (!options.isAlive()) return void 0;
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
442
|
+
const snapshot = await fetch(`${API}/job?id=${encodeURIComponent(id)}`, { credentials: "same-origin" }).then((response) => readJson(response)).catch(() => void 0);
|
|
443
|
+
if (snapshot === void 0) {
|
|
444
|
+
missed += 1;
|
|
445
|
+
if (missed >= WATCH_MISS_LIMIT) return void 0;
|
|
446
|
+
await wait(POLL_MS);
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
missed = 0;
|
|
402
450
|
if (options.isAlive()) options.onSnapshot(snapshot);
|
|
403
451
|
if (snapshot.status !== "running" && snapshot.status !== "queued") return snapshot;
|
|
404
|
-
await
|
|
452
|
+
await wait(POLL_MS);
|
|
405
453
|
}
|
|
406
454
|
}
|
|
407
455
|
async function submitJob(steps, watch) {
|
|
@@ -430,6 +478,10 @@ window.__ModuleLoader__.load({
|
|
|
430
478
|
});
|
|
431
479
|
return readJson(response);
|
|
432
480
|
}
|
|
481
|
+
async function readHostInfo() {
|
|
482
|
+
const response = await fetch(`${API}/host`, { credentials: "same-origin" });
|
|
483
|
+
return readJson(response);
|
|
484
|
+
}
|
|
433
485
|
|
|
434
486
|
// src/client/boot.ts
|
|
435
487
|
function bootBatches(wire) {
|
|
@@ -740,6 +792,7 @@ window.__ModuleLoader__.load({
|
|
|
740
792
|
.dsh-pu-tag { font-size: 10px; line-height: 1; padding: 3px 6px; border-radius: 999px; border: 1px solid var(--dsw-alias-border-l1); color: var(--dsw-alias-label-secondary); font-weight: 500; white-space: nowrap; }
|
|
741
793
|
.dsh-pu-tag.is-new { border-color: var(--dsw-alias-brand-primary); color: var(--dsw-alias-brand-primary); background: color-mix(in srgb, var(--dsw-alias-brand-primary) 14%, transparent); }
|
|
742
794
|
.dsh-pu-tag.is-err { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }
|
|
795
|
+
.dsh-pu-tag.is-foreign { border-color: var(--dsw-alias-state-warn-primary); color: var(--dsw-alias-state-warn-primary); }
|
|
743
796
|
.dsh-pu-vers { display: flex; align-items: center; gap: 6px; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--dsw-alias-label-secondary); flex: none; }
|
|
744
797
|
.dsh-pu-vers b { color: var(--dsw-alias-label-primary); font-weight: 600; }
|
|
745
798
|
.dsh-pu-vers i { font-style: normal; color: var(--dsw-alias-label-tertiary); }
|
|
@@ -752,6 +805,7 @@ window.__ModuleLoader__.load({
|
|
|
752
805
|
.dsh-pu-hist-row { display: flex; align-items: center; gap: 10px; padding: 5px 6px; border-radius: 6px; font-size: 11px; }
|
|
753
806
|
.dsh-pu-hist-row:hover { background: var(--dsw-alias-interactive-bg-hover); }
|
|
754
807
|
.dsh-pu-hist-row.is-current { background: var(--dsw-alias-interactive-bg-hover); box-shadow: inset 2px 0 0 var(--dsw-alias-brand-primary); }
|
|
808
|
+
.dsh-pu-hist-row.is-foreign .dsh-pu-mono, .dsh-pu-hist-row.is-foreign time { opacity: .6; }
|
|
755
809
|
.dsh-pu-hist-row .dsh-pu-mono { flex: none; min-width: 108px; color: var(--dsw-alias-label-primary); }
|
|
756
810
|
.dsh-pu-link { display: inline-flex; align-items: center; gap: 4px; border: 0; padding: 0; margin: 0; background: none; cursor: pointer; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--dsw-alias-link); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--dsw-alias-link) 40%, transparent); text-underline-offset: 2px; }
|
|
757
811
|
.dsh-pu-link:hover { color: var(--dsw-alias-brand-primary); text-decoration-color: currentColor; }
|
|
@@ -774,6 +828,8 @@ window.__ModuleLoader__.load({
|
|
|
774
828
|
.dsh-pu-banner.is-warn { border-color: var(--dsw-alias-state-warn-primary); color: var(--dsw-alias-state-warn-primary); }
|
|
775
829
|
.dsh-pu-banner.is-err { border-color: var(--dsw-alias-state-error-primary); color: var(--dsw-alias-state-error-primary); }
|
|
776
830
|
.dsh-pu-foot { display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--dsw-alias-label-tertiary); flex-wrap: wrap; }
|
|
831
|
+
.dsh-pu-cmdbox { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; }
|
|
832
|
+
.dsh-pu-cmd { display: block; width: 100%; box-sizing: border-box; margin: 0; padding: 7px 9px; border-radius: 8px; border: 1px solid var(--dsw-alias-border-l1); background: var(--dsw-alias-bg-layer-2); color: var(--dsw-alias-label-primary); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; line-height: 1.5; white-space: pre-wrap; word-break: break-all; user-select: all; }
|
|
777
833
|
.dsh-pu-spin { width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--dsw-alias-border-l2); border-top-color: var(--dsw-alias-brand-primary); animation: dsh-pu-spin .8s linear infinite; flex: none; }
|
|
778
834
|
@keyframes dsh-pu-spin { to { transform: rotate(360deg); } }
|
|
779
835
|
@media (prefers-reduced-motion: reduce) { .dsh-pu-spin { animation-duration: 2.4s; } .dsh-pu-bar-inner.is-busy { animation-duration: 3s; } }
|
|
@@ -871,9 +927,11 @@ window.__ModuleLoader__.load({
|
|
|
871
927
|
const link = resolveVersionLink(row, version);
|
|
872
928
|
const linkLabel = link !== void 0 && /\/releases\/tag\//.test(link) ? t("githubVersion") : t("githubReleases");
|
|
873
929
|
const title = link === void 0 ? void 0 : `${linkLabel} \u2192${link}`;
|
|
930
|
+
const foreign = version.compatible === false;
|
|
931
|
+
const why = foreign ? t("incompatibleWhy", version.requires ?? "") : title;
|
|
874
932
|
return h(
|
|
875
933
|
"div",
|
|
876
|
-
{ className: `dsh-pu-hist-row${version.current ? " is-current" : ""}` },
|
|
934
|
+
{ className: `dsh-pu-hist-row${version.current ? " is-current" : ""}${foreign ? " is-foreign" : ""}` },
|
|
877
935
|
link !== void 0 ? h(
|
|
878
936
|
"button",
|
|
879
937
|
{
|
|
@@ -887,6 +945,7 @@ window.__ModuleLoader__.load({
|
|
|
887
945
|
h("time", null, formatDate(version.time)),
|
|
888
946
|
version.latest ? h("span", { className: "dsh-pu-tag is-new" }, t("latest")) : null,
|
|
889
947
|
version.current ? h("span", { className: "dsh-pu-tag" }, t("current")) : null,
|
|
948
|
+
foreign ? h("span", { className: "dsh-pu-tag is-foreign", title: why }, t("incompatible")) : null,
|
|
890
949
|
h("span", { className: "dsh-pu-note" }, note),
|
|
891
950
|
link === void 0 ? null : h(
|
|
892
951
|
"button",
|
|
@@ -904,7 +963,8 @@ window.__ModuleLoader__.load({
|
|
|
904
963
|
{
|
|
905
964
|
type: "button",
|
|
906
965
|
className: "dsh-pu-btn is-tiny",
|
|
907
|
-
disabled: busy || version.current === true,
|
|
966
|
+
disabled: busy || version.current === true || foreign,
|
|
967
|
+
title: why,
|
|
908
968
|
onClick: () => onSwitch(row, version.version)
|
|
909
969
|
},
|
|
910
970
|
/*
|
|
@@ -991,6 +1051,20 @@ window.__ModuleLoader__.load({
|
|
|
991
1051
|
},
|
|
992
1052
|
`${t("mirrorBehind")}: ${row.mirrorMissing.slice(0, 3).join(", ")}${row.mirrorMissing.length > 3 ? " \u2026" : ""}`
|
|
993
1053
|
) : null,
|
|
1054
|
+
/*
|
|
1055
|
+
* The newest release refuses to run on this DSH version. The row's
|
|
1056
|
+
* upgrade button points at `latest`, so it is no longer an upgrade:
|
|
1057
|
+
* naming the requirement is the only thing that turns "nothing happens"
|
|
1058
|
+
* into something the person can act on.
|
|
1059
|
+
*/
|
|
1060
|
+
row.blocked !== void 0 ? h(
|
|
1061
|
+
"div",
|
|
1062
|
+
{
|
|
1063
|
+
className: "dsh-pu-note is-err",
|
|
1064
|
+
title: t("incompatibleLatest", row.blocked.version, row.blocked.requires)
|
|
1065
|
+
},
|
|
1066
|
+
t("incompatibleLatest", row.blocked.version, row.blocked.requires)
|
|
1067
|
+
) : null,
|
|
994
1068
|
failure !== void 0 && retriable ? h(
|
|
995
1069
|
"div",
|
|
996
1070
|
{ className: "dsh-pu-note is-err", title: failure },
|
|
@@ -1102,6 +1176,158 @@ window.__ModuleLoader__.load({
|
|
|
1102
1176
|
);
|
|
1103
1177
|
}
|
|
1104
1178
|
|
|
1179
|
+
// src/client/components/RestartDialog.ts
|
|
1180
|
+
var PROBE_MS = 1e3;
|
|
1181
|
+
var WAIT_LIMIT_MS = 12e4;
|
|
1182
|
+
function stalledMessage(problem, t) {
|
|
1183
|
+
return problem.trim() === "" ? t("restartStillOld") : problem;
|
|
1184
|
+
}
|
|
1185
|
+
function RestartDialog(props) {
|
|
1186
|
+
const { t, onClose } = props;
|
|
1187
|
+
const h = getH();
|
|
1188
|
+
const React = getReact();
|
|
1189
|
+
const [host, setHost] = React.useState(void 0);
|
|
1190
|
+
const [phase, setPhase] = React.useState("loading");
|
|
1191
|
+
const [problem, setProblem] = React.useState("");
|
|
1192
|
+
const [copied, setCopied] = React.useState(false);
|
|
1193
|
+
const timerRef = React.useRef(void 0);
|
|
1194
|
+
React.useEffect(() => {
|
|
1195
|
+
let live = true;
|
|
1196
|
+
void readHostInfo().then((info) => {
|
|
1197
|
+
if (!live) return;
|
|
1198
|
+
setHost(info);
|
|
1199
|
+
setPhase("ready");
|
|
1200
|
+
}).catch((error) => {
|
|
1201
|
+
if (!live) return;
|
|
1202
|
+
setProblem(error instanceof Error ? error.message : String(error));
|
|
1203
|
+
setPhase("failed");
|
|
1204
|
+
});
|
|
1205
|
+
return () => {
|
|
1206
|
+
live = false;
|
|
1207
|
+
};
|
|
1208
|
+
}, []);
|
|
1209
|
+
const stop = React.useCallback(() => {
|
|
1210
|
+
const timer = timerRef.current;
|
|
1211
|
+
if (timer === void 0) return;
|
|
1212
|
+
timerRef.current = void 0;
|
|
1213
|
+
window.clearInterval(timer);
|
|
1214
|
+
}, []);
|
|
1215
|
+
React.useEffect(() => stop, [stop]);
|
|
1216
|
+
const waitForRestart = React.useCallback(() => {
|
|
1217
|
+
const before = host?.pid;
|
|
1218
|
+
if (before === void 0) return;
|
|
1219
|
+
setProblem("");
|
|
1220
|
+
setPhase("waiting");
|
|
1221
|
+
const startedAt = Date.now();
|
|
1222
|
+
const timer = window.setInterval(() => {
|
|
1223
|
+
void readHostInfo().then((info) => {
|
|
1224
|
+
if (info.pid === before) {
|
|
1225
|
+
if (Date.now() - startedAt > WAIT_LIMIT_MS) {
|
|
1226
|
+
stop();
|
|
1227
|
+
setPhase("stalled");
|
|
1228
|
+
}
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
stop();
|
|
1232
|
+
let blocked = false;
|
|
1233
|
+
void reloadWhenBootDocumentFresh({
|
|
1234
|
+
onBlocked: () => {
|
|
1235
|
+
blocked = true;
|
|
1236
|
+
setProblem(t("restartReloadBlocked"));
|
|
1237
|
+
setPhase("stalled");
|
|
1238
|
+
}
|
|
1239
|
+
}).then((done) => {
|
|
1240
|
+
if (!done && !blocked) {
|
|
1241
|
+
setProblem(t("restartReloadRefused"));
|
|
1242
|
+
setPhase("stalled");
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
}).catch(() => {
|
|
1246
|
+
});
|
|
1247
|
+
}, PROBE_MS);
|
|
1248
|
+
timerRef.current = timer;
|
|
1249
|
+
}, [host?.pid, stop, t]);
|
|
1250
|
+
const copy = React.useCallback(() => {
|
|
1251
|
+
const command = host?.command ?? "";
|
|
1252
|
+
if (command === "") return;
|
|
1253
|
+
void navigator.clipboard?.writeText(command).then(() => {
|
|
1254
|
+
setCopied(true);
|
|
1255
|
+
}).catch(() => {
|
|
1256
|
+
});
|
|
1257
|
+
}, [host?.command]);
|
|
1258
|
+
React.useEffect(() => {
|
|
1259
|
+
const onKey = (event) => {
|
|
1260
|
+
if (event.key === "Escape") onClose();
|
|
1261
|
+
};
|
|
1262
|
+
document.addEventListener("keydown", onKey);
|
|
1263
|
+
return () => {
|
|
1264
|
+
document.removeEventListener("keydown", onKey);
|
|
1265
|
+
};
|
|
1266
|
+
}, [onClose]);
|
|
1267
|
+
const desktop = host?.kind === "desktop";
|
|
1268
|
+
return h(
|
|
1269
|
+
"div",
|
|
1270
|
+
{ className: "dsh-pu-modal" },
|
|
1271
|
+
h("div", { className: "dsh-pu-modal-backdrop", onClick: onClose, "aria-hidden": "true" }),
|
|
1272
|
+
h(
|
|
1273
|
+
"div",
|
|
1274
|
+
{
|
|
1275
|
+
className: "dsh-pu-modal-body",
|
|
1276
|
+
role: "dialog",
|
|
1277
|
+
"aria-modal": "true",
|
|
1278
|
+
"aria-label": t("restartTitle")
|
|
1279
|
+
},
|
|
1280
|
+
h(
|
|
1281
|
+
"div",
|
|
1282
|
+
{ className: "dsh-pu-modal-head" },
|
|
1283
|
+
h("span", { className: "dsh-pu-modal-title" }, t("restartTitle")),
|
|
1284
|
+
h("button", { type: "button", className: "dsh-pu-btn is-ghost is-tiny", onClick: onClose }, "\u2715")
|
|
1285
|
+
),
|
|
1286
|
+
h("p", { className: "dsh-pu-modal-sub" }, t("restartBody")),
|
|
1287
|
+
phase === "loading" ? h("p", { className: "dsh-pu-hint" }, t("restartLoading")) : null,
|
|
1288
|
+
phase === "failed" ? h("p", { className: "dsh-pu-hint" }, t("restartLoadFailed", problem)) : null,
|
|
1289
|
+
desktop ? h("p", { className: "dsh-pu-hint" }, t("restartDesktopHint")) : host === void 0 ? null : h(
|
|
1290
|
+
"div",
|
|
1291
|
+
{ className: "dsh-pu-cmdbox" },
|
|
1292
|
+
h("p", { className: "dsh-pu-hint" }, t("restartCommandHint")),
|
|
1293
|
+
h("code", { className: "dsh-pu-cmd" }, host.command),
|
|
1294
|
+
h(
|
|
1295
|
+
"button",
|
|
1296
|
+
{
|
|
1297
|
+
type: "button",
|
|
1298
|
+
className: "dsh-pu-btn is-tiny",
|
|
1299
|
+
onClick: copy,
|
|
1300
|
+
disabled: host.command === ""
|
|
1301
|
+
},
|
|
1302
|
+
copied ? t("restartCopied") : t("restartCopy")
|
|
1303
|
+
)
|
|
1304
|
+
),
|
|
1305
|
+
host === void 0 ? null : h("p", { className: "dsh-pu-hint" }, t("restartPid", host.pid, host.profileName ?? "\u2014")),
|
|
1306
|
+
phase === "waiting" ? h("p", { className: "dsh-pu-hint" }, t("restartWaiting")) : null,
|
|
1307
|
+
phase === "stalled" ? h("p", { className: "dsh-pu-hint" }, stalledMessage(problem, t)) : null,
|
|
1308
|
+
h(
|
|
1309
|
+
"div",
|
|
1310
|
+
{ className: "dsh-pu-src-foot" },
|
|
1311
|
+
h(
|
|
1312
|
+
"button",
|
|
1313
|
+
{
|
|
1314
|
+
type: "button",
|
|
1315
|
+
className: "dsh-pu-btn is-primary is-tiny",
|
|
1316
|
+
onClick: waitForRestart,
|
|
1317
|
+
disabled: host === void 0 || phase === "waiting"
|
|
1318
|
+
},
|
|
1319
|
+
phase === "waiting" ? t("restartWaiting") : t("restartRefresh")
|
|
1320
|
+
),
|
|
1321
|
+
h(
|
|
1322
|
+
"button",
|
|
1323
|
+
{ type: "button", className: "dsh-pu-btn is-ghost is-tiny", onClick: onClose },
|
|
1324
|
+
t("sourcesClose")
|
|
1325
|
+
)
|
|
1326
|
+
)
|
|
1327
|
+
)
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1105
1331
|
// src/client/components/SourceDialog.ts
|
|
1106
1332
|
function RegistrySourceButton(props) {
|
|
1107
1333
|
const h = getH();
|
|
@@ -1578,6 +1804,8 @@ window.__ModuleLoader__.load({
|
|
|
1578
1804
|
const [busyName, setBusyName] = React.useState(void 0);
|
|
1579
1805
|
const [cancelling, setCancelling] = React.useState(false);
|
|
1580
1806
|
const [banner, setBanner] = React.useState(void 0);
|
|
1807
|
+
const [restartOpen, setRestartOpen] = React.useState(false);
|
|
1808
|
+
const [restartPending, setRestartPending] = React.useState(false);
|
|
1581
1809
|
const alive = useAlive();
|
|
1582
1810
|
const watch = React.useCallback(
|
|
1583
1811
|
async (id) => {
|
|
@@ -1585,6 +1813,7 @@ window.__ModuleLoader__.load({
|
|
|
1585
1813
|
if (!alive.current) return settled;
|
|
1586
1814
|
setBusyName(void 0);
|
|
1587
1815
|
setCancelling(false);
|
|
1816
|
+
setRestartPending(false);
|
|
1588
1817
|
reload(false);
|
|
1589
1818
|
if (settled === void 0) {
|
|
1590
1819
|
setJob(void 0);
|
|
@@ -1602,12 +1831,15 @@ window.__ModuleLoader__.load({
|
|
|
1602
1831
|
});
|
|
1603
1832
|
} else if (settled?.results?.some((result) => result.application === "restart-required") === true) {
|
|
1604
1833
|
setBanner({ tone: "warn", text: t("restart") });
|
|
1834
|
+
setRestartPending(true);
|
|
1605
1835
|
} else if (replacedAppearance(settled?.results)) {
|
|
1606
1836
|
setBanner({ tone: "info", text: t("reloadForAppearance") });
|
|
1607
1837
|
window.setTimeout(() => {
|
|
1608
1838
|
void reloadWhenBootDocumentFresh({
|
|
1609
1839
|
onBlocked: () => {
|
|
1610
|
-
if (alive.current)
|
|
1840
|
+
if (!alive.current) return;
|
|
1841
|
+
setBanner({ tone: "warn", text: t("reloadBlocked") });
|
|
1842
|
+
setRestartPending(true);
|
|
1611
1843
|
}
|
|
1612
1844
|
});
|
|
1613
1845
|
}, APPEARANCE_RELOAD_DELAY_MS);
|
|
@@ -1630,6 +1862,7 @@ window.__ModuleLoader__.load({
|
|
|
1630
1862
|
async (steps, label) => {
|
|
1631
1863
|
if (steps.length === 0) return;
|
|
1632
1864
|
setBanner(void 0);
|
|
1865
|
+
setRestartPending(false);
|
|
1633
1866
|
setBusyName(label);
|
|
1634
1867
|
setJob({ id: "", status: "queued", total: steps.length, done: 0, failed: 0, log: [] });
|
|
1635
1868
|
const outcome = await submitJob(steps, watch);
|
|
@@ -1685,6 +1918,7 @@ window.__ModuleLoader__.load({
|
|
|
1685
1918
|
return;
|
|
1686
1919
|
}
|
|
1687
1920
|
setBanner(void 0);
|
|
1921
|
+
setRestartPending(false);
|
|
1688
1922
|
install({ spec: `${row.name}@${version}`, title: row.title, version });
|
|
1689
1923
|
},
|
|
1690
1924
|
[props.install, t]
|
|
@@ -1788,12 +2022,29 @@ window.__ModuleLoader__.load({
|
|
|
1788
2022
|
},
|
|
1789
2023
|
h("span", null, banner.text),
|
|
1790
2024
|
banner.tone === "warn" ? h("span", null, t("restartHint")) : null,
|
|
2025
|
+
/**
|
|
2026
|
+
* The restart button belongs to the restart banner only. A `warn`
|
|
2027
|
+
* banner is also raised for "the reload was stopped" and for "this
|
|
2028
|
+
* page has no install entry", and offering a restart for those would
|
|
2029
|
+
* be advice that does not apply — so the flag set by the result
|
|
2030
|
+
* decides, not the tone.
|
|
2031
|
+
*/
|
|
2032
|
+
restartPending ? h(
|
|
2033
|
+
"button",
|
|
2034
|
+
{
|
|
2035
|
+
type: "button",
|
|
2036
|
+
className: "dsh-pu-btn is-tiny",
|
|
2037
|
+
onClick: () => setRestartOpen(true)
|
|
2038
|
+
},
|
|
2039
|
+
t("restartOpen")
|
|
2040
|
+
) : null,
|
|
1791
2041
|
h(
|
|
1792
2042
|
"button",
|
|
1793
2043
|
{ type: "button", className: "dsh-pu-btn is-ghost is-tiny", onClick: () => setBanner(void 0) },
|
|
1794
2044
|
"\u2715"
|
|
1795
2045
|
)
|
|
1796
2046
|
),
|
|
2047
|
+
restartOpen ? h(RestartDialog, { t, onClose: () => setRestartOpen(false) }) : null,
|
|
1797
2048
|
job === void 0 ? null : h(JobPanel, { job, t, onCancel: cancel, cancelling }),
|
|
1798
2049
|
rows.length === 0 ? null : h(
|
|
1799
2050
|
"div",
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How this host was started, in terms a person can act on.
|
|
3
|
+
*
|
|
4
|
+
* A change the manager reports as `restart-required` can only be finished by
|
|
5
|
+
* restarting the process that refused it, and nothing here can do that to
|
|
6
|
+
* itself: the desktop shell exposes no relaunch channel to a page, and a host
|
|
7
|
+
* started from a terminal has nobody to start it again. What the page *can* do
|
|
8
|
+
* is name the one action that finishes the job, and for that it needs two
|
|
9
|
+
* facts that only the host process has — whether it was started by the desktop
|
|
10
|
+
* app or by a command line, and what that command line was.
|
|
11
|
+
*
|
|
12
|
+
* `pid` is the load-bearing half of the answer. Every other field describes the
|
|
13
|
+
* profile, which survives a restart untouched; the pid is the only value that
|
|
14
|
+
* tells a polling page whether the host answering it is still the old one.
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-plugin-upgrader/host/hostinfo
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Who started this process.
|
|
20
|
+
*
|
|
21
|
+
* `desktop` means the Electron shell owns the lifecycle and the user finishes
|
|
22
|
+
* the restart by quitting and reopening the app; `cli` means the host *is* the
|
|
23
|
+
* terminal command and the user finishes it by running that command again.
|
|
24
|
+
*/
|
|
25
|
+
export type HostKind = 'desktop' | 'cli';
|
|
26
|
+
/** What `/api/plugin-upgrader/host` answers with. */
|
|
27
|
+
export interface HostInfo {
|
|
28
|
+
/** The process id; a restart is the only thing that changes it. */
|
|
29
|
+
pid: number;
|
|
30
|
+
/** When this process started, in the same clock as `Date.now()`. */
|
|
31
|
+
startedAt: number;
|
|
32
|
+
kind: HostKind;
|
|
33
|
+
/** The profile directory's last path segment, for display only. */
|
|
34
|
+
profileName: string | null;
|
|
35
|
+
/** The profile directory this host opened, when it could be resolved. */
|
|
36
|
+
profileDir: string | null;
|
|
37
|
+
/** A command line that starts this same host again; empty for `desktop`. */
|
|
38
|
+
command: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Decide who owns this process's lifecycle from its entry point.
|
|
42
|
+
*
|
|
43
|
+
* The check is on the entry script rather than on an environment variable
|
|
44
|
+
* because the entry script is what the shell actually executes: the desktop
|
|
45
|
+
* shell runs `dsh-desktop-host/lib/index.js` and nothing else in this install
|
|
46
|
+
* runs from that path.
|
|
47
|
+
*
|
|
48
|
+
* @param entry - `process.argv[1]`, possibly absent.
|
|
49
|
+
* @returns which kind of start this was.
|
|
50
|
+
*/
|
|
51
|
+
export declare function hostKindOf(entry: string): HostKind;
|
|
52
|
+
/**
|
|
53
|
+
* Rebuild the command that started this process.
|
|
54
|
+
*
|
|
55
|
+
* The desktop shell is deliberately answered with an empty string: its host is
|
|
56
|
+
* a child of the app, and replaying the child's own command line would start a
|
|
57
|
+
* second host holding the same profile. The instruction that actually works
|
|
58
|
+
* there is "quit the app and open it again", which the page writes itself.
|
|
59
|
+
*
|
|
60
|
+
* @param execPath - `process.execPath`.
|
|
61
|
+
* @param argv - `process.argv`.
|
|
62
|
+
* @param kind - who owns the lifecycle.
|
|
63
|
+
* @returns the command line, or an empty string when there is none to give.
|
|
64
|
+
*/
|
|
65
|
+
export declare function relaunchCommand(execPath: string, argv: readonly string[], kind: HostKind): string;
|
|
66
|
+
/**
|
|
67
|
+
* Assemble the answer for one host process.
|
|
68
|
+
*
|
|
69
|
+
* Pure on purpose: the pid, the start time and the profile directory are all
|
|
70
|
+
* inputs, so the shape can be tested without a host.
|
|
71
|
+
*
|
|
72
|
+
* @param input - the facts the process has about itself.
|
|
73
|
+
* @returns what the page may show.
|
|
74
|
+
*/
|
|
75
|
+
export declare function buildHostInfo(input: {
|
|
76
|
+
pid: number;
|
|
77
|
+
startedAt: number;
|
|
78
|
+
execPath: string;
|
|
79
|
+
argv: readonly string[];
|
|
80
|
+
profileDir: string | null;
|
|
81
|
+
}): HostInfo;
|
|
82
|
+
//# sourceMappingURL=hostinfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostinfo.d.ts","sourceRoot":"","sources":["../../src/host/hostinfo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAA;AAExC,qDAAqD;AACrD,MAAM,WAAW,QAAQ;IACvB,mEAAmE;IACnE,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,QAAQ,CAAA;IACd,mEAAmE;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,yEAAyE;IACzE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAA;CAChB;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAElD;AAeD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM,CAIjG;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B,GAAG,QAAQ,CAkBX"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How this host was started, in terms a person can act on.
|
|
3
|
+
*
|
|
4
|
+
* A change the manager reports as `restart-required` can only be finished by
|
|
5
|
+
* restarting the process that refused it, and nothing here can do that to
|
|
6
|
+
* itself: the desktop shell exposes no relaunch channel to a page, and a host
|
|
7
|
+
* started from a terminal has nobody to start it again. What the page *can* do
|
|
8
|
+
* is name the one action that finishes the job, and for that it needs two
|
|
9
|
+
* facts that only the host process has — whether it was started by the desktop
|
|
10
|
+
* app or by a command line, and what that command line was.
|
|
11
|
+
*
|
|
12
|
+
* `pid` is the load-bearing half of the answer. Every other field describes the
|
|
13
|
+
* profile, which survives a restart untouched; the pid is the only value that
|
|
14
|
+
* tells a polling page whether the host answering it is still the old one.
|
|
15
|
+
*
|
|
16
|
+
* @module dsh-plugin-upgrader/host/hostinfo
|
|
17
|
+
*/
|
|
18
|
+
/** The entry point the desktop shell spawns for its host child process. */
|
|
19
|
+
const DESKTOP_ENTRY = /[\\/]dsh-desktop-host[\\/]lib[\\/]index\.js$/i;
|
|
20
|
+
/**
|
|
21
|
+
* Decide who owns this process's lifecycle from its entry point.
|
|
22
|
+
*
|
|
23
|
+
* The check is on the entry script rather than on an environment variable
|
|
24
|
+
* because the entry script is what the shell actually executes: the desktop
|
|
25
|
+
* shell runs `dsh-desktop-host/lib/index.js` and nothing else in this install
|
|
26
|
+
* runs from that path.
|
|
27
|
+
*
|
|
28
|
+
* @param entry - `process.argv[1]`, possibly absent.
|
|
29
|
+
* @returns which kind of start this was.
|
|
30
|
+
*/
|
|
31
|
+
export function hostKindOf(entry) {
|
|
32
|
+
return DESKTOP_ENTRY.test(entry) ? 'desktop' : 'cli';
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Quote one argument for the platform's shell.
|
|
36
|
+
*
|
|
37
|
+
* Only the case a person can paste is handled: an argument with whitespace is
|
|
38
|
+
* wrapped in double quotes, which both `cmd.exe` and POSIX shells accept.
|
|
39
|
+
*
|
|
40
|
+
* @param argument - one raw argv entry.
|
|
41
|
+
* @returns the entry as it would be typed.
|
|
42
|
+
*/
|
|
43
|
+
function quoted(argument) {
|
|
44
|
+
return /\s/.test(argument) ? `"${argument}"` : argument;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Rebuild the command that started this process.
|
|
48
|
+
*
|
|
49
|
+
* The desktop shell is deliberately answered with an empty string: its host is
|
|
50
|
+
* a child of the app, and replaying the child's own command line would start a
|
|
51
|
+
* second host holding the same profile. The instruction that actually works
|
|
52
|
+
* there is "quit the app and open it again", which the page writes itself.
|
|
53
|
+
*
|
|
54
|
+
* @param execPath - `process.execPath`.
|
|
55
|
+
* @param argv - `process.argv`.
|
|
56
|
+
* @param kind - who owns the lifecycle.
|
|
57
|
+
* @returns the command line, or an empty string when there is none to give.
|
|
58
|
+
*/
|
|
59
|
+
export function relaunchCommand(execPath, argv, kind) {
|
|
60
|
+
if (kind === 'desktop')
|
|
61
|
+
return '';
|
|
62
|
+
const rest = argv.slice(1).map(quoted).join(' ');
|
|
63
|
+
return rest === '' ? quoted(execPath) : `${quoted(execPath)} ${rest}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Assemble the answer for one host process.
|
|
67
|
+
*
|
|
68
|
+
* Pure on purpose: the pid, the start time and the profile directory are all
|
|
69
|
+
* inputs, so the shape can be tested without a host.
|
|
70
|
+
*
|
|
71
|
+
* @param input - the facts the process has about itself.
|
|
72
|
+
* @returns what the page may show.
|
|
73
|
+
*/
|
|
74
|
+
export function buildHostInfo(input) {
|
|
75
|
+
const kind = hostKindOf(input.argv[1] ?? '');
|
|
76
|
+
const profileDir = input.profileDir;
|
|
77
|
+
const profileName = profileDir === null
|
|
78
|
+
? null
|
|
79
|
+
: (profileDir
|
|
80
|
+
.split(/[\\/]/)
|
|
81
|
+
.filter((segment) => segment !== '')
|
|
82
|
+
.at(-1) ?? null);
|
|
83
|
+
return {
|
|
84
|
+
pid: input.pid,
|
|
85
|
+
startedAt: input.startedAt,
|
|
86
|
+
kind,
|
|
87
|
+
profileName,
|
|
88
|
+
profileDir,
|
|
89
|
+
command: relaunchCommand(input.execPath, input.argv, kind),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=hostinfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hostinfo.js","sourceRoot":"","sources":["../../src/host/hostinfo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AA0BH,2EAA2E;AAC3E,MAAM,aAAa,GAAG,+CAA+C,CAAA;AAErE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;AACtD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,MAAM,CAAC,QAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAA;AACzD,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,IAAuB,EAAE,IAAc;IACvF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAChD,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAA;AACvE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,KAM7B;IACC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAA;IACnC,MAAM,WAAW,GACf,UAAU,KAAK,IAAI;QACjB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,CAAC,UAAU;aACR,KAAK,CAAC,OAAO,CAAC;aACd,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC;aACnC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAA;IACxB,OAAO;QACL,GAAG,EAAE,KAAK,CAAC,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI;QACJ,WAAW;QACX,UAAU;QACV,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC;KAC3D,CAAA;AACH,CAAC"}
|
package/lib/host/install.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export interface StepOutcome {
|
|
|
26
26
|
detail?: string;
|
|
27
27
|
pendingBuilds?: string[];
|
|
28
28
|
warnings?: string[];
|
|
29
|
+
/** The version this step put back after destroying the one that was there. */
|
|
30
|
+
rolledBack?: string;
|
|
29
31
|
packageResult?: {
|
|
30
32
|
exitCode: number;
|
|
31
33
|
kind?: string;
|
|
@@ -35,6 +37,21 @@ export interface StepOutcome {
|
|
|
35
37
|
}
|
|
36
38
|
/** Allowed per-step actions. */
|
|
37
39
|
export declare const ACTIONS: Set<string>;
|
|
40
|
+
/**
|
|
41
|
+
* One version's DSH requirement, looked up only when a step is about to run.
|
|
42
|
+
*
|
|
43
|
+
* The lookup is injected rather than imported so this module keeps no registry
|
|
44
|
+
* client: the caller already has the packument cache and the chosen registry,
|
|
45
|
+
* and asking the network here would duplicate both.
|
|
46
|
+
*/
|
|
47
|
+
export interface InstallGuard {
|
|
48
|
+
/** The DSH build this process runs, when it could be read. */
|
|
49
|
+
runtimeVersion?: string | undefined;
|
|
50
|
+
/** The requirement `name@version` declares, or `undefined` when unknown. */
|
|
51
|
+
requirementOf: (name: string, version: string) => Promise<{
|
|
52
|
+
range: string;
|
|
53
|
+
} | undefined>;
|
|
54
|
+
}
|
|
38
55
|
/**
|
|
39
56
|
* Re-apply the enabled state a step asked for after the package was replaced.
|
|
40
57
|
*
|
|
@@ -78,9 +95,10 @@ export declare function restoreSelection(manager: PluginManager, name: string, l
|
|
|
78
95
|
* @param log - progress sink.
|
|
79
96
|
* @param announce - receives the request id the step installs under.
|
|
80
97
|
* @param registry - the registry chosen in this plugin's config, if any.
|
|
98
|
+
* @param guard - the compatibility check, when the caller can supply one.
|
|
81
99
|
* @returns the outcome record.
|
|
82
100
|
*/
|
|
83
|
-
export declare function runStep(manager: PluginManager, step: StepRecord, log: LogSink, announce?: RequestIdSink, registry?: string): Promise<StepOutcome>;
|
|
101
|
+
export declare function runStep(manager: PluginManager, step: StepRecord, log: LogSink, announce?: RequestIdSink, registry?: string, guard?: InstallGuard): Promise<StepOutcome>;
|
|
84
102
|
/**
|
|
85
103
|
* Whether a step names something this plugin is willing to install.
|
|
86
104
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/host/install.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAc,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/host/install.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAc,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAIvF,iCAAiC;AACjC,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;AAE/C;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;AAEvD,yDAAyD;AACzD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,EAAE,EAAE,OAAO,CAAA;IACX,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;IACzC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAA;IACvC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IACnB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,aAAa,CAAC,EAAE;QACd,QAAQ,EAAE,MAAM,CAAA;QAChB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;CACF;AAED,gCAAgC;AAChC,eAAO,MAAM,OAAO,aAAyC,CAAA;AA+H7D;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACnC,4EAA4E;IAC5E,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC,CAAA;CACzF;AA8GD;;;;;;;;;;;GAWG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,OAAO,GAAG,SAAS,EAC3B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAuB9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,OAAO,CAAC,CAmBlB;AA0MD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,aAAa,EACtB,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,aAAa,EACxB,QAAQ,CAAC,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,WAAW,CAAC,CAuLtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAM9D"}
|