dsh-plugin 1.6.11 → 2.0.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/README.en.md +1 -1
- package/README.md +1 -1
- package/client/client.js +705 -803
- package/client/client.js.map +1 -1
- package/lib/http/catalog.js +2 -3
- package/lib/http/diagnostics.js +6 -7
- package/lib/http/install.js +47 -213
- package/lib/http/logs.js +1 -2
- package/lib/http/npm-release-age.js +42 -0
- package/lib/http/routes.js +8 -7
- package/lib/http/settings.js +2 -2
- package/lib/http/shared.js +2 -2
- package/lib/http/task.js +1 -2
- package/lib/index.js +5 -6
- package/lib/services/install/install-types.js +4 -4
- package/lib/services/install/install.js +1 -1
- package/lib/services/install/npm-check.js +3 -2
- package/lib/services/install/npm-resolve.js +9 -96
- package/lib/services/install/package-entry.js +6 -11
- package/lib/services/install/registry-check.js +5 -16
- package/lib/services/install/release-target.js +8 -9
- package/lib/services/install/task-queue.js +74 -57
- package/lib/services/npm-release-age.js +119 -0
- package/lib/services/probe.js +4 -4
- package/lib/services/profile/installed-versions.js +15 -21
- package/lib/services/profile/profile.js +16 -44
- package/lib/services/profile/progress.js +8 -11
- package/lib/services/settings.js +2 -5
- package/lib/types/http/catalog.d.ts +1 -1
- package/lib/types/http/install.d.ts +2 -2
- package/lib/types/http/npm-release-age.d.ts +2 -0
- package/lib/types/http/routes.d.ts +10 -12
- package/lib/types/http/shared.d.ts +5 -6
- package/lib/types/index.d.ts +7 -8
- package/lib/types/services/install/install-types.d.ts +12 -13
- package/lib/types/services/install/install.d.ts +1 -1
- package/lib/types/services/install/npm-resolve.d.ts +4 -16
- package/lib/types/services/install/package-entry.d.ts +6 -11
- package/lib/types/services/install/release-target.d.ts +7 -8
- package/lib/types/services/install/task-queue.d.ts +32 -31
- package/lib/types/services/npm-release-age.d.ts +15 -0
- package/lib/types/services/probe.d.ts +4 -4
- package/lib/types/services/profile/installed-versions.d.ts +5 -7
- package/lib/types/services/profile/profile.d.ts +14 -18
- package/lib/types/services/profile/progress.d.ts +7 -10
- package/lib/types/services/settings.d.ts +0 -4
- package/package.json +1 -1
- package/src/client/components/PluginHubSection.tsx +23 -27
- package/src/client/components/catalog/CatalogList.tsx +2 -4
- package/src/client/components/catalog/PluginCard.tsx +2 -3
- package/src/client/components/layout/CatalogControls.tsx +5 -6
- package/src/client/components/layout/CatalogHeader.tsx +1 -2
- package/src/client/components/layout/CategoryTabs.tsx +2 -3
- package/src/client/components/layout/SectionTabs.tsx +3 -5
- package/src/client/components/modals/ConfirmDialog.tsx +4 -6
- package/src/client/components/modals/InstalledDetailModal.tsx +3 -6
- package/src/client/components/modals/LogsModal.tsx +7 -12
- package/src/client/components/modals/NotificationsModal.tsx +52 -24
- package/src/client/components/modals/ProgressView.tsx +3 -4
- package/src/client/components/modals/modals.tsx +58 -30
- package/src/client/components/ui/Dropdown.tsx +4 -6
- package/src/client/components/ui/Toggle.tsx +2 -3
- package/src/client/components/ui/icons.tsx +1 -2
- package/src/client/components/views/CustomInstallView.tsx +20 -178
- package/src/client/components/views/DiagnosticsView.tsx +3 -6
- package/src/client/components/views/InstalledView.tsx +6 -11
- package/src/client/components/views/MarketView.tsx +2 -4
- package/src/client/components/views/SettingsView.tsx +9 -32
- package/src/client/css-modules.d.ts +1 -1
- package/src/client/data/catalog.ts +2 -3
- package/src/client/data/host.ts +26 -3
- package/src/client/data/hub.ts +2 -3
- package/src/client/hooks/useCatalog.ts +79 -24
- package/src/client/hooks/useIncrementalList.ts +3 -5
- package/src/client/hooks/useLanguage.ts +4 -6
- package/src/client/hooks/useSettings.ts +4 -11
- package/src/client/hooks/useTaskQueue.ts +36 -42
- package/src/client/index.tsx +2 -3
- package/src/client/locales.ts +96 -123
- package/src/client/logic/constants.ts +1 -2
- package/src/client/logic/ensure-plugin-css.ts +8 -12
- package/src/client/logic/failures.ts +41 -28
- package/src/client/logic/format.ts +1 -1
- package/src/client/logic/install-command.ts +14 -35
- package/src/client/logic/installed.ts +15 -10
- package/src/client/logic/normalize.ts +3 -3
- package/src/client/logic/release-age.ts +19 -0
- package/src/client/logic/urls.ts +55 -50
- package/src/client/styles/CustomInstallView.module.css +3 -30
- package/src/client/styles/DiagnosticsView.module.css +3 -5
- package/src/client/styles/Dropdown.module.css +2 -4
- package/src/client/styles/Header.module.css +6 -7
- package/src/client/styles/InstalledView.module.css +4 -7
- package/src/client/styles/List.module.css +4 -5
- package/src/client/styles/LogsView.module.css +2 -3
- package/src/client/styles/Modal.module.css +4 -5
- package/src/client/styles/SectionTabs.module.css +2 -4
- package/src/client/styles/SettingsView.module.css +3 -5
- package/src/client/styles/Toggle.module.css +2 -4
- package/src/client/styles/tokens.module.css +14 -18
- package/src/client/types.ts +11 -11
- package/src/server/http/catalog.ts +2 -3
- package/src/server/http/diagnostics.ts +6 -7
- package/src/server/http/install.ts +47 -208
- package/src/server/http/logs.ts +1 -2
- package/src/server/http/npm-release-age.ts +42 -0
- package/src/server/http/routes.ts +12 -12
- package/src/server/http/settings.ts +2 -2
- package/src/server/http/shared.ts +5 -6
- package/src/server/http/task.ts +1 -2
- package/src/server/index.ts +7 -8
- package/src/server/services/install/install-types.ts +12 -13
- package/src/server/services/install/install.ts +0 -1
- package/src/server/services/install/npm-check.ts +3 -2
- package/src/server/services/install/npm-resolve.ts +9 -99
- package/src/server/services/install/package-entry.ts +6 -11
- package/src/server/services/install/registry-check.ts +5 -16
- package/src/server/services/install/release-target.ts +8 -9
- package/src/server/services/install/task-queue.ts +79 -63
- package/src/server/services/npm-release-age.ts +107 -0
- package/src/server/services/probe.ts +4 -4
- package/src/server/services/profile/installed-versions.ts +16 -22
- package/src/server/services/profile/profile.ts +16 -42
- package/src/server/services/profile/progress.ts +8 -11
- package/src/server/services/settings.ts +2 -9
- package/lib/services/install/preflight.js +0 -178
- package/lib/types/services/install/preflight.d.ts +0 -23
- package/src/server/services/install/preflight.ts +0 -184
package/client/client.js
CHANGED
|
@@ -11,7 +11,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
11
11
|
* Website: https://dsh-plugin.org
|
|
12
12
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
13
13
|
*
|
|
14
|
-
* zh/en
|
|
14
|
+
* 插件中心设置板块的 zh/en 字典。
|
|
15
15
|
*/
|
|
16
16
|
const zh = {
|
|
17
17
|
nav: "插件市场",
|
|
@@ -46,34 +46,23 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
46
46
|
viewSettings: "设置",
|
|
47
47
|
viewMarketHint: "浏览与发现插件",
|
|
48
48
|
viewInstalledHint: "管理已安装插件",
|
|
49
|
-
viewCustomHint: "手动安装 NPM
|
|
49
|
+
viewCustomHint: "手动安装 NPM 包",
|
|
50
50
|
viewSettingsHint: "网络通道与偏好设置",
|
|
51
51
|
installedEmpty: "还没有安装插件",
|
|
52
|
-
installedEmptyDesc: "可以去「自定义安装」,手动安装 NPM
|
|
52
|
+
installedEmptyDesc: "可以去「自定义安装」,手动安装 NPM 包",
|
|
53
53
|
npmInstallLabel: "NPM 包 / 命令",
|
|
54
54
|
npmInstallPlaceholder: "npm install <包名> 或直接输包名",
|
|
55
55
|
npmInstallExample: "支持原生命令:npm install lodash、npm i lodash、pnpm add @scope/pkg",
|
|
56
56
|
npmInstallExample2: "全局安装 CLI:npm install -g @scope/cli;或直接输入包名 lodash",
|
|
57
57
|
npmInstallInvalid: "请输入 npm 包名(如 lodash、@scope/pkg),或原生安装命令(如 npm install lodash、npm i lodash、pnpm add @scope/pkg、npm install -g @scope/cli)",
|
|
58
|
-
gitInstallLabel: "GitHub 源码",
|
|
59
|
-
gitInstallPlaceholder: "输入仓库地址",
|
|
60
|
-
gitInstallExample: "例如:owner/repo 或 https://github.com/owner/repo",
|
|
61
|
-
gitInstallInvalid: "请输入 GitHub 仓库地址,例如:owner/repo 或 https://github.com/owner/repo",
|
|
62
|
-
dshCmdLabel: "DeepSeek Harness 命令",
|
|
63
|
-
dshCmdPlaceholder: "粘贴官方 dsh plugin 命令",
|
|
64
|
-
dshCmdInsertHubUpdate: "插入更新命令",
|
|
65
|
-
dshCmdExample: "例如:dsh plugin --profile {profile} add github:owner/repo,或 dsh plugin --profile {profile} update dsh-plugin",
|
|
66
|
-
dshCmdInvalid: "请输入官方 dsh plugin 命令(--profile 必填,支持 add / update)。例如:dsh plugin --profile {profile} update dsh-plugin",
|
|
67
58
|
installHelp: "帮助",
|
|
68
59
|
helpModalTitle: "支持的命令格式",
|
|
69
60
|
npmInstallHelp: "lodash、@scope/pkg 直接输入包名\nnpm install lodash\nnpm i lodash\npnpm add @scope/pkg\npnpm i @scope/pkg\nnpm install -g @scope/cli 全局安装 CLI 工具,不进「已安装」列表",
|
|
70
|
-
gitInstallHelp: "owner/repo\nhttps://github.com/owner/repo\ngithub:owner/repo\ngit+https://github.com/owner/repo.git\ngit@github.com:owner/repo.git",
|
|
71
|
-
dshCmdHelp: "dsh plugin --profile {profile} add <目标> 安装\ndsh plugin --profile {profile} update <目标> 更新已安装目标到最新版本\ndsh plugin --profile={profile} add <目标>\ndsh plugin --profile={profile} update <目标>\n --profile 必填(此处已填当前 profile),官方 CLI 无 -p 简写;<目标> 可为 npm 包名或 github:owner/repo;卸载请用「已安装」列表",
|
|
72
61
|
globalNpmHint: "将全局安装 CLI 工具(npm install -g),不会出现在「已安装」列表,无需重启宿主",
|
|
73
62
|
installCliBtn: "安装",
|
|
74
63
|
channelDisabledHint: "该安装通道已关闭,请在「设置 → 安全信任」中打开开关",
|
|
75
64
|
goToSettings: "前往设置",
|
|
76
|
-
customViewDesc: "手动安装目录外的 NPM
|
|
65
|
+
customViewDesc: "手动安装目录外的 NPM 包。装完的条目会出现在「已安装」列表,并标记为自定义安装。",
|
|
77
66
|
customLabel: "自定义安装",
|
|
78
67
|
installedSearch: "搜索已安装的插件…",
|
|
79
68
|
installedFilterCatalog: "目录插件",
|
|
@@ -125,13 +114,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
125
114
|
mirrorTencent: "腾讯云镜像",
|
|
126
115
|
mirrorTsinghua: "清华大学 TUNA 镜像",
|
|
127
116
|
settingsSecurity: "安全信任",
|
|
128
|
-
settingsSecurityDesc: "
|
|
117
|
+
settingsSecurityDesc: "命令行安装的开关:NPM 包",
|
|
129
118
|
settingsEnableNpm: "启用 NPM 安装",
|
|
130
119
|
settingsEnableNpmDesc: "允许通过命令行安装 npm 包;关闭后输入包名安装会被拦截",
|
|
131
|
-
settingsEnableGit: "启用 GitHub 源码安装",
|
|
132
|
-
settingsEnableGitDesc: "允许通过命令行安装 GitHub 源码;关闭后输入仓库地址安装会被拦截",
|
|
133
|
-
settingsEnableDsh: "启用 DSH 命令安装",
|
|
134
|
-
settingsEnableDshDesc: "允许通过命令行粘贴 dsh plugin 命令安装;关闭后命令输入会被禁用",
|
|
135
120
|
settingsDiagnostics: "系统诊断",
|
|
136
121
|
settingsDiagnosticsDesc: "检测 npm 源 / GitHub / 目录站点等安装通道的连通状态",
|
|
137
122
|
settingsLogs: "系统日志",
|
|
@@ -283,6 +268,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
283
268
|
errorTitleInstall: "安装失败",
|
|
284
269
|
errorTitleUninstall: "卸载失败",
|
|
285
270
|
errorTitleUpdate: "更新失败",
|
|
271
|
+
actionInstall: "安装",
|
|
272
|
+
actionUpdate: "更新",
|
|
273
|
+
actionUninstall: "卸载",
|
|
286
274
|
errorPlugin: "插件",
|
|
287
275
|
errorClose: "知道了",
|
|
288
276
|
errorCopy: "复制错误信息",
|
|
@@ -292,18 +280,19 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
292
280
|
failIssueBig: "一键提交 BUG 到 GitHub Issue 为开源作贡献",
|
|
293
281
|
failHubIssueHint: "此失败已被判定为环境或插件中心自身问题(非插件作者问题),带着错误日志到插件中心仓库一键提交 Issue",
|
|
294
282
|
failHubIssueBig: "反馈给插件中心排查",
|
|
295
|
-
failUnclassifiedHint: "
|
|
296
|
-
failHubStateHint: "
|
|
297
|
-
failTimeoutHint: "
|
|
298
|
-
failProfileLockHint: "DSH 在写入插件清单时等不到文件锁、超时中止 —— 通常是同时有另一个 DSH 进程或安装任务在写同一个 profile(也可能是上一次的进程没退干净留下的锁)。请先关掉其他 dsh 窗口或正在跑的命令,再重试一次;若反复出现,重启一次 DSH
|
|
299
|
-
|
|
283
|
+
failUnclassifiedHint: "{action}失败,原因未能自动识别。这通常不是插件自身的问题(可能与本机环境或插件中心有关),请将错误信息反馈给插件中心,由维护者排查。",
|
|
284
|
+
failHubStateHint: "插件列表状态已过期或与本地不一致:这次{action}的目标可能已经在列表里了(要升级请点「更新」),也可能已经不在已安装列表中,或已在队列中。这不是插件本身的问题 —— 请刷新页面后重试。",
|
|
285
|
+
failTimeoutHint: "本次操作耗时超过本地上限、已被中断 —— 但很可能其实已经生效了(安装器在超时后会先核对本地已安装列表)。请刷新页面确认当前状态;若确实没生效,可在终端手动执行一次对应命令查看完整输出。这不是插件本身的问题。",
|
|
286
|
+
failProfileLockHint: "DSH 在写入插件清单时等不到文件锁、超时中止 —— 通常是同时有另一个 DSH 进程或安装任务在写同一个 profile(也可能是上一次的进程没退干净留下的锁)。请先关掉其他 dsh 窗口或正在跑的命令,再重试一次;若反复出现,重启一次 DSH。这不是插件本身的问题,也不需要重复{action}。",
|
|
287
|
+
failHostCliSpawnHint: "DSH 没能启动自身来完成这次操作(系统报「找不到可执行文件」):通常是因为 DSH 的安装目录被移动或正在更新,或该 profile 目录还不存在。请重启一次 DSH 后重试;若反复出现,重新安装 DSH。这不是插件本身的问题,换别的插件也一样。",
|
|
288
|
+
failPrepareHint: "该插件安装时的构建脚本执行失败(npm 分发物不完整),属插件打包分发问题。请向作者仓库提交 Issue 反馈。",
|
|
300
289
|
failMisjudgeHint: "如果这个插件其实能正常安装(上面这个判定是插件中心误报的),请反馈给插件中心:文字提示里的判据由市场自身产出,误报只有靠你的反馈才能被发现。",
|
|
301
290
|
failMisjudgeLink: "插件能装却被拦下?反馈给插件中心",
|
|
302
|
-
failPackagingHint: "
|
|
303
|
-
failIgnoredBuild: "该插件(或其依赖)需要在安装时执行构建脚本,被 pnpm 的安全白名单(allowBuilds
|
|
291
|
+
failPackagingHint: "该插件的 npm 分发物不完整:缺少它需要的文件(`main` / `exports` 声明的入口、补丁按本包名 mount 的入口,或 `dsh.bundle.patch` 声明的补丁)。请到作者仓库提交 Issue 反馈,请其发布包含完整构建产物的 npm 包。",
|
|
292
|
+
failIgnoredBuild: "该插件(或其依赖)需要在安装时执行构建脚本,被 pnpm 的安全白名单(allowBuilds)默认拦截,本次操作因此失败(如原生模块 node-pty,或 git 安装时插件自己的 prepare 脚本)。安装器已自动放行该 key 并重试过一次;仍失败说明构建本身没通过、任何用户都装不上。可先在终端手动执行一次安装命令查看完整构建错误;这属插件的构建/分发问题,请到作者仓库反馈:建议作者预置构建产物、发布含构建产物的 npm 包或提供预构建 .tgz。",
|
|
304
293
|
failNpmTooLow: "怀疑本机 npm 版本过低:npm 解析插件依赖时内部崩溃(这是 npm 自身的已知缺陷,不是插件问题)。请升级 npm 后重试:npm install -g npm@latest",
|
|
305
294
|
failNpmTooLowV: "本机 npm 版本过低(当前 v{v}):npm 解析插件依赖时内部崩溃(这是 npm 自身的已知缺陷,不是插件问题)。请升级 npm 后重试:npm install -g npm@latest",
|
|
306
|
-
failNetworkHint: "
|
|
295
|
+
failNetworkHint: "{action}前检测到网络不通:无法连接到安装源(可能是断网、DNS 解析失败、被防火墙拦截,或代理配置有问题)。这不是插件本身的问题 —— 请检查网络连接,或到「设置」里确认 HTTP 代理配置,再到「系统诊断」运行一次连通性检测,然后重试。",
|
|
307
296
|
failNetworkRegistryHint: "你的 npm/pnpm 源(registry)被配置为 {host},插件包需从该源下载但失败了。这通常是内网/自定义源没有同步该包(或需要内网认证)—— 请把 npm/pnpm 的 registry 指回官方源 https://registry.npmjs.org(或确认此源可访问该包)后重试。",
|
|
308
297
|
failNetworkTarget: "无法访问 {url} —— 你的网络连接不通",
|
|
309
298
|
failNetworkRunDiag: "去系统诊断检测网络",
|
|
@@ -329,8 +318,6 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
329
318
|
failPnpmPolicyHint: "安装器调用 pnpm 时被其供应链安全策略拦截——装任何插件都会撞墙,不是插件本身的问题。分两种情况处理:① 提示「Minimum release age」(ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION):包发布还不满 24 小时,pnpm 11 出于安全会拒收这种刚发布的新包。可在 pnpm 配置(pnpm-workspace.yaml)里加 minimumReleaseAge: 0 豁免,或等满 24 小时后重试。② 提示「untrusted origin」(ERR_PNPM_UNTRUSTED_ORIGIN):依赖来源不被本机 pnpm 信任,通常是该 profile 里之前用 github: 或非官方 npm 源装过插件,锁文件记录了不受信任的来源。请删除该 profile 目录下的 node_modules 与 pnpm-lock.yaml 后重新安装(可先到「系统日志」或 ~/.dsh/profiles/<profile>/hub.log 查看完整报错)。",
|
|
330
319
|
failPnpmReleaseAgeHint: "安装器调用 pnpm 时被其供应链安全策略拦住了,任何插件装进这个 profile 都会先撞上它——与插件本身无关。原因是这个包发布还不满 24 小时,pnpm 11 出于安全会拒收刚发布的新包,这段时间内该 profile 的安装与卸载都会被拦下。可重试时间:{time}(即该包发布满 24 小时后)。如确需立刻安装,可在 profile 目录(~/.dsh/profiles/<profile>)的 pnpm-workspace.yaml 里加 minimumReleaseAge: 0 豁免,但这会放宽整个 profile 的供应链保护。",
|
|
331
320
|
installChannelNpm: "NPM 包",
|
|
332
|
-
installChannelGit: "GitHub 源码",
|
|
333
|
-
installChannelDsh: "DSH 命令",
|
|
334
321
|
installEntryLine: "安装入口:{c}。",
|
|
335
322
|
reportIssue: "去插件仓库提交 Issue",
|
|
336
323
|
detail: "打开详情",
|
|
@@ -402,34 +389,23 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
402
389
|
viewSettings: "Settings",
|
|
403
390
|
viewMarketHint: "Browse and discover plugins",
|
|
404
391
|
viewInstalledHint: "Manage installed plugins",
|
|
405
|
-
viewCustomHint: "Install npm packages
|
|
392
|
+
viewCustomHint: "Install npm packages manually",
|
|
406
393
|
viewSettingsHint: "Network sources and preferences",
|
|
407
394
|
installedEmpty: "No plugins installed yet",
|
|
408
|
-
installedEmptyDesc: "Go to Custom to add an npm package
|
|
395
|
+
installedEmptyDesc: "Go to Custom to add an npm package manually",
|
|
409
396
|
npmInstallLabel: "npm package / command",
|
|
410
397
|
npmInstallPlaceholder: "npm install <pkg> or a bare package name",
|
|
411
398
|
npmInstallExample: "Native commands: npm install lodash, npm i lodash, pnpm add @scope/pkg",
|
|
412
399
|
npmInstallExample2: "Global CLI: npm install -g @scope/cli; or just type a package name like lodash",
|
|
413
400
|
npmInstallInvalid: "Enter an npm package name (e.g. lodash, @scope/pkg), or a native install command (e.g. npm install lodash, npm i lodash, pnpm add @scope/pkg, npm install -g @scope/cli)",
|
|
414
|
-
gitInstallLabel: "GitHub source",
|
|
415
|
-
gitInstallPlaceholder: "Repository address",
|
|
416
|
-
gitInstallExample: "e.g. owner/repo or https://github.com/owner/repo",
|
|
417
|
-
gitInstallInvalid: "Enter a GitHub repository address, e.g. owner/repo or https://github.com/owner/repo",
|
|
418
|
-
dshCmdLabel: "DeepSeek Harness command",
|
|
419
|
-
dshCmdPlaceholder: "Paste an official dsh plugin command",
|
|
420
|
-
dshCmdInsertHubUpdate: "Insert update command",
|
|
421
|
-
dshCmdExample: "e.g. dsh plugin --profile {profile} add github:owner/repo, or dsh plugin --profile {profile} update dsh-plugin",
|
|
422
|
-
dshCmdInvalid: "Paste an official dsh plugin command (--profile required, add / update), e.g. dsh plugin --profile {profile} update dsh-plugin",
|
|
423
401
|
installHelp: "Help",
|
|
424
402
|
helpModalTitle: "Supported command formats",
|
|
425
403
|
npmInstallHelp: "lodash or @scope/pkg just type the package name\nnpm install lodash\nnpm i lodash\npnpm add @scope/pkg\npnpm i @scope/pkg\nnpm install -g @scope/cli installs the CLI globally, not shown in Installed",
|
|
426
|
-
gitInstallHelp: "owner/repo\nhttps://github.com/owner/repo\ngithub:owner/repo\ngit+https://github.com/owner/repo.git\ngit@github.com:owner/repo.git",
|
|
427
|
-
dshCmdHelp: "dsh plugin --profile {profile} add <target> install\ndsh plugin --profile {profile} update <target> update an installed target to the latest version\ndsh plugin --profile={profile} add <target>\ndsh plugin --profile={profile} update <target>\n --profile is required (prefilled with the current profile here) and there is no -p shorthand; <target> can be an npm package or github:owner/repo; uninstall from the Installed list",
|
|
428
404
|
globalNpmHint: "This installs CLI tools globally (npm install -g). They won't appear in Installed and no host restart is needed.",
|
|
429
405
|
installCliBtn: "Install",
|
|
430
406
|
channelDisabledHint: "This install channel is disabled — enable it in Settings → Security & Trust",
|
|
431
407
|
goToSettings: "Go to Settings",
|
|
432
|
-
customViewDesc: "Manually install an npm package
|
|
408
|
+
customViewDesc: "Manually install an npm package outside the catalog. Finished installs appear in Installed, marked as custom.",
|
|
433
409
|
customLabel: "Custom install",
|
|
434
410
|
installedSearch: "Search installed plugins…",
|
|
435
411
|
installedFilterCatalog: "Catalog",
|
|
@@ -483,13 +459,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
483
459
|
mirrorTencent: "Tencent Cloud mirror",
|
|
484
460
|
mirrorTsinghua: "Tsinghua TUNA mirror",
|
|
485
461
|
settingsSecurity: "Security & Trust",
|
|
486
|
-
settingsSecurityDesc: "Toggles for
|
|
462
|
+
settingsSecurityDesc: "Toggles for command-line installs: npm packages",
|
|
487
463
|
settingsEnableNpm: "Enable npm installs",
|
|
488
464
|
settingsEnableNpmDesc: "Allow installing npm packages from the command line; turning this off rejects package-name installs",
|
|
489
|
-
settingsEnableGit: "Enable GitHub source installs",
|
|
490
|
-
settingsEnableGitDesc: "Allow installing from GitHub sources on the command line; turning this off rejects repository-address installs",
|
|
491
|
-
settingsEnableDsh: "Enable DSH command installs",
|
|
492
|
-
settingsEnableDshDesc: "Allow pasting a dsh plugin command to install; turning this off disables the command input",
|
|
493
465
|
settingsDiagnostics: "System Diagnostics",
|
|
494
466
|
settingsDiagnosticsDesc: "Check the connectivity of install channels: npm registry, GitHub and the catalog site",
|
|
495
467
|
settingsLogs: "System Logs",
|
|
@@ -642,6 +614,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
642
614
|
errorTitleInstall: "Install failed",
|
|
643
615
|
errorTitleUninstall: "Removal failed",
|
|
644
616
|
errorTitleUpdate: "Update failed",
|
|
617
|
+
actionInstall: "install",
|
|
618
|
+
actionUpdate: "update",
|
|
619
|
+
actionUninstall: "removal",
|
|
645
620
|
errorPlugin: "Plugin",
|
|
646
621
|
errorClose: "Got it",
|
|
647
622
|
errorCopy: "Copy error",
|
|
@@ -651,18 +626,19 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
651
626
|
failIssueBig: "Report this bug to GitHub — contribute to open source",
|
|
652
627
|
failHubIssueHint: "This failure was classified as an environment or Plugin Hub issue (not a plugin-author issue). Open a pre-filled issue on the Plugin Hub repo with this error log.",
|
|
653
628
|
failHubIssueBig: "Report to the Plugin Hub for triage",
|
|
654
|
-
failUnclassifiedHint: "The
|
|
655
|
-
failHubStateHint: "The plugin list is out of date or out of sync: this
|
|
656
|
-
failTimeoutHint: "
|
|
657
|
-
failProfileLockHint: "DSH timed out waiting for the file lock while writing the plugin list — usually because another DSH process or install task is writing the same profile (sometimes a previous run left the lock behind). Close other dsh windows or running commands, then retry; if it keeps happening, restart DSH once. This is not a plugin problem, and
|
|
658
|
-
|
|
629
|
+
failUnclassifiedHint: "The {action} failed and the cause could not be identified automatically. This is usually not the plugin itself (it may relate to your local environment or the Plugin Hub). Please report the error to the Plugin Hub so the maintainers can triage it.",
|
|
630
|
+
failHubStateHint: "The plugin list is out of date or out of sync: the target of this {action} may already be in the list (use \"Update\" to upgrade), may no longer be in the installed list, or may already be queued. This is not a plugin problem — refresh the page and retry.",
|
|
631
|
+
failTimeoutHint: "This operation exceeded the local time limit and was interrupted — but it may well have taken effect already (the installer re-checks the installed list after a timeout). Refresh the page to confirm the current state; if it did not take effect, run the corresponding command in a terminal to see the full output. This is not a plugin problem.",
|
|
632
|
+
failProfileLockHint: "DSH timed out waiting for the file lock while writing the plugin list — usually because another DSH process or install task is writing the same profile (sometimes a previous run left the lock behind). Close other dsh windows or running commands, then retry; if it keeps happening, restart DSH once. This is not a plugin problem, and there is no need to repeat the {action}.",
|
|
633
|
+
failHostCliSpawnHint: "DSH could not start itself to perform this operation (the system reported that the executable was not found). This usually means the DSH installation folder has been moved or is being updated, or that the profile directory does not exist yet. Restart DSH and retry; if it keeps happening, reinstall DSH. This is not a plugin problem — other plugins would fail the same way.",
|
|
634
|
+
failPrepareHint: "This plugin failed while running its build scripts during install (the published npm package is incomplete). This is a packaging issue of the plugin itself — please report it to the author repository.",
|
|
659
635
|
failMisjudgeHint: "If this plugin actually installs fine (the verdict above is the Plugin Hub misjudging it), please report it to the Hub: that verdict is produced by the marketplace itself, so a false positive can only be found through your feedback.",
|
|
660
636
|
failMisjudgeLink: "Plugin installs fine but got blocked? Report to the Plugin Hub",
|
|
661
637
|
failPackagingHint: "This plugin does not support the official default install method: its git distribution lacks a file the package needs (the entry from `main` / `exports`, an entry its own patch mounts by name, or the patch declared by `dsh.bundle.patch`), so it has not been adapted to the official install flow. Please file an Issue on the author's repo asking for committed build output, a prebuilt release `.tgz` (`releases/download/<tag>/<asset>.tgz`), or a complete npm release.",
|
|
662
|
-
failIgnoredBuild: "This plugin (or one of its dependencies) needs to run build scripts at install time, which pnpm blocks by default via its allowBuilds allowlist — so
|
|
638
|
+
failIgnoredBuild: "This plugin (or one of its dependencies) needs to run build scripts at install time, which pnpm blocks by default via its allowBuilds allowlist — so this operation fails (e.g. native modules like node-pty, or the plugin's own prepare script on git installs). The installer already auto-allows that key and retries once; if it still fails, the build itself is the problem, so no user can install it. Run the install command in a terminal to see the full build error; this is a build/distribution issue of the plugin itself — please report it to the author repository, asking them to ship prebuilt output, a complete npm release, or a prebuilt .tgz.",
|
|
663
639
|
failNpmTooLow: "Your local npm may be too old: npm crashed internally while resolving the plugin's dependencies (a known npm bug — not a plugin issue). Please upgrade npm and retry: npm install -g npm@latest",
|
|
664
640
|
failNpmTooLowV: "Your local npm is too old (v{v}): npm crashed internally while resolving the plugin's dependencies (a known npm bug — not a plugin issue). Please upgrade npm and retry: npm install -g npm@latest",
|
|
665
|
-
failNetworkHint: "The network could not be reached before
|
|
641
|
+
failNetworkHint: "The network could not be reached before the {action}: the install source is unreachable (offline, DNS failure, firewall block, or a misconfigured proxy). This is not a problem with the plugin itself — please check your connection, confirm the HTTP proxy in Settings, run a connectivity check under System Diagnostics, then retry.",
|
|
666
642
|
failNetworkRegistryHint: "Your npm/pnpm registry is set to {host}, and the package tarball could not be downloaded from it. This usually means a private/internal mirror that has not synced the package (or requires intranet auth) — point the registry back to https://registry.npmjs.org (or make sure this source can serve the package), then retry.",
|
|
667
643
|
failNetworkTarget: "Cannot reach {url} — your network connection is down",
|
|
668
644
|
failNetworkRunDiag: "Run a network diagnostic",
|
|
@@ -688,8 +664,6 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
688
664
|
failPnpmPolicyHint: "The installer was blocked by pnpm supply-chain security policy — every plugin install would hit the same wall, so this is not a problem with the plugin itself. Two cases: ① \"Minimum release age\" (ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION): the package was published less than 24 hours ago, and pnpm 11 refuses freshly-published packages for safety. Add minimumReleaseAge: 0 to your pnpm config (pnpm-workspace.yaml) to opt out, or wait until the 24 hours have passed and retry. ② \"untrusted origin\" (ERR_PNPM_UNTRUSTED_ORIGIN): a dependency source is not trusted by this machine, usually because plugins were previously installed via github: or a non-official npm registry, so the lockfile records an untrusted source. Delete node_modules and pnpm-lock.yaml under the profile directory (see System Logs or ~/.dsh/profiles/<profile>/hub.log for the full output), then reinstall.",
|
|
689
665
|
failPnpmReleaseAgeHint: "The installer was blocked by pnpm supply-chain security policy, and every plugin installed into this profile would hit the same wall — this is not a problem with the plugin itself. The package was published less than 24 hours ago, and pnpm 11 refuses freshly-published packages for safety, so both installs and removals are blocked for this profile in the meantime. Retry after: {time} (i.e. 24 hours after the package was published). If you must install right now, add minimumReleaseAge: 0 to pnpm-workspace.yaml inside the profile directory (~/.dsh/profiles/<profile>) to opt out, but that loosens supply-chain protection for the whole profile.",
|
|
690
666
|
installChannelNpm: "NPM package",
|
|
691
|
-
installChannelGit: "GitHub source",
|
|
692
|
-
installChannelDsh: "DSH command",
|
|
693
667
|
installEntryLine: "Install entry: {c}.",
|
|
694
668
|
reportIssue: "Report an Issue to the plugin repo",
|
|
695
669
|
detail: "Open details",
|
|
@@ -744,42 +718,42 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
744
718
|
css: css$11
|
|
745
719
|
});
|
|
746
720
|
var Header_module_css_default = {
|
|
747
|
-
"
|
|
748
|
-
"
|
|
749
|
-
"
|
|
750
|
-
"
|
|
751
|
-
"
|
|
752
|
-
"version": "qikqja_version",
|
|
753
|
-
"logoIcon": "qikqja_logoIcon",
|
|
721
|
+
"githubIcon": "qikqja_githubIcon",
|
|
722
|
+
"tab": "qikqja_tab",
|
|
723
|
+
"resultSeg": "qikqja_resultSeg",
|
|
724
|
+
"searchRow": "qikqja_searchRow",
|
|
725
|
+
"header": "qikqja_header",
|
|
754
726
|
"segBtnActive": "qikqja_segBtnActive",
|
|
755
|
-
"
|
|
727
|
+
"version": "qikqja_version",
|
|
756
728
|
"brandTitle": "qikqja_brandTitle",
|
|
729
|
+
"root": "qikqja_root",
|
|
730
|
+
"sortGroup": "qikqja_sortGroup",
|
|
731
|
+
"tabsRow": "qikqja_tabsRow",
|
|
732
|
+
"adText": "qikqja_adText",
|
|
733
|
+
"segBtn": "qikqja_segBtn",
|
|
734
|
+
"tagline": "qikqja_tagline",
|
|
735
|
+
"resultCount": "qikqja_resultCount",
|
|
736
|
+
"headerRight": "qikqja_headerRight",
|
|
737
|
+
"segGroup": "qikqja_segGroup",
|
|
757
738
|
"langBtn": "qikqja_langBtn",
|
|
739
|
+
"title": "qikqja_title",
|
|
740
|
+
"githubLink": "qikqja_githubLink",
|
|
741
|
+
"headerTitleRow": "qikqja_headerTitleRow",
|
|
742
|
+
"tabCount": "qikqja_tabCount",
|
|
743
|
+
"versionBtn": "qikqja_versionBtn",
|
|
744
|
+
"hubUpdateBadge": "qikqja_hubUpdateBadge",
|
|
758
745
|
"controls": "qikqja_controls",
|
|
759
|
-
"aboutBtn": "qikqja_aboutBtn",
|
|
760
746
|
"adBadge": "qikqja_adBadge",
|
|
761
|
-
"
|
|
762
|
-
"headerTitleRow": "qikqja_headerTitleRow",
|
|
747
|
+
"segLabel": "qikqja_segLabel",
|
|
763
748
|
"taglineLink": "qikqja_taglineLink",
|
|
764
|
-
"
|
|
765
|
-
"adText": "qikqja_adText",
|
|
766
|
-
"copyIcon": "qikqja_copyIcon",
|
|
767
|
-
"adBanner": "qikqja_adBanner",
|
|
768
|
-
"tabsRow": "qikqja_tabsRow",
|
|
769
|
-
"headerRight": "qikqja_headerRight",
|
|
770
|
-
"resultSeg": "qikqja_resultSeg",
|
|
771
|
-
"root": "qikqja_root",
|
|
772
|
-
"tagline": "qikqja_tagline",
|
|
773
|
-
"segBtn": "qikqja_segBtn",
|
|
774
|
-
"searchRow": "qikqja_searchRow",
|
|
775
|
-
"githubIcon": "qikqja_githubIcon",
|
|
749
|
+
"logoIcon": "qikqja_logoIcon",
|
|
776
750
|
"tabs": "qikqja_tabs",
|
|
777
|
-
"
|
|
778
|
-
"
|
|
779
|
-
"
|
|
780
|
-
"
|
|
781
|
-
"
|
|
782
|
-
"
|
|
751
|
+
"adBanner": "qikqja_adBanner",
|
|
752
|
+
"aboutBtn": "qikqja_aboutBtn",
|
|
753
|
+
"search": "qikqja_search",
|
|
754
|
+
"copyIcon": "qikqja_copyIcon",
|
|
755
|
+
"adArrow": "qikqja_adArrow",
|
|
756
|
+
"tabActive": "qikqja_tabActive"
|
|
783
757
|
};
|
|
784
758
|
//#endregion
|
|
785
759
|
//#region \0dsh-css:src/client/styles/Modal.module.css.mjs
|
|
@@ -798,153 +772,153 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
798
772
|
css: css$10
|
|
799
773
|
});
|
|
800
774
|
var Modal_module_css_default = {
|
|
801
|
-
"noticeRowMain": "BiQ1zG_noticeRowMain",
|
|
802
|
-
"toastFail": "BiQ1zG_toastFail",
|
|
803
|
-
"noticeTextOk": "BiQ1zG_noticeTextOk",
|
|
804
|
-
"noticeRemove": "BiQ1zG_noticeRemove",
|
|
805
775
|
"hubUpdateNotes": "BiQ1zG_hubUpdateNotes",
|
|
806
|
-
"
|
|
807
|
-
"
|
|
808
|
-
"
|
|
809
|
-
"
|
|
810
|
-
"progressHead": "BiQ1zG_progressHead",
|
|
811
|
-
"modalBody": "BiQ1zG_modalBody",
|
|
812
|
-
"noticeUpdateGo": "BiQ1zG_noticeUpdateGo",
|
|
813
|
-
"modalValue": "BiQ1zG_modalValue",
|
|
814
|
-
"confirmIconWrap": "BiQ1zG_confirmIconWrap",
|
|
815
|
-
"toastIn": "BiQ1zG_toastIn",
|
|
816
|
-
"queuedHint": "BiQ1zG_queuedHint",
|
|
817
|
-
"noticeRow": "BiQ1zG_noticeRow",
|
|
818
|
-
"modalLink": "BiQ1zG_modalLink",
|
|
819
|
-
"failNetworkTarget": "BiQ1zG_failNetworkTarget",
|
|
820
|
-
"failRow": "BiQ1zG_failRow",
|
|
821
|
-
"toast": "BiQ1zG_toast",
|
|
776
|
+
"noticeRowOk": "BiQ1zG_noticeRowOk",
|
|
777
|
+
"queueRowStatus": "BiQ1zG_queueRowStatus",
|
|
778
|
+
"toastFail": "BiQ1zG_toastFail",
|
|
779
|
+
"failHead": "BiQ1zG_failHead",
|
|
822
780
|
"queueRowPct": "BiQ1zG_queueRowPct",
|
|
823
|
-
"
|
|
824
|
-
"failPrepareHint": "BiQ1zG_failPrepareHint",
|
|
825
|
-
"noticeHead": "BiQ1zG_noticeHead",
|
|
826
|
-
"failCopy": "BiQ1zG_failCopy",
|
|
827
|
-
"confirmPrimary": "BiQ1zG_confirmPrimary",
|
|
828
|
-
"noticeVersion": "BiQ1zG_noticeVersion",
|
|
829
|
-
"overlay": "BiQ1zG_overlay",
|
|
781
|
+
"modalBody": "BiQ1zG_modalBody",
|
|
830
782
|
"resultTitle": "BiQ1zG_resultTitle",
|
|
831
|
-
"
|
|
832
|
-
"
|
|
833
|
-
"
|
|
834
|
-
"
|
|
835
|
-
"
|
|
836
|
-
"errorBox": "BiQ1zG_errorBox",
|
|
837
|
-
"noticeTime": "BiQ1zG_noticeTime",
|
|
783
|
+
"errorHint": "BiQ1zG_errorHint",
|
|
784
|
+
"queueRowDesc": "BiQ1zG_queueRowDesc",
|
|
785
|
+
"detailLabel": "BiQ1zG_detailLabel",
|
|
786
|
+
"detailArrow": "BiQ1zG_detailArrow",
|
|
787
|
+
"hubUpdateMeta": "BiQ1zG_hubUpdateMeta",
|
|
838
788
|
"errorModal": "BiQ1zG_errorModal",
|
|
839
|
-
"resultDesc": "BiQ1zG_resultDesc",
|
|
840
|
-
"detailPath": "BiQ1zG_detailPath",
|
|
841
|
-
"detailPathActions": "BiQ1zG_detailPathActions",
|
|
842
|
-
"detailModal": "BiQ1zG_detailModal",
|
|
843
|
-
"modalTitle": "BiQ1zG_modalTitle",
|
|
844
|
-
"resultCheckIcon": "BiQ1zG_resultCheckIcon",
|
|
845
|
-
"restartNow": "BiQ1zG_restartNow",
|
|
846
|
-
"failEmpty": "BiQ1zG_failEmpty",
|
|
847
|
-
"modalWide": "BiQ1zG_modalWide",
|
|
848
|
-
"failList": "BiQ1zG_failList",
|
|
849
|
-
"noticeRowUpdate": "BiQ1zG_noticeRowUpdate",
|
|
850
|
-
"cliOnlyHint": "BiQ1zG_cliOnlyHint",
|
|
851
|
-
"failClear": "BiQ1zG_failClear",
|
|
852
|
-
"progressFillFail": "BiQ1zG_progressFillFail",
|
|
853
|
-
"queueRowStatus": "BiQ1zG_queueRowStatus",
|
|
854
|
-
"detailGrid": "BiQ1zG_detailGrid",
|
|
855
|
-
"queueRowHead": "BiQ1zG_queueRowHead",
|
|
856
|
-
"aboutMeta": "BiQ1zG_aboutMeta",
|
|
857
|
-
"modalCloseIcon": "BiQ1zG_modalCloseIcon",
|
|
858
|
-
"noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
|
|
859
|
-
"noticeRowOk": "BiQ1zG_noticeRowOk",
|
|
860
789
|
"detailStars": "BiQ1zG_detailStars",
|
|
861
|
-
"
|
|
862
|
-
"
|
|
863
|
-
"
|
|
864
|
-
"
|
|
865
|
-
"
|
|
866
|
-
"
|
|
867
|
-
"
|
|
868
|
-
"failMisjudgeLink": "BiQ1zG_failMisjudgeLink",
|
|
790
|
+
"pendingRowActions": "BiQ1zG_pendingRowActions",
|
|
791
|
+
"overlay": "BiQ1zG_overlay",
|
|
792
|
+
"failRepo": "BiQ1zG_failRepo",
|
|
793
|
+
"linkIcon": "BiQ1zG_linkIcon",
|
|
794
|
+
"failKind": "BiQ1zG_failKind",
|
|
795
|
+
"modalLabel": "BiQ1zG_modalLabel",
|
|
796
|
+
"modalWide": "BiQ1zG_modalWide",
|
|
869
797
|
"errorCopySoft": "BiQ1zG_errorCopySoft",
|
|
870
|
-
"
|
|
871
|
-
"
|
|
872
|
-
"
|
|
873
|
-
"
|
|
874
|
-
"
|
|
798
|
+
"restartNowWarning": "BiQ1zG_restartNowWarning",
|
|
799
|
+
"noticeIgnore": "BiQ1zG_noticeIgnore",
|
|
800
|
+
"confirmIcon": "BiQ1zG_confirmIcon",
|
|
801
|
+
"restartLater": "BiQ1zG_restartLater",
|
|
802
|
+
"detailPath": "BiQ1zG_detailPath",
|
|
803
|
+
"detailStatusRunning": "BiQ1zG_detailStatusRunning",
|
|
875
804
|
"modalCmdText": "BiQ1zG_modalCmdText",
|
|
805
|
+
"modalTitleQueued": "BiQ1zG_modalTitleQueued",
|
|
806
|
+
"queueRowTrack": "BiQ1zG_queueRowTrack",
|
|
807
|
+
"failList": "BiQ1zG_failList",
|
|
876
808
|
"queueRowTarget": "BiQ1zG_queueRowTarget",
|
|
877
|
-
"
|
|
878
|
-
"
|
|
879
|
-
"
|
|
880
|
-
"
|
|
881
|
-
"
|
|
809
|
+
"queueRowHead": "BiQ1zG_queueRowHead",
|
|
810
|
+
"modalActions": "BiQ1zG_modalActions",
|
|
811
|
+
"failCopy": "BiQ1zG_failCopy",
|
|
812
|
+
"noticeFoot": "BiQ1zG_noticeFoot",
|
|
813
|
+
"dangerConfirm": "BiQ1zG_dangerConfirm",
|
|
814
|
+
"modalLink": "BiQ1zG_modalLink",
|
|
815
|
+
"failKindInstall": "BiQ1zG_failKindInstall",
|
|
816
|
+
"aboutModal": "BiQ1zG_aboutModal",
|
|
817
|
+
"confirmIconDanger": "BiQ1zG_confirmIconDanger",
|
|
818
|
+
"hubUpdateModal": "BiQ1zG_hubUpdateModal",
|
|
882
819
|
"failedCopyHint": "BiQ1zG_failedCopyHint",
|
|
883
|
-
"
|
|
820
|
+
"stripCancel": "BiQ1zG_stripCancel",
|
|
884
821
|
"overlayIn": "BiQ1zG_overlayIn",
|
|
885
|
-
"
|
|
886
|
-
"
|
|
887
|
-
"
|
|
888
|
-
"
|
|
889
|
-
"
|
|
890
|
-
"
|
|
822
|
+
"resultCheck": "BiQ1zG_resultCheck",
|
|
823
|
+
"resultRestarting": "BiQ1zG_resultRestarting",
|
|
824
|
+
"detailMono": "BiQ1zG_detailMono",
|
|
825
|
+
"noticeRemove": "BiQ1zG_noticeRemove",
|
|
826
|
+
"modal": "BiQ1zG_modal",
|
|
827
|
+
"errorTitle": "BiQ1zG_errorTitle",
|
|
891
828
|
"detailDim": "BiQ1zG_detailDim",
|
|
892
|
-
"
|
|
893
|
-
"
|
|
894
|
-
"
|
|
895
|
-
"
|
|
829
|
+
"noticeUpdateGo": "BiQ1zG_noticeUpdateGo",
|
|
830
|
+
"failKindUninstall": "BiQ1zG_failKindUninstall",
|
|
831
|
+
"failNetworkTarget": "BiQ1zG_failNetworkTarget",
|
|
832
|
+
"queuedHint": "BiQ1zG_queuedHint",
|
|
833
|
+
"trustHint": "BiQ1zG_trustHint",
|
|
834
|
+
"detailPathActions": "BiQ1zG_detailPathActions",
|
|
835
|
+
"failClear": "BiQ1zG_failClear",
|
|
836
|
+
"noticeHead": "BiQ1zG_noticeHead",
|
|
837
|
+
"noticeBadgeIcon": "BiQ1zG_noticeBadgeIcon",
|
|
838
|
+
"aboutContent": "BiQ1zG_aboutContent",
|
|
839
|
+
"modalTitle": "BiQ1zG_modalTitle",
|
|
840
|
+
"detailModal": "BiQ1zG_detailModal",
|
|
841
|
+
"noticeRowMain": "BiQ1zG_noticeRowMain",
|
|
896
842
|
"progressFill": "BiQ1zG_progressFill",
|
|
897
|
-
"
|
|
898
|
-
"
|
|
899
|
-
"
|
|
843
|
+
"queueRow": "BiQ1zG_queueRow",
|
|
844
|
+
"detailGrid": "BiQ1zG_detailGrid",
|
|
845
|
+
"progressHead": "BiQ1zG_progressHead",
|
|
846
|
+
"result": "BiQ1zG_result",
|
|
847
|
+
"failEmpty": "BiQ1zG_failEmpty",
|
|
848
|
+
"hubUpdateMetaItem": "BiQ1zG_hubUpdateMetaItem",
|
|
849
|
+
"queueSection": "BiQ1zG_queueSection",
|
|
850
|
+
"modalClose": "BiQ1zG_modalClose",
|
|
851
|
+
"progressText": "BiQ1zG_progressText",
|
|
852
|
+
"errorBox": "BiQ1zG_errorBox",
|
|
853
|
+
"noticeTextFail": "BiQ1zG_noticeTextFail",
|
|
854
|
+
"detailPathText": "BiQ1zG_detailPathText",
|
|
855
|
+
"toastIn": "BiQ1zG_toastIn",
|
|
856
|
+
"failDiagBtn": "BiQ1zG_failDiagBtn",
|
|
857
|
+
"modalInstall": "BiQ1zG_modalInstall",
|
|
858
|
+
"queueSectionTitle": "BiQ1zG_queueSectionTitle",
|
|
900
859
|
"detailValue": "BiQ1zG_detailValue",
|
|
901
|
-
"
|
|
902
|
-
"
|
|
903
|
-
"
|
|
860
|
+
"failMisjudgeLink": "BiQ1zG_failMisjudgeLink",
|
|
861
|
+
"resultCheckIcon": "BiQ1zG_resultCheckIcon",
|
|
862
|
+
"modalTitleBusy": "BiQ1zG_modalTitleBusy",
|
|
863
|
+
"confirmIconWrap": "BiQ1zG_confirmIconWrap",
|
|
864
|
+
"noticeRow": "BiQ1zG_noticeRow",
|
|
865
|
+
"modalCloseIcon": "BiQ1zG_modalCloseIcon",
|
|
866
|
+
"modalCopy": "BiQ1zG_modalCopy",
|
|
867
|
+
"confirmPrimary": "BiQ1zG_confirmPrimary",
|
|
868
|
+
"cliOnlyHint": "BiQ1zG_cliOnlyHint",
|
|
869
|
+
"modalRow": "BiQ1zG_modalRow",
|
|
870
|
+
"detailLink": "BiQ1zG_detailLink",
|
|
904
871
|
"noticeBadgeOk": "BiQ1zG_noticeBadgeOk",
|
|
905
|
-
"
|
|
906
|
-
"aboutContent": "BiQ1zG_aboutContent",
|
|
872
|
+
"modalCancel": "BiQ1zG_modalCancel",
|
|
907
873
|
"detailStatusPending": "BiQ1zG_detailStatusPending",
|
|
908
|
-
"
|
|
909
|
-
"
|
|
910
|
-
"
|
|
911
|
-
"
|
|
912
|
-
"
|
|
913
|
-
"
|
|
874
|
+
"modalHead": "BiQ1zG_modalHead",
|
|
875
|
+
"queueRowBody": "BiQ1zG_queueRowBody",
|
|
876
|
+
"failPrepareHint": "BiQ1zG_failPrepareHint",
|
|
877
|
+
"aboutMeta": "BiQ1zG_aboutMeta",
|
|
878
|
+
"resultDesc": "BiQ1zG_resultDesc",
|
|
879
|
+
"helpModal": "BiQ1zG_helpModal",
|
|
914
880
|
"noticeMain": "BiQ1zG_noticeMain",
|
|
915
|
-
"
|
|
916
|
-
"
|
|
917
|
-
"
|
|
918
|
-
"
|
|
919
|
-
"
|
|
920
|
-
"
|
|
921
|
-
"
|
|
922
|
-
"
|
|
923
|
-
"
|
|
924
|
-
"
|
|
925
|
-
"
|
|
881
|
+
"noticeTime": "BiQ1zG_noticeTime",
|
|
882
|
+
"modalDesc": "BiQ1zG_modalDesc",
|
|
883
|
+
"modalCmd": "BiQ1zG_modalCmd",
|
|
884
|
+
"noticeList": "BiQ1zG_noticeList",
|
|
885
|
+
"failRow": "BiQ1zG_failRow",
|
|
886
|
+
"noticeRowUpdate": "BiQ1zG_noticeRowUpdate",
|
|
887
|
+
"detailPathBtn": "BiQ1zG_detailPathBtn",
|
|
888
|
+
"failBigIssue": "BiQ1zG_failBigIssue",
|
|
889
|
+
"pendingRowStatus": "BiQ1zG_pendingRowStatus",
|
|
890
|
+
"restartNow": "BiQ1zG_restartNow",
|
|
891
|
+
"noticeTextOk": "BiQ1zG_noticeTextOk",
|
|
892
|
+
"uninstallConfirm": "BiQ1zG_uninstallConfirm",
|
|
893
|
+
"modalIn": "BiQ1zG_modalIn",
|
|
926
894
|
"progress": "BiQ1zG_progress",
|
|
927
|
-
"
|
|
928
|
-
"
|
|
929
|
-
"
|
|
930
|
-
"
|
|
931
|
-
"
|
|
895
|
+
"noticeBadgeFail": "BiQ1zG_noticeBadgeFail",
|
|
896
|
+
"progressTrack": "BiQ1zG_progressTrack",
|
|
897
|
+
"modalCmdCopy": "BiQ1zG_modalCmdCopy",
|
|
898
|
+
"progressFillFail": "BiQ1zG_progressFillFail",
|
|
899
|
+
"detailUpdateHint": "BiQ1zG_detailUpdateHint",
|
|
900
|
+
"toast": "BiQ1zG_toast",
|
|
901
|
+
"detailStatusText": "BiQ1zG_detailStatusText",
|
|
902
|
+
"logModal": "BiQ1zG_logModal",
|
|
903
|
+
"modalValue": "BiQ1zG_modalValue",
|
|
904
|
+
"noticeVersion": "BiQ1zG_noticeVersion",
|
|
905
|
+
"detailRow": "BiQ1zG_detailRow"
|
|
932
906
|
};
|
|
933
907
|
//#endregion
|
|
934
908
|
//#region src/server/services/install/release-target.ts
|
|
935
|
-
/**
|
|
936
|
-
const DSH_PLUGIN_CMD_RE
|
|
909
|
+
/** 完整命令前缀:`dsh plugin --profile <p> add|update <target>`(与 profile.ts installTargetOf 同口径)。 */
|
|
910
|
+
const DSH_PLUGIN_CMD_RE = /^dsh[ \t]+plugin[ \t]+--profile(?:[ \t]+|=)[A-Za-z0-9_-]+[ \t]+(?:add|update)[ \t]+(.+)$/i;
|
|
937
911
|
/** 固定形态的 release .tgz 直链:主机、路径段与扩展名全部锁死。 */
|
|
938
912
|
const RELEASE_URL_RE = /^https:\/\/github\.com\/([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)\/releases\/download\/([A-Za-z0-9._+-]+)\/([A-Za-z0-9._+-]+\.tgz)$/;
|
|
939
913
|
/**
|
|
940
|
-
*
|
|
941
|
-
* @param value -
|
|
914
|
+
* 解析一个历史安装目标里的 release 直链。
|
|
915
|
+
* @param value - 完整命令(`dsh plugin --profile web add <url>`)或裸直链。
|
|
942
916
|
* @returns 命中返回 `{ target, repo }`,否则 null。
|
|
943
917
|
*/
|
|
944
918
|
function githubReleaseTarget(value) {
|
|
945
919
|
const input = typeof value === "string" ? value.trim() : "";
|
|
946
920
|
if (input === "") return null;
|
|
947
|
-
const command = DSH_PLUGIN_CMD_RE
|
|
921
|
+
const command = DSH_PLUGIN_CMD_RE.exec(input);
|
|
948
922
|
const raw = command !== null ? command[1].trim() : input;
|
|
949
923
|
const match = RELEASE_URL_RE.exec(raw);
|
|
950
924
|
if (match === null) return null;
|
|
@@ -956,54 +930,30 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
956
930
|
}
|
|
957
931
|
//#endregion
|
|
958
932
|
//#region src/client/logic/install-command.ts
|
|
959
|
-
/**
|
|
960
|
-
*
|
|
933
|
+
/** 后端 attempts 按时间先后排列:取最后一次实际执行的命令,取不到再回退到展示用命令。
|
|
934
|
+
* 这里匹配的是任务队列记录的指令形态,不是要在此执行的命令。
|
|
961
935
|
*/
|
|
962
936
|
function executedCommandOf(command, attempts) {
|
|
963
937
|
if (attempts === void 0) return command;
|
|
964
938
|
return attempts.slice().reverse().find((attempt) => /^dsh plugin --profile(?:=| )\S+ (?:add|remove|update) \S/.test(attempt) || /^npm install -g \S/.test(attempt));
|
|
965
939
|
}
|
|
966
940
|
/**
|
|
967
|
-
*
|
|
968
|
-
* (走 npm registry tarball
|
|
969
|
-
*
|
|
970
|
-
* 都没有 → git 直装。
|
|
971
|
-
* 返回值 target 即传给后端 /install 的安装目标(npm 包名 / release URL / owner/repo)。
|
|
941
|
+
* 目录条目的安装目标(用户无感知):目录条目必带 npm 包名,直接用该包名安装
|
|
942
|
+
* (走 npm registry tarball)。
|
|
943
|
+
* 返回值即传给后端 /install 的安装目标(npm 包名)。
|
|
972
944
|
*/
|
|
973
945
|
function installTargetOf(p) {
|
|
974
|
-
|
|
975
|
-
const repo = (p.source?.repo ?? "").trim();
|
|
976
|
-
if (pkg && repo) return {
|
|
977
|
-
target: pkg,
|
|
978
|
-
via: "npm"
|
|
979
|
-
};
|
|
980
|
-
const release = githubReleaseTarget(p.install?.githubCommand ?? "");
|
|
981
|
-
if (release !== null && repo !== "" && release.repo.toLowerCase() === repo.toLowerCase()) return {
|
|
982
|
-
target: release.target,
|
|
983
|
-
via: "release"
|
|
984
|
-
};
|
|
985
|
-
return {
|
|
986
|
-
target: repo,
|
|
987
|
-
via: "github"
|
|
988
|
-
};
|
|
946
|
+
return (p.source?.npmPackage ?? "").trim();
|
|
989
947
|
}
|
|
990
948
|
/** 展示用安装命令(复制/弹窗):目录下发的权威命令优先(CLI-only 插件如 dsh-tui
|
|
991
|
-
* 需专属 profile(--profile dsh-tui),无法从
|
|
992
|
-
*
|
|
949
|
+
* 需专属 profile(--profile dsh-tui),无法从 npm 包名推断,必须用官方命令);
|
|
950
|
+
* 常规插件无目录命令时用 npm 包名回退生成。 */
|
|
993
951
|
function installCommandOf(p, withProfile = false) {
|
|
994
|
-
const
|
|
995
|
-
if (
|
|
996
|
-
|
|
997
|
-
if (cmd) return cmd;
|
|
998
|
-
} else {
|
|
999
|
-
const cmd = p.install?.githubCommand;
|
|
1000
|
-
if (cmd) return cmd;
|
|
1001
|
-
}
|
|
1002
|
-
const prefix = `dsh plugin${withProfile ? " --profile web" : ""} add `;
|
|
1003
|
-
if (via === "npm" || via === "release") return `${prefix}${target}`;
|
|
1004
|
-
return `${prefix}git+https://github.com/${target}.git`;
|
|
952
|
+
const cmd = p.install?.command;
|
|
953
|
+
if (cmd) return cmd;
|
|
954
|
+
return `${`dsh plugin${withProfile ? " --profile web" : ""} add `}${installTargetOf(p)}`;
|
|
1005
955
|
}
|
|
1006
|
-
/**
|
|
956
|
+
/** 把任务/安装目标归一化为 owner/repo 展示身份。 */
|
|
1007
957
|
function repoFromInstallTarget(value) {
|
|
1008
958
|
const input = value.trim();
|
|
1009
959
|
const release = githubReleaseTarget(input);
|
|
@@ -1042,7 +992,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1042
992
|
* tsdown 构建时用 define 把 __PLUGIN_VERSION__ 替换成 package.json 的版本号;
|
|
1043
993
|
* node --test 直接 import 本模块时该标识符不存在,typeof 守卫兜底为空串。
|
|
1044
994
|
*/
|
|
1045
|
-
const PLUGIN_VERSION = "
|
|
995
|
+
const PLUGIN_VERSION = "2.0.0";
|
|
1046
996
|
const CATEGORY_ORDER = [
|
|
1047
997
|
"interface",
|
|
1048
998
|
"session",
|
|
@@ -1161,7 +1111,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1161
1111
|
];
|
|
1162
1112
|
//#endregion
|
|
1163
1113
|
//#region src/client/logic/ensure-plugin-css.ts
|
|
1164
|
-
/**
|
|
1114
|
+
/** 补注入 DOM 中缺失的已登记样式表,幂等。 */
|
|
1165
1115
|
function ensurePluginCss() {
|
|
1166
1116
|
if (typeof document === "undefined") return;
|
|
1167
1117
|
const registry = window.__DSH_PLUGIN_CSS__;
|
|
@@ -1195,6 +1145,22 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1195
1145
|
return null;
|
|
1196
1146
|
}
|
|
1197
1147
|
}
|
|
1148
|
+
/** 批量查询已安装插件 npm 包的最新版本发布时间(供应链门禁用);失败返回 null(调用方按原逻辑照常提示)。 */
|
|
1149
|
+
async function fetchNpmReleaseAge(packages) {
|
|
1150
|
+
if (packages.length === 0) return {};
|
|
1151
|
+
try {
|
|
1152
|
+
const res = await fetch("/dsh-plugin-hub/npm-release-age", {
|
|
1153
|
+
method: "POST",
|
|
1154
|
+
headers: { "content-type": "application/json" },
|
|
1155
|
+
body: JSON.stringify({ packages }),
|
|
1156
|
+
cache: "no-store"
|
|
1157
|
+
});
|
|
1158
|
+
if (!res.ok) return null;
|
|
1159
|
+
return (await res.json()).packages ?? null;
|
|
1160
|
+
} catch {
|
|
1161
|
+
return null;
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1198
1164
|
let envPromise = null;
|
|
1199
1165
|
/** 在系统文件管理器里定位并打开已安装插件的目录(服务端 spawn open,跨平台);失败返回 false。 */
|
|
1200
1166
|
async function revealInstallFolder(name) {
|
|
@@ -1354,13 +1320,32 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1354
1320
|
}
|
|
1355
1321
|
}
|
|
1356
1322
|
//#endregion
|
|
1323
|
+
//#region src/client/logic/release-age.ts
|
|
1324
|
+
/**
|
|
1325
|
+
* DSH Plugin Hub — the community plugin marketplace for DeepSeek Harness.
|
|
1326
|
+
* Website: https://dsh-plugin.org
|
|
1327
|
+
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
1328
|
+
*
|
|
1329
|
+
* 供应链门禁的时间判定(纯函数):pnpm 会静默回退发布未满门槛的版本,
|
|
1330
|
+
* 故发布太新的版本不该提示更新。Hub 自身更新与插件更新共用同一门槛。
|
|
1331
|
+
*/
|
|
1332
|
+
/** pnpm 供应链门禁:dsh profile 默认 minimumReleaseAge=1440(分钟);+30 分钟缓冲抵消网络/CDN 边缘时间偏差。 */
|
|
1333
|
+
const MIN_RELEASE_AGE_MS = 882e5;
|
|
1334
|
+
/** 发布时间是否仍在门禁窗口内(太新 → 暂缓提示);无值/解析不出返回 false(不拦真实更新)。 */
|
|
1335
|
+
function isReleaseTooFresh(publishedAt, now) {
|
|
1336
|
+
if (typeof publishedAt !== "string" || publishedAt === "") return false;
|
|
1337
|
+
const ms = Date.parse(publishedAt);
|
|
1338
|
+
if (Number.isNaN(ms)) return false;
|
|
1339
|
+
return now - ms < MIN_RELEASE_AGE_MS;
|
|
1340
|
+
}
|
|
1341
|
+
//#endregion
|
|
1357
1342
|
//#region src/client/logic/installed.ts
|
|
1358
1343
|
/** 安装时记录的目录信号(按仓库小写 key 查表)。 */
|
|
1359
1344
|
function signalOf(repo, versions) {
|
|
1360
1345
|
if (!repo) return null;
|
|
1361
1346
|
return versions[repo.toLowerCase()] ?? null;
|
|
1362
1347
|
}
|
|
1363
|
-
/** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm
|
|
1348
|
+
/** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm 安装的依赖包名;命中返回 npm 包名。 */
|
|
1364
1349
|
function installedNameOf(plugin, installed, versions) {
|
|
1365
1350
|
const repo = plugin.source?.repo;
|
|
1366
1351
|
if (!repo) return null;
|
|
@@ -1379,6 +1364,12 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1379
1364
|
if (!repo) return null;
|
|
1380
1365
|
return versions[repo.toLowerCase()]?.version ?? null;
|
|
1381
1366
|
}
|
|
1367
|
+
/** 该插件对应的 npm 包名(目录下发,或安装时持久化的映射);无则 null。决定更新是否走 npm registry。 */
|
|
1368
|
+
function npmPackageOf(plugin, versions) {
|
|
1369
|
+
const repo = plugin.source?.repo;
|
|
1370
|
+
const pkg = (plugin.source?.npmPackage || (repo ? versions[repo.toLowerCase()]?.npmPackage : void 0) || "").trim();
|
|
1371
|
+
return pkg === "" ? null : pkg;
|
|
1372
|
+
}
|
|
1382
1373
|
/**
|
|
1383
1374
|
* 是否有更新:仅对已安装插件有意义。
|
|
1384
1375
|
* 双信号判定——有 release 版本的比版本;无版本(repo 不打 tag)的比仓库最近更新时间
|
|
@@ -1506,14 +1497,15 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1506
1497
|
* Website: https://dsh-plugin.org
|
|
1507
1498
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
1508
1499
|
*
|
|
1509
|
-
*
|
|
1500
|
+
* 插件中心的数据 + 视图状态。
|
|
1510
1501
|
*
|
|
1511
|
-
*
|
|
1512
|
-
*
|
|
1513
|
-
* state, exposing the derived visible list and per-category counts.
|
|
1502
|
+
* 掌管在线数据管道(从 api.dsh-plugin.org 实时拉取)、本地已装插件表,以及
|
|
1503
|
+
* 筛选/搜索/排序/安装状态等视图状态,对外暴露派生出的可见列表与各分类计数。
|
|
1514
1504
|
*/
|
|
1515
1505
|
/** 插件市场自身仓库:DSH Plugin Hub 不显示在目录里(自己不进自己的插件列表) */
|
|
1516
1506
|
const SELF_REPO = "dshplugin/dsh-plugin-hub";
|
|
1507
|
+
/** 共享的空门禁集合:无暂缓包时复用,避免每次渲染新建 Set。 */
|
|
1508
|
+
const EMPTY_PACKAGES = /* @__PURE__ */ new Set();
|
|
1517
1509
|
/** 市场各排序的默认方向:全部按倒序(Star/Fork 多、更新/收录近的在前) */
|
|
1518
1510
|
const SORT_DEFAULT_DIR$1 = {
|
|
1519
1511
|
sortStars: "desc",
|
|
@@ -1566,7 +1558,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1566
1558
|
/** 当前 profile 已安装插件:npm 包名 -> manifest spec(来自宿主本地路由) */
|
|
1567
1559
|
const [installed, setInstalled] = (0, react.useState)({});
|
|
1568
1560
|
/** 安装时记录的目录信号:repo(小写) -> { version, updatedAt }(来自宿主本地路由);
|
|
1569
|
-
* npmPackage
|
|
1561
|
+
* npmPackage 为安装时记录的包名映射(目录数据未下发时客户端靠它把依赖 key 匹配回仓库) */
|
|
1570
1562
|
const [versions, setVersions] = (0, react.useState)({});
|
|
1571
1563
|
/** 每个依赖在系统上的安装目录(profile/node_modules/<包名>),详情视图展示用 */
|
|
1572
1564
|
const [installPaths, setInstallPaths] = (0, react.useState)(null);
|
|
@@ -1649,18 +1641,20 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1649
1641
|
cancelled = true;
|
|
1650
1642
|
};
|
|
1651
1643
|
}, [reloadKey]);
|
|
1652
|
-
/** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm
|
|
1644
|
+
/** 插件是否已安装:匹配 Git spec 中的 owner/repo,或 npm 安装的依赖包名;命中返回 npm 包名。 */
|
|
1653
1645
|
const installedName = (p) => installedNameOf(p, installed, versions);
|
|
1654
1646
|
/** 该插件安装时记录的目录版本(无记录/未安装 → null)。 */
|
|
1655
1647
|
const installedVersion = (p) => installedVersionOf(p, versions);
|
|
1656
1648
|
/**
|
|
1657
|
-
*
|
|
1658
|
-
*
|
|
1659
|
-
* (repoUpdatedAt,ISO 字符串字典序 = 时间序),更新时间变新说明有新提交。
|
|
1649
|
+
* 供应链门禁状态:包名集合为当前「暂缓提示」的 npm 包(最新版本发布未满门槛)。
|
|
1650
|
+
* key 是这批候选包名的指纹,与已查出的 key 一致才算就绪,避免查询未回来时先显示更新。
|
|
1660
1651
|
*/
|
|
1661
|
-
const
|
|
1662
|
-
|
|
1663
|
-
|
|
1652
|
+
const [releaseAge, setReleaseAge] = (0, react.useState)({
|
|
1653
|
+
key: "",
|
|
1654
|
+
held: EMPTY_PACKAGES
|
|
1655
|
+
});
|
|
1656
|
+
/** 已安装项原始列表(未套门禁):先算出来才能收集需要查发布时间的候选包名。 */
|
|
1657
|
+
const rawInstalledItems = (0, react.useMemo)(() => installedItemsOf(plugins, installed, versions, installPaths, loadedNames, dshCapableNames), [
|
|
1664
1658
|
plugins,
|
|
1665
1659
|
installed,
|
|
1666
1660
|
versions,
|
|
@@ -1668,6 +1662,74 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1668
1662
|
loadedNames,
|
|
1669
1663
|
dshCapableNames
|
|
1670
1664
|
]);
|
|
1665
|
+
/** 门禁候选:有更新、且有 npm 包名(更新走 npm registry)的已安装插件包名。 */
|
|
1666
|
+
const releaseAgeCandidates = (0, react.useMemo)(() => {
|
|
1667
|
+
const names = /* @__PURE__ */ new Set();
|
|
1668
|
+
for (const item of rawInstalledItems) {
|
|
1669
|
+
if (!item.hasUpdate || !item.plugin) continue;
|
|
1670
|
+
const pkg = npmPackageOf(item.plugin, versions);
|
|
1671
|
+
if (pkg !== null) names.add(pkg);
|
|
1672
|
+
}
|
|
1673
|
+
return [...names].sort();
|
|
1674
|
+
}, [rawInstalledItems, versions]);
|
|
1675
|
+
const releaseAgeKey = releaseAgeCandidates.join("\n");
|
|
1676
|
+
(0, react.useEffect)(() => {
|
|
1677
|
+
if (releaseAgeKey === releaseAge.key) return;
|
|
1678
|
+
if (releaseAgeCandidates.length === 0) {
|
|
1679
|
+
setReleaseAge({
|
|
1680
|
+
key: "",
|
|
1681
|
+
held: EMPTY_PACKAGES
|
|
1682
|
+
});
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
let cancelled = false;
|
|
1686
|
+
fetchNpmReleaseAge(releaseAgeCandidates).then((result) => {
|
|
1687
|
+
if (cancelled) return;
|
|
1688
|
+
const now = Date.now();
|
|
1689
|
+
const held = /* @__PURE__ */ new Set();
|
|
1690
|
+
for (const name of releaseAgeCandidates) {
|
|
1691
|
+
const info = result?.[name];
|
|
1692
|
+
if (info && isReleaseTooFresh(info.publishedAt, now)) held.add(name);
|
|
1693
|
+
}
|
|
1694
|
+
setReleaseAge({
|
|
1695
|
+
key: releaseAgeKey,
|
|
1696
|
+
held
|
|
1697
|
+
});
|
|
1698
|
+
});
|
|
1699
|
+
return () => {
|
|
1700
|
+
cancelled = true;
|
|
1701
|
+
};
|
|
1702
|
+
}, [releaseAgeKey, releaseAge.key]);
|
|
1703
|
+
/** 门禁结果是否已就绪(候选为空也算就绪):未就绪时不写更新提醒,等查询回来再定。 */
|
|
1704
|
+
const releaseAgeReady = releaseAgeKey === releaseAge.key;
|
|
1705
|
+
const heldPackages = releaseAgeReady ? releaseAge.held : EMPTY_PACKAGES;
|
|
1706
|
+
/**
|
|
1707
|
+
* 是否有更新:仅对已安装插件有意义。
|
|
1708
|
+
* 双信号判定——有 release 版本的比版本;无版本(repo 不打 tag)的比仓库最近更新时间
|
|
1709
|
+
* (repoUpdatedAt,ISO 字符串字典序 = 时间序),更新时间变新说明有新提交。
|
|
1710
|
+
* 另加供应链门禁:npm 包最新版本发布未满门槛时视为暂缓,不打更新标记。
|
|
1711
|
+
*/
|
|
1712
|
+
const hasUpdate = (p) => {
|
|
1713
|
+
if (!hasUpdateOf(p, installed, versions)) return false;
|
|
1714
|
+
const pkg = npmPackageOf(p, versions);
|
|
1715
|
+
return pkg === null || !heldPackages.has(pkg);
|
|
1716
|
+
};
|
|
1717
|
+
/** 已安装项统一列表(目录元数据 + 运行时信息合并):门禁命中的去掉更新标记,驱动「已安装」tab。 */
|
|
1718
|
+
const installedItems = (0, react.useMemo)(() => {
|
|
1719
|
+
if (heldPackages.size === 0) return rawInstalledItems;
|
|
1720
|
+
return rawInstalledItems.map((item) => {
|
|
1721
|
+
if (!item.hasUpdate || !item.plugin) return item;
|
|
1722
|
+
const pkg = npmPackageOf(item.plugin, versions);
|
|
1723
|
+
return pkg !== null && heldPackages.has(pkg) ? {
|
|
1724
|
+
...item,
|
|
1725
|
+
hasUpdate: false
|
|
1726
|
+
} : item;
|
|
1727
|
+
});
|
|
1728
|
+
}, [
|
|
1729
|
+
rawInstalledItems,
|
|
1730
|
+
heldPackages,
|
|
1731
|
+
versions
|
|
1732
|
+
]);
|
|
1671
1733
|
/**
|
|
1672
1734
|
* Hub 自身更新状态:Hub 就是当前运行的应用(始终已安装,无需 installedName 命中)。
|
|
1673
1735
|
* 以 Worker 版本控制中心返回的「最新版本」为准,与当前运行的版本号比对——
|
|
@@ -1679,17 +1741,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1679
1741
|
* registry 真实发布时间下发(同源),据此判断最准。门槛命中要单列成 `pending` 而不是
|
|
1680
1742
|
* 落回「无更新」——回落会让弹窗在本机版本落后时谎称「已是最新」。
|
|
1681
1743
|
*/
|
|
1682
|
-
const hubCurrentVersion = "
|
|
1744
|
+
const hubCurrentVersion = "2.0.0";
|
|
1683
1745
|
const hubUpdateState = (() => {
|
|
1684
1746
|
if (!hubUpdateInfo) return "none";
|
|
1685
1747
|
if (hubUpdateInfo.version === hubCurrentVersion) return "latest";
|
|
1686
|
-
|
|
1687
|
-
if (publishedAt) {
|
|
1688
|
-
const publishedMs = Date.parse(publishedAt);
|
|
1689
|
-
if (!Number.isNaN(publishedMs)) {
|
|
1690
|
-
if (Date.now() - publishedMs < 882e5) return "pending";
|
|
1691
|
-
}
|
|
1692
|
-
}
|
|
1748
|
+
if (isReleaseTooFresh(hubUpdateInfo.publishedAt, Date.now())) return "pending";
|
|
1693
1749
|
return "available";
|
|
1694
1750
|
})();
|
|
1695
1751
|
const hubHasUpdate = hubUpdateState === "available";
|
|
@@ -1721,7 +1777,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1721
1777
|
sortDir,
|
|
1722
1778
|
installed
|
|
1723
1779
|
]);
|
|
1724
|
-
/**
|
|
1780
|
+
/** 分类 chip 上展示的各分类插件计数。 */
|
|
1725
1781
|
const categoryCounts = (0, react.useMemo)(() => {
|
|
1726
1782
|
const counts = {};
|
|
1727
1783
|
for (const p of plugins ?? []) if (p.category) counts[p.category] = (counts[p.category] ?? 0) + 1;
|
|
@@ -1743,6 +1799,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1743
1799
|
hasUpdate,
|
|
1744
1800
|
hubHasUpdate,
|
|
1745
1801
|
hubUpdateState,
|
|
1802
|
+
releaseAgeReady,
|
|
1746
1803
|
hubCurrentVersion,
|
|
1747
1804
|
hubUpdateInfo,
|
|
1748
1805
|
hubAboutInfo,
|
|
@@ -1871,7 +1928,20 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1871
1928
|
save(next);
|
|
1872
1929
|
return next;
|
|
1873
1930
|
}
|
|
1874
|
-
/**
|
|
1931
|
+
/** 动作词(英文):名词短语,标题与句子里都成立。 */
|
|
1932
|
+
function actionWordEn(action) {
|
|
1933
|
+
return action === "uninstall" ? "removal" : action === "update" ? "update" : "install";
|
|
1934
|
+
}
|
|
1935
|
+
/** 动作词(中文):安装 / 更新 / 卸载。 */
|
|
1936
|
+
function actionWordZh(action) {
|
|
1937
|
+
return action === "uninstall" ? "卸载" : action === "update" ? "更新" : "安装";
|
|
1938
|
+
}
|
|
1939
|
+
/** 记录的动作:老记录只有 kind,按 kind 兜底。 */
|
|
1940
|
+
function actionOfRecord(rec) {
|
|
1941
|
+
if (rec.action !== void 0) return rec.action;
|
|
1942
|
+
return rec.kind === "uninstall" ? "uninstall" : rec.kind === "update" ? "update" : "install";
|
|
1943
|
+
}
|
|
1944
|
+
/** 只匹配 pnpm 的错误码,不匹配泛泛出现的 checksum / integrity 字样。 */
|
|
1875
1945
|
function missingTarballIntegrity(message) {
|
|
1876
1946
|
return /\bERR_PNPM_MISSING_TARBALL_INTEGRITY\b/.test(message);
|
|
1877
1947
|
}
|
|
@@ -1884,9 +1954,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1884
1954
|
return `${new Date(published + 864e5).toISOString().slice(0, 16)}Z`;
|
|
1885
1955
|
}
|
|
1886
1956
|
/**
|
|
1887
|
-
*
|
|
1888
|
-
*
|
|
1889
|
-
*
|
|
1957
|
+
* 同一策略子类型也用于选择实时/已保存失败的提示文案:minimumReleaseAge 只有在能算出
|
|
1958
|
+
* 可重试时刻时才走专属文案(给出确切的「何时可再试」),算不出时退回通用文案,
|
|
1959
|
+
* 避免出现「预计可重试时间:」后接空值的残缺句子。
|
|
1890
1960
|
*/
|
|
1891
1961
|
function pnpmPolicyHintOf(message) {
|
|
1892
1962
|
if (missingTarballIntegrity(message)) return "failPnpmTarballIntegrityHint";
|
|
@@ -1917,7 +1987,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1917
1987
|
if (/os error 5\b|ERROR_ACCESS_DENIED|\bEPERM\b|\bEACCES\b|access is denied/i.test(message)) return "accessDenied";
|
|
1918
1988
|
if (/os error 112\b|os error 19\b|ERROR_DISK_FULL|ERROR_WRITE_PROTECT|\bENOSPC\b|\bEROFS\b|\bEMFILE\b|\bENFILE\b|no space left on device|read-only file system|too many open files/i.test(message)) return "fsUnavailable";
|
|
1919
1989
|
if (/ERR_PNPM_IGNORED_BUILDS|Ignored build scripts:|ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED/i.test(message)) return "pnpmIgnoredBuild";
|
|
1920
|
-
if (/\[network\]|ERR_PNPM_GIT_FETCH_FAILED|ETIMEDOUT|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|EPIPE|EHOSTUNREACH|ENETUNREACH|getaddrinfo|Could not connect|Could not resolve host|Network unreachable|Failed to connect|socket hang up|CERT_HAS_EXPIRED|SSL certificate problem|\bTLS\b|\bSSL\b|fetch failed|failed to fetch|\bGET https?:\/\/\S+\.tgz\s+error \(
|
|
1990
|
+
if (/\[network\]|ERR_PNPM_GIT_FETCH_FAILED|ETIMEDOUT|ECONNREFUSED|ECONNRESET|ENOTFOUND|EAI_AGAIN|EPIPE|EHOSTUNREACH|ENETUNREACH|UND_ERR_[A-Z0-9_]+|getaddrinfo|Could not connect|Could not resolve host|Network unreachable|Failed to connect|socket hang up|CERT_HAS_EXPIRED|SSL certificate problem|\bTLS\b|\bSSL\b|fetch failed|failed to fetch|\bGET https?:\/\/\S+\.tgz\s+error \([A-Za-z0-9_]+\)/i.test(message)) return "network";
|
|
1921
1991
|
if (/\[packaging\]|entry file missing/i.test(message)) return "pluginPrepare";
|
|
1922
1992
|
if (/\[registry-missing\]/i.test(message)) return "pluginMissingDep";
|
|
1923
1993
|
if (/ERR_PNPM_FETCH_404|404 Not Found|Not Found - 404/i.test(message)) return "pnpmMissingDep";
|
|
@@ -1928,6 +1998,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1928
1998
|
if (/^\[timed out\]$/m.test(message)) return "timeout";
|
|
1929
1999
|
if (/atomic-write: timed out waiting for the writer lock|timed out waiting for the writer lock/i.test(message)) return "profileLock";
|
|
1930
2000
|
if (/git-hosted plugins build on install via their prepare script|add the exact key pnpm printed above under allowBuilds/i.test(message)) return "pnpmIgnoredBuild";
|
|
2001
|
+
if (/\[host-spawn\]/i.test(message)) return "hostCliSpawn";
|
|
1931
2002
|
return "hub";
|
|
1932
2003
|
}
|
|
1933
2004
|
/** 从服务端 `[npm-too-low]` 标记行提取本机 npm 版本(如 `[npm-too-low] npm@11.3.0` → "11.3.0");
|
|
@@ -1986,8 +2057,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
1986
2057
|
return m ? m[0].replace(/^\[|\]$/g, "") : null;
|
|
1987
2058
|
}
|
|
1988
2059
|
/** 「包在 registry 不存在」失败的提示变体:服务端用官方源复核过(会注入 `[registry-mirror-lag]`)
|
|
1989
|
-
* 时,说明包在官方源上存在、是本机镜像源未同步 →
|
|
1990
|
-
*
|
|
2060
|
+
* 时,说明包在官方源上存在、是本机镜像源未同步 → 提示换源;否则按「profile 残留依赖」提示
|
|
2061
|
+
* (删掉 profile 里那条依赖即可)。 */
|
|
1991
2062
|
function registryMissingHintOf(message) {
|
|
1992
2063
|
return /\[registry-mirror-lag\]/i.test(message) ? "failRegistryMirrorLagHint" : "failPnpmMissingDepHint";
|
|
1993
2064
|
}
|
|
@@ -2003,7 +2074,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2003
2074
|
}
|
|
2004
2075
|
/**
|
|
2005
2076
|
* 从网络类失败消息里提取「具体连不上的地址」,供弹窗精准提示(你的网络无法访问什么)。
|
|
2006
|
-
* 优先取服务端 [network]
|
|
2077
|
+
* 优先取服务端 [network] 网络探测消息括号里的探测地址(中文「(…)」/ 英文「(…)」),
|
|
2007
2078
|
* 否则取消息里出现的第一个 URL(git fetch 的仓库地址、registry 域名等)。
|
|
2008
2079
|
* 提取不到返回 null —— 调用方据此跳过地址行。
|
|
2009
2080
|
*/
|
|
@@ -2062,18 +2133,18 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2062
2133
|
function pluginSiteUrl(repo) {
|
|
2063
2134
|
return siteUrl(`plugins/${repo}`);
|
|
2064
2135
|
}
|
|
2065
|
-
/**
|
|
2066
|
-
*
|
|
2067
|
-
|
|
2068
|
-
|
|
2136
|
+
/** 错误原因标题(对外英文):点明问题出在哪一侧,便于 issue 列表分流;
|
|
2137
|
+
* 动作级原因(未分类/超时…)带动作词,卸载失败不写成 install failed。 */
|
|
2138
|
+
function reasonTitleOf(kind, action) {
|
|
2139
|
+
const word = actionWordEn(action);
|
|
2069
2140
|
switch (kind) {
|
|
2070
|
-
case "npmTooOld": return
|
|
2141
|
+
case "npmTooOld": return `npm too old for this ${word}`;
|
|
2071
2142
|
case "dshMissing": return "dsh command not found on the user machine";
|
|
2072
2143
|
case "pnpmMissing": return "pnpm command not found on the user machine";
|
|
2073
2144
|
case "pnpmStore": return "pnpm store version mismatch on the user machine";
|
|
2074
|
-
case "pnpmWorkspace": return
|
|
2145
|
+
case "pnpmWorkspace": return `pnpm workspace-root check blocked the ${word} on the user machine`;
|
|
2075
2146
|
case "originRejected": return "request origin rejected by the local service on the user machine";
|
|
2076
|
-
case "pnpmPolicy": return
|
|
2147
|
+
case "pnpmPolicy": return `pnpm supply-chain policy blocked the ${word} on the user machine`;
|
|
2077
2148
|
case "pnpmUnusedPatch": return "stale pnpm patch entry on the user machine";
|
|
2078
2149
|
case "pnpmMissingDep": return "dependency not found on the npm registry on the user machine";
|
|
2079
2150
|
case "registryVersionStale": return "requested version not available on the npm registry in use on the user machine";
|
|
@@ -2084,12 +2155,13 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2084
2155
|
case "pnpmIgnoredBuild": return "build scripts blocked by pnpm allowlist";
|
|
2085
2156
|
case "pluginPrepare": return "plugin distribution incomplete";
|
|
2086
2157
|
case "network": return "network failure on the user side";
|
|
2087
|
-
case "
|
|
2088
|
-
case "
|
|
2158
|
+
case "hostCliSpawn": return "the DSH host could not be launched on the user machine";
|
|
2159
|
+
case "hubState": return `stale ${word} state in the plugin hub`;
|
|
2160
|
+
case "timeout": return `${word} timed out`;
|
|
2089
2161
|
case "profileLock": return "DSH profile is locked by another process";
|
|
2090
2162
|
case "pluginMissingDep": return "a dependency of the plugin is not published on npm";
|
|
2091
|
-
case "hub": return
|
|
2092
|
-
default: return
|
|
2163
|
+
case "hub": return `${word} failed (cause unclassified)`;
|
|
2164
|
+
default: return `plugin ${word} failed`;
|
|
2093
2165
|
}
|
|
2094
2166
|
}
|
|
2095
2167
|
/**
|
|
@@ -2098,14 +2170,15 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2098
2170
|
* 错误核心摘要(完整日志太长,塞进 URL 会被 GitHub 以「request URL too long」拒绝,
|
|
2099
2171
|
* 故只收集重点)。错误弹窗、失败记录共用此逻辑。
|
|
2100
2172
|
* env 取不到时为 null,链接照常生成、只是少环境段。
|
|
2101
|
-
* attempts
|
|
2173
|
+
* attempts(尝试过的安装方式,实际执行过的命令):作者看到我们试过的命令,
|
|
2102
2174
|
* 组织 scope 与 GitHub 用户名不一致时也能直接指认正确的 npm 包名。
|
|
2103
2175
|
*/
|
|
2104
|
-
function pluginIssueUrl(repo, message, env, command, attempts) {
|
|
2176
|
+
function pluginIssueUrl(repo, message, env, command, attempts, action = "install") {
|
|
2105
2177
|
const kind = classifyFailure(message);
|
|
2106
2178
|
const executed = executedCommandOf(command, attempts);
|
|
2107
|
-
const
|
|
2108
|
-
const
|
|
2179
|
+
const zhWord = actionWordZh(action);
|
|
2180
|
+
const title = `[dsh-plugin.org | dsh-plugin-hub] ${reasonTitleOf(kind, action)}: ${repo}`;
|
|
2181
|
+
const reason = /\[packaging\]/i.test(message) ? "plugin distribution is incomplete — a file the package needs (its entry from main / exports, an entry a bundled patch mounts, or the patch declared by dsh.bundle.patch) is missing from the published npm package; please publish a complete package" : /\[registry-missing\]/i.test(message) ? "a dependency declared by the plugin is not published on the public npm registry (missing, removed, or never released); please publish or correct that dependency, or ship it with the plugin" : kind === "network" ? "network connectivity issue on the user side (DNS, proxy, firewall, or a blocked connection)" : kind === "pluginPrepare" ? "plugin prepare/build script failed during install (packaging/distribution issue)" : kind === "pnpmIgnoredBuild" ? "plugin depends on a native module whose build script pnpm blocks by default (use a prebuilt variant)" : kind === "originRejected" ? "the request never reached the install flow — the local service rejected its origin (local environment issue)" : kind === "pnpmPolicy" ? pnpmPolicyHintOf(message) === "failPnpmTarballIntegrityHint" ? "pnpm rejected a lockfile entry without tarball integrity; inspect and back up the profile lockfile before resolving it again, keeping integrity checks enabled" : "the pnpm supply-chain policy on the user machine blocked the install (minimum release age for freshly published packages / untrusted origin)" : kind === "pnpmUnusedPatch" ? "the profile keeps a pnpm patch entry for an older dsh-plugin version, so pnpm aborted the install (local config issue)" : kind === "fileLocked" ? "a file in the profile is locked by another process on the user machine (local environment issue)" : kind === "accessDenied" ? "the system denied write access to a file in the profile on the user machine (local environment issue)" : kind === "fsUnavailable" ? "the local file system could not accept the write — no space left, read-only volume, or too many open file handles on the user machine (local environment issue)" : "plugin-side install failure";
|
|
2109
2182
|
const code = coreErrorCode(message);
|
|
2110
2183
|
const build = (coreChars) => {
|
|
2111
2184
|
const body = [
|
|
@@ -2113,19 +2186,19 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2113
2186
|
`- Cause: ${reason}`,
|
|
2114
2187
|
...code ? [`- Key error: \`${code}\``] : [],
|
|
2115
2188
|
"",
|
|
2116
|
-
`## [DSH Plugin 插件市场](${SITE_URL}) ·
|
|
2117
|
-
`本错误信息由 [dsh-plugin-hub](${GITHUB_URL})
|
|
2118
|
-
`-
|
|
2119
|
-
`-
|
|
2189
|
+
`## [DSH Plugin 插件市场](${SITE_URL}) · ${zhWord} Plugin 失败错误信息`,
|
|
2190
|
+
`本错误信息由 [dsh-plugin-hub](${GITHUB_URL}) 插件市场的安装程序自动生成,随本次${zhWord}失败一并提交。`,
|
|
2191
|
+
`- 实际执行的${zhWord}命令:${executed ? `\`${executed}\`` : "unknown (no executed command recorded)"}`,
|
|
2192
|
+
`- 执行结果:${zhWord}失败,未能${zhWord}该插件。`,
|
|
2120
2193
|
...attempts && attempts.length > 0 ? [
|
|
2121
2194
|
"",
|
|
2122
|
-
"## Attempted
|
|
2195
|
+
"## Attempted channels(已尝试的方式)",
|
|
2123
2196
|
...attempts.map((a) => `- ${a}`)
|
|
2124
2197
|
] : [],
|
|
2125
2198
|
.../\[packaging\]/i.test(message) ? [
|
|
2126
2199
|
"",
|
|
2127
2200
|
"## 安装方式说明",
|
|
2128
|
-
"
|
|
2201
|
+
"当前插件的 npm 分发物缺少它需要的文件(`main` / `exports` 声明的入口、补丁按本包名 mount 的入口,或 `dsh.bundle.patch` 声明的补丁)。请发布包含完整构建产物的 npm 包后重试。"
|
|
2129
2202
|
] : [],
|
|
2130
2203
|
"",
|
|
2131
2204
|
"## Environment",
|
|
@@ -2169,27 +2242,28 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2169
2242
|
}
|
|
2170
2243
|
return url;
|
|
2171
2244
|
}
|
|
2172
|
-
function hubIssueUrl(pluginRepo, message, env, command, attempts, variant = "triage") {
|
|
2245
|
+
function hubIssueUrl(pluginRepo, message, env, command, attempts, variant = "triage", action = "install") {
|
|
2173
2246
|
const kind = classifyFailure(message);
|
|
2174
2247
|
const executed = executedCommandOf(command, attempts);
|
|
2248
|
+
const zhWord = actionWordZh(action);
|
|
2175
2249
|
const repo = pluginRepo && pluginRepo.trim() !== "" ? pluginRepo.trim() : "unknown";
|
|
2176
|
-
const title = variant === "misjudge" ? `[dsh-plugin-hub] possible misjudgment: ${repo}` : `[dsh-plugin-hub] ${reasonTitleOf(kind)}: ${repo}`;
|
|
2250
|
+
const title = variant === "misjudge" ? `[dsh-plugin-hub] possible misjudgment: ${repo}` : `[dsh-plugin-hub] ${reasonTitleOf(kind, action)}: ${repo}`;
|
|
2177
2251
|
const code = coreErrorCode(message);
|
|
2178
2252
|
const build = (coreChars) => {
|
|
2179
2253
|
const body = [
|
|
2180
2254
|
"## Summary",
|
|
2181
|
-
`- Auto-classified cause: ${reasonTitleOf(kind)}`,
|
|
2255
|
+
`- Auto-classified cause: ${reasonTitleOf(kind, action)}`,
|
|
2182
2256
|
`- Target plugin: \`${repo}\``,
|
|
2183
2257
|
...code ? [`- Key error: \`${code}\``] : [],
|
|
2184
|
-
...variant === "misjudge" ? ["- Filed from:
|
|
2258
|
+
...variant === "misjudge" ? ["- Filed from: a branch that normally routes to the plugin repo — filed here because that verdict may be our own misjudgment.", "- Source of that verdict: produced by dsh-plugin-hub's own check or its auto-allow retry, not by plain pnpm output."] : ["- Why filed here: the installer only routes a failure to the plugin repo when the cause is demonstrably the plugin's own build/distribution (pluginPrepare, or build scripts pnpm blocks that even an auto-allow retry cannot get past). This failure does not match that, so it is routed here for triage."],
|
|
2185
2259
|
"",
|
|
2186
|
-
`## [DSH Plugin 插件市场](${SITE_URL}) ·
|
|
2187
|
-
`本错误信息由 [dsh-plugin-hub](${GITHUB_URL})
|
|
2188
|
-
`-
|
|
2189
|
-
`-
|
|
2260
|
+
`## [DSH Plugin 插件市场](${SITE_URL}) · ${zhWord} Plugin 失败错误信息`,
|
|
2261
|
+
`本错误信息由 [dsh-plugin-hub](${GITHUB_URL}) 插件市场的安装程序自动生成,随本次${zhWord}失败一并提交。`,
|
|
2262
|
+
`- 实际执行的${zhWord}命令:${executed ? `\`${executed}\`` : "unknown (no executed command recorded)"}`,
|
|
2263
|
+
`- 执行结果:${zhWord}失败,未能${zhWord}该插件。`,
|
|
2190
2264
|
...attempts && attempts.length > 0 ? [
|
|
2191
2265
|
"",
|
|
2192
|
-
"## Attempted
|
|
2266
|
+
"## Attempted channels(已尝试的方式)",
|
|
2193
2267
|
...attempts.map((a) => `- ${a}`)
|
|
2194
2268
|
] : [],
|
|
2195
2269
|
"",
|
|
@@ -2241,11 +2315,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2241
2315
|
* Website: https://dsh-plugin.org
|
|
2242
2316
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
2243
2317
|
*
|
|
2244
|
-
*
|
|
2245
|
-
*
|
|
2246
|
-
*
|
|
2247
|
-
* together instead of drifting apart. Exposes the localized dictionary lookup
|
|
2248
|
-
* `t()` plus the zh/en language flag and the /zh/ URL path prefix.
|
|
2318
|
+
* 板块的语言状态:Hub 与宿主(系统)locale 共用 —— 头部语言开关通过 setLocale 写入
|
|
2319
|
+
* 宿主语言偏好,让宿主界面(左侧菜单、设置弹窗)与 Hub 面板一起切换、不会各说各话。
|
|
2320
|
+
* 对外暴露本地化字典查询 `t()`、zh/en 语言标记与 /zh/ URL 路径前缀。
|
|
2249
2321
|
*/
|
|
2250
2322
|
function useLanguage(locale) {
|
|
2251
2323
|
const [, setRev] = (0, react.useState)(0);
|
|
@@ -2273,19 +2345,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2273
2345
|
* Website: https://dsh-plugin.org
|
|
2274
2346
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
2275
2347
|
*
|
|
2276
|
-
*
|
|
2277
|
-
*
|
|
2278
|
-
*
|
|
2279
|
-
*
|
|
2280
|
-
* the defaults and keeps working (settings simply do not persist).
|
|
2348
|
+
* 插件中心设置状态:从宿主本地 /settings 路由加载一次(持久化在
|
|
2349
|
+
* ~/.dsh/profiles/<profile>/hub-settings.json),并按乐观方式更新。
|
|
2350
|
+
* 每次改动立即 POST 补丁,切换过的开关刷新后仍在;宿主未挂服务端路由时退回默认值
|
|
2351
|
+
* 继续可用(设置不持久化而已)。
|
|
2281
2352
|
*/
|
|
2282
2353
|
const DEFAULT_SETTINGS = {
|
|
2283
2354
|
checkUpdatesOnStart: true,
|
|
2284
2355
|
proxy: "",
|
|
2285
2356
|
npmRegistry: "",
|
|
2286
2357
|
enableNpmInstall: true,
|
|
2287
|
-
enableGitInstall: true,
|
|
2288
|
-
enableDshInstall: true,
|
|
2289
2358
|
logPath: ""
|
|
2290
2359
|
};
|
|
2291
2360
|
async function loadRemote() {
|
|
@@ -2349,20 +2418,17 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2349
2418
|
* Website: https://dsh-plugin.org
|
|
2350
2419
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
2351
2420
|
*
|
|
2352
|
-
*
|
|
2421
|
+
* 插件中心的后台安装/卸载任务队列。
|
|
2353
2422
|
*
|
|
2354
|
-
*
|
|
2355
|
-
*
|
|
2356
|
-
* uninstall, cancel) plus the modal task lookups used by the dialogs.
|
|
2423
|
+
* 通过轮询 /active 镜像服务端 FIFO 活动队列,对消失的任务用 /status 收尾,并暴露
|
|
2424
|
+
* 队列动作(安装、卸载、取消)以及弹窗用的任务查找。
|
|
2357
2425
|
*/
|
|
2358
|
-
/** 安装/卸载请求超时(ms
|
|
2359
|
-
*
|
|
2426
|
+
/** 安装/卸载请求超时(ms):服务端入队前要做目录包校验与网络探测(各自有超时,合计可达十几秒),
|
|
2427
|
+
* 给足余量;超时主动中止,避免服务端网络挂起时前端永久卡「安装中 0%」。 */
|
|
2360
2428
|
const REQUEST_TIMEOUT_MS = 6e4;
|
|
2361
|
-
/** 入口渠道的 i18n key:NPM 包 / GitHub 源码 / DSH 命令。 */
|
|
2362
|
-
const channelKeyOf = (channel) => channel === "git" ? "installChannelGit" : channel === "dsh" ? "installChannelDsh" : "installChannelNpm";
|
|
2363
2429
|
/** 失败消息的入口溯源前缀:自定义安装(带渠道)在错误正文顶部精准指出从哪张卡片发起;
|
|
2364
2430
|
* 目录插件安装(无渠道)返回 null,错误正文保持原样。 */
|
|
2365
|
-
const entryLineOf = (t, channel) => channel ? t("installEntryLine", { c: t(
|
|
2431
|
+
const entryLineOf = (t, channel) => channel ? t("installEntryLine", { c: t("installChannelNpm") }) : null;
|
|
2366
2432
|
function useTaskQueue(opts) {
|
|
2367
2433
|
const { t, langKey, refreshInstalled, onInstallDone, onUninstallDone, onError, installPlugin, installCustomTarget, installGlobalTarget, uninstallPlugin, uninstallName, installedName, resolvePending } = opts;
|
|
2368
2434
|
const [queue, setQueue] = (0, react.useState)([]);
|
|
@@ -2579,7 +2645,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2579
2645
|
lines: Array.isArray(a.lines) ? a.lines : prevTask?.lines ?? [],
|
|
2580
2646
|
attempts: Array.isArray(a.attempts) ? a.attempts : prevTask?.attempts ?? [],
|
|
2581
2647
|
needsRestart: typeof a.needsRestart === "boolean" ? a.needsRestart : prevTask?.needsRestart ?? true,
|
|
2582
|
-
channel: a.installChannel === "npm"
|
|
2648
|
+
channel: a.installChannel === "npm" ? "npm" : prevTask?.channel
|
|
2583
2649
|
});
|
|
2584
2650
|
}
|
|
2585
2651
|
const keepOpt = prev.filter((q) => q.optimistic && !next.some((x) => x.id === q.id));
|
|
@@ -2625,7 +2691,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2625
2691
|
lines: Array.isArray(a.lines) ? a.lines : [],
|
|
2626
2692
|
attempts: Array.isArray(a.attempts) ? a.attempts : [],
|
|
2627
2693
|
needsRestart: typeof a.needsRestart === "boolean" ? a.needsRestart : true,
|
|
2628
|
-
channel: a.installChannel === "npm"
|
|
2694
|
+
channel: a.installChannel === "npm" ? "npm" : void 0
|
|
2629
2695
|
};
|
|
2630
2696
|
});
|
|
2631
2697
|
if (items.length > 0 || pendingRef.current.length > 0) {
|
|
@@ -2642,7 +2708,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2642
2708
|
/** 弹窗动作:直接安装。请求宿主本地路由,任务进入服务端队列(FIFO),弹窗内实时显示进度。 */
|
|
2643
2709
|
/** 安装入队核心:目录插件(catalog,后端走目录白名单)与命令行安装(custom,
|
|
2644
2710
|
* 受安全开关控制)共用。队列条目一律用仓库名(repo)展示/防重,只有发给后端的
|
|
2645
|
-
* 实际安装目标(target
|
|
2711
|
+
* 实际安装目标(target)为 npm 包名。 */
|
|
2646
2712
|
const submitInstall = async (input) => {
|
|
2647
2713
|
if (queueRef.current.some((q) => q.kind === "install" && q.target === input.repo)) return;
|
|
2648
2714
|
if (submittingRef.current.has(input.repo)) return;
|
|
@@ -2718,11 +2784,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2718
2784
|
setSubmitting(false);
|
|
2719
2785
|
}
|
|
2720
2786
|
};
|
|
2721
|
-
/**
|
|
2787
|
+
/** 目录插件安装:安装目标取目录数据的 npm 包名,走 catalog 白名单。 */
|
|
2722
2788
|
const installNow = async (p, opts) => {
|
|
2723
2789
|
const repo = p.source?.repo ?? "";
|
|
2724
2790
|
if (!repo) return;
|
|
2725
|
-
const
|
|
2791
|
+
const target = installTargetOf(p);
|
|
2726
2792
|
if (!target) return;
|
|
2727
2793
|
await submitInstall({
|
|
2728
2794
|
target,
|
|
@@ -2735,12 +2801,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2735
2801
|
update: opts?.update
|
|
2736
2802
|
});
|
|
2737
2803
|
};
|
|
2738
|
-
/** 命令行安装:用户手输 npm
|
|
2804
|
+
/** 命令行安装:用户手输 npm 包名,走 custom 源(受安全开关控制)。
|
|
2739
2805
|
* update=true 时对已安装目标放行覆盖重装(与目录插件「更新」同一语义)。
|
|
2740
|
-
* channel=入口渠道(NPM
|
|
2741
|
-
*
|
|
2742
|
-
*
|
|
2743
|
-
* 弹窗目标匹配同口径,npm 包名透传不受影响。 */
|
|
2806
|
+
* channel=入口渠道(NPM 包卡片):上报服务端落日志,失败弹窗/通知据此精准溯源。
|
|
2807
|
+
* 队列展示/防重一律用归一化身份:与服务端 /active 合并、弹窗目标匹配同口径,
|
|
2808
|
+
* npm 包名透传不受影响。 */
|
|
2744
2809
|
const installCustom = async (raw, opts) => {
|
|
2745
2810
|
const target = raw.trim();
|
|
2746
2811
|
if (!target) return;
|
|
@@ -2873,8 +2938,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
2873
2938
|
* Website: https://dsh-plugin.org
|
|
2874
2939
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
2875
2940
|
*
|
|
2876
|
-
*
|
|
2877
|
-
* they adapt to themes and disabled states automatically.
|
|
2941
|
+
* 客户端各处使用的内联 SVG 图标。图标继承 currentColor,自动适配主题与禁用态。
|
|
2878
2942
|
*/
|
|
2879
2943
|
/** 弹窗右上角关闭按钮图标:内联 SVG 十字(stroke 继承 currentColor),随按钮禁用态一起变淡。 */
|
|
2880
2944
|
function CloseIcon() {
|
|
@@ -3362,10 +3426,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3362
3426
|
* Website: https://dsh-plugin.org
|
|
3363
3427
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
3364
3428
|
*
|
|
3365
|
-
*
|
|
3366
|
-
*
|
|
3367
|
-
*
|
|
3368
|
-
* empty for most of the run; failures surface their full output in ErrorModal.
|
|
3429
|
+
* 安装与卸载弹窗共用的内联进度块:真实百分比进度条(服务端估算、客户端轮询)。
|
|
3430
|
+
* 不做实时终端窗口 —— pnpm 在 git clone/构建期间几乎无输出,日志面板大部分时间是空的;
|
|
3431
|
+
* 失败时完整输出在 ErrorModal 里展示。
|
|
3369
3432
|
*/
|
|
3370
3433
|
function ProgressView({ task }) {
|
|
3371
3434
|
return (0, react.createElement)("div", { className: Modal_module_css_default.progress }, (0, react.createElement)("div", { className: Modal_module_css_default.progressHead }, (0, react.createElement)("span", { className: Modal_module_css_default.progressText }, `${Math.round(task.progress)}%`)), (0, react.createElement)("div", { className: Modal_module_css_default.progressTrack }, (0, react.createElement)("div", {
|
|
@@ -3380,11 +3443,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3380
3443
|
* Website: https://dsh-plugin.org
|
|
3381
3444
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
3382
3445
|
*
|
|
3383
|
-
*
|
|
3384
|
-
*
|
|
3385
|
-
*
|
|
3386
|
-
* the common case (the page refreshes on close so the change applies), or a
|
|
3387
|
-
* single "restart now" for the rare changes a refresh cannot pick up.
|
|
3446
|
+
* 插件中心的弹窗层:安装确认弹窗、卸载弹窗与全局 Toast。两个弹窗在变更执行期间
|
|
3447
|
+
* 自我锁定,随后切到只有一个动作的结果视图 —— 常见情况给「完成」(关闭时刷新页面即生效),
|
|
3448
|
+
* 刷新解决不了的少数情况才给单个「立即重启」。
|
|
3388
3449
|
*/
|
|
3389
3450
|
/** 完成结果视图:绿色对勾 + 标题/描述;
|
|
3390
3451
|
* 终态只有两种:
|
|
@@ -3524,10 +3585,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3524
3585
|
onClick: onConfirm
|
|
3525
3586
|
}, busy ? task && task.status === "pending" ? t("queuedUninstallTitle") : t("uninstalling") : t("uninstallConfirm"))))));
|
|
3526
3587
|
}
|
|
3527
|
-
/**
|
|
3528
|
-
|
|
3529
|
-
function ErrorModal({ message, repo, kind, command, attempts, t, env, onCopy, onClose, onRunDiagnostics }) {
|
|
3588
|
+
/** 安装/更新/卸载失败弹窗:标题、徽标、提示文案与 issue 正文都按传入的动作取词。 */
|
|
3589
|
+
function ErrorModal({ message, repo, action, command, attempts, t, env, onCopy, onClose, onRunDiagnostics }) {
|
|
3530
3590
|
const failureKind = classifyFailure(message);
|
|
3591
|
+
const actionWord = t(action === "uninstall" ? "actionUninstall" : action === "update" ? "actionUpdate" : "actionInstall");
|
|
3531
3592
|
const npmVersion = npmTooLowVersion(message);
|
|
3532
3593
|
const copyText = [
|
|
3533
3594
|
...command ? [command] : [],
|
|
@@ -3543,11 +3604,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3543
3604
|
className: Modal_module_css_default.errorModal,
|
|
3544
3605
|
role: "dialog",
|
|
3545
3606
|
"aria-modal": "true"
|
|
3546
|
-
}, (0, react.createElement)("div", { className: Modal_module_css_default.modalHead }, (0, react.createElement)("div", { className: Modal_module_css_default.errorTitle },
|
|
3607
|
+
}, (0, react.createElement)("div", { className: Modal_module_css_default.modalHead }, (0, react.createElement)("div", { className: Modal_module_css_default.errorTitle }, t(action === "uninstall" ? "errorTitleUninstall" : action === "update" ? "errorTitleUpdate" : "errorTitleInstall")), (0, react.createElement)("button", {
|
|
3547
3608
|
className: Modal_module_css_default.modalClose,
|
|
3548
3609
|
"aria-label": t("errorClose"),
|
|
3549
3610
|
onClick: onClose
|
|
3550
|
-
}, (0, react.createElement)(CloseIcon))), (0, react.createElement)("div", { className: Modal_module_css_default.modalBody }, (0, react.createElement)("div", { className: Modal_module_css_default.failRow }, (0, react.createElement)("div", { className: Modal_module_css_default.failHead }, (0, react.createElement)("span", { className:
|
|
3611
|
+
}, (0, react.createElement)(CloseIcon))), (0, react.createElement)("div", { className: Modal_module_css_default.modalBody }, (0, react.createElement)("div", { className: Modal_module_css_default.failRow }, (0, react.createElement)("div", { className: Modal_module_css_default.failHead }, (0, react.createElement)("span", { className: action === "install" ? Modal_module_css_default.failKindInstall : Modal_module_css_default.failKindUninstall }, actionWord), repo ? (0, react.createElement)("a", {
|
|
3551
3612
|
className: Modal_module_css_default.failRepo,
|
|
3552
3613
|
href: pluginSiteUrl(repo),
|
|
3553
3614
|
target: "_blank",
|
|
@@ -3567,7 +3628,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3567
3628
|
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failPluginMissingDepHint")),
|
|
3568
3629
|
repo ? (0, react.createElement)("a", {
|
|
3569
3630
|
className: Modal_module_css_default.failBigIssue,
|
|
3570
|
-
href: pluginIssueUrl(repo, message, env, command, attempts),
|
|
3631
|
+
href: pluginIssueUrl(repo, message, env, command, attempts, action),
|
|
3571
3632
|
target: "_blank",
|
|
3572
3633
|
rel: "noopener noreferrer",
|
|
3573
3634
|
title: t("failIssueHint")
|
|
@@ -3581,7 +3642,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3581
3642
|
const host = registryHostOf(message);
|
|
3582
3643
|
return host ? (0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failNetworkRegistryHint", { host })) : null;
|
|
3583
3644
|
})(),
|
|
3584
|
-
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failNetworkHint")),
|
|
3645
|
+
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failNetworkHint", { action: actionWord })),
|
|
3585
3646
|
onRunDiagnostics ? (0, react.createElement)("button", {
|
|
3586
3647
|
className: Modal_module_css_default.failDiagBtn,
|
|
3587
3648
|
onClick: onRunDiagnostics
|
|
@@ -3590,21 +3651,37 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3590
3651
|
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, /\[packaging\]/i.test(message) ? t("failPackagingHint") : t("failPrepareHint")),
|
|
3591
3652
|
repo ? (0, react.createElement)("a", {
|
|
3592
3653
|
className: Modal_module_css_default.failBigIssue,
|
|
3593
|
-
href: pluginIssueUrl(repo, message, env, command, attempts),
|
|
3654
|
+
href: pluginIssueUrl(repo, message, env, command, attempts, action),
|
|
3655
|
+
target: "_blank",
|
|
3656
|
+
rel: "noopener noreferrer",
|
|
3657
|
+
title: t("failIssueHint")
|
|
3658
|
+
}, t("failIssueBig")) : null,
|
|
3659
|
+
repo ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failMisjudgeHint")), (0, react.createElement)("a", {
|
|
3660
|
+
className: Modal_module_css_default.failMisjudgeLink,
|
|
3661
|
+
href: hubIssueUrl(repo, message, env, command, attempts, "misjudge", action),
|
|
3662
|
+
target: "_blank",
|
|
3663
|
+
rel: "noopener noreferrer",
|
|
3664
|
+
title: t("failHubIssueHint")
|
|
3665
|
+
}, t("failMisjudgeLink"))]) : null
|
|
3666
|
+
]) : failureKind === "hubState" ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failHubStateHint", { action: actionWord }))]) : failureKind === "timeout" ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failTimeoutHint"))]) : failureKind === "profileLock" ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failProfileLockHint", { action: actionWord }))]) : failureKind === "hostCliSpawn" ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failHostCliSpawnHint"))]) : failureKind === "pnpmIgnoredBuild" ? (0, react.createElement)("div", null, [
|
|
3667
|
+
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failIgnoredBuild")),
|
|
3668
|
+
repo ? (0, react.createElement)("a", {
|
|
3669
|
+
className: Modal_module_css_default.failBigIssue,
|
|
3670
|
+
href: pluginIssueUrl(repo, message, env, command, attempts, action),
|
|
3594
3671
|
target: "_blank",
|
|
3595
3672
|
rel: "noopener noreferrer",
|
|
3596
3673
|
title: t("failIssueHint")
|
|
3597
3674
|
}, t("failIssueBig")) : null,
|
|
3598
3675
|
repo ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failMisjudgeHint")), (0, react.createElement)("a", {
|
|
3599
3676
|
className: Modal_module_css_default.failMisjudgeLink,
|
|
3600
|
-
href: hubIssueUrl(repo, message, env, command, attempts, "misjudge"),
|
|
3677
|
+
href: hubIssueUrl(repo, message, env, command, attempts, "misjudge", action),
|
|
3601
3678
|
target: "_blank",
|
|
3602
3679
|
rel: "noopener noreferrer",
|
|
3603
3680
|
title: t("failHubIssueHint")
|
|
3604
3681
|
}, t("failMisjudgeLink"))]) : null
|
|
3605
|
-
]) :
|
|
3682
|
+
]) : (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failUnclassifiedHint", { action: actionWord })), (0, react.createElement)("a", {
|
|
3606
3683
|
className: Modal_module_css_default.failBigIssue,
|
|
3607
|
-
href: hubIssueUrl(repo, message, env, command, attempts),
|
|
3684
|
+
href: hubIssueUrl(repo, message, env, command, attempts, "triage", action),
|
|
3608
3685
|
target: "_blank",
|
|
3609
3686
|
rel: "noopener noreferrer",
|
|
3610
3687
|
title: t("failHubIssueHint")
|
|
@@ -3874,12 +3951,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3874
3951
|
* Website: https://dsh-plugin.org
|
|
3875
3952
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
3876
3953
|
*
|
|
3877
|
-
*
|
|
3878
|
-
*
|
|
3879
|
-
*
|
|
3880
|
-
* latest version) merged with the host runtime facts (install path, installed
|
|
3881
|
-
* version, install time, last update). Update / uninstall actions are
|
|
3882
|
-
* offered from here too, mirroring the row actions.
|
|
3954
|
+
* 已安装插件详情弹窗:从「已安装」视图打开(行点击或详情按钮),展示我们对某个已安装项
|
|
3955
|
+
* 掌握的全部信息 —— 目录元数据(分类、收录入口、Star/Fork、最新版本)与宿主运行时事实
|
|
3956
|
+
* (安装路径、已装版本、安装时间、最后更新)合并呈现。此处的更新/卸载动作与行内动作一致。
|
|
3883
3957
|
*/
|
|
3884
3958
|
/** ISO 安装时间 → 本地可读;非法值返回 null(行内不显示)。 */
|
|
3885
3959
|
function fmtDate(iso, lang) {
|
|
@@ -3956,13 +4030,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
3956
4030
|
* Website: https://dsh-plugin.org
|
|
3957
4031
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
3958
4032
|
*
|
|
3959
|
-
*
|
|
3960
|
-
*
|
|
3961
|
-
* in-button double-click.
|
|
4033
|
+
* 通用确认弹窗 —— 应用里所有「确定吗?」问题的唯一入口。规则:任何询问都必须是
|
|
4034
|
+
* 弹窗,绝不用按钮内双击。
|
|
3962
4035
|
*
|
|
3963
|
-
*
|
|
3964
|
-
*
|
|
3965
|
-
* action glyph for destructive ones (clear / delete / uninstall / reset).
|
|
4036
|
+
* 中间的图标一眼说明类型:常规确认(安装/更新/重启/忽略)用蓝色问号,
|
|
4037
|
+
* 危险操作(清空/删除/卸载/重置)用红色动作图形。
|
|
3966
4038
|
*/
|
|
3967
4039
|
/** 通用确认弹窗:标题 + 类型图标 + 描述 + 取消/确认按钮。
|
|
3968
4040
|
* type='question' → 蓝问号 + 品牌蓝确认按钮;危险类型 → 红图形 + 红色确认按钮。 */
|
|
@@ -4001,15 +4073,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4001
4073
|
* Website: https://dsh-plugin.org
|
|
4002
4074
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4003
4075
|
*
|
|
4004
|
-
*
|
|
4005
|
-
* remove task — successes and failures alike.
|
|
4076
|
+
* 通知中心弹窗:每个已结算的安装/卸载任务(成功与失败)的持久化清单。
|
|
4006
4077
|
*
|
|
4007
|
-
*
|
|
4008
|
-
*
|
|
4009
|
-
*
|
|
4010
|
-
* success, red cross for failure) with white glyph and message text;
|
|
4011
|
-
* failures keep their copy / fix / file-an-issue actions. Opened from the
|
|
4012
|
-
* header entry button (after the Settings tab).
|
|
4078
|
+
* 记录在结算时写入 localStorage(见 logic/failures.ts),即使弹窗被关闭或用户离开,
|
|
4079
|
+
* 结果也不会丢失。每条带圆形状态徽标(成功绿勾、失败红叉,白色图形)与消息文本;
|
|
4080
|
+
* 失败项保留复制/修复/提 Issue 动作。由头部入口按钮(「设置」tab 之后)打开。
|
|
4013
4081
|
*/
|
|
4014
4082
|
/** 记录时间完整展示:YYYY-MM-DD HH:mm:ss(每条通知都带精确到秒的时间戳)。 */
|
|
4015
4083
|
function fmtTime(at) {
|
|
@@ -4140,6 +4208,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4140
4208
|
}
|
|
4141
4209
|
}, (0, react.createElement)(CloseIcon))), !r.ok && (() => {
|
|
4142
4210
|
const kind = classifyFailure(r.message);
|
|
4211
|
+
const action = actionOfRecord(r);
|
|
4212
|
+
const actionWord = t(action === "uninstall" ? "actionUninstall" : action === "update" ? "actionUpdate" : "actionInstall");
|
|
4143
4213
|
if (kind === "npmTooOld") {
|
|
4144
4214
|
const v = npmTooLowVersion(r.message);
|
|
4145
4215
|
return (0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t(v ? "failNpmTooLowV" : "failNpmTooLow", v ? { v } : void 0));
|
|
@@ -4163,7 +4233,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4163
4233
|
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failPluginMissingDepHint")),
|
|
4164
4234
|
r.repo && shownRepo ? (0, react.createElement)("a", {
|
|
4165
4235
|
className: Modal_module_css_default.failBigIssue,
|
|
4166
|
-
href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts),
|
|
4236
|
+
href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts, action),
|
|
4167
4237
|
target: "_blank",
|
|
4168
4238
|
rel: "noopener noreferrer",
|
|
4169
4239
|
title: t("failIssueHint")
|
|
@@ -4185,7 +4255,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4185
4255
|
const host = registryHostOf(r.message);
|
|
4186
4256
|
return host ? (0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failNetworkRegistryHint", { host })) : null;
|
|
4187
4257
|
})(),
|
|
4188
|
-
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failNetworkHint")),
|
|
4258
|
+
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failNetworkHint", { action: actionWord })),
|
|
4189
4259
|
onRunDiagnostics ? (0, react.createElement)("button", {
|
|
4190
4260
|
className: Modal_module_css_default.failDiagBtn,
|
|
4191
4261
|
onClick: onRunDiagnostics
|
|
@@ -4195,25 +4265,43 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4195
4265
|
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, /\[packaging\]/i.test(r.message) ? t("failPackagingHint") : t("failPrepareHint")),
|
|
4196
4266
|
r.repo && shownRepo ? (0, react.createElement)("a", {
|
|
4197
4267
|
className: Modal_module_css_default.failBigIssue,
|
|
4198
|
-
href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts),
|
|
4268
|
+
href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts, action),
|
|
4199
4269
|
target: "_blank",
|
|
4200
4270
|
rel: "noopener noreferrer",
|
|
4201
4271
|
title: t("failIssueHint")
|
|
4202
4272
|
}, t("failIssueBig")) : null,
|
|
4203
4273
|
r.repo && shownRepo ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failMisjudgeHint")), (0, react.createElement)("a", {
|
|
4204
4274
|
className: Modal_module_css_default.failMisjudgeLink,
|
|
4205
|
-
href: hubIssueUrl(shownRepo, r.message, env, r.command, r.attempts, "misjudge"),
|
|
4275
|
+
href: hubIssueUrl(shownRepo, r.message, env, r.command, r.attempts, "misjudge", action),
|
|
4206
4276
|
target: "_blank",
|
|
4207
4277
|
rel: "noopener noreferrer",
|
|
4208
4278
|
title: t("failHubIssueHint")
|
|
4209
4279
|
}, t("failMisjudgeLink"))]) : null
|
|
4210
4280
|
]);
|
|
4211
|
-
if (kind === "hubState") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failHubStateHint"))]);
|
|
4281
|
+
if (kind === "hubState") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failHubStateHint", { action: actionWord }))]);
|
|
4212
4282
|
if (kind === "timeout") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failTimeoutHint"))]);
|
|
4213
|
-
if (kind === "profileLock") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failProfileLockHint"))]);
|
|
4214
|
-
|
|
4283
|
+
if (kind === "profileLock") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failProfileLockHint", { action: actionWord }))]);
|
|
4284
|
+
if (kind === "hostCliSpawn") return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failHostCliSpawnHint"))]);
|
|
4285
|
+
if (kind === "pnpmIgnoredBuild") return (0, react.createElement)("div", null, [
|
|
4286
|
+
(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failIgnoredBuild")),
|
|
4287
|
+
r.repo && shownRepo ? (0, react.createElement)("a", {
|
|
4288
|
+
className: Modal_module_css_default.failBigIssue,
|
|
4289
|
+
href: pluginIssueUrl(shownRepo, r.message, env, r.command, r.attempts, action),
|
|
4290
|
+
target: "_blank",
|
|
4291
|
+
rel: "noopener noreferrer",
|
|
4292
|
+
title: t("failIssueHint")
|
|
4293
|
+
}, t("failIssueBig")) : null,
|
|
4294
|
+
r.repo && shownRepo ? (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failMisjudgeHint")), (0, react.createElement)("a", {
|
|
4295
|
+
className: Modal_module_css_default.failMisjudgeLink,
|
|
4296
|
+
href: hubIssueUrl(shownRepo, r.message, env, r.command, r.attempts, "misjudge", action),
|
|
4297
|
+
target: "_blank",
|
|
4298
|
+
rel: "noopener noreferrer",
|
|
4299
|
+
title: t("failHubIssueHint")
|
|
4300
|
+
}, t("failMisjudgeLink"))]) : null
|
|
4301
|
+
]);
|
|
4302
|
+
return (0, react.createElement)("div", null, [(0, react.createElement)("div", { className: Modal_module_css_default.failPrepareHint }, t("failUnclassifiedHint", { action: actionWord })), (0, react.createElement)("a", {
|
|
4215
4303
|
className: Modal_module_css_default.failBigIssue,
|
|
4216
|
-
href: hubIssueUrl(shownRepo || r.repo, r.message, env, r.command, r.attempts),
|
|
4304
|
+
href: hubIssueUrl(shownRepo || r.repo, r.message, env, r.command, r.attempts, "triage", action),
|
|
4217
4305
|
target: "_blank",
|
|
4218
4306
|
rel: "noopener noreferrer",
|
|
4219
4307
|
title: t("failHubIssueHint")
|
|
@@ -4259,8 +4347,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4259
4347
|
* Website: https://dsh-plugin.org
|
|
4260
4348
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4261
4349
|
*
|
|
4262
|
-
*
|
|
4263
|
-
* by the purple ad banner that promotes the catalog stats.
|
|
4350
|
+
* 板块头部:品牌标题行(H1 + 官网入口按钮)+ 副标题,其后是宣传目录统计的紫色广告条。
|
|
4264
4351
|
*/
|
|
4265
4352
|
function CatalogHeader({ t, langPath, statsTotal, statsVerified, onToggleLang, hubUpdate, onVersionClick, onAboutClick }) {
|
|
4266
4353
|
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)("div", { className: Header_module_css_default.header }, (0, react.createElement)("div", { className: Header_module_css_default.headerTitleRow }, (0, react.createElement)("a", {
|
|
@@ -4321,9 +4408,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4321
4408
|
* Website: https://dsh-plugin.org
|
|
4322
4409
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4323
4410
|
*
|
|
4324
|
-
*
|
|
4325
|
-
*
|
|
4326
|
-
* carry no counts so their widths stay uniform.
|
|
4411
|
+
* 分类 Tab:先是「全部」chip,其后每个目录分类一个 chip。「全部」chip 带插件总数,
|
|
4412
|
+
* 各分类 chip 不带计数以保持宽度一致。
|
|
4327
4413
|
*/
|
|
4328
4414
|
function CategoryTabs({ category, setCategory, allLabel, totalCount, langKey }) {
|
|
4329
4415
|
return (0, react.createElement)("div", { className: Header_module_css_default.tabs }, (0, react.createElement)("button", {
|
|
@@ -4343,12 +4429,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4343
4429
|
* Website: https://dsh-plugin.org
|
|
4344
4430
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4345
4431
|
*
|
|
4346
|
-
*
|
|
4347
|
-
*
|
|
4348
|
-
*
|
|
4349
|
-
*
|
|
4350
|
-
*
|
|
4351
|
-
* button shows an up/down arrow for the current direction).
|
|
4432
|
+
* 市场列表上方的工具栏:
|
|
4433
|
+
* 第一行 —— 整行宽的搜索框;
|
|
4434
|
+
* 第二行 —— 左侧结果计数,右侧排序分段控件
|
|
4435
|
+
* (与已安装视图一致:点同一排序切换正/倒序,点新排序用其默认方向;
|
|
4436
|
+
* 激活按钮显示当前方向的上/下箭头)。
|
|
4352
4437
|
*/
|
|
4353
4438
|
/** 单选按钮组中的一个按钮(segmented control,与已安装视图排序按钮同款) */
|
|
4354
4439
|
function SegBtn$1({ active, onClick, label, icon }) {
|
|
@@ -4398,40 +4483,40 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4398
4483
|
css: css$9
|
|
4399
4484
|
});
|
|
4400
4485
|
var List_module_css_default = {
|
|
4401
|
-
"
|
|
4402
|
-
"verified": "_3XaZHa_verified",
|
|
4403
|
-
"stateActions": "_3XaZHa_stateActions",
|
|
4404
|
-
"body": "_3XaZHa_body",
|
|
4405
|
-
"moreSentinel": "_3XaZHa_moreSentinel",
|
|
4406
|
-
"cardHead": "_3XaZHa_cardHead",
|
|
4407
|
-
"updateBadge": "_3XaZHa_updateBadge",
|
|
4408
|
-
"fork": "_3XaZHa_fork",
|
|
4486
|
+
"uninstallBtn": "_3XaZHa_uninstallBtn",
|
|
4409
4487
|
"diagBtn": "_3XaZHa_diagBtn",
|
|
4410
|
-
"
|
|
4411
|
-
"footer": "_3XaZHa_footer",
|
|
4412
|
-
"versionBadge": "_3XaZHa_versionBadge",
|
|
4413
|
-
"detailBtn": "_3XaZHa_detailBtn",
|
|
4414
|
-
"state": "_3XaZHa_state",
|
|
4415
|
-
"cardSide": "_3XaZHa_cardSide",
|
|
4416
|
-
"cardMain": "_3XaZHa_cardMain",
|
|
4488
|
+
"installBtnUpdate": "_3XaZHa_installBtnUpdate",
|
|
4417
4489
|
"desc": "_3XaZHa_desc",
|
|
4418
|
-
"
|
|
4490
|
+
"installBtn": "_3XaZHa_installBtn",
|
|
4419
4491
|
"retryBtn": "_3XaZHa_retryBtn",
|
|
4492
|
+
"state": "_3XaZHa_state",
|
|
4493
|
+
"footLink": "_3XaZHa_footLink",
|
|
4420
4494
|
"date": "_3XaZHa_date",
|
|
4421
|
-
"
|
|
4422
|
-
"installBtn": "_3XaZHa_installBtn",
|
|
4423
|
-
"installBtnCopied": "_3XaZHa_installBtnCopied",
|
|
4424
|
-
"uninstallBtn": "_3XaZHa_uninstallBtn",
|
|
4495
|
+
"stats": "_3XaZHa_stats",
|
|
4425
4496
|
"topic": "_3XaZHa_topic",
|
|
4426
4497
|
"cardTitle": "_3XaZHa_cardTitle",
|
|
4427
|
-
"stateDesc": "_3XaZHa_stateDesc",
|
|
4428
|
-
"stateTitle": "_3XaZHa_stateTitle",
|
|
4429
4498
|
"topics": "_3XaZHa_topics",
|
|
4430
|
-
"
|
|
4431
|
-
"installBtnUpdate": "_3XaZHa_installBtnUpdate",
|
|
4499
|
+
"categoryBadge": "_3XaZHa_categoryBadge",
|
|
4432
4500
|
"star": "_3XaZHa_star",
|
|
4433
|
-
"
|
|
4434
|
-
"
|
|
4501
|
+
"verified": "_3XaZHa_verified",
|
|
4502
|
+
"versionBadge": "_3XaZHa_versionBadge",
|
|
4503
|
+
"moreSentinel": "_3XaZHa_moreSentinel",
|
|
4504
|
+
"installBtnInstalled": "_3XaZHa_installBtnInstalled",
|
|
4505
|
+
"list": "_3XaZHa_list",
|
|
4506
|
+
"updateBadge": "_3XaZHa_updateBadge",
|
|
4507
|
+
"footer": "_3XaZHa_footer",
|
|
4508
|
+
"card": "_3XaZHa_card",
|
|
4509
|
+
"installBtnCopied": "_3XaZHa_installBtnCopied",
|
|
4510
|
+
"cardMain": "_3XaZHa_cardMain",
|
|
4511
|
+
"body": "_3XaZHa_body",
|
|
4512
|
+
"detailBtn": "_3XaZHa_detailBtn",
|
|
4513
|
+
"fork": "_3XaZHa_fork",
|
|
4514
|
+
"stateTitle": "_3XaZHa_stateTitle",
|
|
4515
|
+
"actions": "_3XaZHa_actions",
|
|
4516
|
+
"cardHead": "_3XaZHa_cardHead",
|
|
4517
|
+
"cardSide": "_3XaZHa_cardSide",
|
|
4518
|
+
"stateDesc": "_3XaZHa_stateDesc",
|
|
4519
|
+
"stateActions": "_3XaZHa_stateActions"
|
|
4435
4520
|
};
|
|
4436
4521
|
//#endregion
|
|
4437
4522
|
//#region src/client/hooks/useIncrementalList.ts
|
|
@@ -4440,11 +4525,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4440
4525
|
* Website: https://dsh-plugin.org
|
|
4441
4526
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4442
4527
|
*
|
|
4443
|
-
*
|
|
4444
|
-
*
|
|
4445
|
-
*
|
|
4446
|
-
* The items reference is the list identity — category / search / sort
|
|
4447
|
-
* changes produce a new array, which resets the window to the first batch.
|
|
4528
|
+
* 增量列表:只渲染(可能很大的)结果集的第一批,末尾哨兵滚入视口时就追加下一批,
|
|
4529
|
+
* 让插件市场绝不一次性挂载成千上万张卡片。
|
|
4530
|
+
* items 引用即列表身份 —— 分类/搜索/排序变化会产出新数组,窗口随之重置回第一批。
|
|
4448
4531
|
*/
|
|
4449
4532
|
/** 首批渲染条数 & 每次滚到底追加的增量(单卡约 80px 高,100 条已远超一屏) */
|
|
4450
4533
|
const PAGE_SIZE = 100;
|
|
@@ -4478,9 +4561,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4478
4561
|
* Website: https://dsh-plugin.org
|
|
4479
4562
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4480
4563
|
*
|
|
4481
|
-
*
|
|
4482
|
-
*
|
|
4483
|
-
* uninstall actions.
|
|
4564
|
+
* 目录列表里的单张插件卡片:名称/分类/verified 徽标、描述 + 标签、Star/Fork/日期
|
|
4565
|
+
* 统计,以及详情/安装/卸载动作。
|
|
4484
4566
|
*/
|
|
4485
4567
|
function PluginCard({ plugin: p, copied, installedName, installedVersion, hasUpdate, t, langKey, langPath, onInstall, onUninstall }) {
|
|
4486
4568
|
const repo = p.source?.repo ?? "";
|
|
@@ -4529,10 +4611,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4529
4611
|
* Website: https://dsh-plugin.org
|
|
4530
4612
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4531
4613
|
*
|
|
4532
|
-
*
|
|
4533
|
-
*
|
|
4534
|
-
* the category or install-status filter changes so the replaced content is
|
|
4535
|
-
* not mistaken for a no-op update.
|
|
4614
|
+
* 目录列表:承载加载/失败/空三态、插件卡片与计数页脚的滚动容器。分类或安装状态
|
|
4615
|
+
* 筛选变化时重置滚动位置,避免替换后的内容被误当成「没变化」。
|
|
4536
4616
|
*/
|
|
4537
4617
|
function CatalogList({ plugins, failed, visible, total, t, langPath, reload, category, copied, installedName, installedVersion, hasUpdate, langKey, onInstall, onUninstall, hasProxy, onOpenDiagnostics }) {
|
|
4538
4618
|
/** 列表滚动容器:分类/搜索切换后列表内容替换但 scrollTop 保留,会让用户误以为列表没更新,需重置回顶部 */
|
|
@@ -4581,10 +4661,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4581
4661
|
* Website: https://dsh-plugin.org
|
|
4582
4662
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4583
4663
|
*
|
|
4584
|
-
*
|
|
4585
|
-
*
|
|
4586
|
-
* it wires catalog state (query/sort/filter/category) to the small
|
|
4587
|
-
* presentational components so PluginHubSection stays free of view internals.
|
|
4664
|
+
* 市场视图:目录的浏览体验 —— 分类 Tab、搜索/排序/安装状态控件与插件列表。自身不持有状态,
|
|
4665
|
+
* 只把目录状态(query/sort/filter/category)接到小型展示组件上,让 PluginHubSection 不掺视图细节。
|
|
4588
4666
|
*/
|
|
4589
4667
|
function MarketView({ catalog, t, langPath, langKey, copied, resultText, onInstall, onUninstall, hasProxy, onOpenDiagnostics }) {
|
|
4590
4668
|
return (0, react.createElement)(react.Fragment, null, (0, react.createElement)(CategoryTabs, {
|
|
@@ -4638,15 +4716,15 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4638
4716
|
css: css$8
|
|
4639
4717
|
});
|
|
4640
4718
|
var SectionTabs_module_css_default = {
|
|
4641
|
-
"
|
|
4642
|
-
"tab": "_7tvizq_tab",
|
|
4719
|
+
"tabCountActive": "_7tvizq_tabCountActive",
|
|
4643
4720
|
"tabActive": "_7tvizq_tabActive",
|
|
4644
|
-
"tabIcon": "_7tvizq_tabIcon",
|
|
4645
|
-
"noticeBtn": "_7tvizq_noticeBtn",
|
|
4646
4721
|
"noticeCount": "_7tvizq_noticeCount",
|
|
4647
|
-
"tabCount": "_7tvizq_tabCount",
|
|
4648
4722
|
"noticeIcon": "_7tvizq_noticeIcon",
|
|
4649
|
-
"
|
|
4723
|
+
"noticeBtn": "_7tvizq_noticeBtn",
|
|
4724
|
+
"tabCount": "_7tvizq_tabCount",
|
|
4725
|
+
"tab": "_7tvizq_tab",
|
|
4726
|
+
"tabIcon": "_7tvizq_tabIcon",
|
|
4727
|
+
"root": "_7tvizq_root"
|
|
4650
4728
|
};
|
|
4651
4729
|
//#endregion
|
|
4652
4730
|
//#region src/client/components/layout/SectionTabs.tsx
|
|
@@ -4655,11 +4733,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4655
4733
|
* Website: https://dsh-plugin.org
|
|
4656
4734
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4657
4735
|
*
|
|
4658
|
-
*
|
|
4659
|
-
*
|
|
4660
|
-
*
|
|
4661
|
-
* Kept visually distinct from the category chips so the hierarchy reads:
|
|
4662
|
-
* section → category → plugin.
|
|
4736
|
+
* 一级导航:紧凑分段控件,在四个顶层板块间切换 —— 市场(浏览)、已安装(管理)、
|
|
4737
|
+
* 自定义(手动命令安装)与设置(网络源与偏好)。与分类 chip 视觉上区分开,
|
|
4738
|
+
* 让层级清晰:板块 → 分类 → 插件。
|
|
4663
4739
|
*/
|
|
4664
4740
|
const ORDER = [
|
|
4665
4741
|
{
|
|
@@ -4723,42 +4799,42 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4723
4799
|
css: css$7
|
|
4724
4800
|
});
|
|
4725
4801
|
var InstalledView_module_css_default = {
|
|
4726
|
-
"
|
|
4802
|
+
"root": "_1nXeGW_root",
|
|
4803
|
+
"rowSourceTagHub": "_1nXeGW_rowSourceTagHub",
|
|
4804
|
+
"toolbar": "_1nXeGW_toolbar",
|
|
4805
|
+
"list": "_1nXeGW_list",
|
|
4806
|
+
"segLabel": "_1nXeGW_segLabel",
|
|
4807
|
+
"segBtn": "_1nXeGW_segBtn",
|
|
4808
|
+
"rowMeta": "_1nXeGW_rowMeta",
|
|
4727
4809
|
"rowActions": "_1nXeGW_rowActions",
|
|
4728
|
-
"
|
|
4810
|
+
"emptyDesc": "_1nXeGW_emptyDesc",
|
|
4811
|
+
"rowSourceTagManual": "_1nXeGW_rowSourceTagManual",
|
|
4812
|
+
"segBtnActive": "_1nXeGW_segBtnActive",
|
|
4813
|
+
"rowTitleLine": "_1nXeGW_rowTitleLine",
|
|
4814
|
+
"exampleRow": "_1nXeGW_exampleRow",
|
|
4815
|
+
"searchWrap": "_1nXeGW_searchWrap",
|
|
4729
4816
|
"rowMain": "_1nXeGW_rowMain",
|
|
4730
|
-
"
|
|
4817
|
+
"segGroup": "_1nXeGW_segGroup",
|
|
4731
4818
|
"updateBadge": "_1nXeGW_updateBadge",
|
|
4732
|
-
"rowDetail": "_1nXeGW_rowDetail",
|
|
4733
|
-
"exampleRow": "_1nXeGW_exampleRow",
|
|
4734
4819
|
"rowUninstall": "_1nXeGW_rowUninstall",
|
|
4735
|
-
"
|
|
4736
|
-
"
|
|
4737
|
-
"
|
|
4738
|
-
"
|
|
4739
|
-
"
|
|
4820
|
+
"row": "_1nXeGW_row",
|
|
4821
|
+
"exampleBadge": "_1nXeGW_exampleBadge",
|
|
4822
|
+
"rowRepo": "_1nXeGW_rowRepo",
|
|
4823
|
+
"segRow": "_1nXeGW_segRow",
|
|
4824
|
+
"statusPending": "_1nXeGW_statusPending",
|
|
4825
|
+
"empty": "_1nXeGW_empty",
|
|
4826
|
+
"rowSourceTag": "_1nXeGW_rowSourceTag",
|
|
4827
|
+
"emptyTitle": "_1nXeGW_emptyTitle",
|
|
4740
4828
|
"statusInactive": "_1nXeGW_statusInactive",
|
|
4741
|
-
"
|
|
4742
|
-
"
|
|
4743
|
-
"
|
|
4744
|
-
"toolbar": "_1nXeGW_toolbar",
|
|
4829
|
+
"rowCategory": "_1nXeGW_rowCategory",
|
|
4830
|
+
"versionBadge": "_1nXeGW_versionBadge",
|
|
4831
|
+
"rowUpdate": "_1nXeGW_rowUpdate",
|
|
4745
4832
|
"searchInput": "_1nXeGW_searchInput",
|
|
4746
|
-
"emptyDesc": "_1nXeGW_emptyDesc",
|
|
4747
|
-
"rowTitleLine": "_1nXeGW_rowTitleLine",
|
|
4748
|
-
"rowSourceTagManual": "_1nXeGW_rowSourceTagManual",
|
|
4749
|
-
"segRow": "_1nXeGW_segRow",
|
|
4750
4833
|
"rowTitle": "_1nXeGW_rowTitle",
|
|
4751
|
-
"rowDesc": "_1nXeGW_rowDesc",
|
|
4752
4834
|
"statusDot": "_1nXeGW_statusDot",
|
|
4753
|
-
"
|
|
4754
|
-
"
|
|
4755
|
-
"
|
|
4756
|
-
"statusPending": "_1nXeGW_statusPending",
|
|
4757
|
-
"rowMeta": "_1nXeGW_rowMeta",
|
|
4758
|
-
"rowUpdate": "_1nXeGW_rowUpdate",
|
|
4759
|
-
"list": "_1nXeGW_list",
|
|
4760
|
-
"segBtnActive": "_1nXeGW_segBtnActive",
|
|
4761
|
-
"exampleBadge": "_1nXeGW_exampleBadge"
|
|
4835
|
+
"rowDetail": "_1nXeGW_rowDetail",
|
|
4836
|
+
"rowDesc": "_1nXeGW_rowDesc",
|
|
4837
|
+
"rowRestart": "_1nXeGW_rowRestart"
|
|
4762
4838
|
};
|
|
4763
4839
|
//#endregion
|
|
4764
4840
|
//#region src/client/components/views/InstalledView.tsx
|
|
@@ -4767,18 +4843,13 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4767
4843
|
* Website: https://dsh-plugin.org
|
|
4768
4844
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
4769
4845
|
*
|
|
4770
|
-
*
|
|
4771
|
-
*
|
|
4772
|
-
*
|
|
4773
|
-
*
|
|
4774
|
-
*
|
|
4775
|
-
* search box plus two segmented radio-button groups: source filter
|
|
4776
|
-
* (all / catalog / custom) and sort (name / recently installed / stars / forks).
|
|
4777
|
-
* Each row carries restart (when pending), update and uninstall actions
|
|
4778
|
-
* and opens a detail modal with the full install metadata.
|
|
4846
|
+
* 已安装视图:管理安装进当前 profile 的插件。沿用主流扩展管理器模式(VSCode 已安装 tab)——
|
|
4847
|
+
* 可搜索、可排序的已安装清单,混排目录插件(完整元数据)与命令行自定义安装(目录之外,
|
|
4848
|
+
* 只有运行时信息,打「自定义」徽标)。工具栏含搜索框与两组分段单选:来源筛选
|
|
4849
|
+
* (全部/目录/自定义)与排序(名称/最近安装/Star/Fork)。每行带重启(待重启时)、更新与
|
|
4850
|
+
* 卸载动作,并打开含完整安装元数据的详情弹窗。
|
|
4779
4851
|
*
|
|
4780
|
-
*
|
|
4781
|
-
* model arrives from the catalog hook and actions bubble up via callbacks.
|
|
4852
|
+
* 纯展示组件:只持有本地搜索/排序状态;InstalledItem 模型来自目录 hook,动作经回调上抛。
|
|
4782
4853
|
*/
|
|
4783
4854
|
const INSTALLED_SORTS = [
|
|
4784
4855
|
"sortName",
|
|
@@ -4992,7 +5063,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
4992
5063
|
}
|
|
4993
5064
|
//#endregion
|
|
4994
5065
|
//#region \0dsh-css:src/client/styles/CustomInstallView.module.css.mjs
|
|
4995
|
-
const css$6 = ".zISxCG_root{flex-direction:column;gap:10px;min-width:0;max-width:560px;display:flex}.zISxCG_desc{color:var(--hub-text-tertiary);margin:0;font-size:12px;line-height:18px}.zISxCG_installCards{flex-direction:column;flex-shrink:0;gap:10px;min-width:0;display:flex}.zISxCG_installCard{background:var(--hub-bg-1);border:1px solid var(--hub-border-1);border-radius:8px;flex-direction:column;gap:8px;min-width:0;padding:10px 12px;display:flex}.zISxCG_installCardHead{align-items:center;min-width:0;display:flex}.zISxCG_installLabel{color:var(--hub-text-primary);font-size:12px;font-weight:600;line-height:18px}.zISxCG_installHelpBtn{width:18px;height:18px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:1px solid #0000;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;margin-left:6px;padding:0;transition:color .12s,background .12s,border-color .12s;display:inline-flex}.zISxCG_installHelpBtn:hover{color:var(--hub-brand);background:var(--hub-brand-tint);border-color:var(--hub-brand-border-soft)}.
|
|
5066
|
+
const css$6 = ".zISxCG_root{flex-direction:column;gap:10px;min-width:0;max-width:560px;display:flex}.zISxCG_desc{color:var(--hub-text-tertiary);margin:0;font-size:12px;line-height:18px}.zISxCG_installCards{flex-direction:column;flex-shrink:0;gap:10px;min-width:0;display:flex}.zISxCG_installCard{background:var(--hub-bg-1);border:1px solid var(--hub-border-1);border-radius:8px;flex-direction:column;gap:8px;min-width:0;padding:10px 12px;display:flex}.zISxCG_installCardHead{align-items:center;min-width:0;display:flex}.zISxCG_installLabel{color:var(--hub-text-primary);font-size:12px;font-weight:600;line-height:18px}.zISxCG_installHelpBtn{width:18px;height:18px;color:var(--hub-text-tertiary);cursor:pointer;-webkit-user-select:none;user-select:none;background:0 0;border:1px solid #0000;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;margin-left:6px;padding:0;transition:color .12s,background .12s,border-color .12s;display:inline-flex}.zISxCG_installHelpBtn:hover{color:var(--hub-brand);background:var(--hub-brand-tint);border-color:var(--hub-brand-border-soft)}.zISxCG_installExample{color:var(--hub-text-tertiary);white-space:nowrap;text-overflow:ellipsis;min-width:0;font-size:11px;line-height:16px;overflow:hidden}.zISxCG_installRow{align-items:center;gap:8px;min-width:0;display:flex}.zISxCG_installInput{min-width:0;height:28px;color:var(--hub-text-primary);border:1px solid var(--hub-border-2);background:0 0;border-radius:6px;outline:none;flex:auto;padding:0 9px;font-size:12px;line-height:26px;transition:border-color .12s}.zISxCG_installInput::placeholder{color:var(--hub-text-tertiary)}.zISxCG_installInput:focus{border-color:var(--hub-brand)}.zISxCG_installInputError,.zISxCG_installInputError:focus{border-color:var(--hub-danger-text)}.zISxCG_installBtn{color:#fff;background:var(--hub-brand);cursor:pointer;-webkit-user-select:none;user-select:none;border:none;border-radius:6px;flex-shrink:0;padding:5px 14px;font-family:inherit;font-size:12px;font-weight:500;line-height:18px;transition:background .12s,opacity .12s}.zISxCG_installBtn:hover{background:var(--hub-brand-hover)}.zISxCG_installBtn:disabled{opacity:.45;cursor:default}.zISxCG_installCardDisabled{opacity:.8}.zISxCG_channelOff{min-width:0;color:var(--hub-warn);background:var(--hub-warn-tint);border:1px solid var(--hub-warn-border);border-radius:6px;justify-content:space-between;align-items:center;gap:8px;padding:6px 9px;font-size:12px;line-height:16px;display:flex}.zISxCG_channelOffText{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.zISxCG_channelOffBtn{color:var(--hub-warn-strong);border:1px solid var(--hub-warn-border);cursor:pointer;white-space:nowrap;background:0 0;border-radius:6px;flex-shrink:0;padding:3px 10px;font-family:inherit;font-size:12px;font-weight:500;line-height:18px;transition:background .12s,color .12s}.zISxCG_channelOffBtn:hover{background:var(--hub-warn-tint);color:var(--hub-warn)}.zISxCG_installError{color:var(--hub-danger-text);background:var(--hub-danger-tint);border:1px solid var(--hub-danger-border);border-radius:6px;padding:5px 8px;font-size:12px;line-height:16px}.zISxCG_helpBody{flex-direction:column;gap:7px;padding:4px 2px;display:flex}.zISxCG_helpLine{align-items:baseline;gap:12px;min-width:0;font-size:12px;line-height:20px;display:flex}.zISxCG_helpCmd{color:var(--hub-text-primary);white-space:nowrap;flex-shrink:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px}.zISxCG_helpNote{min-width:0;color:var(--hub-text-tertiary);font-size:11px}";
|
|
4996
5067
|
const tagId$6 = "dsh-plugin/CustomInstallView.module.css";
|
|
4997
5068
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
|
|
4998
5069
|
const tag = document.createElement("style");
|
|
@@ -5007,27 +5078,26 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5007
5078
|
css: css$6
|
|
5008
5079
|
});
|
|
5009
5080
|
var CustomInstallView_module_css_default = {
|
|
5010
|
-
"
|
|
5011
|
-
"
|
|
5081
|
+
"installCard": "zISxCG_installCard",
|
|
5082
|
+
"installCards": "zISxCG_installCards",
|
|
5012
5083
|
"installRow": "zISxCG_installRow",
|
|
5013
|
-
"channelOff": "zISxCG_channelOff",
|
|
5014
|
-
"helpCmd": "zISxCG_helpCmd",
|
|
5015
5084
|
"helpBody": "zISxCG_helpBody",
|
|
5016
|
-
"
|
|
5017
|
-
"helpNote": "zISxCG_helpNote",
|
|
5018
|
-
"installError": "zISxCG_installError",
|
|
5085
|
+
"root": "zISxCG_root",
|
|
5019
5086
|
"installBtn": "zISxCG_installBtn",
|
|
5087
|
+
"installCardDisabled": "zISxCG_installCardDisabled",
|
|
5088
|
+
"installError": "zISxCG_installError",
|
|
5020
5089
|
"installLabel": "zISxCG_installLabel",
|
|
5090
|
+
"installExample": "zISxCG_installExample",
|
|
5091
|
+
"installHelpBtn": "zISxCG_installHelpBtn",
|
|
5092
|
+
"channelOffBtn": "zISxCG_channelOffBtn",
|
|
5021
5093
|
"helpLine": "zISxCG_helpLine",
|
|
5022
|
-
"installCardHead": "zISxCG_installCardHead",
|
|
5023
5094
|
"installInputError": "zISxCG_installInputError",
|
|
5024
|
-
"
|
|
5025
|
-
"root": "zISxCG_root",
|
|
5026
|
-
"installInput": "zISxCG_installInput",
|
|
5027
|
-
"installCard": "zISxCG_installCard",
|
|
5095
|
+
"installCardHead": "zISxCG_installCardHead",
|
|
5028
5096
|
"channelOffText": "zISxCG_channelOffText",
|
|
5029
|
-
"
|
|
5030
|
-
"
|
|
5097
|
+
"helpCmd": "zISxCG_helpCmd",
|
|
5098
|
+
"helpNote": "zISxCG_helpNote",
|
|
5099
|
+
"channelOff": "zISxCG_channelOff",
|
|
5100
|
+
"installInput": "zISxCG_installInput",
|
|
5031
5101
|
"desc": "zISxCG_desc"
|
|
5032
5102
|
};
|
|
5033
5103
|
//#endregion
|
|
@@ -5037,47 +5107,21 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5037
5107
|
* Website: https://dsh-plugin.org
|
|
5038
5108
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
5039
5109
|
*
|
|
5040
|
-
*
|
|
5041
|
-
*
|
|
5042
|
-
*
|
|
5043
|
-
* npm/pnpm install command, including the official global `npm install -g`),
|
|
5044
|
-
* GitHub source and the official `dsh plugin ... add <target>` command —
|
|
5045
|
-
* each with a placeholder example above the input and its own format check.
|
|
5046
|
-
* The cards stay separate so a user never has to guess which format goes
|
|
5047
|
-
* where. Finished installs surface in the Installed view, marked as custom.
|
|
5110
|
+
* 自定义安装视图:独立一级板块,用于手动安装目录之外的 npm 包。安装卡片接受裸包名或完整的
|
|
5111
|
+
* npm/pnpm 安装命令(含官方全局 `npm install -g`),输入框上方带示例并自带格式校验。
|
|
5112
|
+
* 装完的插件出现在「已安装」视图,标记为自定义安装。
|
|
5048
5113
|
*
|
|
5049
|
-
*
|
|
5050
|
-
*
|
|
5051
|
-
* via onInstallCustom.
|
|
5114
|
+
* 纯展示组件:只持有本地输入/错误状态;真正的安装(custom 源,受安全开关控制)经
|
|
5115
|
+
* onInstallCustom 上抛。
|
|
5052
5116
|
*/
|
|
5053
|
-
/** GitHub 地址(带前缀形态):github:、https://github.com/、git+https://github.com/、git@github.com: */
|
|
5054
|
-
const GITHUB_URL_RE = /^(?:github:|https?:\/\/github\.com\/|git\+https?:\/\/github\.com\/|git@github\.com:)([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+?)(?:\.git)?$/;
|
|
5055
|
-
/** 裸 owner/repo(npm 包名只有 @scope/pkg 才带斜杠,无 @ 前缀的 a/b 一定是 GitHub 仓库) */
|
|
5056
|
-
const GITHUB_BARE_RE = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
5057
5117
|
/** npm 包名(含 @scope/pkg) */
|
|
5058
5118
|
const NPM_PACKAGE_RE = /^(?:@[a-z0-9._-]+\/)?[a-z0-9._-]+$/;
|
|
5059
|
-
/** DSH 命令行前缀(官方唯一形式 `dsh plugin --profile <name> <add|update> <target>`)—— 提取其中的动作与目标。
|
|
5060
|
-
* 官方 CLI(apps/cli/src/args.ts,commander):--profile 为必填长选项(无 -p 简写,省略即报错),
|
|
5061
|
-
* 支持 `--profile=<name>` 等号形式;命令大小写不敏感。update = 已安装目标覆盖更新到最新;
|
|
5062
|
-
* remove 不走这里(卸载由「已安装」列表的卸载按钮执行,命令框不认卸载动词)。
|
|
5063
|
-
* 与 server 端 installTargetOf 口径一致。 */
|
|
5064
|
-
const DSH_PLUGIN_CMD_RE = /^dsh\s+plugin\s+--profile(?:\s+|=)\S+\s+(add|update)\s+(.+)$/i;
|
|
5065
5119
|
/** npm 全局安装命令(官方 README 格式,如 `npm install -g @deepseek-ai/dsh @deepseek-harness-tui/dsh-tui`)——
|
|
5066
5120
|
* 提取 -g 之后的包列表;任一包名非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 口径一致。 */
|
|
5067
5121
|
const NPM_GLOBAL_CMD_RE = /^npm\s+(?:install|i)\s+(?:-g|--global)\s+(.+)$/i;
|
|
5068
5122
|
/** 常规 npm/pnpm 安装命令(装进当前 profile,如 `npm install lodash`、`pnpm add @scope/pkg`)——
|
|
5069
5123
|
* 提取命令后的包列表;包列表在 splitPackages 里逐个校验。 */
|
|
5070
5124
|
const NPM_INSTALL_CMD_RE = /^(?:npm\s+(?:install|i)|pnpm\s+(?:add|i|install))\s+(.+)$/i;
|
|
5071
|
-
/** 解析 DSH 命令:返回 { action, target };非官方命令返回 null(交给格式错误提示)。 */
|
|
5072
|
-
function parseDshCommand(raw) {
|
|
5073
|
-
const input = raw.trim();
|
|
5074
|
-
const match = DSH_PLUGIN_CMD_RE.exec(input);
|
|
5075
|
-
if (match === null) return null;
|
|
5076
|
-
return {
|
|
5077
|
-
action: match[1].toLowerCase(),
|
|
5078
|
-
target: match[2].trim()
|
|
5079
|
-
};
|
|
5080
|
-
}
|
|
5081
5125
|
/** 空格分隔的包列表:逐个按 npm 包名语法校验 + 拒绝以 - 开头的 token(npm 会把 --xxx 当参数而非包名),
|
|
5082
5126
|
* 任一非法返回 null(交给格式错误提示)。与 server 端 globalNpmPackagesOf 同口径。 */
|
|
5083
5127
|
function splitPackages(raw) {
|
|
@@ -5111,36 +5155,16 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5111
5155
|
}
|
|
5112
5156
|
return null;
|
|
5113
5157
|
}
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
npm: {
|
|
5121
|
-
titleKey: "npmInstallLabel",
|
|
5122
|
-
contentKey: "npmInstallHelp"
|
|
5123
|
-
},
|
|
5124
|
-
git: {
|
|
5125
|
-
titleKey: "gitInstallLabel",
|
|
5126
|
-
contentKey: "gitInstallHelp"
|
|
5127
|
-
},
|
|
5128
|
-
cmd: {
|
|
5129
|
-
titleKey: "dshCmdLabel",
|
|
5130
|
-
contentKey: "dshCmdHelp"
|
|
5131
|
-
}
|
|
5132
|
-
};
|
|
5133
|
-
function CustomInstallView({ t, onInstallCustom, enableNpm, enableGit, enableDsh, onOpenSettings, profile }) {
|
|
5158
|
+
/** 卡片标题旁的「帮助」弹窗:该卡片的标题与格式清单语言包 key。 */
|
|
5159
|
+
const HELP_CARDS = { npm: {
|
|
5160
|
+
titleKey: "npmInstallLabel",
|
|
5161
|
+
contentKey: "npmInstallHelp"
|
|
5162
|
+
} };
|
|
5163
|
+
function CustomInstallView({ t, onInstallCustom, enableNpm, onOpenSettings }) {
|
|
5134
5164
|
/** 自定义安装:NPM 包输入与格式错误('' = 无错误) */
|
|
5135
5165
|
const [npmQuery, setNpmQuery] = (0, react.useState)("");
|
|
5136
5166
|
const [npmError, setNpmError] = (0, react.useState)("");
|
|
5137
|
-
/**
|
|
5138
|
-
const [gitQuery, setGitQuery] = (0, react.useState)("");
|
|
5139
|
-
const [gitError, setGitError] = (0, react.useState)("");
|
|
5140
|
-
/** 自定义安装:DSH 命令输入与格式错误('' = 无错误) */
|
|
5141
|
-
const [cmdQuery, setCmdQuery] = (0, react.useState)("");
|
|
5142
|
-
const [cmdError, setCmdError] = (0, react.useState)("");
|
|
5143
|
-
/** 卡片标题旁「帮助」弹窗:null = 未打开;'npm' | 'git' | 'cmd' = 打开对应卡片的格式清单 */
|
|
5167
|
+
/** 卡片标题旁「帮助」弹窗:null = 未打开;'npm' = 打开该卡片的格式清单 */
|
|
5144
5168
|
const [helpFor, setHelpFor] = (0, react.useState)(null);
|
|
5145
5169
|
/** 通道关闭提示行:开关关掉后替代示例与输入行,引导去设置打开 */
|
|
5146
5170
|
const channelOffRow = (0, react.createElement)("div", { className: CustomInstallView_module_css_default.channelOff }, (0, react.createElement)("span", { className: CustomInstallView_module_css_default.channelOffText }, t("channelDisabledHint")), (0, react.createElement)("button", {
|
|
@@ -5164,34 +5188,6 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5164
5188
|
setNpmQuery("");
|
|
5165
5189
|
setNpmError("");
|
|
5166
5190
|
};
|
|
5167
|
-
const submitGit = () => {
|
|
5168
|
-
const target = gitQuery.trim();
|
|
5169
|
-
if (!target) return;
|
|
5170
|
-
if (!isGitHubInput(target)) {
|
|
5171
|
-
setGitError(t("gitInstallInvalid"));
|
|
5172
|
-
return;
|
|
5173
|
-
}
|
|
5174
|
-
onInstallCustom(target, { installChannel: "git" });
|
|
5175
|
-
setGitQuery("");
|
|
5176
|
-
setGitError("");
|
|
5177
|
-
};
|
|
5178
|
-
const submitCmd = () => {
|
|
5179
|
-
const raw = cmdQuery.trim();
|
|
5180
|
-
if (!raw) return;
|
|
5181
|
-
const parsed = parseDshCommand(raw);
|
|
5182
|
-
if (parsed === null) {
|
|
5183
|
-
setCmdError(t("dshCmdInvalid", { profile }));
|
|
5184
|
-
return;
|
|
5185
|
-
}
|
|
5186
|
-
onInstallCustom(parsed.target, { installChannel: "dsh" });
|
|
5187
|
-
setCmdQuery("");
|
|
5188
|
-
setCmdError("");
|
|
5189
|
-
};
|
|
5190
|
-
/** 一键插入 DSH Plugin Hub 自身的更新命令:按当前 profile 拼官方命令填进输入框,用户确认后提交 */
|
|
5191
|
-
const insertHubUpdate = () => {
|
|
5192
|
-
setCmdQuery(`dsh plugin --profile ${profile} update dsh-plugin`);
|
|
5193
|
-
setCmdError("");
|
|
5194
|
-
};
|
|
5195
5191
|
return (0, react.createElement)("div", { className: CustomInstallView_module_css_default.root }, (0, react.createElement)("p", { className: CustomInstallView_module_css_default.desc }, t("customViewDesc")), (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installCards }, (0, react.createElement)("div", { className: enableNpm ? CustomInstallView_module_css_default.installCard : `${CustomInstallView_module_css_default.installCard} ${CustomInstallView_module_css_default.installCardDisabled}` }, (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installCardHead }, (0, react.createElement)("span", { className: CustomInstallView_module_css_default.installLabel }, t("npmInstallLabel")), (0, react.createElement)("button", {
|
|
5196
5192
|
type: "button",
|
|
5197
5193
|
className: CustomInstallView_module_css_default.installHelpBtn,
|
|
@@ -5220,66 +5216,6 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5220
5216
|
onClick: submitNpm
|
|
5221
5217
|
}, t("installCliBtn"))),
|
|
5222
5218
|
npmError ? (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installError }, npmError) : null
|
|
5223
|
-
]), (0, react.createElement)("div", { className: enableGit ? CustomInstallView_module_css_default.installCard : `${CustomInstallView_module_css_default.installCard} ${CustomInstallView_module_css_default.installCardDisabled}` }, (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installCardHead }, (0, react.createElement)("span", { className: CustomInstallView_module_css_default.installLabel }, t("gitInstallLabel")), (0, react.createElement)("button", {
|
|
5224
|
-
type: "button",
|
|
5225
|
-
className: CustomInstallView_module_css_default.installHelpBtn,
|
|
5226
|
-
title: t("installHelp"),
|
|
5227
|
-
"aria-label": t("installHelp"),
|
|
5228
|
-
onClick: () => setHelpFor("git")
|
|
5229
|
-
}, (0, react.createElement)(HelpIcon))), !enableGit ? channelOffRow : [
|
|
5230
|
-
(0, react.createElement)("div", { className: CustomInstallView_module_css_default.installExample }, t("gitInstallExample")),
|
|
5231
|
-
(0, react.createElement)("div", { className: CustomInstallView_module_css_default.installRow }, (0, react.createElement)("input", {
|
|
5232
|
-
className: gitError ? `${CustomInstallView_module_css_default.installInput} ${CustomInstallView_module_css_default.installInputError}` : CustomInstallView_module_css_default.installInput,
|
|
5233
|
-
type: "text",
|
|
5234
|
-
placeholder: t("gitInstallPlaceholder"),
|
|
5235
|
-
value: gitQuery,
|
|
5236
|
-
spellCheck: false,
|
|
5237
|
-
onInput: (e) => {
|
|
5238
|
-
setGitQuery(e.target.value);
|
|
5239
|
-
setGitError("");
|
|
5240
|
-
},
|
|
5241
|
-
onKeyDown: (e) => {
|
|
5242
|
-
if (e.key === "Enter") submitGit();
|
|
5243
|
-
}
|
|
5244
|
-
}), (0, react.createElement)("button", {
|
|
5245
|
-
className: CustomInstallView_module_css_default.installBtn,
|
|
5246
|
-
type: "button",
|
|
5247
|
-
disabled: gitQuery.trim() === "",
|
|
5248
|
-
onClick: submitGit
|
|
5249
|
-
}, t("installCliBtn"))),
|
|
5250
|
-
gitError ? (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installError }, gitError) : null
|
|
5251
|
-
]), (0, react.createElement)("div", { className: enableDsh ? CustomInstallView_module_css_default.installCard : `${CustomInstallView_module_css_default.installCard} ${CustomInstallView_module_css_default.installCardDisabled}` }, (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installCardHead }, (0, react.createElement)("span", { className: CustomInstallView_module_css_default.installLabel }, t("dshCmdLabel")), (0, react.createElement)("button", {
|
|
5252
|
-
type: "button",
|
|
5253
|
-
className: CustomInstallView_module_css_default.installHelpBtn,
|
|
5254
|
-
title: t("installHelp"),
|
|
5255
|
-
"aria-label": t("installHelp"),
|
|
5256
|
-
onClick: () => setHelpFor("cmd")
|
|
5257
|
-
}, (0, react.createElement)(HelpIcon)), enableDsh ? (0, react.createElement)("button", {
|
|
5258
|
-
type: "button",
|
|
5259
|
-
className: CustomInstallView_module_css_default.installInsertBtn,
|
|
5260
|
-
onClick: insertHubUpdate
|
|
5261
|
-
}, t("dshCmdInsertHubUpdate")) : null), !enableDsh ? channelOffRow : [
|
|
5262
|
-
(0, react.createElement)("div", { className: CustomInstallView_module_css_default.installExample }, t("dshCmdExample", { profile })),
|
|
5263
|
-
(0, react.createElement)("div", { className: CustomInstallView_module_css_default.installRow }, (0, react.createElement)("input", {
|
|
5264
|
-
className: cmdError ? `${CustomInstallView_module_css_default.installInput} ${CustomInstallView_module_css_default.installInputError}` : CustomInstallView_module_css_default.installInput,
|
|
5265
|
-
type: "text",
|
|
5266
|
-
placeholder: t("dshCmdPlaceholder"),
|
|
5267
|
-
value: cmdQuery,
|
|
5268
|
-
spellCheck: false,
|
|
5269
|
-
onInput: (e) => {
|
|
5270
|
-
setCmdQuery(e.target.value);
|
|
5271
|
-
setCmdError("");
|
|
5272
|
-
},
|
|
5273
|
-
onKeyDown: (e) => {
|
|
5274
|
-
if (e.key === "Enter") submitCmd();
|
|
5275
|
-
}
|
|
5276
|
-
}), (0, react.createElement)("button", {
|
|
5277
|
-
className: CustomInstallView_module_css_default.installBtn,
|
|
5278
|
-
type: "button",
|
|
5279
|
-
disabled: cmdQuery.trim() === "",
|
|
5280
|
-
onClick: submitCmd
|
|
5281
|
-
}, t("installCliBtn"))),
|
|
5282
|
-
cmdError ? (0, react.createElement)("div", { className: CustomInstallView_module_css_default.installError }, cmdError) : null
|
|
5283
5219
|
])), helpFor !== null ? (0, react.createElement)("div", {
|
|
5284
5220
|
className: Modal_module_css_default.overlay,
|
|
5285
5221
|
onClick: (e) => {
|
|
@@ -5293,7 +5229,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5293
5229
|
className: Modal_module_css_default.modalClose,
|
|
5294
5230
|
"aria-label": t("errorClose"),
|
|
5295
5231
|
onClick: () => setHelpFor(null)
|
|
5296
|
-
}, (0, react.createElement)(CloseIcon))), (0, react.createElement)("div", { className: Modal_module_css_default.modalBody }, (0, react.createElement)("div", { className: CustomInstallView_module_css_default.helpBody }, t(HELP_CARDS[helpFor].contentKey
|
|
5232
|
+
}, (0, react.createElement)(CloseIcon))), (0, react.createElement)("div", { className: Modal_module_css_default.modalBody }, (0, react.createElement)("div", { className: CustomInstallView_module_css_default.helpBody }, t(HELP_CARDS[helpFor].contentKey).split("\n").map((line, i) => {
|
|
5297
5233
|
const [cmd, note] = line.split(" ");
|
|
5298
5234
|
return (0, react.createElement)("div", {
|
|
5299
5235
|
key: i,
|
|
@@ -5318,30 +5254,30 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5318
5254
|
css: css$5
|
|
5319
5255
|
});
|
|
5320
5256
|
var SettingsView_module_css_default = {
|
|
5321
|
-
"
|
|
5322
|
-
"settingControlStack": "_506LLG_settingControlStack",
|
|
5323
|
-
"resetBtn": "_506LLG_resetBtn",
|
|
5324
|
-
"settingDesc": "_506LLG_settingDesc",
|
|
5325
|
-
"navIcon": "_506LLG_navIcon",
|
|
5326
|
-
"navItemActive": "_506LLG_navItemActive",
|
|
5327
|
-
"proxyHint": "_506LLG_proxyHint",
|
|
5257
|
+
"pageHeader": "_506LLG_pageHeader",
|
|
5328
5258
|
"sidebar": "_506LLG_sidebar",
|
|
5329
|
-
"
|
|
5330
|
-
"settingTitle": "_506LLG_settingTitle",
|
|
5259
|
+
"root": "_506LLG_root",
|
|
5331
5260
|
"pageDesc": "_506LLG_pageDesc",
|
|
5332
|
-
"proxyHintOk": "_506LLG_proxyHintOk",
|
|
5333
5261
|
"pageTitle": "_506LLG_pageTitle",
|
|
5334
|
-
"
|
|
5335
|
-
"
|
|
5336
|
-
"
|
|
5262
|
+
"settingTitle": "_506LLG_settingTitle",
|
|
5263
|
+
"settingControl": "_506LLG_settingControl",
|
|
5264
|
+
"card": "_506LLG_card",
|
|
5337
5265
|
"settingLabel": "_506LLG_settingLabel",
|
|
5338
|
-
"settingRow": "_506LLG_settingRow",
|
|
5339
5266
|
"content": "_506LLG_content",
|
|
5267
|
+
"settingControlStack": "_506LLG_settingControlStack",
|
|
5268
|
+
"proxyHintFail": "_506LLG_proxyHintFail",
|
|
5269
|
+
"proxyHintOk": "_506LLG_proxyHintOk",
|
|
5270
|
+
"controlDropdown": "_506LLG_controlDropdown",
|
|
5340
5271
|
"settingRowStack": "_506LLG_settingRowStack",
|
|
5341
|
-
"
|
|
5272
|
+
"navItem": "_506LLG_navItem",
|
|
5342
5273
|
"proxyControl": "_506LLG_proxyControl",
|
|
5343
|
-
"
|
|
5344
|
-
"
|
|
5274
|
+
"proxyHint": "_506LLG_proxyHint",
|
|
5275
|
+
"resetBtn": "_506LLG_resetBtn",
|
|
5276
|
+
"navIcon": "_506LLG_navIcon",
|
|
5277
|
+
"navItemActive": "_506LLG_navItemActive",
|
|
5278
|
+
"settingRow": "_506LLG_settingRow",
|
|
5279
|
+
"textInput": "_506LLG_textInput",
|
|
5280
|
+
"settingDesc": "_506LLG_settingDesc"
|
|
5345
5281
|
};
|
|
5346
5282
|
//#endregion
|
|
5347
5283
|
//#region \0dsh-css:src/client/styles/Dropdown.module.css.mjs
|
|
@@ -5360,18 +5296,18 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5360
5296
|
css: css$4
|
|
5361
5297
|
});
|
|
5362
5298
|
var Dropdown_module_css_default = {
|
|
5363
|
-
"dropdownPanel": "B_Gxsq_dropdownPanel",
|
|
5364
5299
|
"dropdownItem": "B_Gxsq_dropdownItem",
|
|
5365
|
-
"
|
|
5300
|
+
"dropdownArrowOpen": "B_Gxsq_dropdownArrowOpen",
|
|
5301
|
+
"dropdownPanel": "B_Gxsq_dropdownPanel",
|
|
5302
|
+
"dropdownBtn": "B_Gxsq_dropdownBtn",
|
|
5366
5303
|
"dropdownFill": "B_Gxsq_dropdownFill",
|
|
5367
|
-
"dropdownLabel": "B_Gxsq_dropdownLabel",
|
|
5368
|
-
"dropdownItemLabel": "B_Gxsq_dropdownItemLabel",
|
|
5369
5304
|
"dropdownArrow": "B_Gxsq_dropdownArrow",
|
|
5370
|
-
"dropdownCount": "B_Gxsq_dropdownCount",
|
|
5371
5305
|
"dropdownItemActive": "B_Gxsq_dropdownItemActive",
|
|
5372
|
-
"
|
|
5306
|
+
"dropdownItemLabel": "B_Gxsq_dropdownItemLabel",
|
|
5307
|
+
"dropdownCount": "B_Gxsq_dropdownCount",
|
|
5373
5308
|
"dropdownCountActive": "B_Gxsq_dropdownCountActive",
|
|
5374
|
-
"
|
|
5309
|
+
"dropdown": "B_Gxsq_dropdown",
|
|
5310
|
+
"dropdownLabel": "B_Gxsq_dropdownLabel"
|
|
5375
5311
|
};
|
|
5376
5312
|
//#endregion
|
|
5377
5313
|
//#region \0dsh-css:src/client/styles/Toggle.module.css.mjs
|
|
@@ -5391,8 +5327,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5391
5327
|
});
|
|
5392
5328
|
var Toggle_module_css_default = {
|
|
5393
5329
|
"toggle": "k-cD4G_toggle",
|
|
5394
|
-
"
|
|
5395
|
-
"
|
|
5330
|
+
"toggleOn": "k-cD4G_toggleOn",
|
|
5331
|
+
"knob": "k-cD4G_knob"
|
|
5396
5332
|
};
|
|
5397
5333
|
//#endregion
|
|
5398
5334
|
//#region src/client/components/ui/Toggle.tsx
|
|
@@ -5401,9 +5337,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5401
5337
|
* Website: https://dsh-plugin.org
|
|
5402
5338
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
5403
5339
|
*
|
|
5404
|
-
*
|
|
5405
|
-
*
|
|
5406
|
-
* by the --hub-* tokens (on = brand fill, off = neutral track).
|
|
5340
|
+
* 设置行用的紧凑开关。基于原生 button,可键盘聚焦并通过 aria-checked 播报状态;
|
|
5341
|
+
* 样式由 --hub-* 变量驱动(开 = 品牌填充,关 = 中性轨道)。
|
|
5407
5342
|
*/
|
|
5408
5343
|
function Toggle({ checked, onChange, title, disabled }) {
|
|
5409
5344
|
return (0, react.createElement)("button", {
|
|
@@ -5423,13 +5358,11 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5423
5358
|
* Website: https://dsh-plugin.org
|
|
5424
5359
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
5425
5360
|
*
|
|
5426
|
-
*
|
|
5361
|
+
* 按钮式下拉框(替代原生 <select>)。
|
|
5427
5362
|
*
|
|
5428
|
-
*
|
|
5429
|
-
*
|
|
5430
|
-
*
|
|
5431
|
-
* outside or pressing Esc closes the panel; options get a hover fill and
|
|
5432
|
-
* the active one a brand highlight, all driven by the --hub-* tokens.
|
|
5363
|
+
* 触发器是紧凑的工具栏按钮 —— 细边框 + 淡灰填充 + 当前值 + 箭头 —— 与其它工具栏按钮
|
|
5364
|
+
* 并排自然,只占一格横向空间。点击外部或按 Esc 关闭面板;选项有 hover 填充、
|
|
5365
|
+
* 激活项为品牌高亮,全部由 --hub-* 变量驱动。
|
|
5433
5366
|
*/
|
|
5434
5367
|
function Dropdown({ value, options, onChange, title, className }) {
|
|
5435
5368
|
const [open, setOpen] = (0, react.useState)(false);
|
|
@@ -5492,29 +5425,29 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5492
5425
|
css: css$2
|
|
5493
5426
|
});
|
|
5494
5427
|
var DiagnosticsView_module_css_default = {
|
|
5495
|
-
"summaryFail": "k9eRya_summaryFail",
|
|
5496
|
-
"runBtn": "k9eRya_runBtn",
|
|
5497
|
-
"panel": "k9eRya_panel",
|
|
5498
5428
|
"badgeOk": "k9eRya_badgeOk",
|
|
5499
|
-
"badge": "k9eRya_badge",
|
|
5500
|
-
"badgeIdle": "k9eRya_badgeIdle",
|
|
5501
|
-
"summaryOk": "k9eRya_summaryOk",
|
|
5502
|
-
"meta": "k9eRya_meta",
|
|
5503
|
-
"envDesc": "k9eRya_envDesc",
|
|
5504
5429
|
"badgeFail": "k9eRya_badgeFail",
|
|
5505
|
-
"
|
|
5506
|
-
"summaryRunning": "k9eRya_summaryRunning",
|
|
5507
|
-
"envLabel": "k9eRya_envLabel",
|
|
5508
|
-
"display": "k9eRya_display",
|
|
5509
|
-
"envTitle": "k9eRya_envTitle",
|
|
5430
|
+
"badgeIdle": "k9eRya_badgeIdle",
|
|
5510
5431
|
"envCopyBtn": "k9eRya_envCopyBtn",
|
|
5432
|
+
"envLabel": "k9eRya_envLabel",
|
|
5511
5433
|
"headHint": "k9eRya_headHint",
|
|
5512
|
-
"
|
|
5434
|
+
"meta": "k9eRya_meta",
|
|
5435
|
+
"summaryFail": "k9eRya_summaryFail",
|
|
5436
|
+
"row": "k9eRya_row",
|
|
5513
5437
|
"badgeRunning": "k9eRya_badgeRunning",
|
|
5438
|
+
"panel": "k9eRya_panel",
|
|
5439
|
+
"envTitle": "k9eRya_envTitle",
|
|
5440
|
+
"display": "k9eRya_display",
|
|
5441
|
+
"name": "k9eRya_name",
|
|
5442
|
+
"badge": "k9eRya_badge",
|
|
5514
5443
|
"diagPulse": "k9eRya_diagPulse",
|
|
5515
|
-
"
|
|
5444
|
+
"summaryOk": "k9eRya_summaryOk",
|
|
5445
|
+
"summaryRunning": "k9eRya_summaryRunning",
|
|
5516
5446
|
"envRow": "k9eRya_envRow",
|
|
5517
|
-
"
|
|
5447
|
+
"summary": "k9eRya_summary",
|
|
5448
|
+
"head": "k9eRya_head",
|
|
5449
|
+
"runBtn": "k9eRya_runBtn",
|
|
5450
|
+
"envDesc": "k9eRya_envDesc"
|
|
5518
5451
|
};
|
|
5519
5452
|
//#endregion
|
|
5520
5453
|
//#region src/client/components/views/DiagnosticsView.tsx
|
|
@@ -5523,12 +5456,9 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5523
5456
|
* Website: https://dsh-plugin.org
|
|
5524
5457
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
5525
5458
|
*
|
|
5526
|
-
*
|
|
5527
|
-
*
|
|
5528
|
-
*
|
|
5529
|
-
* automatically when the page opens; every row is a button that re-probes
|
|
5530
|
-
* just that channel, so a click always yields visible feedback
|
|
5531
|
-
* (row pulses → badge flips → latency refreshes).
|
|
5459
|
+
* 系统诊断列表:每个连通性通道(npm registry / GitHub API / 目录站点)一行,各带实时
|
|
5460
|
+
* 状态徽标 —— 200 OK 绿、不可达红、探测中显示「检测中…」。页面打开时自动跑一轮;
|
|
5461
|
+
* 每行都是按钮,点击只重测该通道,因此点击总有可见反馈(行脉冲 → 徽标翻转 → 延迟刷新)。
|
|
5532
5462
|
*/
|
|
5533
5463
|
/** 系统版本文本:提交 Issue 时粘贴到正文,方便作者复现。 */
|
|
5534
5464
|
function formatEnv(env) {
|
|
@@ -5692,57 +5622,57 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5692
5622
|
css: css$1
|
|
5693
5623
|
});
|
|
5694
5624
|
var LogsView_module_css_default = {
|
|
5695
|
-
"
|
|
5696
|
-
"
|
|
5697
|
-
"
|
|
5625
|
+
"headActions": "_3j77BW_headActions",
|
|
5626
|
+
"head": "_3j77BW_head",
|
|
5627
|
+
"badgeDebug": "_3j77BW_badgeDebug",
|
|
5628
|
+
"btn": "_3j77BW_btn",
|
|
5629
|
+
"pathDialogFoot": "_3j77BW_pathDialogFoot",
|
|
5698
5630
|
"pathDialogRow": "_3j77BW_pathDialogRow",
|
|
5699
|
-
"
|
|
5631
|
+
"catUninstall": "_3j77BW_catUninstall",
|
|
5632
|
+
"footPath": "_3j77BW_footPath",
|
|
5633
|
+
"pathLabel": "_3j77BW_pathLabel",
|
|
5634
|
+
"panel": "_3j77BW_panel",
|
|
5635
|
+
"catDiagnostics": "_3j77BW_catDiagnostics",
|
|
5636
|
+
"catSystem": "_3j77BW_catSystem",
|
|
5637
|
+
"footFail": "_3j77BW_footFail",
|
|
5700
5638
|
"pathRow": "_3j77BW_pathRow",
|
|
5701
|
-
"
|
|
5702
|
-
"pathText": "_3j77BW_pathText",
|
|
5703
|
-
"filterChipActive": "_3j77BW_filterChipActive",
|
|
5639
|
+
"linkBtn": "_3j77BW_linkBtn",
|
|
5704
5640
|
"searchInput": "_3j77BW_searchInput",
|
|
5705
|
-
"footActions": "_3j77BW_footActions",
|
|
5706
|
-
"filterChip": "_3j77BW_filterChip",
|
|
5707
|
-
"footFail": "_3j77BW_footFail",
|
|
5708
|
-
"pathDialogDesc": "_3j77BW_pathDialogDesc",
|
|
5709
|
-
"badgeSuccess": "_3j77BW_badgeSuccess",
|
|
5710
|
-
"badgeInfo": "_3j77BW_badgeInfo",
|
|
5711
|
-
"catBadge": "_3j77BW_catBadge",
|
|
5712
5641
|
"footCount": "_3j77BW_footCount",
|
|
5713
5642
|
"list": "_3j77BW_list",
|
|
5714
|
-
"
|
|
5715
|
-
"
|
|
5716
|
-
"
|
|
5717
|
-
"
|
|
5718
|
-
"
|
|
5719
|
-
"
|
|
5720
|
-
"
|
|
5721
|
-
"
|
|
5722
|
-
"foot": "_3j77BW_foot",
|
|
5723
|
-
"head": "_3j77BW_head",
|
|
5724
|
-
"catInstall": "_3j77BW_catInstall",
|
|
5725
|
-
"pathDialogReset": "_3j77BW_pathDialogReset",
|
|
5726
|
-
"catDiagnostics": "_3j77BW_catDiagnostics",
|
|
5727
|
-
"pathLabel": "_3j77BW_pathLabel",
|
|
5728
|
-
"logList": "_3j77BW_logList",
|
|
5643
|
+
"entry": "_3j77BW_entry",
|
|
5644
|
+
"pathDialog": "_3j77BW_pathDialog",
|
|
5645
|
+
"actions": "_3j77BW_actions",
|
|
5646
|
+
"pathDialogDesc": "_3j77BW_pathDialogDesc",
|
|
5647
|
+
"filterChip": "_3j77BW_filterChip",
|
|
5648
|
+
"filterChipActive": "_3j77BW_filterChipActive",
|
|
5649
|
+
"moreEnd": "_3j77BW_moreEnd",
|
|
5650
|
+
"time": "_3j77BW_time",
|
|
5729
5651
|
"clearBtn": "_3j77BW_clearBtn",
|
|
5730
|
-
"
|
|
5731
|
-
"
|
|
5732
|
-
"
|
|
5733
|
-
"
|
|
5734
|
-
"footPath": "_3j77BW_footPath",
|
|
5735
|
-
"search": "_3j77BW_search",
|
|
5652
|
+
"foot": "_3j77BW_foot",
|
|
5653
|
+
"badge": "_3j77BW_badge",
|
|
5654
|
+
"badgeSuccess": "_3j77BW_badgeSuccess",
|
|
5655
|
+
"headHint": "_3j77BW_headHint",
|
|
5736
5656
|
"badgeError": "_3j77BW_badgeError",
|
|
5737
5657
|
"badgeWarn": "_3j77BW_badgeWarn",
|
|
5738
|
-
"
|
|
5658
|
+
"badgeInfo": "_3j77BW_badgeInfo",
|
|
5739
5659
|
"catUpdate": "_3j77BW_catUpdate",
|
|
5740
|
-
"
|
|
5660
|
+
"search": "_3j77BW_search",
|
|
5661
|
+
"catSettings": "_3j77BW_catSettings",
|
|
5662
|
+
"event": "_3j77BW_event",
|
|
5663
|
+
"logList": "_3j77BW_logList",
|
|
5664
|
+
"catBadge": "_3j77BW_catBadge",
|
|
5665
|
+
"footActions": "_3j77BW_footActions",
|
|
5666
|
+
"empty": "_3j77BW_empty",
|
|
5667
|
+
"more": "_3j77BW_more",
|
|
5741
5668
|
"message": "_3j77BW_message",
|
|
5742
|
-
"
|
|
5743
|
-
"
|
|
5669
|
+
"pathText": "_3j77BW_pathText",
|
|
5670
|
+
"filterBar": "_3j77BW_filterBar",
|
|
5671
|
+
"previewRow": "_3j77BW_previewRow",
|
|
5744
5672
|
"pathDraft": "_3j77BW_pathDraft",
|
|
5745
|
-
"
|
|
5673
|
+
"pathDialogReset": "_3j77BW_pathDialogReset",
|
|
5674
|
+
"catInstall": "_3j77BW_catInstall",
|
|
5675
|
+
"pathDialogHint": "_3j77BW_pathDialogHint"
|
|
5746
5676
|
};
|
|
5747
5677
|
//#endregion
|
|
5748
5678
|
//#region src/client/components/modals/LogsModal.tsx
|
|
@@ -5751,20 +5681,15 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
5751
5681
|
* Website: https://dsh-plugin.org
|
|
5752
5682
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
5753
5683
|
*
|
|
5754
|
-
*
|
|
5755
|
-
*
|
|
5756
|
-
* ~/.dsh/profiles/<profile>/hub.log) straight from the server, one page at
|
|
5757
|
-
* a time.
|
|
5684
|
+
* 内置日志查看器弹窗:无需外部软件 —— 应用自己开窗,从服务端直接分页加载本地系统日志
|
|
5685
|
+
* (JSONL,位于 ~/.dsh/profiles/<profile>/hub.log)。
|
|
5758
5686
|
*
|
|
5759
|
-
*
|
|
5760
|
-
*
|
|
5761
|
-
*
|
|
5762
|
-
* say, only install errors — so the exact incompatible step of an install
|
|
5763
|
-
* (or uninstall) is easy to spot. Search narrows by event code or message.
|
|
5687
|
+
* 每行双重归类:功能域(安装/卸载/更新/诊断/设置/系统)与严重级别(debug/info/success/
|
|
5688
|
+
* warn/error)。两轴筛选可只盯某类,比如只看安装错误 —— 便于定位安装(或卸载)中真正
|
|
5689
|
+
* 卡住的那一步;搜索按事件码或消息缩小范围。
|
|
5764
5690
|
*
|
|
5765
|
-
*
|
|
5766
|
-
*
|
|
5767
|
-
* real file location and reveals it in the system file manager.
|
|
5691
|
+
* 服务端分页:GET /dsh-plugin-hub/logs?offset=&limit=&category=&level=&query=
|
|
5692
|
+
* → { entries, total, hasMore, path }。底部展示日志真实路径并可在系统文件管理器中定位。
|
|
5768
5693
|
*/
|
|
5769
5694
|
const PAGE = 100;
|
|
5770
5695
|
/** 类别筛选标签:值 → 语言包 key(弹窗内 chip 与行内类别徽章共用)。 */
|
|
@@ -6301,17 +6226,14 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6301
6226
|
* Website: https://dsh-plugin.org
|
|
6302
6227
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
6303
6228
|
*
|
|
6304
|
-
*
|
|
6305
|
-
*
|
|
6306
|
-
* active section's rows. New settings only add rows, new areas only add a
|
|
6307
|
-
* sidebar entry.
|
|
6229
|
+
* 设置视图:桌面设置式导航 —— 固定左侧栏列出各分组(图标 + 名称,点击切换),
|
|
6230
|
+
* 右侧面板展示当前分组的设置行。新增设置只加行,新增区域只加一条侧栏项。
|
|
6308
6231
|
*
|
|
6309
|
-
*
|
|
6310
|
-
*
|
|
6311
|
-
*
|
|
6312
|
-
*
|
|
6313
|
-
*
|
|
6314
|
-
* Logs — system log viewer + storage location
|
|
6232
|
+
* 各分组对应本地服务端实际强制的行为:
|
|
6233
|
+
* 更新与源 —— 启动检查更新 / npm 镜像 / HTTP 代理(都接进安装命令链路)
|
|
6234
|
+
* 安全与信任 —— 受限的自定义安装(服务端 403 门禁)
|
|
6235
|
+
* 诊断 —— 实时连通性探测 + 环境快照
|
|
6236
|
+
* 日志 —— 系统日志查看器 + 存放位置
|
|
6315
6237
|
*/
|
|
6316
6238
|
/** npm 镜像源预设:空串 = 未配置(跟随用户本机 npm 配置,本插件不注入任何 registry)。
|
|
6317
6239
|
* 只提供常见国内顶级镜像下拉,不做自定义输入 —— 想用其它镜像直接在 ~/.npmrc 配置即可。 */
|
|
@@ -6477,22 +6399,6 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6477
6399
|
onChange: (v) => update({ enableNpmInstall: v }),
|
|
6478
6400
|
title: t("settingsEnableNpm")
|
|
6479
6401
|
})
|
|
6480
|
-
}), (0, react.createElement)(SettingRow, {
|
|
6481
|
-
title: t("settingsEnableGit"),
|
|
6482
|
-
desc: t("settingsEnableGitDesc"),
|
|
6483
|
-
children: (0, react.createElement)(Toggle, {
|
|
6484
|
-
checked: settings.enableGitInstall,
|
|
6485
|
-
onChange: (v) => update({ enableGitInstall: v }),
|
|
6486
|
-
title: t("settingsEnableGit")
|
|
6487
|
-
})
|
|
6488
|
-
}), (0, react.createElement)(SettingRow, {
|
|
6489
|
-
title: t("settingsEnableDsh"),
|
|
6490
|
-
desc: t("settingsEnableDshDesc"),
|
|
6491
|
-
children: (0, react.createElement)(Toggle, {
|
|
6492
|
-
checked: settings.enableDshInstall,
|
|
6493
|
-
onChange: (v) => update({ enableDshInstall: v }),
|
|
6494
|
-
title: t("settingsEnableDsh")
|
|
6495
|
-
})
|
|
6496
6402
|
}));
|
|
6497
6403
|
const diagnosticsCard = (0, react.createElement)("div", { className: SettingsView_module_css_default.card }, (0, react.createElement)(DiagnosticsView, {
|
|
6498
6404
|
t,
|
|
@@ -6558,10 +6464,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6558
6464
|
* Website: https://dsh-plugin.org
|
|
6559
6465
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
6560
6466
|
*
|
|
6561
|
-
*
|
|
6562
|
-
*
|
|
6563
|
-
* rendering is delegated to the small presentational components in this
|
|
6564
|
-
* folder; it hosts the dialogs/toast and the section-level copy actions.
|
|
6467
|
+
* 插件中心板块:把目录数据管道、后台任务队列与反馈状态接在一起。数据/队列逻辑在 hooks/,
|
|
6468
|
+
* 渲染交给本目录下的小型展示组件;本文件托管各弹窗/Toast 与板块级复制动作。
|
|
6565
6469
|
*/
|
|
6566
6470
|
function PluginHubSection({ t: _hostT, locale }) {
|
|
6567
6471
|
const { lang, langKey, langPath, t, toggleLang } = useLanguage(locale);
|
|
@@ -6599,10 +6503,10 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6599
6503
|
const [confirmPlugin, setConfirmPlugin] = (0, react.useState)(null);
|
|
6600
6504
|
/** 弹窗动作是否为「更新」:已安装插件点「更新」→ 走同一条 add 命令原位覆盖重装,文案区分安装/更新 */
|
|
6601
6505
|
const [confirmIsUpdate, setConfirmIsUpdate] = (0, react.useState)(false);
|
|
6602
|
-
/** 命令行安装确认弹窗:记录待安装的裸目标(npm
|
|
6506
|
+
/** 命令行安装确认弹窗:记录待安装的裸目标(npm 包名)——
|
|
6603
6507
|
* 与应用商店同一套确认/进度/结果弹窗,提供时 plugin 传 null 走 customTarget 模式 */
|
|
6604
6508
|
const [confirmCustomTarget, setConfirmCustomTarget] = (0, react.useState)(null);
|
|
6605
|
-
/**
|
|
6509
|
+
/** 自定义安装入口渠道(NPM 包卡片):随确认弹窗记录,提交时上报服务端,
|
|
6606
6510
|
* 报错/日志据此精准溯源「从哪个入口发起」(npm 全局安装固定为 'npm') */
|
|
6607
6511
|
const [confirmCustomChannel, setConfirmCustomChannel] = (0, react.useState)(null);
|
|
6608
6512
|
/** 全局 npm 安装确认弹窗(官方 `npm install -g <pkgs>`):记录原始命令 + 解析出的包列表,
|
|
@@ -6635,7 +6539,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6635
6539
|
const [uninstallNeedsReload, setUninstallNeedsReload] = (0, react.useState)(false);
|
|
6636
6540
|
/** 结果视图「立即重启」:请求宿主重启后进入等待,服务回来后整页刷新 */
|
|
6637
6541
|
const [restarting, setRestarting] = (0, react.useState)(false);
|
|
6638
|
-
/**
|
|
6542
|
+
/** 操作失败信息 + 归属仓库 + 动作(决定弹窗标题与上报措辞)+ 命令与尝试记录(issue 预填用) */
|
|
6639
6543
|
const [errorMsg, setErrorMsg] = (0, react.useState)(null);
|
|
6640
6544
|
/** 通知中心记录:localStorage 持久化,每次安装/卸载任务成败都留痕(启动时读回) */
|
|
6641
6545
|
const [notifications, setNotifications] = (0, react.useState)(() => loadNotifications());
|
|
@@ -6702,7 +6606,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6702
6606
|
setErrorMsg({
|
|
6703
6607
|
message,
|
|
6704
6608
|
repo: issueRepo,
|
|
6705
|
-
kind,
|
|
6609
|
+
action: update ? "update" : kind,
|
|
6706
6610
|
command,
|
|
6707
6611
|
attempts
|
|
6708
6612
|
});
|
|
@@ -6751,6 +6655,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6751
6655
|
(0, react.useEffect)(() => {
|
|
6752
6656
|
if (startupCheckedRef.current) return;
|
|
6753
6657
|
if (!settingsReady || catalog.plugins === null || catalog.failed) return;
|
|
6658
|
+
if (!catalog.releaseAgeReady) return;
|
|
6754
6659
|
startupCheckedRef.current = true;
|
|
6755
6660
|
if (!hubSettings.checkUpdatesOnStart) return;
|
|
6756
6661
|
syncUpdateNotices();
|
|
@@ -6760,6 +6665,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6760
6665
|
catalog.plugins,
|
|
6761
6666
|
catalog.failed,
|
|
6762
6667
|
catalog.installedItems,
|
|
6668
|
+
catalog.releaseAgeReady,
|
|
6763
6669
|
queue
|
|
6764
6670
|
]);
|
|
6765
6671
|
(0, react.useEffect)(() => {
|
|
@@ -6834,7 +6740,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6834
6740
|
const pkg = repo.replace(/@[^@]*$/, "").toLowerCase();
|
|
6835
6741
|
return catalog.installedItems.some((i) => i.name.toLowerCase() === pkg) || Object.keys(catalog.installed).some((k) => k.toLowerCase() === pkg);
|
|
6836
6742
|
};
|
|
6837
|
-
/** 弹窗动作一:复制安装命令到剪贴板,引导去终端粘贴执行(npm
|
|
6743
|
+
/** 弹窗动作一:复制安装命令到剪贴板,引导去终端粘贴执行(npm 安装显示包名命令)。 */
|
|
6838
6744
|
const copyCommand = async (p) => {
|
|
6839
6745
|
const repo = p.source?.repo ?? "";
|
|
6840
6746
|
if (await doCopy(installCommandOf(p))) {
|
|
@@ -6928,7 +6834,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6928
6834
|
t,
|
|
6929
6835
|
noticeCount: notifications.length + queue.queue.length + queue.pendingRestarts.length,
|
|
6930
6836
|
onOpenNotifications: () => {
|
|
6931
|
-
if (hubSettings.checkUpdatesOnStart) syncUpdateNotices();
|
|
6837
|
+
if (hubSettings.checkUpdatesOnStart && catalog.releaseAgeReady) syncUpdateNotices();
|
|
6932
6838
|
setShowNotifications(true);
|
|
6933
6839
|
}
|
|
6934
6840
|
})), view === "market" ? (0, react.createElement)(MarketView, {
|
|
@@ -6979,10 +6885,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
6979
6885
|
}) : view === "custom" ? (0, react.createElement)(CustomInstallView, {
|
|
6980
6886
|
t,
|
|
6981
6887
|
enableNpm: hubSettings.enableNpmInstall,
|
|
6982
|
-
enableGit: hubSettings.enableGitInstall,
|
|
6983
|
-
enableDsh: hubSettings.enableDshInstall,
|
|
6984
6888
|
onOpenSettings: () => setView("settings"),
|
|
6985
|
-
profile: env?.profile ?? "web",
|
|
6986
6889
|
onInstallCustom: (raw, opts) => {
|
|
6987
6890
|
const target = raw.trim();
|
|
6988
6891
|
if (!target) return;
|
|
@@ -7019,7 +6922,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
7019
6922
|
openSection: settingsSection,
|
|
7020
6923
|
onConsumedOpenSection: () => setSettingsSection(null)
|
|
7021
6924
|
}), showHubUpdate && (0, react.createElement)(HubUpdateModal, {
|
|
7022
|
-
info: catalog.hubUpdateInfo ?? { version: "
|
|
6925
|
+
info: catalog.hubUpdateInfo ?? { version: "2.0.0" },
|
|
7023
6926
|
state: catalog.hubUpdateState,
|
|
7024
6927
|
currentVersion: catalog.hubCurrentVersion,
|
|
7025
6928
|
lang,
|
|
@@ -7243,7 +7146,7 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
7243
7146
|
}), errorMsg && (0, react.createElement)(ErrorModal, {
|
|
7244
7147
|
message: errorMsg.message,
|
|
7245
7148
|
repo: errorMsg.repo,
|
|
7246
|
-
|
|
7149
|
+
action: errorMsg.action,
|
|
7247
7150
|
command: errorMsg.command,
|
|
7248
7151
|
attempts: errorMsg.attempts,
|
|
7249
7152
|
t,
|
|
@@ -7290,9 +7193,8 @@ window.__ModuleLoader__.load({ id: "dsh-plugin", factory: (require) => {
|
|
|
7290
7193
|
* Website: https://dsh-plugin.org
|
|
7291
7194
|
* GitHub: https://github.com/dshplugin/dsh-plugin-hub
|
|
7292
7195
|
*
|
|
7293
|
-
* dsh-plugin
|
|
7294
|
-
*
|
|
7295
|
-
* PluginHubSection; this file only performs the cordis apply wiring.
|
|
7196
|
+
* dsh-plugin 客户端入口:通过模块加载器 bundle(见 tsdown.config.ts)把插件中心接入宿主设置。
|
|
7197
|
+
* 全部 UI 逻辑都在 PluginHubSection;本文件只做 cordis apply 接线。
|
|
7296
7198
|
*/
|
|
7297
7199
|
const NS = "dsh-plugin";
|
|
7298
7200
|
const name = NS;
|