dsh-plugin-discovery 1.2.0 → 1.2.5
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/README.md +104 -96
- package/client.js +646 -24
- package/data/recommended.json +1206 -1206
- package/index.js +318 -14
- package/package.json +74 -74
package/client.js
CHANGED
|
@@ -49,6 +49,27 @@ window.__ModuleLoader__.load({
|
|
|
49
49
|
installLog: "安装输出:{text}",
|
|
50
50
|
installFailed: "安装失败",
|
|
51
51
|
retry: "重试",
|
|
52
|
+
copy: "复制",
|
|
53
|
+
copied: "已复制",
|
|
54
|
+
copyFailed: "复制失败",
|
|
55
|
+
riskInstall: "承担风险安装",
|
|
56
|
+
riskTitle: "版本不兼容,确认风险后安装?",
|
|
57
|
+
riskDesc:
|
|
58
|
+
"插件 {package} 与当前 DSH {runtime} 声明的 peer 不匹配。强行安装可能导致崩溃或数据丢失。仅在你明确愿意承担该风险时继续。",
|
|
59
|
+
riskAck: "我已了解风险,仍要为这对精确版本授予豁免并重试安装",
|
|
60
|
+
riskCancel: "取消",
|
|
61
|
+
riskConfirm: "确认豁免并安装",
|
|
62
|
+
riskWorking: "正在授权并重试…",
|
|
63
|
+
riskAltTitle: "推荐改用兼容插件",
|
|
64
|
+
riskAltDesc: "以下精选包更可能匹配当前 DSH 版本,可直接安装代替强行豁免:",
|
|
65
|
+
riskAltInstall: "安装推荐",
|
|
66
|
+
buildTitle: "需要批准依赖构建脚本",
|
|
67
|
+
buildDesc:
|
|
68
|
+
"安装「{spec}」时,pnpm 拦截了以下依赖的安装脚本(常用于编译原生模块)。批准后将以你的用户权限执行这些脚本,并重试安装。",
|
|
69
|
+
buildAck: "我已了解风险,允许这些依赖运行安装脚本并重试",
|
|
70
|
+
buildCancel: "取消",
|
|
71
|
+
buildConfirm: "批准并重试安装",
|
|
72
|
+
buildWorking: "正在批准并重试…",
|
|
52
73
|
browseRecommend: "为你推荐",
|
|
53
74
|
browseCategory: "分类浏览",
|
|
54
75
|
browseSearch: "在线搜索",
|
|
@@ -129,6 +150,27 @@ window.__ModuleLoader__.load({
|
|
|
129
150
|
installLog: "Output: {text}",
|
|
130
151
|
installFailed: "Install failed",
|
|
131
152
|
retry: "Retry",
|
|
153
|
+
copy: "Copy",
|
|
154
|
+
copied: "Copied",
|
|
155
|
+
copyFailed: "Copy failed",
|
|
156
|
+
riskInstall: "Install anyway",
|
|
157
|
+
riskTitle: "Incompatible version — install at your own risk?",
|
|
158
|
+
riskDesc:
|
|
159
|
+
"Plugin {package} does not match peers for DSH {runtime}. Forcing install may crash or lose data. Continue only if you accept that risk.",
|
|
160
|
+
riskAck: "I understand the risk and grant an exact-version exemption for this pair",
|
|
161
|
+
riskCancel: "Cancel",
|
|
162
|
+
riskConfirm: "Grant exemption and install",
|
|
163
|
+
riskWorking: "Granting and retrying…",
|
|
164
|
+
riskAltTitle: "Try a compatible plugin instead",
|
|
165
|
+
riskAltDesc: "These curated packages are more likely to match this DSH version:",
|
|
166
|
+
riskAltInstall: "Install recommended",
|
|
167
|
+
buildTitle: "Dependency build scripts need approval",
|
|
168
|
+
buildDesc:
|
|
169
|
+
"Installing “{spec}” was blocked because pnpm ignored build scripts for: the packages listed below (often native modules). Approving runs those scripts as your user and retries the install.",
|
|
170
|
+
buildAck: "I understand and allow these packages to run install scripts",
|
|
171
|
+
buildCancel: "Cancel",
|
|
172
|
+
buildConfirm: "Approve and retry",
|
|
173
|
+
buildWorking: "Approving and retrying…",
|
|
132
174
|
browseRecommend: "For you",
|
|
133
175
|
browseCategory: "Categories",
|
|
134
176
|
browseSearch: "Online search",
|
|
@@ -593,7 +635,7 @@ window.__ModuleLoader__.load({
|
|
|
593
635
|
},
|
|
594
636
|
errorBox: {
|
|
595
637
|
display: "flex",
|
|
596
|
-
alignItems: "
|
|
638
|
+
alignItems: "flex-start",
|
|
597
639
|
justifyContent: "space-between",
|
|
598
640
|
gap: "12px",
|
|
599
641
|
padding: "12px 14px",
|
|
@@ -602,6 +644,115 @@ window.__ModuleLoader__.load({
|
|
|
602
644
|
background: "var(--dsw-alias-settings-card-fill, #ffffff)",
|
|
603
645
|
color: "var(--dsw-alias-state-warn-primary, var(--dsw-alias-label-secondary))",
|
|
604
646
|
fontSize: "13px",
|
|
647
|
+
lineHeight: "20px",
|
|
648
|
+
},
|
|
649
|
+
errorText: {
|
|
650
|
+
flex: 1,
|
|
651
|
+
minWidth: 0,
|
|
652
|
+
whiteSpace: "pre-wrap",
|
|
653
|
+
wordBreak: "break-word",
|
|
654
|
+
overflowWrap: "anywhere",
|
|
655
|
+
},
|
|
656
|
+
errorActions: {
|
|
657
|
+
display: "flex",
|
|
658
|
+
alignItems: "center",
|
|
659
|
+
gap: "8px",
|
|
660
|
+
flexShrink: 0,
|
|
661
|
+
flexWrap: "wrap",
|
|
662
|
+
justifyContent: "flex-end",
|
|
663
|
+
},
|
|
664
|
+
riskOverlay: {
|
|
665
|
+
position: "fixed",
|
|
666
|
+
inset: 0,
|
|
667
|
+
zIndex: 10000,
|
|
668
|
+
display: "flex",
|
|
669
|
+
alignItems: "center",
|
|
670
|
+
justifyContent: "center",
|
|
671
|
+
padding: "24px",
|
|
672
|
+
background: "rgba(15, 23, 42, 0.45)",
|
|
673
|
+
},
|
|
674
|
+
riskDialog: {
|
|
675
|
+
width: "min(520px, 100%)",
|
|
676
|
+
maxHeight: "90vh",
|
|
677
|
+
overflow: "auto",
|
|
678
|
+
borderRadius: "var(--dsw-radius-md, 12px)",
|
|
679
|
+
border: "1px solid var(--dsw-alias-border-l2, #d0d5dd)",
|
|
680
|
+
background: "var(--dsw-alias-settings-card-fill, #ffffff)",
|
|
681
|
+
color: "var(--dsw-alias-label-primary)",
|
|
682
|
+
padding: "20px",
|
|
683
|
+
boxShadow: "0 16px 40px rgba(15, 23, 42, 0.18)",
|
|
684
|
+
},
|
|
685
|
+
riskTitle: {
|
|
686
|
+
margin: "0 0 10px",
|
|
687
|
+
fontSize: "16px",
|
|
688
|
+
fontWeight: 600,
|
|
689
|
+
lineHeight: "24px",
|
|
690
|
+
},
|
|
691
|
+
riskDesc: {
|
|
692
|
+
margin: "0 0 14px",
|
|
693
|
+
fontSize: "13px",
|
|
694
|
+
lineHeight: "20px",
|
|
695
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
696
|
+
whiteSpace: "pre-wrap",
|
|
697
|
+
},
|
|
698
|
+
riskAckRow: {
|
|
699
|
+
display: "flex",
|
|
700
|
+
alignItems: "flex-start",
|
|
701
|
+
gap: "10px",
|
|
702
|
+
margin: "0 0 16px",
|
|
703
|
+
fontSize: "13px",
|
|
704
|
+
lineHeight: "20px",
|
|
705
|
+
},
|
|
706
|
+
riskAltBox: {
|
|
707
|
+
margin: "0 0 16px",
|
|
708
|
+
padding: "12px",
|
|
709
|
+
borderRadius: "var(--dsw-radius-sm, 8px)",
|
|
710
|
+
border: "1px solid var(--dsw-alias-border-l2, #d0d5dd)",
|
|
711
|
+
background: "var(--dsw-alias-settings-card-fill-secondary, #f8fafc)",
|
|
712
|
+
},
|
|
713
|
+
riskAltTitle: {
|
|
714
|
+
margin: "0 0 6px",
|
|
715
|
+
fontSize: "13px",
|
|
716
|
+
fontWeight: 600,
|
|
717
|
+
lineHeight: "20px",
|
|
718
|
+
},
|
|
719
|
+
riskAltDesc: {
|
|
720
|
+
margin: "0 0 10px",
|
|
721
|
+
fontSize: "12px",
|
|
722
|
+
lineHeight: "18px",
|
|
723
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
724
|
+
},
|
|
725
|
+
riskAltList: {
|
|
726
|
+
display: "flex",
|
|
727
|
+
flexDirection: "column",
|
|
728
|
+
gap: "8px",
|
|
729
|
+
},
|
|
730
|
+
riskAltRow: {
|
|
731
|
+
display: "flex",
|
|
732
|
+
alignItems: "center",
|
|
733
|
+
justifyContent: "space-between",
|
|
734
|
+
gap: "10px",
|
|
735
|
+
},
|
|
736
|
+
riskAltMeta: {
|
|
737
|
+
minWidth: 0,
|
|
738
|
+
flex: 1,
|
|
739
|
+
},
|
|
740
|
+
riskAltSpec: {
|
|
741
|
+
fontSize: "13px",
|
|
742
|
+
fontWeight: 500,
|
|
743
|
+
lineHeight: "18px",
|
|
744
|
+
wordBreak: "break-all",
|
|
745
|
+
},
|
|
746
|
+
riskAltHint: {
|
|
747
|
+
fontSize: "12px",
|
|
748
|
+
lineHeight: "16px",
|
|
749
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
750
|
+
},
|
|
751
|
+
riskFooter: {
|
|
752
|
+
display: "flex",
|
|
753
|
+
justifyContent: "flex-end",
|
|
754
|
+
gap: "8px",
|
|
755
|
+
flexWrap: "wrap",
|
|
605
756
|
},
|
|
606
757
|
updateBox: {
|
|
607
758
|
display: "flex",
|
|
@@ -751,12 +902,25 @@ window.__ModuleLoader__.load({
|
|
|
751
902
|
const err = result.error;
|
|
752
903
|
return {
|
|
753
904
|
ok: false,
|
|
754
|
-
message: (err && (err.message || err.code)) || fallbackMessage,
|
|
905
|
+
message: (err && (err.message || err.diagnostic || err.code)) || fallbackMessage,
|
|
755
906
|
};
|
|
756
907
|
}
|
|
757
908
|
return result.value;
|
|
758
909
|
}
|
|
759
910
|
|
|
911
|
+
function pickInstallError(res, fallback, lastDetail) {
|
|
912
|
+
const primary = String((res && (res.detail || res.message)) || "").trim();
|
|
913
|
+
const weak =
|
|
914
|
+
!primary ||
|
|
915
|
+
/^install failed$/i.test(primary) ||
|
|
916
|
+
/^安装失败([((]failed[))])?$/i.test(primary);
|
|
917
|
+
if (!weak) return primary;
|
|
918
|
+
const extra = String(lastDetail || "").trim();
|
|
919
|
+
const title = fallback || "安装失败";
|
|
920
|
+
if (extra && extra !== primary) return `${title}\n${extra}`;
|
|
921
|
+
return primary || title;
|
|
922
|
+
}
|
|
923
|
+
|
|
760
924
|
function Panel(props) {
|
|
761
925
|
const api = props.api;
|
|
762
926
|
const t = props.t;
|
|
@@ -775,6 +939,15 @@ window.__ModuleLoader__.load({
|
|
|
775
939
|
const [results, setResults] = React.useState([]);
|
|
776
940
|
const [message, setMessage] = React.useState("");
|
|
777
941
|
const [error, setError] = React.useState("");
|
|
942
|
+
const [copyHint, setCopyHint] = React.useState("");
|
|
943
|
+
const [riskPrompt, setRiskPrompt] = React.useState(null);
|
|
944
|
+
const [riskOpen, setRiskOpen] = React.useState(false);
|
|
945
|
+
const [riskAck, setRiskAck] = React.useState(false);
|
|
946
|
+
const [riskBusy, setRiskBusy] = React.useState(false);
|
|
947
|
+
const [buildPrompt, setBuildPrompt] = React.useState(null);
|
|
948
|
+
const [buildOpen, setBuildOpen] = React.useState(false);
|
|
949
|
+
const [buildAck, setBuildAck] = React.useState(false);
|
|
950
|
+
const [buildBusy, setBuildBusy] = React.useState(false);
|
|
778
951
|
const [busy, setBusy] = React.useState(false);
|
|
779
952
|
const [resolveInput, setResolveInput] = React.useState("");
|
|
780
953
|
const [installDetail, setInstallDetail] = React.useState("");
|
|
@@ -783,6 +956,7 @@ window.__ModuleLoader__.load({
|
|
|
783
956
|
const [page, setPage] = React.useState(1);
|
|
784
957
|
const jobsRef = React.useRef(jobs);
|
|
785
958
|
const installedNamesRef = React.useRef(installedNames);
|
|
959
|
+
const installDetailRef = React.useRef("");
|
|
786
960
|
React.useEffect(() => {
|
|
787
961
|
jobsRef.current = jobs;
|
|
788
962
|
writeJobCache(jobs);
|
|
@@ -790,6 +964,55 @@ window.__ModuleLoader__.load({
|
|
|
790
964
|
React.useEffect(() => {
|
|
791
965
|
installedNamesRef.current = installedNames;
|
|
792
966
|
}, [installedNames]);
|
|
967
|
+
React.useEffect(() => {
|
|
968
|
+
installDetailRef.current = installDetail;
|
|
969
|
+
}, [installDetail]);
|
|
970
|
+
React.useEffect(() => {
|
|
971
|
+
setCopyHint("");
|
|
972
|
+
}, [error]);
|
|
973
|
+
|
|
974
|
+
const openRiskPrompt = React.useCallback((res, item) => {
|
|
975
|
+
const rows = Array.isArray(res && res.incompatible) ? res.incompatible : [];
|
|
976
|
+
const first = rows[0];
|
|
977
|
+
if (!(res && res.needsRiskExemption) || !first) return;
|
|
978
|
+
const packageVersion = `${first.name}@${first.version}`;
|
|
979
|
+
const runtimeVersion = first.runtimeVersion || "unknown";
|
|
980
|
+
const recommendations = Array.isArray(res && res.recommendations) ? res.recommendations : [];
|
|
981
|
+
setRiskAck(false);
|
|
982
|
+
setRiskPrompt({
|
|
983
|
+
spec: (res && res.installSpec) || (item && (item.installSpec || item.spec)) || first.name,
|
|
984
|
+
item: item || null,
|
|
985
|
+
packageVersion,
|
|
986
|
+
runtimeVersion,
|
|
987
|
+
incompatible: rows,
|
|
988
|
+
recommendations,
|
|
989
|
+
});
|
|
990
|
+
setRiskOpen(true);
|
|
991
|
+
}, []);
|
|
992
|
+
|
|
993
|
+
const closeRiskPrompt = React.useCallback(() => {
|
|
994
|
+
if (riskBusy) return;
|
|
995
|
+
setRiskOpen(false);
|
|
996
|
+
setRiskAck(false);
|
|
997
|
+
}, [riskBusy]);
|
|
998
|
+
|
|
999
|
+
const openBuildPrompt = React.useCallback((res, item) => {
|
|
1000
|
+
const pending = Array.isArray(res && res.pendingBuilds) ? res.pendingBuilds.filter(Boolean) : [];
|
|
1001
|
+
if (!(res && res.needsBuildApproval) || !pending.length) return;
|
|
1002
|
+
setBuildAck(false);
|
|
1003
|
+
setBuildPrompt({
|
|
1004
|
+
spec: (res && res.installSpec) || (item && (item.installSpec || item.spec)) || "",
|
|
1005
|
+
item: item || null,
|
|
1006
|
+
pendingBuilds: pending,
|
|
1007
|
+
});
|
|
1008
|
+
setBuildOpen(true);
|
|
1009
|
+
}, []);
|
|
1010
|
+
|
|
1011
|
+
const closeBuildPrompt = React.useCallback(() => {
|
|
1012
|
+
if (buildBusy) return;
|
|
1013
|
+
setBuildOpen(false);
|
|
1014
|
+
setBuildAck(false);
|
|
1015
|
+
}, [buildBusy]);
|
|
793
1016
|
|
|
794
1017
|
const refreshInstalled = React.useCallback(async () => {
|
|
795
1018
|
if (!api || typeof api.listInstalled !== "function") return;
|
|
@@ -1045,18 +1268,38 @@ window.__ModuleLoader__.load({
|
|
|
1045
1268
|
setMessage(res.message || t("installed"));
|
|
1046
1269
|
await refreshInstalled();
|
|
1047
1270
|
} else {
|
|
1271
|
+
const lastDetail =
|
|
1272
|
+
(jobsRef.current[job.requestId] && jobsRef.current[job.requestId].detail) ||
|
|
1273
|
+
installDetailRef.current;
|
|
1274
|
+
const errText = pickInstallError(res, t("installFailed"), lastDetail);
|
|
1048
1275
|
finishJob(job.requestId, {
|
|
1049
1276
|
status: "failed",
|
|
1050
|
-
detail:
|
|
1277
|
+
detail: errText,
|
|
1051
1278
|
});
|
|
1052
|
-
setError(
|
|
1279
|
+
setError(errText);
|
|
1280
|
+
const jobItem = {
|
|
1281
|
+
spec: job.spec,
|
|
1282
|
+
installSpec: job.spec,
|
|
1283
|
+
title: job.packageName || job.spec,
|
|
1284
|
+
};
|
|
1285
|
+
openBuildPrompt(res, jobItem);
|
|
1286
|
+
openRiskPrompt(res, jobItem);
|
|
1053
1287
|
}
|
|
1054
1288
|
} catch (e) {
|
|
1055
1289
|
if (cancelled) return;
|
|
1290
|
+
const lastDetail =
|
|
1291
|
+
(jobsRef.current[job.requestId] && jobsRef.current[job.requestId].detail) ||
|
|
1292
|
+
installDetailRef.current;
|
|
1293
|
+
const errText = pickInstallError(
|
|
1294
|
+
{ message: (e && e.message) || String(e) },
|
|
1295
|
+
t("installFailed"),
|
|
1296
|
+
lastDetail,
|
|
1297
|
+
);
|
|
1056
1298
|
finishJob(job.requestId, {
|
|
1057
1299
|
status: "failed",
|
|
1058
|
-
detail:
|
|
1300
|
+
detail: errText,
|
|
1059
1301
|
});
|
|
1302
|
+
setError(errText);
|
|
1060
1303
|
} finally {
|
|
1061
1304
|
if (!cancelled) setInstallDetail("");
|
|
1062
1305
|
}
|
|
@@ -1151,11 +1394,22 @@ window.__ModuleLoader__.load({
|
|
|
1151
1394
|
setMessage(installed.message || t("installed"));
|
|
1152
1395
|
await refreshInstalled();
|
|
1153
1396
|
} else {
|
|
1397
|
+
const lastDetail =
|
|
1398
|
+
(jobsRef.current[requestId] && jobsRef.current[requestId].detail) ||
|
|
1399
|
+
installDetailRef.current;
|
|
1400
|
+
const errText = pickInstallError(installed, t("installFailed"), lastDetail);
|
|
1154
1401
|
finishJob(requestId, {
|
|
1155
1402
|
status: "failed",
|
|
1156
|
-
detail:
|
|
1403
|
+
detail: errText,
|
|
1157
1404
|
});
|
|
1158
|
-
setError(
|
|
1405
|
+
setError(errText);
|
|
1406
|
+
const resolveItem = {
|
|
1407
|
+
spec: res.spec,
|
|
1408
|
+
installSpec: res.spec,
|
|
1409
|
+
title: (res.inspection && res.inspection.name) || res.spec,
|
|
1410
|
+
};
|
|
1411
|
+
openBuildPrompt(installed, resolveItem);
|
|
1412
|
+
openRiskPrompt(installed, resolveItem);
|
|
1159
1413
|
}
|
|
1160
1414
|
} else {
|
|
1161
1415
|
setResults([]);
|
|
@@ -1169,10 +1423,14 @@ window.__ModuleLoader__.load({
|
|
|
1169
1423
|
}
|
|
1170
1424
|
};
|
|
1171
1425
|
|
|
1172
|
-
const onInstall = async (item) => {
|
|
1426
|
+
const onInstall = async (item, installOpts) => {
|
|
1173
1427
|
const spec = item.installSpec || item.spec;
|
|
1428
|
+
const approvedBuilds = Array.isArray(installOpts && installOpts.approvedBuilds)
|
|
1429
|
+
? installOpts.approvedBuilds.filter(Boolean)
|
|
1430
|
+
: [];
|
|
1174
1431
|
const current = resolveItemStatus(item, installedNames, jobs);
|
|
1175
|
-
if (!spec || current.status === "installed"
|
|
1432
|
+
if (!spec || current.status === "installed") return;
|
|
1433
|
+
if (current.status === "installing" && !approvedBuilds.length) return;
|
|
1176
1434
|
const requestId = newRequestId();
|
|
1177
1435
|
upsertJob(requestId, {
|
|
1178
1436
|
status: "installing",
|
|
@@ -1185,7 +1443,10 @@ window.__ModuleLoader__.load({
|
|
|
1185
1443
|
setMessage("");
|
|
1186
1444
|
setError("");
|
|
1187
1445
|
try {
|
|
1188
|
-
const res = await api.install(spec, {
|
|
1446
|
+
const res = await api.install(spec, {
|
|
1447
|
+
requestId,
|
|
1448
|
+
...(approvedBuilds.length ? { approvedBuilds } : {}),
|
|
1449
|
+
});
|
|
1189
1450
|
if (res && res.alreadyInstalled) {
|
|
1190
1451
|
finishJob(requestId, {
|
|
1191
1452
|
status: "installed",
|
|
@@ -1204,23 +1465,103 @@ window.__ModuleLoader__.load({
|
|
|
1204
1465
|
await refreshInstalled();
|
|
1205
1466
|
setMessage(res.message || t("installed"));
|
|
1206
1467
|
} else {
|
|
1468
|
+
const lastDetail =
|
|
1469
|
+
(jobsRef.current[requestId] && jobsRef.current[requestId].detail) || installDetailRef.current;
|
|
1470
|
+
const errText = pickInstallError(res, t("installFailed"), lastDetail);
|
|
1207
1471
|
finishJob(requestId, {
|
|
1208
1472
|
status: "failed",
|
|
1209
|
-
detail:
|
|
1473
|
+
detail: errText,
|
|
1210
1474
|
});
|
|
1211
|
-
setError(
|
|
1475
|
+
setError(errText);
|
|
1476
|
+
openBuildPrompt(res, item);
|
|
1477
|
+
openRiskPrompt(res, item);
|
|
1212
1478
|
}
|
|
1213
1479
|
} catch (e) {
|
|
1480
|
+
const lastDetail =
|
|
1481
|
+
(jobsRef.current[requestId] && jobsRef.current[requestId].detail) || installDetailRef.current;
|
|
1482
|
+
const errText = pickInstallError(
|
|
1483
|
+
{ message: (e && e.message) || String(e) },
|
|
1484
|
+
t("installFailed"),
|
|
1485
|
+
lastDetail,
|
|
1486
|
+
);
|
|
1214
1487
|
finishJob(requestId, {
|
|
1215
1488
|
status: "failed",
|
|
1216
|
-
detail:
|
|
1489
|
+
detail: errText,
|
|
1217
1490
|
});
|
|
1218
|
-
setError(
|
|
1491
|
+
setError(errText);
|
|
1219
1492
|
} finally {
|
|
1220
1493
|
setInstallDetail("");
|
|
1221
1494
|
}
|
|
1222
1495
|
};
|
|
1223
1496
|
|
|
1497
|
+
const confirmRiskInstall = async () => {
|
|
1498
|
+
if (!riskPrompt || !riskAck || !api || typeof api.grantVersionExemption !== "function") return;
|
|
1499
|
+
setRiskBusy(true);
|
|
1500
|
+
setMessage("");
|
|
1501
|
+
try {
|
|
1502
|
+
const granted = await api.grantVersionExemption(
|
|
1503
|
+
riskPrompt.packageVersion,
|
|
1504
|
+
riskPrompt.runtimeVersion,
|
|
1505
|
+
true,
|
|
1506
|
+
);
|
|
1507
|
+
if (!granted || !granted.ok) {
|
|
1508
|
+
setError((granted && granted.message) || t("installFailed"));
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
const item = riskPrompt.item || {
|
|
1512
|
+
spec: riskPrompt.spec,
|
|
1513
|
+
installSpec: riskPrompt.spec,
|
|
1514
|
+
title: riskPrompt.packageVersion,
|
|
1515
|
+
};
|
|
1516
|
+
setRiskOpen(false);
|
|
1517
|
+
setRiskAck(false);
|
|
1518
|
+
setError("");
|
|
1519
|
+
await onInstall(item);
|
|
1520
|
+
} catch (e) {
|
|
1521
|
+
setError((e && e.message) || String(e));
|
|
1522
|
+
} finally {
|
|
1523
|
+
setRiskBusy(false);
|
|
1524
|
+
}
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
const confirmBuildInstall = async () => {
|
|
1528
|
+
if (!buildPrompt || !buildAck || !api) return;
|
|
1529
|
+
const pending = Array.isArray(buildPrompt.pendingBuilds) ? buildPrompt.pendingBuilds.filter(Boolean) : [];
|
|
1530
|
+
if (!pending.length) return;
|
|
1531
|
+
setBuildBusy(true);
|
|
1532
|
+
setMessage("");
|
|
1533
|
+
try {
|
|
1534
|
+
const item = buildPrompt.item || {
|
|
1535
|
+
spec: buildPrompt.spec,
|
|
1536
|
+
installSpec: buildPrompt.spec,
|
|
1537
|
+
title: buildPrompt.spec,
|
|
1538
|
+
};
|
|
1539
|
+
setBuildOpen(false);
|
|
1540
|
+
setBuildAck(false);
|
|
1541
|
+
setError("");
|
|
1542
|
+
await onInstall(item, { approvedBuilds: pending });
|
|
1543
|
+
} catch (e) {
|
|
1544
|
+
setError((e && e.message) || String(e));
|
|
1545
|
+
} finally {
|
|
1546
|
+
setBuildBusy(false);
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1549
|
+
|
|
1550
|
+
const installRecommendedAlt = async (alt) => {
|
|
1551
|
+
if (!alt || riskBusy) return;
|
|
1552
|
+
const item = {
|
|
1553
|
+
spec: alt.installSpec || alt.spec,
|
|
1554
|
+
installSpec: alt.installSpec || alt.spec,
|
|
1555
|
+
title: alt.title || alt.spec,
|
|
1556
|
+
source: alt.source || "catalog",
|
|
1557
|
+
catalogId: alt.catalogId,
|
|
1558
|
+
};
|
|
1559
|
+
setRiskOpen(false);
|
|
1560
|
+
setRiskAck(false);
|
|
1561
|
+
setError("");
|
|
1562
|
+
await onInstall(item);
|
|
1563
|
+
};
|
|
1564
|
+
|
|
1224
1565
|
const sourceOptions = [
|
|
1225
1566
|
{ value: "all", label: t("sourceAll") },
|
|
1226
1567
|
{ value: "npm", label: t("sourceNpm") },
|
|
@@ -1334,6 +1675,9 @@ window.__ModuleLoader__.load({
|
|
|
1334
1675
|
: t("selfUpdateOriginNpm");
|
|
1335
1676
|
|
|
1336
1677
|
return h(
|
|
1678
|
+
React.Fragment,
|
|
1679
|
+
null,
|
|
1680
|
+
h(
|
|
1337
1681
|
"div",
|
|
1338
1682
|
{ style: styles.page },
|
|
1339
1683
|
h(
|
|
@@ -1501,16 +1845,67 @@ window.__ModuleLoader__.load({
|
|
|
1501
1845
|
? h(
|
|
1502
1846
|
"div",
|
|
1503
1847
|
{ style: styles.errorBox },
|
|
1504
|
-
h("
|
|
1848
|
+
h("div", { style: styles.errorText }, error),
|
|
1505
1849
|
h(
|
|
1506
|
-
|
|
1507
|
-
{
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1850
|
+
"div",
|
|
1851
|
+
{ style: styles.errorActions },
|
|
1852
|
+
h(
|
|
1853
|
+
Btn,
|
|
1854
|
+
{
|
|
1855
|
+
size: "sm",
|
|
1856
|
+
variant: "outline",
|
|
1857
|
+
disabled: busy || riskBusy,
|
|
1858
|
+
onClick: async () => {
|
|
1859
|
+
const text = String(error || "");
|
|
1860
|
+
try {
|
|
1861
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
1862
|
+
await navigator.clipboard.writeText(text);
|
|
1863
|
+
} else {
|
|
1864
|
+
const ta = document.createElement("textarea");
|
|
1865
|
+
ta.value = text;
|
|
1866
|
+
ta.setAttribute("readonly", "");
|
|
1867
|
+
ta.style.position = "fixed";
|
|
1868
|
+
ta.style.left = "-9999px";
|
|
1869
|
+
document.body.appendChild(ta);
|
|
1870
|
+
ta.select();
|
|
1871
|
+
document.execCommand("copy");
|
|
1872
|
+
document.body.removeChild(ta);
|
|
1873
|
+
}
|
|
1874
|
+
setCopyHint(t("copied"));
|
|
1875
|
+
window.setTimeout(() => setCopyHint(""), 1600);
|
|
1876
|
+
} catch {
|
|
1877
|
+
setCopyHint(t("copyFailed"));
|
|
1878
|
+
window.setTimeout(() => setCopyHint(""), 1600);
|
|
1879
|
+
}
|
|
1880
|
+
},
|
|
1881
|
+
},
|
|
1882
|
+
copyHint || t("copy"),
|
|
1883
|
+
),
|
|
1884
|
+
riskPrompt
|
|
1885
|
+
? h(
|
|
1886
|
+
Btn,
|
|
1887
|
+
{
|
|
1888
|
+
size: "sm",
|
|
1889
|
+
variant: "outline",
|
|
1890
|
+
disabled: busy || riskBusy,
|
|
1891
|
+
onClick: () => {
|
|
1892
|
+
setRiskAck(false);
|
|
1893
|
+
setRiskOpen(true);
|
|
1894
|
+
},
|
|
1895
|
+
},
|
|
1896
|
+
t("riskInstall"),
|
|
1897
|
+
)
|
|
1898
|
+
: null,
|
|
1899
|
+
h(
|
|
1900
|
+
Btn,
|
|
1901
|
+
{
|
|
1902
|
+
size: "sm",
|
|
1903
|
+
variant: "outline",
|
|
1904
|
+
disabled: busy || riskBusy,
|
|
1905
|
+
onClick: onSearch,
|
|
1906
|
+
},
|
|
1907
|
+
t("retry"),
|
|
1908
|
+
),
|
|
1514
1909
|
),
|
|
1515
1910
|
)
|
|
1516
1911
|
: null,
|
|
@@ -1634,6 +2029,182 @@ window.__ModuleLoader__.load({
|
|
|
1634
2029
|
)
|
|
1635
2030
|
: null,
|
|
1636
2031
|
),
|
|
2032
|
+
),
|
|
2033
|
+
buildOpen && buildPrompt
|
|
2034
|
+
? h(
|
|
2035
|
+
"div",
|
|
2036
|
+
{
|
|
2037
|
+
style: styles.riskOverlay,
|
|
2038
|
+
onClick: (e) => {
|
|
2039
|
+
if (e.target === e.currentTarget) closeBuildPrompt();
|
|
2040
|
+
},
|
|
2041
|
+
},
|
|
2042
|
+
h(
|
|
2043
|
+
"div",
|
|
2044
|
+
{
|
|
2045
|
+
style: styles.riskDialog,
|
|
2046
|
+
role: "dialog",
|
|
2047
|
+
"aria-modal": "true",
|
|
2048
|
+
onClick: (e) => e.stopPropagation(),
|
|
2049
|
+
},
|
|
2050
|
+
h("h2", { style: styles.riskTitle }, t("buildTitle")),
|
|
2051
|
+
h(
|
|
2052
|
+
"p",
|
|
2053
|
+
{ style: styles.riskDesc },
|
|
2054
|
+
format(t("buildDesc"), { spec: buildPrompt.spec || "" }),
|
|
2055
|
+
),
|
|
2056
|
+
h(
|
|
2057
|
+
"div",
|
|
2058
|
+
{ style: styles.riskAltBox },
|
|
2059
|
+
h(
|
|
2060
|
+
"div",
|
|
2061
|
+
{ style: styles.riskAltList },
|
|
2062
|
+
...(Array.isArray(buildPrompt.pendingBuilds) ? buildPrompt.pendingBuilds : []).map(
|
|
2063
|
+
(name) =>
|
|
2064
|
+
h("div", { key: name, style: styles.riskAltSpec }, name),
|
|
2065
|
+
),
|
|
2066
|
+
),
|
|
2067
|
+
),
|
|
2068
|
+
h(
|
|
2069
|
+
"label",
|
|
2070
|
+
{ style: styles.riskAckRow },
|
|
2071
|
+
h("input", {
|
|
2072
|
+
type: "checkbox",
|
|
2073
|
+
checked: buildAck,
|
|
2074
|
+
disabled: buildBusy,
|
|
2075
|
+
onChange: (e) => setBuildAck(!!e.target.checked),
|
|
2076
|
+
}),
|
|
2077
|
+
h("span", null, t("buildAck")),
|
|
2078
|
+
),
|
|
2079
|
+
h(
|
|
2080
|
+
"div",
|
|
2081
|
+
{ style: styles.riskFooter },
|
|
2082
|
+
h(
|
|
2083
|
+
Btn,
|
|
2084
|
+
{
|
|
2085
|
+
size: "sm",
|
|
2086
|
+
variant: "outline",
|
|
2087
|
+
disabled: buildBusy,
|
|
2088
|
+
onClick: closeBuildPrompt,
|
|
2089
|
+
},
|
|
2090
|
+
t("buildCancel"),
|
|
2091
|
+
),
|
|
2092
|
+
h(
|
|
2093
|
+
Btn,
|
|
2094
|
+
{
|
|
2095
|
+
size: "sm",
|
|
2096
|
+
disabled: buildBusy || !buildAck,
|
|
2097
|
+
onClick: () => void confirmBuildInstall(),
|
|
2098
|
+
},
|
|
2099
|
+
buildBusy ? t("buildWorking") : t("buildConfirm"),
|
|
2100
|
+
),
|
|
2101
|
+
),
|
|
2102
|
+
),
|
|
2103
|
+
)
|
|
2104
|
+
: null,
|
|
2105
|
+
riskOpen && riskPrompt
|
|
2106
|
+
? h(
|
|
2107
|
+
"div",
|
|
2108
|
+
{
|
|
2109
|
+
style: styles.riskOverlay,
|
|
2110
|
+
onClick: (e) => {
|
|
2111
|
+
if (e.target === e.currentTarget) closeRiskPrompt();
|
|
2112
|
+
},
|
|
2113
|
+
},
|
|
2114
|
+
h(
|
|
2115
|
+
"div",
|
|
2116
|
+
{
|
|
2117
|
+
style: styles.riskDialog,
|
|
2118
|
+
role: "dialog",
|
|
2119
|
+
"aria-modal": "true",
|
|
2120
|
+
onClick: (e) => e.stopPropagation(),
|
|
2121
|
+
},
|
|
2122
|
+
h("h2", { style: styles.riskTitle }, t("riskTitle")),
|
|
2123
|
+
h(
|
|
2124
|
+
"p",
|
|
2125
|
+
{ style: styles.riskDesc },
|
|
2126
|
+
format(t("riskDesc"), {
|
|
2127
|
+
package: riskPrompt.packageVersion,
|
|
2128
|
+
runtime: riskPrompt.runtimeVersion,
|
|
2129
|
+
}),
|
|
2130
|
+
),
|
|
2131
|
+
Array.isArray(riskPrompt.recommendations) && riskPrompt.recommendations.length
|
|
2132
|
+
? h(
|
|
2133
|
+
"div",
|
|
2134
|
+
{ style: styles.riskAltBox },
|
|
2135
|
+
h("div", { style: styles.riskAltTitle }, t("riskAltTitle")),
|
|
2136
|
+
h("p", { style: styles.riskAltDesc }, t("riskAltDesc")),
|
|
2137
|
+
h(
|
|
2138
|
+
"div",
|
|
2139
|
+
{ style: styles.riskAltList },
|
|
2140
|
+
...riskPrompt.recommendations.map((alt) =>
|
|
2141
|
+
h(
|
|
2142
|
+
"div",
|
|
2143
|
+
{ key: alt.spec, style: styles.riskAltRow },
|
|
2144
|
+
h(
|
|
2145
|
+
"div",
|
|
2146
|
+
{ style: styles.riskAltMeta },
|
|
2147
|
+
h("div", { style: styles.riskAltSpec }, alt.title || alt.spec),
|
|
2148
|
+
h(
|
|
2149
|
+
"div",
|
|
2150
|
+
{ style: styles.riskAltHint },
|
|
2151
|
+
alt.spec === (alt.title || "")
|
|
2152
|
+
? alt.reason || ""
|
|
2153
|
+
: alt.spec,
|
|
2154
|
+
),
|
|
2155
|
+
),
|
|
2156
|
+
h(
|
|
2157
|
+
Btn,
|
|
2158
|
+
{
|
|
2159
|
+
size: "sm",
|
|
2160
|
+
variant: "outline",
|
|
2161
|
+
disabled: riskBusy,
|
|
2162
|
+
onClick: () => void installRecommendedAlt(alt),
|
|
2163
|
+
},
|
|
2164
|
+
t("riskAltInstall"),
|
|
2165
|
+
),
|
|
2166
|
+
),
|
|
2167
|
+
),
|
|
2168
|
+
),
|
|
2169
|
+
)
|
|
2170
|
+
: null,
|
|
2171
|
+
h(
|
|
2172
|
+
"label",
|
|
2173
|
+
{ style: styles.riskAckRow },
|
|
2174
|
+
h("input", {
|
|
2175
|
+
type: "checkbox",
|
|
2176
|
+
checked: riskAck,
|
|
2177
|
+
disabled: riskBusy,
|
|
2178
|
+
onChange: (e) => setRiskAck(!!e.target.checked),
|
|
2179
|
+
}),
|
|
2180
|
+
h("span", null, t("riskAck")),
|
|
2181
|
+
),
|
|
2182
|
+
h(
|
|
2183
|
+
"div",
|
|
2184
|
+
{ style: styles.riskFooter },
|
|
2185
|
+
h(
|
|
2186
|
+
Btn,
|
|
2187
|
+
{
|
|
2188
|
+
size: "sm",
|
|
2189
|
+
variant: "outline",
|
|
2190
|
+
disabled: riskBusy,
|
|
2191
|
+
onClick: closeRiskPrompt,
|
|
2192
|
+
},
|
|
2193
|
+
t("riskCancel"),
|
|
2194
|
+
),
|
|
2195
|
+
h(
|
|
2196
|
+
Btn,
|
|
2197
|
+
{
|
|
2198
|
+
size: "sm",
|
|
2199
|
+
disabled: riskBusy || !riskAck,
|
|
2200
|
+
onClick: () => void confirmRiskInstall(),
|
|
2201
|
+
},
|
|
2202
|
+
riskBusy ? t("riskWorking") : t("riskConfirm"),
|
|
2203
|
+
),
|
|
2204
|
+
),
|
|
2205
|
+
),
|
|
2206
|
+
)
|
|
2207
|
+
: null,
|
|
1637
2208
|
);
|
|
1638
2209
|
}
|
|
1639
2210
|
|
|
@@ -1651,6 +2222,10 @@ window.__ModuleLoader__.load({
|
|
|
1651
2222
|
const SPEC_CODEC = strictJson("dsh-plugin-discovery#pluginDiscovery/installPlugin:spec");
|
|
1652
2223
|
const INSTALL_OPTIONS_CODEC = strictJson("dsh-plugin-discovery#pluginDiscovery/installPlugin:options");
|
|
1653
2224
|
const INSTALL_RESULT = strictJson("dsh-plugin-discovery#pluginDiscovery/installPlugin:result");
|
|
2225
|
+
const GRANT_PACKAGE = strictJson("dsh-plugin-discovery#pluginDiscovery/grantVersionExemption:packageVersion");
|
|
2226
|
+
const GRANT_RUNTIME = strictJson("dsh-plugin-discovery#pluginDiscovery/grantVersionExemption:runtimeVersion");
|
|
2227
|
+
const GRANT_ACCEPT = strictJson("dsh-plugin-discovery#pluginDiscovery/grantVersionExemption:acceptRisk");
|
|
2228
|
+
const GRANT_RESULT = strictJson("dsh-plugin-discovery#pluginDiscovery/grantVersionExemption:result");
|
|
1654
2229
|
const LIST_INSTALLED_RESULT = strictJson("dsh-plugin-discovery#pluginDiscovery/listInstalled:result");
|
|
1655
2230
|
const WAIT_REQUEST_ID = strictJson("dsh-plugin-discovery#pluginDiscovery/waitInstall:requestId");
|
|
1656
2231
|
const WAIT_RESULT = strictJson("dsh-plugin-discovery#pluginDiscovery/waitInstall:result");
|
|
@@ -1754,6 +2329,19 @@ window.__ModuleLoader__.load({
|
|
|
1754
2329
|
],
|
|
1755
2330
|
result: INSTALL_RESULT,
|
|
1756
2331
|
},
|
|
2332
|
+
{
|
|
2333
|
+
id: "dsh-plugin-discovery#pluginDiscovery/grantVersionExemption",
|
|
2334
|
+
service: "pluginDiscovery",
|
|
2335
|
+
namespace: "pluginDiscovery",
|
|
2336
|
+
method: "grantVersionExemption",
|
|
2337
|
+
invocation: { kind: "direct" },
|
|
2338
|
+
parameters: [
|
|
2339
|
+
{ name: "packageVersion", wire: "packageVersion", source: "json", codec: GRANT_PACKAGE },
|
|
2340
|
+
{ name: "runtimeVersion", wire: "runtimeVersion", source: "json", codec: GRANT_RUNTIME },
|
|
2341
|
+
{ name: "acceptRisk", wire: "acceptRisk", source: "json", codec: GRANT_ACCEPT },
|
|
2342
|
+
],
|
|
2343
|
+
result: GRANT_RESULT,
|
|
2344
|
+
},
|
|
1757
2345
|
{
|
|
1758
2346
|
id: "dsh-plugin-discovery#pluginDiscovery/listInstalled",
|
|
1759
2347
|
service: "pluginDiscovery",
|
|
@@ -1875,10 +2463,29 @@ window.__ModuleLoader__.load({
|
|
|
1875
2463
|
packageName: value && value.packageName,
|
|
1876
2464
|
requestId: value && value.requestId,
|
|
1877
2465
|
message: value && value.message,
|
|
2466
|
+
detail: value && value.detail,
|
|
2467
|
+
code: value && value.code,
|
|
2468
|
+
incompatible: value && value.incompatible,
|
|
2469
|
+
needsRiskExemption: !!(value && value.needsRiskExemption),
|
|
2470
|
+
pendingBuilds: value && value.pendingBuilds,
|
|
2471
|
+
needsBuildApproval: !!(value && value.needsBuildApproval),
|
|
2472
|
+
recommendations: value && value.recommendations,
|
|
2473
|
+
installSpec: (value && value.installSpec) || spec,
|
|
1878
2474
|
};
|
|
1879
2475
|
}
|
|
1880
2476
|
return value;
|
|
1881
2477
|
},
|
|
2478
|
+
grantVersionExemption: async (packageVersion, runtimeVersion, acceptRisk) => {
|
|
2479
|
+
if (mountError) return { ok: false, message: mountError };
|
|
2480
|
+
const remote = remoteNs();
|
|
2481
|
+
if (!remote || typeof remote.grantVersionExemption !== "function") {
|
|
2482
|
+
return { ok: false, message: "remote.pluginDiscovery.grantVersionExemption unavailable" };
|
|
2483
|
+
}
|
|
2484
|
+
const wire = await remote.grantVersionExemption(packageVersion, runtimeVersion, acceptRisk);
|
|
2485
|
+
const value = unwrapRemote(wire, "grantVersionExemption failed");
|
|
2486
|
+
if (wire && wire.ok === false) return { ok: false, message: value.message };
|
|
2487
|
+
return value;
|
|
2488
|
+
},
|
|
1882
2489
|
listInstalled: async () => {
|
|
1883
2490
|
if (mountError) return { ok: false, names: [] };
|
|
1884
2491
|
const remote = remoteNs();
|
|
@@ -1898,7 +2505,22 @@ window.__ModuleLoader__.load({
|
|
|
1898
2505
|
}
|
|
1899
2506
|
const wire = await remote.waitInstall(requestId);
|
|
1900
2507
|
const value = unwrapRemote(wire, "waitInstall failed");
|
|
1901
|
-
if (wire && wire.ok === false)
|
|
2508
|
+
if (wire && wire.ok === false) {
|
|
2509
|
+
return {
|
|
2510
|
+
ok: false,
|
|
2511
|
+
message: (value && value.message) || "waitInstall failed",
|
|
2512
|
+
detail: value && value.detail,
|
|
2513
|
+
code: value && value.code,
|
|
2514
|
+
incompatible: value && value.incompatible,
|
|
2515
|
+
needsRiskExemption: !!(value && value.needsRiskExemption),
|
|
2516
|
+
pendingBuilds: value && value.pendingBuilds,
|
|
2517
|
+
needsBuildApproval: !!(value && value.needsBuildApproval),
|
|
2518
|
+
recommendations: value && value.recommendations,
|
|
2519
|
+
installSpec: value && value.installSpec,
|
|
2520
|
+
packageName: value && value.packageName,
|
|
2521
|
+
pending: !!(value && value.pending),
|
|
2522
|
+
};
|
|
2523
|
+
}
|
|
1902
2524
|
return value;
|
|
1903
2525
|
},
|
|
1904
2526
|
subscribePluginChanged: (listener) => {
|