@noob-stupid/dsh-plugin-console 0.3.52 → 0.3.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README.zh.md +2 -2
- package/lib/client.js +120 -44
- package/lib/index.js +49 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -308,7 +308,7 @@ MIT
|
|
|
308
308
|
|
|
309
309
|
The layered-refactor preview lives in its **own repository**: [**`Noob-stupid/dsh-plugin-hub-refactor`**](https://github.com/Noob-stupid/dsh-plugin-hub-refactor)
|
|
310
310
|
|
|
311
|
-
- **What it is**: the monolithic `lib/index.js` (7637 lines) split into layers — `lib/index.js` **142 lines** + `lib/server/**` **36 modules**; **feature-equivalent to `0.3.
|
|
311
|
+
- **What it is**: the monolithic `lib/index.js` (7637 lines) split into layers — `lib/index.js` **142 lines** + `lib/server/**` **36 modules**; **feature-equivalent to `0.3.53`**, maintainability only;
|
|
312
312
|
- **Verified**: 18 test suites green · 8 architecture-guard assertions · **47/47 routes identical** (`status` + response fields) against the stable build;
|
|
313
313
|
- **Not yet exercised**: real framework upgrade / rollback, restart guardian, real install/uninstall, component start/stop, real AI run, Gitee OAuth (~10–25% long-tail risk, subjective);
|
|
314
|
-
- **For everyday use** stick to npm `@noob-stupid/dsh-plugin-console@0.3.
|
|
314
|
+
- **For everyday use** stick to npm `@noob-stupid/dsh-plugin-console@0.3.53`, or `main` of this repo.
|
package/README.zh.md
CHANGED
|
@@ -275,8 +275,8 @@ MIT
|
|
|
275
275
|
|
|
276
276
|
分层重构预览线在**独立仓库**:[**`Noob-stupid/dsh-plugin-hub-refactor`**](https://github.com/Noob-stupid/dsh-plugin-hub-refactor)
|
|
277
277
|
|
|
278
|
-
- **它是什么**:把单体 `lib/index.js`(7637 行)拆成分层结构 —— `lib/index.js` **142 行** + `lib/server/**` **36 个模块**,**功能与 `0.3.
|
|
278
|
+
- **它是什么**:把单体 `lib/index.js`(7637 行)拆成分层结构 —— `lib/index.js` **142 行** + `lib/server/**` **36 个模块**,**功能与 `0.3.53` 等价**,只为可维护性;
|
|
279
279
|
- **已验证**:18 套测试全绿 · 8 条架构守卫断言 · 与稳定版逐条对打 **47 条路由,`status` + 响应字段 47/47 一致**;
|
|
280
280
|
- **尚未实测**:真框架升级 / 真回滚、重启守护链路、真装真卸、组件进程启停、AI 真跑、Gitee OAuth 回调(长尾风险主观估计 **10%~25%**);
|
|
281
|
-
- **日常使用请继续用**:npm `@noob-stupid/dsh-plugin-console@0.3.
|
|
281
|
+
- **日常使用请继续用**:npm `@noob-stupid/dsh-plugin-console@0.3.53`,或本仓库 `main`。
|
|
282
282
|
- 请多反馈问题
|
package/lib/client.js
CHANGED
|
@@ -203,6 +203,10 @@ window.__ModuleLoader__.load({
|
|
|
203
203
|
loadingDetails: "正在读取详情…",
|
|
204
204
|
githubLoggedIn: "已登录 GitHub:",
|
|
205
205
|
githubCornerOut: "未登录 GitHub",
|
|
206
|
+
githubLoginViaApp: "GitHub 登录",
|
|
207
|
+
githubLoginOpened: "已打开 GitHub 授权窗口,请在页面上输入验证码完成授权…",
|
|
208
|
+
githubLoginUnavailable: "无法使用窗口登录",
|
|
209
|
+
githubLoginOrToken: "或用 Token 登录",
|
|
206
210
|
githubLoginTip: "粘贴 GitHub Token 登录(fine-grained,需 read:user 权限)。登录后可用代码搜索(按子包名搜索)并提高 API 限额;也可用 dsh-github-login 插件登录。",
|
|
207
211
|
githubTokenPlaceholder: "粘贴 token(ghp_… 或 github_pat_…)",
|
|
208
212
|
githubLoginBtn: "登录",
|
|
@@ -584,6 +588,10 @@ window.__ModuleLoader__.load({
|
|
|
584
588
|
hubUpdateAvailable: "Download update",
|
|
585
589
|
cleanResiduals: "Clean residual backups",
|
|
586
590
|
githubCornerOut: "Not signed in to GitHub",
|
|
591
|
+
githubLoginViaApp: "GitHub login",
|
|
592
|
+
githubLoginOpened: "Authorization window opened — enter the code on the GitHub page to finish",
|
|
593
|
+
githubLoginUnavailable: "Window login unavailable",
|
|
594
|
+
githubLoginOrToken: "Or sign in with a token",
|
|
587
595
|
githubLoginTip: "Paste a GitHub token to sign in (fine-grained, needs the read:user scope). Signing in enables code search (search by subpackage name) and raises API rate limits; you can also sign in with the dsh-github-login plugin.",
|
|
588
596
|
githubTokenPlaceholder: "Paste token (ghp_… or github_pat_…)",
|
|
589
597
|
githubLoginBtn: "Sign in",
|
|
@@ -1906,16 +1914,6 @@ window.__ModuleLoader__.load({
|
|
|
1906
1914
|
document.addEventListener("mousedown", onDown);
|
|
1907
1915
|
return () => document.removeEventListener("mousedown", onDown);
|
|
1908
1916
|
}, [sourceMenuOpen]);
|
|
1909
|
-
// GitHub 登录面板:点击外部收起(与搜索源菜单同一模式)
|
|
1910
|
-
react.useEffect(() => {
|
|
1911
|
-
if (!ghLoginOpen) return;
|
|
1912
|
-
const onDown = (event) => {
|
|
1913
|
-
const area = document.getElementById("pc-ghlogin");
|
|
1914
|
-
if (area && !area.contains(event.target)) setGhLoginOpen(false);
|
|
1915
|
-
};
|
|
1916
|
-
document.addEventListener("mousedown", onDown);
|
|
1917
|
-
return () => document.removeEventListener("mousedown", onDown);
|
|
1918
|
-
}, [ghLoginOpen]);
|
|
1919
1917
|
// 已安装搜索:点击搜索区以外且无内容时立即收起(无延迟)
|
|
1920
1918
|
react.useEffect(() => {
|
|
1921
1919
|
if (!installedSearchOpen) return;
|
|
@@ -1943,6 +1941,69 @@ window.__ModuleLoader__.load({
|
|
|
1943
1941
|
);
|
|
1944
1942
|
}, []);
|
|
1945
1943
|
react.useEffect(() => { refresh(); }, [refresh]);
|
|
1944
|
+
// ── GitHub 登录态的两个读数:面板里多处要用(徽章文案、菜单项、内联子面板)──
|
|
1945
|
+
const ghAuthed = state.status === "ready" && state.data.github !== undefined && state.data.github.loggedIn === true;
|
|
1946
|
+
const ghLoginName = state.status === "ready" && state.data.github !== undefined && state.data.github.login !== null && state.data.github.login !== undefined
|
|
1947
|
+
? state.data.github.login
|
|
1948
|
+
: "unknown";
|
|
1949
|
+
// 设备码登录的轮询句柄:拿到登录态就停,用户手动收起菜单也停(不留后台空转的定时器)
|
|
1950
|
+
const ghPollRef = react.useRef(null);
|
|
1951
|
+
const stopGhPoll = react.useCallback(() => {
|
|
1952
|
+
if (ghPollRef.current !== null) { window.clearInterval(ghPollRef.current); ghPollRef.current = null; }
|
|
1953
|
+
}, []);
|
|
1954
|
+
// 组件卸载时收尾(本面板是长驻 UI,正常不卸载,但热重载/关闭面板会)
|
|
1955
|
+
react.useEffect(() => () => stopGhPoll(), [stopGhPoll]);
|
|
1956
|
+
// 菜单收起 = 用户手动关掉了这次登录尝试 → 立刻停止轮询(对应"最多 60s 或用户手动关闭")
|
|
1957
|
+
react.useEffect(() => { if (!sourceMenuOpen) stopGhPoll(); }, [sourceMenuOpen, stopGhPoll]);
|
|
1958
|
+
// 窗口登录开始后等登录态:每 2s 问一次 /state,最多 60s。
|
|
1959
|
+
// 为什么只能轮询:设备码流程在**另一个进程**里完成(用户在 GitHub 页面上输验证码授权),
|
|
1960
|
+
// 本插件收不到任何回调,只能盯 <DSH_HOME>/github-auth.json(/state 的 github 字段)有没有变。
|
|
1961
|
+
const startGhPoll = () => {
|
|
1962
|
+
stopGhPoll();
|
|
1963
|
+
const deadline = Date.now() + 60000;
|
|
1964
|
+
ghPollRef.current = window.setInterval(() => {
|
|
1965
|
+
call("/plugin-console/state").then(
|
|
1966
|
+
(snap) => {
|
|
1967
|
+
const github = snap !== null && snap !== undefined ? snap.github : null;
|
|
1968
|
+
if (github !== null && github !== undefined && github.loggedIn === true) {
|
|
1969
|
+
stopGhPoll();
|
|
1970
|
+
setMessage(t("githubLoginOk").replace("{login}", github.login ?? ""));
|
|
1971
|
+
refresh();
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
if (Date.now() >= deadline) stopGhPoll();
|
|
1975
|
+
},
|
|
1976
|
+
// 单次失败不中断:授权期间用户可能正在重启服务,下一拍再问
|
|
1977
|
+
() => { if (Date.now() >= deadline) stopGhPoll(); },
|
|
1978
|
+
);
|
|
1979
|
+
}, 2000);
|
|
1980
|
+
};
|
|
1981
|
+
// 菜单里的主入口「GitHub 登录」:首选设备码窗口流程(在 GitHub 页面上输验证码),
|
|
1982
|
+
// 通道不可用才降级到 token 粘贴子面板(token 是兜底,不是正路)。
|
|
1983
|
+
const githubOpenLogin = () => {
|
|
1984
|
+
if (ghLoginBusy) return;
|
|
1985
|
+
setGhLoginBusy(true);
|
|
1986
|
+
// 先给一句反馈:环回调用最长要等 8s,中间没有提示会让人以为点了没反应
|
|
1987
|
+
setMessage(t("githubLoginOpened"));
|
|
1988
|
+
call("/plugin-console/github-open-login", {}).then(
|
|
1989
|
+
(r) => {
|
|
1990
|
+
setGhLoginBusy(false);
|
|
1991
|
+
if (r !== null && r !== undefined && r.started === true) {
|
|
1992
|
+
setMessage(t("githubLoginOpened"));
|
|
1993
|
+
startGhPoll();
|
|
1994
|
+
return;
|
|
1995
|
+
}
|
|
1996
|
+
// 服务端回 started:false 时一定带 reason(插件没装/没有 exe/平台不支持),照念给用户
|
|
1997
|
+
setMessage(t("githubLoginUnavailable") + ":" + (r !== null && r !== undefined && typeof r.reason === "string" ? r.reason : ""));
|
|
1998
|
+
setGhLoginOpen(true);
|
|
1999
|
+
},
|
|
2000
|
+
(error) => {
|
|
2001
|
+
setGhLoginBusy(false);
|
|
2002
|
+
setMessage(t("githubLoginFail") + ":" + (error?.message ?? ""));
|
|
2003
|
+
setGhLoginOpen(true);
|
|
2004
|
+
},
|
|
2005
|
+
);
|
|
2006
|
+
};
|
|
1946
2007
|
// 粘贴 token 登录:成功后清空输入 + 收起面板 + 刷新登录态(让徽章/代码搜索立刻用上新身份);
|
|
1947
2008
|
// 失败**不清空输入**——用户多半是复制时多带了空格/少了一段,保留原文才好改。
|
|
1948
2009
|
const githubLogin = () => {
|
|
@@ -3683,14 +3744,19 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
|
|
|
3683
3744
|
el("button", {
|
|
3684
3745
|
type: "button",
|
|
3685
3746
|
className: styles.ghpill,
|
|
3747
|
+
// 外观回退:市场页只有**这一颗** pill,登录态体现在它的绿色描边上(data-on),
|
|
3748
|
+
// 不再单独占一颗登录徽章
|
|
3749
|
+
"data-on": ghAuthed ? "true" : "false",
|
|
3686
3750
|
title: t("searchSourceTitle"),
|
|
3687
3751
|
"aria-label": t("searchSourceTitle"),
|
|
3688
3752
|
onClick: () => setSourceMenuOpen((v) => !v),
|
|
3689
3753
|
},
|
|
3690
|
-
//
|
|
3691
|
-
//
|
|
3692
|
-
|
|
3693
|
-
|
|
3754
|
+
// 源选在 GitHub 时这颗 pill 顺手报登录态(回到上一批之前的形态);
|
|
3755
|
+
// 选别的源时只报源名 —— 否则"未登录 GitHub"看着像徽章却点开的是源菜单
|
|
3756
|
+
searchSource === "github"
|
|
3757
|
+
? (ghAuthed ? t("githubLoggedIn") + ghLoginName : t("githubCornerOut"))
|
|
3758
|
+
: t("sourceOf") + ((searchSourcesList !== null ? searchSourcesList.find((s) => s.id === searchSource)?.name : undefined)
|
|
3759
|
+
?? (searchSource === "gitee" ? "Gitee" : searchSource)),
|
|
3694
3760
|
" ▾"),
|
|
3695
3761
|
sourceMenuOpen
|
|
3696
3762
|
? el("div", { className: styles.sourceMenu },
|
|
@@ -3708,37 +3774,47 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
|
|
|
3708
3774
|
try { localStorage.setItem("pc-search-source", s.id); } catch {}
|
|
3709
3775
|
setSourceMenuOpen(false);
|
|
3710
3776
|
},
|
|
3711
|
-
}, s.name))
|
|
3777
|
+
}, s.name)),
|
|
3778
|
+
// ── 登录区(登录入口收进这颗 pill 的菜单里,不再单独一颗徽章)──
|
|
3779
|
+
el("div", { style: { height: 1, margin: "4px 2px", background: "var(--dsw-alias-border-l2)" } }),
|
|
3780
|
+
ghAuthed
|
|
3781
|
+
// 已登录:这行只报状态(点了把状态念到消息栏,不做别的)
|
|
3782
|
+
? el("button", {
|
|
3783
|
+
type: "button",
|
|
3784
|
+
className: styles.sourceOpt,
|
|
3785
|
+
"data-active": "true",
|
|
3786
|
+
title: t("githubLoginTip"),
|
|
3787
|
+
onClick: () => setMessage(t("githubLoggedIn") + ghLoginName),
|
|
3788
|
+
}, t("githubLoggedIn") + ghLoginName)
|
|
3789
|
+
// 未登录:主入口走设备码窗口登录;窗口不可用时它自己会展开下面的 token 子面板
|
|
3790
|
+
: el("button", {
|
|
3791
|
+
type: "button",
|
|
3792
|
+
className: styles.sourceOpt,
|
|
3793
|
+
disabled: ghLoginBusy,
|
|
3794
|
+
title: t("githubLoginTip"),
|
|
3795
|
+
onClick: githubOpenLogin,
|
|
3796
|
+
}, t("githubLoginViaApp")),
|
|
3797
|
+
// 次要入口:token 兜底(已登录时也留着 —— 换账号/换 token 就靠它)
|
|
3798
|
+
el("button", {
|
|
3799
|
+
type: "button",
|
|
3800
|
+
className: styles.sourceOpt,
|
|
3801
|
+
onClick: () => setGhLoginOpen((v) => !v),
|
|
3802
|
+
}, t("githubLoginOrToken")),
|
|
3803
|
+
// token 兜底子面板:窗口登录不可用(插件没装/非 Windows/没有 exe)时自动展开;
|
|
3804
|
+
// 也可以从上面「或用 Token 登录」主动开合。样式内联,不为它改 CSS 表。
|
|
3805
|
+
ghLoginOpen
|
|
3806
|
+
? el("div", { style: { display: "flex", flexDirection: "column", gap: 6, width: 280, boxSizing: "border-box", padding: "2px 2px 4px" } },
|
|
3807
|
+
el("p", { className: styles.message, style: { margin: 0 } }, t("githubLoginTip")),
|
|
3808
|
+
el("input", {
|
|
3809
|
+
type: "password",
|
|
3810
|
+
placeholder: t("githubTokenPlaceholder"),
|
|
3811
|
+
value: ghToken,
|
|
3812
|
+
onChange: (event) => setGhToken(event.currentTarget.value),
|
|
3813
|
+
style: { width: "100%", boxSizing: "border-box" },
|
|
3814
|
+
}),
|
|
3815
|
+
el("button", { type: "button", className: styles.toggle, disabled: ghLoginBusy || ghToken.trim() === "", onClick: githubLogin }, t("githubLoginBtn")))
|
|
3816
|
+
: null)
|
|
3712
3817
|
: null,
|
|
3713
|
-
// 「未登录 GitHub / 已登录 GitHub:xxx」徽章:原来只是展示(点了没反应),
|
|
3714
|
-
// 现在点开内联登录面板(粘贴 PAT 即登录),面板样式内联,避免为它改 CSS 表。
|
|
3715
|
-
el("div", { id: "pc-ghlogin", style: { position: "relative", display: "inline-flex" } },
|
|
3716
|
-
el("button", {
|
|
3717
|
-
type: "button",
|
|
3718
|
-
className: styles.ghpill,
|
|
3719
|
-
"data-on": state.status === "ready" && state.data.github && state.data.github.loggedIn ? "true" : "false",
|
|
3720
|
-
title: t("githubLoginTip"),
|
|
3721
|
-
"aria-label": t("githubLoginTip"),
|
|
3722
|
-
onClick: () => setGhLoginOpen((v) => !v),
|
|
3723
|
-
},
|
|
3724
|
-
state.status === "ready" && state.data.github && state.data.github.loggedIn
|
|
3725
|
-
? t("githubLoggedIn") + (state.data.github.login ?? "unknown")
|
|
3726
|
-
: t("githubCornerOut")),
|
|
3727
|
-
ghLoginOpen
|
|
3728
|
-
? el("div", { style: { position: "absolute", right: 0, top: "calc(100% + 6px)", zIndex: 95, width: 300, boxSizing: "border-box", border: "1px solid var(--dsw-alias-border-l2)", background: "var(--dsw-alias-bg-layer-1)", borderRadius: 8, padding: 10, display: "flex", flexDirection: "column", gap: 8, textAlign: "left", boxShadow: "0 8px 24px rgba(0,0,0,.18)" } },
|
|
3729
|
-
el("p", { className: styles.message, style: { margin: 0 } }, t("githubLoginTip")),
|
|
3730
|
-
state.status === "ready" && state.data.github && state.data.github.loggedIn
|
|
3731
|
-
? el("p", { className: styles.message, style: { margin: 0 } }, t("githubLoggedIn") + (state.data.github.login ?? "unknown"))
|
|
3732
|
-
: null,
|
|
3733
|
-
el("input", {
|
|
3734
|
-
type: "password",
|
|
3735
|
-
placeholder: t("githubTokenPlaceholder"),
|
|
3736
|
-
value: ghToken,
|
|
3737
|
-
onChange: (event) => setGhToken(event.currentTarget.value),
|
|
3738
|
-
style: { width: "100%", boxSizing: "border-box" },
|
|
3739
|
-
}),
|
|
3740
|
-
el("button", { type: "button", className: styles.toggle, disabled: ghLoginBusy || ghToken.trim() === "", onClick: githubLogin }, t("githubLoginBtn")))
|
|
3741
|
-
: null),
|
|
3742
3818
|
)),
|
|
3743
3819
|
(aiRunning || aiJobsList.some((x) => x.status === "running"))
|
|
3744
3820
|
? el("button", {
|
package/lib/index.js
CHANGED
|
@@ -5555,6 +5555,55 @@ async function handle(ctx, req, res) {
|
|
|
5555
5555
|
return
|
|
5556
5556
|
}
|
|
5557
5557
|
|
|
5558
|
+
if (pathname === `${ROUTE_PREFIX}/github-open-login`) {
|
|
5559
|
+
// 设备码(窗口)登录:唤起独立插件 dsh-github-login 的登录窗口 —— 登录的首选通道,token 只是兜底。
|
|
5560
|
+
//
|
|
5561
|
+
// 为什么是"调另一个插件的 HTTP 接口"而不是自己实现设备码:Device Flow + 桌面窗口 + 令牌落盘
|
|
5562
|
+
// 已经由那个插件实现好了,它挂在**同一个宿主 webServer** 上(源码:<profile>/node_modules/
|
|
5563
|
+
// dsh-github-login/lib/index.js):
|
|
5564
|
+
// POST /github-auth/open → { ok:true, launched:"<exe 路径>" } 或 { ok:true, launched:false, hint }
|
|
5565
|
+
// GET /github-auth/status → { ok, loggedIn, login }
|
|
5566
|
+
// 为什么失败也回 200:这个能力是**外挂**的 —— 插件可能没装、装了也可能没打包 exe、当前 profile
|
|
5567
|
+
// 也可能没把它挂上(2026-09-20 实测:本机装了它,但跑着的宿主里 GET /github-auth/status 仍是 404)。
|
|
5568
|
+
// 那是"这条通道现在不可用",不是"服务端出错":回 500 只会让用户看到一句看不懂的报错,还看不出
|
|
5569
|
+
// "该走 token 兜底"这条正路。所以统一回 200 + started:false + 可读 reason,由前端决定降级。
|
|
5570
|
+
const port = webPort(ctx)
|
|
5571
|
+
const base = `http://127.0.0.1:${port}`
|
|
5572
|
+
const unavailable = '未检测到 dsh-github-login 插件(或当前平台不支持它的登录窗口)'
|
|
5573
|
+
const fallback = (detail) => {
|
|
5574
|
+
sendJson(res, 200, { ok: true, started: false, reason: detail ? `${unavailable}:${detail}` : unavailable })
|
|
5575
|
+
}
|
|
5576
|
+
let opened = null
|
|
5577
|
+
try {
|
|
5578
|
+
const response = await fetch(`${base}/github-auth/open`, { method: 'POST', signal: AbortSignal.timeout(8000) })
|
|
5579
|
+
if (!response.ok) {
|
|
5580
|
+
fallback(`对方接口返回 HTTP ${response.status}`)
|
|
5581
|
+
return
|
|
5582
|
+
}
|
|
5583
|
+
opened = await response.json()
|
|
5584
|
+
} catch (error) {
|
|
5585
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
5586
|
+
// fetch 的 "fetch failed" 不带 cause 等于没说;超时原文也没有信息量 —— 都压成一行可读文案
|
|
5587
|
+
const cause = error?.cause?.code ?? error?.cause?.message ?? ''
|
|
5588
|
+
fallback(/abort/iu.test(message) ? '调用超时(8000ms)' : (cause ? `${message}(${cause})` : message))
|
|
5589
|
+
return
|
|
5590
|
+
}
|
|
5591
|
+
// 对方"接口在、但本机没有登录工具 exe"时回 { ok:true, launched:false, hint }:窗口其实没起来。
|
|
5592
|
+
// 这里必须跟着报 started:false —— 报 true 会让前端开 60s 轮询,等一个永远不会出现的登录。
|
|
5593
|
+
if (opened?.launched === false) {
|
|
5594
|
+
fallback(typeof opened.hint === 'string' && opened.hint !== '' ? opened.hint : '对方未启动登录窗口(未找到 DSH-GitHub-Login 可执行文件)')
|
|
5595
|
+
return
|
|
5596
|
+
}
|
|
5597
|
+
// 顺手把对方的登录态透传给前端(best-effort:拿不到就 status:null,不影响"窗口已打开"这个结论)
|
|
5598
|
+
let status = null
|
|
5599
|
+
try {
|
|
5600
|
+
const stateRes = await fetch(`${base}/github-auth/status`, { signal: AbortSignal.timeout(2000) })
|
|
5601
|
+
if (stateRes.ok) status = await stateRes.json()
|
|
5602
|
+
} catch {}
|
|
5603
|
+
sendJson(res, 200, { ok: true, started: true, status })
|
|
5604
|
+
return
|
|
5605
|
+
}
|
|
5606
|
+
|
|
5558
5607
|
if (pathname === `${ROUTE_PREFIX}/details`) {
|
|
5559
5608
|
const { entryId } = body
|
|
5560
5609
|
if (typeof entryId !== 'string' || !/^[A-Za-z0-9_:.-]{1,80}$/u.test(entryId)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noob-stupid/dsh-plugin-console",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.53",
|
|
4
4
|
"description": "DSH plugin management panel & marketplace: one-click enable/disable, multi-source market (GitHub/Gitee/custom), static-index market (500+ plugins / 300 skills), skills, suites, and one-click framework upgrade.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|