@noob-stupid/dsh-plugin-console 0.3.47 → 0.3.49

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/lib/client.js CHANGED
@@ -338,6 +338,9 @@ window.__ModuleLoader__.load({
338
338
  gitUrlPlaceholder: "如 https://gitee.com/{owner}/{repo}.git",
339
339
  gitSourceBtn: "Git 源",
340
340
  marketIndexOffline: "离线数据 · 缓存于 {time}(索引源不可达,已回退上次成功结果)",
341
+ marketIndexStale: "市场索引未加载:搜索只覆盖 GitHub 实时结果(仓库名/描述/topics),收录条目与本地索引模糊匹配都用不上",
342
+ marketIndexRetry: "重试加载索引",
343
+ searchLoginHint: "未登录 GitHub:代码搜索不可用(按子包名搜索需要登录);仓库搜索仍可用",
341
344
  marketIndexFrom: "索引来源:{source}",
342
345
  marketIndexFailed: "市场索引加载失败",
343
346
  unknown: "未知",
@@ -709,6 +712,9 @@ window.__ModuleLoader__.load({
709
712
  gitUrlPlaceholder: "e.g. https://gitee.com/{owner}/{repo}.git",
710
713
  gitSourceBtn: "Git sources",
711
714
  marketIndexOffline: "Offline data · cached {time} (index sources unreachable, showing last successful result)",
715
+ marketIndexStale: "Market index not loaded: search only covers live GitHub results (name/description/topics); curated entries and local fuzzy matching are unavailable",
716
+ marketIndexRetry: "Retry loading index",
717
+ searchLoginHint: "GitHub not signed in: code search is unavailable (searching by subpackage name needs sign-in); repository search still works",
712
718
  marketIndexFrom: "Index source: {source}",
713
719
  marketIndexFailed: "Failed to load market index",
714
720
  unknown: "unknown",
@@ -1152,6 +1158,8 @@ window.__ModuleLoader__.load({
1152
1158
  const [updateCheck, setUpdateCheck] = react.useState(null);
1153
1159
  // 静态插件索引(dsh-plugin topic 全量浏览):null=未加载 / {items, skills, loaded}
1154
1160
  const [indexData, setIndexData] = react.useState(null);
1161
+ // 索引加载失败原因:null = 还没失败过(用于市场页顶部"索引未加载 + 重试"提示)
1162
+ const [indexError, setIndexError] = react.useState(null);
1155
1163
  // 索引浏览当前展示条数(分页展示,避免一次渲染 500 条)
1156
1164
  const [indexShown, setIndexShown] = react.useState(50);
1157
1165
  // 已补标(官方/聚合标记)到的索引位置:随「加载更多」增量推进,避免一次性发上千请求
@@ -1725,11 +1733,15 @@ window.__ModuleLoader__.load({
1725
1733
  () => {},
1726
1734
  );
1727
1735
  }, []);
1728
- // 挂载时加载静态插件索引(GitHub 源空查询时秒开浏览,零 API 调用)
1729
- react.useEffect(() => {
1736
+ // 加载静态插件索引(GitHub 源空查询时秒开浏览,零 API 调用)。
1737
+ // 失败时记下原因:市场页顶部给出"索引未加载 → 只能搜 GitHub 实时结果"的提示 + 重试按钮
1738
+ //(2026-09-20 事故:另一位用户索引源全挂 + 未登录,三条检索路全断,搜 web-all 搜不到 dsh-web,
1739
+ // 而界面上只有一句"市场索引加载失败",看不出后果也没有重试入口)
1740
+ const loadMarketIndex = () => {
1730
1741
  call("/plugin-console/market-index", {}).then(
1731
1742
  (data) => {
1732
1743
  if (data && Array.isArray(data.items)) {
1744
+ setIndexError(null);
1733
1745
  setIndexData({
1734
1746
  items: data.items,
1735
1747
  skills: Array.isArray(data.skills) ? data.skills : [],
@@ -1748,8 +1760,15 @@ window.__ModuleLoader__.load({
1748
1760
  }
1749
1761
  }
1750
1762
  },
1751
- (error) => setMessage(t("marketIndexFailed") + ":" + (error?.message ?? t("unknown"))),
1763
+ (error) => {
1764
+ const text = error?.message ?? t("unknown");
1765
+ setIndexError(text);
1766
+ setMessage(t("marketIndexFailed") + ":" + text);
1767
+ },
1752
1768
  );
1769
+ };
1770
+ react.useEffect(() => {
1771
+ loadMarketIndex();
1753
1772
  // 市场状态记忆:关闭前搜索过 → 重开时自动恢复该搜索(query 已从 localStorage 初始化)
1754
1773
  if (query !== "") {
1755
1774
  search();
@@ -1994,6 +2013,36 @@ window.__ModuleLoader__.load({
1994
2013
  scored.sort((a, b) => b.s - a.s);
1995
2014
  return scored.slice(0, 12).map((x) => x.it);
1996
2015
  };
2016
+ /** 合并服务端"增量检索"结果(npm 包名映射 / in:readme 重查 / 代码搜索子包):
2017
+ * npm 命中置顶,其余按增量顺序追加,最后接原有直连结果,全部按 fullName 去重。
2018
+ * 背景(2026-09-20):浏览器直连 GitHub 搜索成功时不会走服务端路由,而未登录用户恰恰只能走直连
2019
+ * →「只存在于 npm 包名 / README / 仓库文件里」的名字(如 web-all)永远补不上。 */
2020
+ function mergeSearchExtras(base, extras) {
2021
+ const seen = new Set();
2022
+ const npm = [];
2023
+ const rest = [];
2024
+ for (const it of extras) {
2025
+ const key = it.fullName ?? JSON.stringify(it);
2026
+ if (seen.has(key)) continue;
2027
+ seen.add(key);
2028
+ if (it.npmPackage === true) npm.push(it); else rest.push(it);
2029
+ }
2030
+ const out = [...npm, ...rest];
2031
+ for (const it of base) {
2032
+ const key = it.fullName ?? JSON.stringify(it);
2033
+ if (seen.has(key)) continue;
2034
+ seen.add(key);
2035
+ out.push(it);
2036
+ }
2037
+ return out;
2038
+ }
2039
+ /** 用 enrich 结果**就地更新**市场列表(按 fullName 打补丁),而不是整表替换——
2040
+ * 否则并行补进来的「增量检索」条目(npm 包名/子包)会被 enrich 回调冲掉。 */
2041
+ const applyEnriched = (enriched) => setMarket((m) => {
2042
+ if (m === null || m.status !== "ready" || !Array.isArray(enriched)) return m;
2043
+ const byName = new Map(enriched.map((x) => [x.fullName, x]));
2044
+ return { ...m, data: m.data.map((x) => byName.get(x.fullName) ?? x) };
2045
+ });
1997
2046
  const search = () => {
1998
2047
  setMarket({ status: "loading" });
1999
2048
  setRepoInfo(null);
@@ -2044,7 +2093,7 @@ window.__ModuleLoader__.load({
2044
2093
  (data) => {
2045
2094
  setMarket({ status: "ready", data: data.items, direct: false, source: searchSource });
2046
2095
  enrichOfficialBundle(data.items).then((enriched) => {
2047
- setMarket((m) => (m !== null && m.status === "ready" ? { ...m, data: enriched } : m));
2096
+ applyEnriched(enriched);
2048
2097
  });
2049
2098
  },
2050
2099
  (error) => setMarket({ status: "error", error: friendlyGithubError(error) }),
@@ -2058,20 +2107,32 @@ window.__ModuleLoader__.load({
2058
2107
  // 并行补标记:
2059
2108
  // ① 客户端浏览器直连读根包 package.json(快,官方/聚合标记立即可筛)
2060
2109
  enrichOfficialBundle(data).then((enriched) => {
2061
- setMarket((m) => (m !== null && m.status === "ready" ? { ...m, data: enriched } : m));
2110
+ applyEnriched(enriched);
2062
2111
  });
2063
2112
  // ② 服务端 curl 双通道 enrich(聚合子包 dsh.bundle 检查 → aggregateInstallable),后台补更精确标记
2064
2113
  call("/plugin-console/enrich", { items: data }).then(
2065
- (r) => { if (r && Array.isArray(r.items)) setMarket((m) => (m !== null && m.status === "ready" ? { ...m, data: r.items } : m)); },
2114
+ (r) => { if (r && Array.isArray(r.items)) applyEnriched(r.items); },
2066
2115
  () => {},
2067
2116
  );
2117
+ // ③ 服务端"增量检索"(并行、不阻塞首屏):npm 包名映射 + in:readme 重查 + 代码搜索子包。
2118
+ // 直连搜索只覆盖 仓库名/描述/topics,包名与 README/文件里的名字补不上(2026-09-20 事故)
2119
+ if (query.trim() !== "") {
2120
+ call("/plugin-console/search", { q: query, page: 1, extras: true, all: repoLandOn === true }).then(
2121
+ (r) => {
2122
+ if (r !== null && r.codeSearchSkipped === true) setMessage(t("searchLoginHint"));
2123
+ if (r === null || !Array.isArray(r.items) || r.items.length === 0) return;
2124
+ setMarket((m) => (m !== null && m.status === "ready" ? { ...m, data: mergeSearchExtras(m.data, r.items) } : m));
2125
+ },
2126
+ () => {},
2127
+ );
2128
+ }
2068
2129
  },
2069
2130
  () => call("/plugin-console/search", { q: query, page: 1 }).then(
2070
2131
  (data) => {
2071
2132
  const items = data.items;
2072
2133
  setMarket({ status: "ready", data: items, direct: false });
2073
2134
  enrichOfficialBundle(items).then((enriched) => {
2074
- setMarket((m) => (m !== null && m.status === "ready" ? { ...m, data: enriched } : m));
2135
+ applyEnriched(enriched);
2075
2136
  });
2076
2137
  },
2077
2138
  (error) => setMarket({ status: "error", error: friendlyGithubError(error) }),
@@ -2561,7 +2622,7 @@ window.__ModuleLoader__.load({
2561
2622
  startSuiteJob(item);
2562
2623
  return;
2563
2624
  }
2564
- if (item.subpackagePath && typeof item.packageName === "string" && item.packageName !== "") {
2625
+ if ((item.subpackagePath || item.npmPackage === true) && typeof item.packageName === "string" && item.packageName !== "") {
2565
2626
  // monorepo 子包:搜索结果带 packageName,按 npm 包名安装
2566
2627
  startJob(item.fullName, item.packageName, item.source ?? "github");
2567
2628
  return;
@@ -3796,6 +3857,17 @@ setMessage(t("failed") + ":" + (data?.reason ?? "未知"));
3796
3857
  t("marketIndexOffline").replace("{time}", indexData.cachedAt !== null ? new Date(indexData.cachedAt).toLocaleString() : "—")
3797
3858
  + (indexData.sourceName !== null ? " · " + t("marketIndexFrom").replace("{source}", indexData.sourceName) : ""))
3798
3859
  : null,
3860
+ // 索引彻底没加载成功:说清后果(只剩 GitHub 实时结果)+ 给重试入口。
3861
+ // 2026-09-20 事故:这种状态下"包名/README/子包里的名字"搜不到,而界面上只有一句加载失败
3862
+ indexData === null && indexError !== null
3863
+ ? el("p", { className: styles.message, "data-warn": "true" },
3864
+ t("marketIndexStale") + " ",
3865
+ el("button", {
3866
+ type: "button",
3867
+ className: styles.toggle,
3868
+ onClick: () => loadMarketIndex(),
3869
+ }, t("marketIndexRetry")))
3870
+ : null,
3799
3871
  el("div", { className: styles.search, id: "pc-market-search" },
3800
3872
  el("div", { className: styles.searchInner },
3801
3873
  el("input", {