@zaimokuza/dsh-plugin-hub 0.1.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/LICENSE +21 -0
- package/README.md +13 -0
- package/THIRD_PARTY_NOTICES.md +21 -0
- package/cordis.patch.yml +3 -0
- package/lib/client.js +500 -0
- package/package.json +83 -0
- package/src/catalog.js +107 -0
- package/src/client/api.js +22 -0
- package/src/client/index.jsx +201 -0
- package/src/client/locale.js +104 -0
- package/src/client/market.css +113 -0
- package/src/client/scope.js +9 -0
- package/src/declarations.js +19 -0
- package/src/dsh.js +66 -0
- package/src/host-peers.js +33 -0
- package/src/identity.js +15 -0
- package/src/index.js +85 -0
- package/src/npm-identity.js +15 -0
- package/src/provider-api.d.ts +36 -0
- package/src/provider-api.js +7 -0
- package/src/providers.js +83 -0
- package/src/registry.js +15 -0
- package/src/release-age.js +34 -0
- package/src/service.js +192 -0
- package/src/source-plugin.js +9 -0
- package/src/source.js +69 -0
package/lib/client.js
ADDED
|
@@ -0,0 +1,500 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({ id: "@zaimokuza/dsh-plugin-hub", factory: (require) => { var module = { exports: {} }; var exports = module.exports;
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name2 in all)
|
|
10
|
+
__defProp(target, name2, { get: all[name2], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/client/index.jsx
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Market: () => Market,
|
|
34
|
+
apply: () => apply,
|
|
35
|
+
inject: () => inject,
|
|
36
|
+
name: () => name
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
|
|
40
|
+
// <define:__HUB_BRAND__>
|
|
41
|
+
var define_HUB_BRAND_default = { title: "Plugin Hub", subTitle: "DSH EXTENSIONS", primaryColor: "#596579", navTitle: "Plugin Hub" };
|
|
42
|
+
|
|
43
|
+
// src/client/index.jsx
|
|
44
|
+
var import_react = __toESM(require("react"), 1);
|
|
45
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
46
|
+
|
|
47
|
+
// src/client/api.js
|
|
48
|
+
var RequestError = class extends Error {
|
|
49
|
+
constructor(key, detail = "") {
|
|
50
|
+
super(key);
|
|
51
|
+
this.detail = detail;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
async function request(path, data, { signal, fetcher = fetch, base = "/dsh-plugin-hub/hub/api/" } = {}) {
|
|
55
|
+
let response;
|
|
56
|
+
try {
|
|
57
|
+
response = await fetcher(base + path, {
|
|
58
|
+
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(2e4)]) : AbortSignal.timeout(2e4),
|
|
59
|
+
...data === void 0 ? {} : { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(data) }
|
|
60
|
+
});
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (signal?.aborted) throw error;
|
|
63
|
+
throw new RequestError(error.name === "TimeoutError" ? "\u8BF7\u6C42\u8D85\u65F6\uFF0C\u6B63\u5728\u7B49\u5F85 DSH \u54CD\u5E94\u3002" : "\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u8BF7\u786E\u8BA4\u672C\u5730 DSH \u5B9E\u4F8B\u6B63\u5728\u8FD0\u884C\u3002\u6062\u590D\u540E\u9875\u9762\u4F1A\u81EA\u52A8\u91CD\u8FDE\u3002");
|
|
64
|
+
}
|
|
65
|
+
if (response.status === 401) throw new RequestError("\u8BF7\u5148\u767B\u5F55\u5F53\u524D DSH \u5B9E\u4F8B");
|
|
66
|
+
let value;
|
|
67
|
+
try {
|
|
68
|
+
value = await response.json();
|
|
69
|
+
} catch {
|
|
70
|
+
throw new RequestError("\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u54CD\u5E94\uFF0C\u8BF7\u5237\u65B0 DSH \u9875\u9762\u3002");
|
|
71
|
+
}
|
|
72
|
+
if (!response.ok) throw new RequestError(value.error ?? `HTTP ${response.status}`);
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/client/scope.js
|
|
77
|
+
function inScope(plugin, scope) {
|
|
78
|
+
if (scope === "all") return true;
|
|
79
|
+
if (scope === "installed") return Boolean(plugin.installedVersion);
|
|
80
|
+
return scope.startsWith("source:") && (plugin.catalogSourceIds ?? [plugin.catalogSource?.id]).includes(scope.slice(7));
|
|
81
|
+
}
|
|
82
|
+
function resolveScope(scope, sources) {
|
|
83
|
+
return scope === "all" || scope === "installed" || sources.some((source) => scope === "source:" + source.id) ? scope : "all";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/client/locale.js
|
|
87
|
+
var pairs = [
|
|
88
|
+
["\u51B7\u9759\u671F\uFF1A{minutes} \u5206\u949F \xB7 {source}", "Release age: {minutes} minutes \xB7 {source}"],
|
|
89
|
+
["\u672C\u673A pnpm \u914D\u7F6E", "Local pnpm configuration"],
|
|
90
|
+
["\u9ED8\u8BA4 48 \u5C0F\u65F6", "Default 48 hours"],
|
|
91
|
+
["\u672A\u6EE1 {minutes} \u5206\u949F", "Under {minutes} minutes"],
|
|
92
|
+
["\u9884\u8BA1\u6EE1 {minutes} \u5206\u949F\uFF1A{date}", "Eligible after {minutes} minutes: {date}"],
|
|
93
|
+
["\u4E0D\u6309\u7248\u672C\u9650\u5236\uFF0C\u8FD0\u884C\u65F6\u68C0\u67E5\u63A5\u53E3", "No version gate; runtime API checks"],
|
|
94
|
+
["\u76EE\u5F55\u683C\u5F0F\u4E0D\u53D7\u652F\u6301\uFF1A\u9700\u8981 schemaVersion: 1 \u548C plugins \u6570\u7EC4", "Unsupported catalog: expected schemaVersion: 1 and a plugins array"],
|
|
95
|
+
["\u76EE\u5F55\u6700\u591A\u652F\u6301 25000 \u4E2A\u63D2\u4EF6", "A catalog supports at most 25000 plugins"],
|
|
96
|
+
["\u63D2\u4EF6\u8BB0\u5F55\u5FC5\u987B\u4E3A\u5BF9\u8C61", "Plugin entry must be an object"],
|
|
97
|
+
["npm \u5305\u540D\u65E0\u6548", "Invalid npm package name"],
|
|
98
|
+
["npm \u5305\u540D\u91CD\u590D", "Duplicate npm package name"],
|
|
99
|
+
["\u76EE\u5F55\u5305 plugins.json \u91CD\u590D\u6216\u8FC7\u5927", "Catalog plugins.json is duplicated or too large"],
|
|
100
|
+
["\u76EE\u5F55\u8FC7\u5927", "Catalog is too large"],
|
|
101
|
+
["\u76EE\u5F55\u5305\u7F3A\u5C11 plugins.json", "Catalog package is missing plugins.json"],
|
|
102
|
+
["\u4ED3\u5E93\u8BF7\u6C42\u5730\u5740\u4E0D\u5C5E\u4E8E\u914D\u7F6E\u7684 Nexus", "Registry request does not belong to the configured Nexus"],
|
|
103
|
+
["Invalid release request", "Invalid release request", "\u65E0\u6548\u7684\u7248\u672C\u67E5\u8BE2\u8BF7\u6C42"],
|
|
104
|
+
["Invalid catalog source id", "Invalid catalog source ID", "\u65E0\u6548\u7684\u6570\u636E\u6E90 ID"],
|
|
105
|
+
["Invalid catalog package name", "Invalid catalog package name", "\u65E0\u6548\u7684\u76EE\u5F55\u6570\u636E\u5305\u540D"],
|
|
106
|
+
["At most 20 catalog sources are supported", "At most 20 catalog sources are supported", "\u6700\u591A\u652F\u6301 20 \u4E2A\u6570\u636E\u6E90"],
|
|
107
|
+
["Catalog source kind must be npm or json", "Catalog source kind must be npm or json", "\u6570\u636E\u6E90\u7C7B\u578B\u5FC5\u987B\u662F npm \u6216 json"],
|
|
108
|
+
["JSON source requires getCatalog({ signal })", "JSON source requires getCatalog({ signal })", "JSON \u6570\u636E\u6E90\u9700\u8981 getCatalog({ signal })"],
|
|
109
|
+
["Source priority must be an integer between -1000 and 1000", "Source priority must be an integer between -1000 and 1000", "\u6570\u636E\u6E90\u4F18\u5148\u7EA7\u5FC5\u987B\u4E3A -1000 \u5230 1000 \u7684\u6574\u6570"],
|
|
110
|
+
["Invalid source displayName", "Invalid source displayName", "\u65E0\u6548\u7684\u6570\u636E\u6E90\u663E\u793A\u540D\u79F0"],
|
|
111
|
+
["Invalid source cacheVersion", "Invalid source cacheVersion", "\u65E0\u6548\u7684\u6570\u636E\u6E90\u7F13\u5B58\u7248\u672C"],
|
|
112
|
+
["\u517C\u5BB9\u58F0\u660E\u5B58\u5728\u51B2\u7A81\uFF0C\u9700\u8981\u7EF4\u62A4\u8005\u786E\u8BA4", "Compatibility declarations conflict; the maintainer must clarify"],
|
|
113
|
+
["\u58F0\u660E\u4E0D\u652F\u6301\u5F53\u524D DSH profile", "This DSH profile is not covered by the declaration"],
|
|
114
|
+
["\u4F5C\u8005\u9010\u7248\u672C\u58F0\u660E", "Author release declaration"],
|
|
115
|
+
["\u4E0D\u652F\u6301\u7684\u8BF7\u6C42\u65B9\u6CD5", "Unsupported request method"],
|
|
116
|
+
["\u63A5\u53E3\u4E0D\u5B58\u5728", "Endpoint not found"],
|
|
117
|
+
["\u8BF7\u6C42\u8FC7\u5927", "Request body is too large"],
|
|
118
|
+
["\u76EE\u5F55 npm \u5305\u6CA1\u6709 integrity\uFF0C\u65E0\u6CD5\u6821\u9A8C", "Catalog package has no integrity field"],
|
|
119
|
+
["\u76EE\u5F55 npm \u5305\u5B8C\u6574\u6027\u6821\u9A8C\u5931\u8D25", "Catalog package integrity check failed"],
|
|
120
|
+
["\u76EE\u5F55\u6765\u6E90\u5FC5\u987B\u662F npm \u6570\u636E\u5305", "Catalog source must be an npm data package"],
|
|
121
|
+
["\u76EE\u5F55 npm \u5305\u6CA1\u6709\u53EF\u4E0B\u8F7D\u7684 latest \u7248\u672C", "Catalog package has no downloadable latest release"],
|
|
122
|
+
["\u76EE\u5F55 tarball \u5730\u5740\u4E0D\u5C5E\u4E8E\u914D\u7F6E\u7684\u4ED3\u5E93", "Catalog tarball does not belong to the configured registry"],
|
|
123
|
+
["\u63D2\u4EF6\u547D\u4EE4\u5931\u8D25", "Plugin command failed"],
|
|
124
|
+
["\u5B89\u88C5\u547D\u4EE4\u7ED3\u675F\uFF0C\u4F46\u5B9E\u9645\u7248\u672C\u4E0D\u5339\u914D", "Installation finished but the installed version does not match"],
|
|
125
|
+
["\u5305\u5DF2\u4E0B\u8F7D\uFF0C\u4F46\u5C1A\u672A\u6CE8\u518C\u4E3A DSH bundle", "Package downloaded but not registered as a DSH bundle"],
|
|
126
|
+
["\u5378\u8F7D\u547D\u4EE4\u7ED3\u675F\uFF0C\u4F46\u63D2\u4EF6\u4ECD\u5728 profile \u4E2D", "Uninstall finished but the plugin is still in the profile"],
|
|
127
|
+
["\u63D2\u4EF6\u64CD\u4F5C\u8D85\u65F6\uFF0C\u8BF7\u68C0\u67E5 profile \u540E\u91CD\u8BD5", "Plugin operation timed out; check the profile and retry"],
|
|
128
|
+
["\u6765\u6E90\u672A\u6838\u5B9E", "Source unverified"],
|
|
129
|
+
["\u5BBF\u4E3B\u4F9D\u8D56\u58F0\u660E", "Host peer declarations"],
|
|
130
|
+
["\u517C\u5BB9\u4F9D\u636E\uFF1A{basis}", "Compatibility evidence: {basis}"],
|
|
131
|
+
["\u5DF2\u786E\u8BA4\u53EF\u5B89\u88C5", "Confirmed installable"],
|
|
132
|
+
["\u5F53\u524D npm \u4ED3\u5E93\u672A\u627E\u5230\u6B64\u5305\uFF08404\uFF09", "Package not found in this npm registry (404)"],
|
|
133
|
+
["\u5F53\u524D\u4ED3\u5E93\u672A\u627E\u5230", "Not found in this registry"],
|
|
134
|
+
["\u6765\u6E90\u4E0D\u5339\u914D", "Source mismatch"],
|
|
135
|
+
["npm \u5305\u672A\u58F0\u660E\u53EF\u6838\u5BF9\u7684 GitHub \u6765\u6E90", "The npm package does not declare a verifiable GitHub repository"],
|
|
136
|
+
["npm \u5305\u5BF9\u5E94\u7684 GitHub \u4ED3\u5E93\u4E0E\u76EE\u5F55\u4E0D\u4E00\u81F4", "The npm package points to a different GitHub repository"],
|
|
137
|
+
["\u8BE5\u7248\u672C\u7684 npm \u6765\u6E90\u65E0\u6CD5\u4E0E\u76EE\u5F55\u4ED3\u5E93\u6838\u5BF9", "This npm version cannot be matched to the catalog repository"],
|
|
138
|
+
["\u6B63\u5728\u67E5\u8BE2\u7248\u672C", "Loading releases"],
|
|
139
|
+
["\u52A0\u8F7D\u66F4\u591A", "Load more"],
|
|
140
|
+
["\u5DF2\u67E5\u8BE2 {done} / {total} \u4E2A\u63D2\u4EF6\u7684\u7248\u672C", "Loaded releases for {done} / {total} plugins"],
|
|
141
|
+
["\u63D2\u4EF6\u76EE\u5F55", "Plugin directory"],
|
|
142
|
+
["\u6570\u636E\u6E90", "Data sources"],
|
|
143
|
+
["\u5173\u95ED\u6570\u636E\u6E90", "Close data sources"],
|
|
144
|
+
["\u6765\u6E90", "Source"],
|
|
145
|
+
["Company catalog", "Company catalog", "\u516C\u53F8\u76EE\u5F55"],
|
|
146
|
+
["Demo catalog", "Demo catalog", "\u6F14\u793A\u76EE\u5F55"],
|
|
147
|
+
["Team handbook", "Team handbook", "\u56E2\u961F\u624B\u518C\u76EE\u5F55"],
|
|
148
|
+
["npm \u6570\u636E\u5305", "npm data package"],
|
|
149
|
+
["\u6269\u5C55\u63D2\u4EF6 JSON", "Provider plugin JSON"],
|
|
150
|
+
["\u5DF2\u52A0\u8F7D", "Loaded"],
|
|
151
|
+
["\u4F7F\u7528\u7F13\u5B58", "Using cache"],
|
|
152
|
+
["\u76EE\u5F55\u6765\u6E90\u8BFB\u53D6\u8D85\u65F6", "Catalog source timed out"],
|
|
153
|
+
["\u76EE\u5F55\u6765\u6E90\u8BFB\u53D6\u5DF2\u53D6\u6D88", "Catalog source read cancelled"],
|
|
154
|
+
["\u4F18\u5148\u7EA7 {priority} \xB7 {count} \u4E2A\u63D2\u4EF6", "Priority {priority} \xB7 {count} plugins"],
|
|
155
|
+
["\u5DF2\u5408\u5E76 {count} \u6761\u91CD\u590D\u8BB0\u5F55", "Merged {count} duplicate entries"],
|
|
156
|
+
["\u540C\u540D\u63D2\u4EF6\u6309\u6765\u6E90\u4F18\u5148\u7EA7\u4FDD\u7559\u4E00\u6761\uFF1B\u4F18\u5148\u7EA7\u76F8\u540C\u65F6\u6309\u6765\u6E90 ID \u6392\u5E8F\u3002", "Duplicate package names use the highest-priority source; equal priorities are ordered by source ID."],
|
|
157
|
+
["\u4ECB\u7ECD\u6587\u6863", "Documentation"],
|
|
158
|
+
["\u6A21\u62DF\u5378\u8F7D", "Simulate uninstall"],
|
|
159
|
+
["\u5378\u8F7D\u63D2\u4EF6", "Uninstall plugin"],
|
|
160
|
+
["\u6B63\u5728\u5378\u8F7D\u2026", "Uninstalling\u2026"],
|
|
161
|
+
["\u5378\u8F7D\u4E2D", "Uninstalling"],
|
|
162
|
+
["\u5378\u8F7D\u5931\u8D25", "Uninstall failed"],
|
|
163
|
+
["\u5378\u8F7D", "Uninstall"],
|
|
164
|
+
["\u5B89\u88C5", "Install"],
|
|
165
|
+
["\u6A21\u62DF\u64CD\u4F5C\u5DF2\u5B8C\u6210", "Simulated operations finished"],
|
|
166
|
+
["\u63D2\u4EF6\u64CD\u4F5C\u5DF2\u5B8C\u6210", "Plugin operations finished"],
|
|
167
|
+
["{count} \u4E2A\u63D2\u4EF6\u64CD\u4F5C\u6B63\u5728\u6267\u884C", "{count} plugin operations in progress"],
|
|
168
|
+
["\u8BE5\u63D2\u4EF6\u5C1A\u672A\u5B89\u88C5", "This plugin is not installed"],
|
|
169
|
+
["\u8BE5\u63D2\u4EF6\u5DF2\u6709\u5176\u5B83\u64CD\u4F5C\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210", "Wait for the other operation on this plugin to finish"],
|
|
170
|
+
["\u8BF7\u901A\u8FC7 DSH CLI \u7BA1\u7406\u5E02\u573A\u63D2\u4EF6\u81EA\u8EAB", "Manage the marketplace itself through the DSH CLI"],
|
|
171
|
+
["\u65E0\u6548\u7684\u63D2\u4EF6\u64CD\u4F5C", "Invalid plugin operation"],
|
|
172
|
+
["nav", "Plugin Hub", "Plugin Hub"],
|
|
173
|
+
["\u63D2\u4EF6\u5E02\u573A", "Marketplace"],
|
|
174
|
+
["\u3002", "."],
|
|
175
|
+
["\u627E\u5230\u9002\u5408\u5F53\u524D DSH \u7684\u5DE5\u5177\u3002", "Find the right tools for your current DSH."],
|
|
176
|
+
["\u6536\u5F55\u63D2\u4EF6", "Plugins"],
|
|
177
|
+
["\u6709\u53EF\u5B89\u88C5\u7248\u672C", "Installable"],
|
|
178
|
+
["\u4F7F\u7528\u4E0E\u6545\u969C\u6392\u67E5", "Help & troubleshooting"],
|
|
179
|
+
["\u672C\u5730\u6F14\u793A", "Local demo"],
|
|
180
|
+
["Nexus npm \u8BF7\u6C42\u5DF2\u62E6\u622A\uFF0C\u76EE\u5F55\u5305\u3001\u7248\u672C\u4E0E\u5B89\u88C5\u7ED3\u679C\u5747\u4E3A\u6A21\u62DF\u3002", "Nexus npm requests are mocked, including the catalog package, versions and installs."],
|
|
181
|
+
["\u5207\u6362\u573A\u666F", "Demo scenarios"],
|
|
182
|
+
["\u6B63\u5E38\u76EE\u5F55", "Normal catalog"],
|
|
183
|
+
["\u65B0\u63D2\u4EF6\u767B\u8BB0", "New plugin registered"],
|
|
184
|
+
["\u76EE\u5F55\u683C\u5F0F\u635F\u574F", "Invalid catalog JSON"],
|
|
185
|
+
["\u76EE\u5F55\u6E90\u4E0D\u53EF\u7528", "Catalog unavailable"],
|
|
186
|
+
["\u67E5\u770B\u62E6\u622A\u8BF7\u6C42", "View intercepted requests"],
|
|
187
|
+
["\u91CD\u7F6E\u6A21\u62DF\u5B89\u88C5", "Reset simulated installs"],
|
|
188
|
+
["\u76EE\u5F55\u66F4\u65B0\u5931\u8D25\uFF0C\u7EE7\u7EED\u4F7F\u7528\u4E0A\u4E00\u4EFD\u6709\u6548\u6570\u636E", "Catalog update failed. Using the last valid catalog."],
|
|
189
|
+
["\u76EE\u5F55\u6682\u4E0D\u53EF\u7528", "Catalog is currently unavailable"],
|
|
190
|
+
["\u91CD\u8BD5", "Retry"],
|
|
191
|
+
["\u5173\u95ED\u9519\u8BEF", "Dismiss error"],
|
|
192
|
+
["\u5173\u95ED\u8BF7\u6C42\u8BB0\u5F55", "Close request log"],
|
|
193
|
+
["\u8BF7\u6C42\u62E6\u622A\u8BB0\u5F55", "Intercepted requests"],
|
|
194
|
+
["\u72EC\u7ACB MockAgent \u8FD4\u56DE npm \u5143\u6570\u636E\u548C\u76EE\u5F55\u538B\u7F29\u5305\uFF0C\u4E0D\u8FDE\u63A5\u771F\u5B9E Nexus\u3002", "An isolated MockAgent returns npm metadata and catalog tarballs without contacting a real Nexus."],
|
|
195
|
+
["\u63D2\u4EF6\u8303\u56F4", "Plugin scope"],
|
|
196
|
+
["\u5168\u90E8\u63D2\u4EF6", "All plugins"],
|
|
197
|
+
["\u5185\u90E8\u63D2\u4EF6", "Internal"],
|
|
198
|
+
["\u793E\u533A\u7CBE\u9009", "Community"],
|
|
199
|
+
["\u5DF2\u5B89\u88C5", "Installed"],
|
|
200
|
+
["\u641C\u7D22\u63D2\u4EF6", "Search plugins"],
|
|
201
|
+
["\u641C\u7D22\u63D2\u4EF6\u3001\u7528\u9014\u6216\u7EF4\u62A4\u56E2\u961F", "Search plugins, purpose or owner"],
|
|
202
|
+
["\u6E05\u7A7A\u641C\u7D22", "Clear search"],
|
|
203
|
+
["\u6309\u6807\u7B7E\u7B5B\u9009", "Filter by tag"],
|
|
204
|
+
["\u6240\u6709\u6807\u7B7E", "All tags"],
|
|
205
|
+
["\u5237\u65B0", "Refresh"],
|
|
206
|
+
["\u5237\u65B0\u76EE\u5F55\u4E0E\u7248\u672C", "Refresh catalog and versions"],
|
|
207
|
+
["\u201C{query}\u201D \u7684\u641C\u7D22\u7ED3\u679C", "Results for \u201C{query}\u201D"],
|
|
208
|
+
["\u4F60\u7684\u5DE5\u4F5C\u5DE5\u5177", "Your tools"],
|
|
209
|
+
["\u4E3A\u56E2\u961F\u7CBE\u9009", "Curated tools"],
|
|
210
|
+
["\u7248\u672C\u4FE1\u606F\u6765\u81EA npm \xB7 \u6309\u5F53\u524D DSH \u68C0\u67E5\u58F0\u660E", "npm versions \xB7 checked against this DSH"],
|
|
211
|
+
["\u5185\u90E8", "Internal"],
|
|
212
|
+
["\u7CBE\u9009", "Curated"],
|
|
213
|
+
["\u9009\u62E9\u7248\u672C", "Version"],
|
|
214
|
+
["{name}\u7248\u672C", "{name} version"],
|
|
215
|
+
["\u6682\u4E0D\u53EF\u7528", "Unavailable"],
|
|
216
|
+
["\u63A8\u8350", "Recommended"],
|
|
217
|
+
["\u53D1\u5E03\u4E8E {date}", "Published {date}"],
|
|
218
|
+
["\u6CA1\u6709\u53EF\u7528\u7248\u672C", "No releases available"],
|
|
219
|
+
["\u6392\u67E5\u6307\u5357", "Troubleshooting"],
|
|
220
|
+
["\u67E5\u8BE2\u5931\u8D25", "Query failed"],
|
|
221
|
+
["\u517C\u5BB9\u6027\u672A\u77E5", "Compatibility unknown"],
|
|
222
|
+
["\u7248\u672C\u4E0D\u517C\u5BB9", "Incompatible"],
|
|
223
|
+
["\u672A\u6EE1 {hours} \u5C0F\u65F6", "Under {hours} hours"],
|
|
224
|
+
["\u53D1\u5E03\u65F6\u95F4\u672A\u77E5", "Release date unknown"],
|
|
225
|
+
["\u7B26\u5408\u5B89\u88C5\u6761\u4EF6", "Eligible to install"],
|
|
226
|
+
["\u6682\u4E0D\u53EF\u5B89\u88C5", "Not installable"],
|
|
227
|
+
["\u5DF2\u52A0\u5165\u961F\u5217", "Queued"],
|
|
228
|
+
["\u6B63\u5728\u5B89\u88C5\u2026", "Installing\u2026"],
|
|
229
|
+
["\u6F14\u793A\u5DF2\u5B89\u88C5", "Demo installed"],
|
|
230
|
+
["\u6A21\u62DF\u5B89\u88C5", "Simulate install"],
|
|
231
|
+
["\u5B89\u88C5\u63D2\u4EF6", "Install plugin"],
|
|
232
|
+
["\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u76EE\u5F55\u2026", "Loading plugin catalog\u2026"],
|
|
233
|
+
["\u91CD\u65B0\u83B7\u53D6", "Try again"],
|
|
234
|
+
["\u65F6\u95F4\u672A\u77E5", "Unknown time"],
|
|
235
|
+
["\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u63D2\u4EF6", "No matching plugins"],
|
|
236
|
+
["\u8BD5\u8BD5\u5176\u5B83\u5173\u952E\u8BCD\uFF0C\u6216\u6E05\u9664\u5F53\u524D\u7B5B\u9009\u6761\u4EF6\u3002", "Try another keyword or clear your filters."],
|
|
237
|
+
["\u67E5\u770B\u5168\u90E8\u63D2\u4EF6", "View all plugins"],
|
|
238
|
+
["\u672A\u52A0\u8F7D", "Not loaded"],
|
|
239
|
+
["\u76EE\u5F55 {version} \xB7 \u66F4\u65B0\u4E8E {date}", "Catalog {version} \xB7 updated {date}"],
|
|
240
|
+
["\u5E02\u573A v{version}", "Marketplace v{version}"],
|
|
241
|
+
["\u201C\u7B26\u5408\u5B89\u88C5\u6761\u4EF6\u201D\u4F9D\u636E\u7248\u672C\u58F0\u660E\u4E0E\u53D1\u5E03\u65F6\u95F4\uFF0C\u5B9E\u9645\u4E0B\u8F7D\u4ECD\u4EE5 Nexus \u4E3A\u51C6\u3002", "Eligibility is based on version declarations and release dates. Nexus determines actual download availability."],
|
|
242
|
+
["\u672C\u9875\u5305\u542B\u6A21\u62DF\u7248\u672C\u58F0\u660E\uFF0C\u4E0D\u4EE3\u8868\u8FD9\u4E9B\u63D2\u4EF6\u7684\u771F\u5B9E\u517C\u5BB9\u8303\u56F4\u3002", "Version declarations on this page are simulated and do not represent actual plugin compatibility."],
|
|
243
|
+
["{count} \u4E2A\u63D2\u4EF6\u6B63\u5728\u6392\u961F\u6216\u5B89\u88C5", "{count} plugins queued or installing"],
|
|
244
|
+
["\u6A21\u62DF\u5B89\u88C5\u5DF2\u5B8C\u6210", "Simulated installs finished"],
|
|
245
|
+
["\u5B89\u88C5\u4EFB\u52A1\u5DF2\u5B8C\u6210", "Install tasks finished"],
|
|
246
|
+
["{count} \u9879\u6A21\u62DF\u5B8C\u6210 \xB7 \u4E0D\u4FEE\u6539\u771F\u5B9E\u63D2\u4EF6", "{count} simulated operations completed \xB7 no real plugins changed"],
|
|
247
|
+
["{count} \u9879\u5F85\u624B\u52A8\u91CD\u542F\u751F\u6548", "{count} installs awaiting a manual restart"],
|
|
248
|
+
["\u6536\u8D77", "Collapse"],
|
|
249
|
+
["\u67E5\u770B\u4EFB\u52A1", "View tasks"],
|
|
250
|
+
["\u6392\u961F\u4E2D", "Queued"],
|
|
251
|
+
["\u5B89\u88C5\u4E2D", "Installing"],
|
|
252
|
+
["\u6A21\u62DF\u5B8C\u6210", "Simulated"],
|
|
253
|
+
["\u5F85\u91CD\u542F", "Restart required"],
|
|
254
|
+
["\u5B89\u88C5\u5931\u8D25", "Install failed"],
|
|
255
|
+
["\u5173\u95ED\u8BE6\u60C5", "Close details"],
|
|
256
|
+
["\u7EF4\u62A4\u56E2\u961F", "Maintainer"],
|
|
257
|
+
["\u5F53\u524D\u5BBF\u4E3B", "Current host"],
|
|
258
|
+
["\u53D1\u884C\u7248\u672C", "Releases"],
|
|
259
|
+
["\u53D1\u5E03\u65F6\u95F4 {date} \xB7 DSH {range}", "Published {date} \xB7 DSH {range}"],
|
|
260
|
+
["\u672A\u58F0\u660E", "Not declared"],
|
|
261
|
+
["\u9884\u8BA1\u6EE1 {hours} \u5C0F\u65F6\uFF1A{date}", "Eligible after {hours} hours: {date}"],
|
|
262
|
+
["\u6253\u5F00 troubleshooting", "Open troubleshooting"],
|
|
263
|
+
["Agent \u63A5\u5165", "Agent access"],
|
|
264
|
+
["\u5F00\u53D1\u5DE5\u5177", "Developer tools"],
|
|
265
|
+
["\u77E5\u8BC6\u6587\u6863", "Knowledge"],
|
|
266
|
+
["\u6548\u7387\u5DE5\u5177", "Productivity"],
|
|
267
|
+
["\u7CFB\u7EDF\u96C6\u6210", "Integrations"],
|
|
268
|
+
["\u754C\u9762", "Interface"],
|
|
269
|
+
["\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u8BF7\u786E\u8BA4\u672C\u5730 DSH \u5B9E\u4F8B\u6B63\u5728\u8FD0\u884C\u3002\u6062\u590D\u540E\u9875\u9762\u4F1A\u81EA\u52A8\u91CD\u8FDE\u3002", "Disconnected. Check that the local DSH instance is running. This page will reconnect automatically."],
|
|
270
|
+
["\u8BF7\u6C42\u8D85\u65F6\uFF0C\u6B63\u5728\u7B49\u5F85 DSH \u54CD\u5E94\u3002", "Request timed out while waiting for DSH."],
|
|
271
|
+
["\u8BF7\u5148\u767B\u5F55\u5F53\u524D DSH \u5B9E\u4F8B", "Please authenticate with this DSH instance"],
|
|
272
|
+
["\u8BF7\u6C42\u6765\u6E90\u4E0D\u5339\u914D", "Request origin does not match this DSH instance"],
|
|
273
|
+
["\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u54CD\u5E94\uFF0C\u8BF7\u5237\u65B0 DSH \u9875\u9762\u3002", "The server returned an invalid response. Reload the DSH page."],
|
|
274
|
+
["\u672A\u63D0\u4F9B\u6709\u6548\u7684 DSH \u517C\u5BB9\u58F0\u660E", "No valid DSH compatibility declaration"],
|
|
275
|
+
["\u4ED3\u5E93\u672A\u8FD4\u56DE\u6709\u6548\u53D1\u5E03\u65F6\u95F4", "The registry did not provide a valid release date"],
|
|
276
|
+
["\u8FD4\u56DE\u5185\u5BB9\u4E0D\u662F\u6709\u6548 JSON\uFF0C\u5DF2\u4FDD\u7559\u4E0A\u4E00\u4EFD\u53EF\u7528\u6570\u636E", "Invalid JSON received. The last valid catalog has been retained."],
|
|
277
|
+
["\u4ED3\u5E93\u6CA1\u6709\u8FD4\u56DE\u6709\u6548\u7684\u53D1\u884C\u7248\u672C", "The registry returned no valid releases"],
|
|
278
|
+
["\u4E0A\u6B21\u8FDB\u7A0B\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u65B0\u5B89\u88C5", "The previous process was interrupted. Please install again."],
|
|
279
|
+
["\u5E02\u573A\u6B63\u5728\u5173\u95ED", "Marketplace is shutting down"],
|
|
280
|
+
["\u63D2\u4EF6\u4E0D\u5728\u5F53\u524D\u76EE\u5F55\u4E2D", "Plugin is not in the current catalog"],
|
|
281
|
+
["\u8BE5\u7248\u672C\u4E0D\u53EF\u5B89\u88C5", "This version cannot be installed"],
|
|
282
|
+
["\u5B89\u88C5\u961F\u5217\u5DF2\u6EE1", "Install queue is full"],
|
|
283
|
+
["\u65E0\u6548\u7684\u6F14\u793A\u573A\u666F", "Invalid demo scenario"],
|
|
284
|
+
["\u53EA\u5728\u6F14\u793A\u6A21\u5F0F\u53EF\u7528", "Only available in demo mode"],
|
|
285
|
+
["\u54CD\u5E94\u8D85\u8FC7\u5927\u5C0F\u9650\u5236", "Response exceeds the size limit"]
|
|
286
|
+
];
|
|
287
|
+
var words = { zh: {}, en: {} };
|
|
288
|
+
for (const [key, en, zh = key] of pairs) {
|
|
289
|
+
words.zh[key] = zh;
|
|
290
|
+
words.en[key] = en;
|
|
291
|
+
}
|
|
292
|
+
var tagKeys = { agent: "Agent \u63A5\u5165", "developer-tools": "\u5F00\u53D1\u5DE5\u5177", knowledge: "\u77E5\u8BC6\u6587\u6863", productivity: "\u6548\u7387\u5DE5\u5177", integration: "\u7CFB\u7EDF\u96C6\u6210", ui: "\u754C\u9762" };
|
|
293
|
+
function diagnostic(value, t, language) {
|
|
294
|
+
if (!value) return "";
|
|
295
|
+
if (words.en[value]) return t(value);
|
|
296
|
+
if (value.includes("\uFF1B") || value.includes("; ")) return value.split(/;|; /).map((part) => diagnostic(part, t, language)).join(language.startsWith("zh") ? "\uFF1B" : "; ");
|
|
297
|
+
const entry = value.match(/^目录第 (\d+) 条:(.*)$/);
|
|
298
|
+
if (entry && !language.startsWith("zh")) return `Catalog entry ${entry[1]}: ${diagnostic(entry[2], t, language)}`;
|
|
299
|
+
if (language.startsWith("zh")) return value.replace(/^Duplicate catalog source id: (.+)$/, "\u6570\u636E\u6E90 ID \u91CD\u590D\uFF1A$1");
|
|
300
|
+
return value.replace(/(\S+) 无效/g, "Invalid $1").replace(/(\S+) 不是有效 URL/g, "$1 is not a valid URL").replace(/(\S+) 必须是无凭据的 HTTPS 链接/g, "$1 must be an HTTPS URL without credentials").replace(/请求失败[( ]HTTP (\d+)[)]?/g, "Request failed (HTTP $1)").replace(/作者声明不兼容 DSH (.+)/g, "The author declares DSH $1 incompatible").replace(/插件命令失败(退出码 (\d+))/g, "Plugin command failed (exit code $1)").replace(/要求 DSH (.+),当前为 (.+)/g, "Requires DSH $1; current version is $2").replace(/要求 Node (.+)/g, "Requires Node $1").replace(/无法确认宿主接口 (.+)/g, "Cannot verify host interface $1").replace(/(.+) 要求 (.+),当前为 (.+)/g, "$1 requires $2; current version is $3").replace(/不支持当前 (os|cpu): (.+)/g, "Unsupported $1: $2").replace(/发布未满 (\d+) 小时/g, "Published less than $1 hours ago").replace(/发布未满 (\d+) 分钟/g, "Published less than $1 minutes ago").replace(/已弃用:(.*)/g, "Deprecated: $1");
|
|
301
|
+
}
|
|
302
|
+
function localizePlugin(plugin, language) {
|
|
303
|
+
const locale = plugin.locales?.[language] ?? plugin.locales?.[language.split("-")[0]];
|
|
304
|
+
return locale ? { ...plugin, ...locale } : plugin;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/client/market.css
|
|
308
|
+
var market_default = "/* Brand and page layout only. Interactive controls use DSH primitives unchanged. */\n.hub-market {\n box-sizing: border-box;\n --red: #596579;\n --ink: var(--dsw-alias-label-primary, #25272b);\n --muted: var(--dsw-alias-label-tertiary, #7b7e86);\n --line: var(--dsw-alias-border-l4, #e9e9ed);\n color: var(--ink);\n font: var(--dsw-font-xs-13);\n padding: 5px 3px 20px;\n width: 100%;\n position: relative;\n isolation: isolate;\n container-type: inline-size;\n}\n.hub-market *, .hub-detail-body * { box-sizing: border-box; }\n.hub-market a:focus-visible, .hub-help-link:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 3px; }\n.hub-market svg { flex-shrink: 0; }\n.hub-topline { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 20px; }\n.hub-brand { display: flex; align-items: center; gap: 8px; font-size: 10px; letter-spacing: 1px; font-weight: 700; color: var(--muted); }\n.hub-brandmark { display: grid; place-items: center; width: 25px; height: 25px; color: white; background: var(--red); border-radius: 50%; font: 700 20px Georgia; letter-spacing: 0; }\n.hub-divider { width: 1px; height: 13px; background: var(--line); margin: 0 3px; }\n.hub-runtime { display: flex; align-items: center; gap: 5px; font: 10px ui-monospace, monospace; color: var(--muted); white-space: nowrap; }\n.hub-runtime i, .hub-footer i { width: 5px; height: 5px; border-radius: 50%; background: var(--dsw-alias-state-success-primary); display: inline-block; }\n.hub-header { display: flex; justify-content: space-between; align-items: center; gap: 18px; margin-bottom: 18px; }\n.hub-eyebrow { font-size: 9px; letter-spacing: 1.9px; color: var(--red); font-weight: 700; }\n.hub-header h1 { font-size: 30px; letter-spacing: -1px; margin: 4px 0 5px; font-weight: 650; line-height: 1.4; }\n.hub-header h1 span { color: var(--red); }\n.hub-header p { margin: 0; color: var(--muted); font-size: 12px; }\n.hub-header-art { position: relative; display: grid; place-items: center; color: var(--red); background: linear-gradient(145deg, color-mix(in srgb, var(--red) 5%, white), color-mix(in srgb, var(--red) 14%, white)); width: 80px; height: 74px; border-radius: 20px; transform: rotate(-8deg); flex-shrink: 0; border: 1px solid color-mix(in srgb, var(--red) 15%, transparent); }\n.hub-art-plus { position: absolute; right: -5px; bottom: 6px; background: white; box-shadow: 0 3px 9px #47172515; border-radius: 9px; width: 28px; height: 28px; text-align: center; font-size: 21px; line-height: 26px; transform: rotate(8deg); }\n.hub-art-dot { position: absolute; width: 8px; height: 8px; background: color-mix(in srgb, var(--red) 40%, white); border-radius: 50%; top: 9px; left: -6px; }\n.hub-stats { display: flex; flex-wrap: wrap; align-items: center; gap: 25px; padding: 12px 0; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); margin-bottom: 14px; }\n.hub-stats > div { display: flex; align-items: baseline; gap: 7px; }\n.hub-stats strong { font-size: 23px; font-weight: 600; letter-spacing: -.6px; font-variant-numeric: tabular-nums; }\n.hub-stats span { font-size: 11px; color: var(--muted); }\n.hub-tabs { display: flex; flex-wrap: wrap; gap: 8px; padding-bottom: 12px; border-bottom: 1px solid var(--line); margin-bottom: 14px; }\n.hub-tab-count { font-size: 10px; color: var(--muted); margin-left: 5px; }\n.hub-toolbar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }\n.hub-search-input { flex: 1; min-width: 180px; }\n.hub-results { display: flex; justify-content: space-between; align-items: center; gap: 10px; color: var(--muted); font-size: 11px; margin: 20px 0 12px; }\n.hub-results b { margin-left: 4px; font-weight: 500; }\n.hub-results small { font-size: 9px; }\n.hub-pagination { display: flex; justify-content: center; padding: 20px 0 0; }\n.hub-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 13px; }\n.hub-card { border: 1px solid var(--line); border-radius: 11px; padding: 16px; background: var(--dsw-alias-bg-layer-2, #fff); display: flex; flex-direction: column; min-width: 0; }\n.hub-card-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; margin-bottom: 10px; flex-wrap: wrap; }\n.hub-plugin-icon { display: grid; place-items: center; border-radius: 10px; width: 40px; height: 40px; background: #f4f0ea; color: #9c754f; }\n.hub-plugin-icon.icon-knowledge { background: #eaf3f2; color: #4c8b80; }\n.hub-plugin-icon.icon-developer-tools { background: #edf0fa; color: #6278ac; }\n.hub-plugin-icon.icon-agent { background: #f8e9ed; color: #b94b63; }\n.hub-plugin-icon.icon-integration { background: #f1eefa; color: #8c6db2; }\n.hub-card-heading { font-size: 14px; margin: 0 -8px; }\n.hub-description { font-size: 12px; color: var(--muted); line-height: 1.85; min-height: 44px; margin: 13px 0 12px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n.hub-tags { display: flex; gap: 5px; flex-wrap: wrap; margin: 0 0 14px; }\n.hub-version-row { border-top: 1px solid var(--line); padding-top: 12px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px; font-size: 11px; color: var(--muted); margin-top: auto; }\n.hub-version-note { font-size: 10px; color: var(--muted); overflow-wrap: anywhere; margin: 7px 0 13px; min-height: 16px; }\n.hub-card-actions { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 9px; }\n.hub-footer { display: flex; justify-content: space-between; flex-wrap: wrap; font-size: 9px; color: var(--muted); margin-top: 21px; gap: 8px; }\n.hub-footer i { margin-right: 5px; }\n.hub-footnote { font-size: 9px; color: var(--muted); margin: 7px 0 0; line-height: 1.7; }\n.hub-empty { padding: 50px 10px; text-align: center; color: var(--muted); }\n.hub-empty svg { margin: auto; }\n.hub-empty h2, .hub-empty h3 { color: var(--ink); font-weight: 500; }\n.hub-notice { display: flex; gap: 8px; align-items: center; font-size: 11px; padding: 12px; border-radius: 7px; margin: 10px 0; }\n.hub-notice.amber { background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 10%, var(--dsw-alias-bg-layer-2)); color: var(--dsw-alias-label-primary); }\n.hub-notice.red { background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, var(--dsw-alias-bg-layer-2)); color: var(--dsw-alias-label-primary); }\n.hub-notice > div, .hub-notice > span { flex: 1; }\n.hub-notice b, .hub-notice div > span { display: block; }\n.hub-notice b { font-weight: 500; }\n.hub-notice div > span { font-size: 10px; }\n.hub-queue { position: sticky; bottom: 0; z-index: 4; margin-top: 16px; background: var(--dsw-alias-bg-layer-2, #fff); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--dsw-elevation-prominent); overflow: hidden; }\n.hub-queue-summary { display: flex; align-items: center; width: 100%; gap: 10px; padding: 12px 15px; color: var(--ink); }\n.hub-queue-summary > span:nth-child(2) { flex: 1; }\n.hub-queue-icon { display: grid; place-items: center; border-radius: 8px; width: 33px; height: 33px; background: color-mix(in srgb, var(--red) 9%, white); color: var(--red); }\n.hub-queue-summary b { font-size: 11px; font-weight: 500; display: block; }\n.hub-queue-summary small { font-size: 9px; color: var(--muted); display: block; }\n.hub-jobs { border-top: 1px solid var(--line); max-height: 170px; overflow: auto; padding: 0 15px; }\n.hub-jobs > div { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line); flex-wrap: wrap; }\n.hub-jobs > div > span:first-child { flex: 1; }\n.hub-jobs b { font-weight: 500; font-size: 10px; }\n.hub-jobs small { font-size: 9px; margin-left: 7px; color: var(--muted); }\n.hub-jobs p { font-size: 10px; width: 100%; color: var(--red); margin: 0; }\n.hub-detail-dialog { width: min(500px, 100%); max-height: 85vh; }\n.hub-detail-scroll { overflow: auto; }\n.hub-detail-body { color: var(--dsw-alias-label-primary); font: var(--dsw-font-xs-13); }\n.hub-package-name { font-size: 11px; color: var(--dsw-alias-label-tertiary); overflow-wrap: anywhere; }\n.hub-detail-info { display: flex; flex-wrap: wrap; gap: 25px; font-size: 11px; color: var(--dsw-alias-label-tertiary); padding: 16px 0; }\n.hub-detail-info b { display: block; color: var(--dsw-alias-label-secondary); font-weight: 500; margin-top: 3px; }\n.hub-detail-body h3 { font-size: 13px; margin: 10px 0; }\n.hub-releases { display: grid; gap: 12px; }\n.hub-release { border-bottom: 1px solid var(--dsw-alias-border-l4); padding-bottom: 12px; }\n.hub-release > div { display: flex; justify-content: space-between; align-items: center; }\n.hub-release small, .hub-release p { font-size: 11px; color: var(--dsw-alias-label-tertiary); margin: 6px 0 0; display: block; }\n.hub-help-link:hover { color: var(--dsw-alias-brand-primary); text-decoration: underline; }\n.hub-help-link { color: var(--dsw-alias-label-secondary); font-size: 11px; display: inline-flex; align-items: center; gap: 4px; text-decoration: none; }\n.spinning { animation: hub-spin .9s linear infinite; }\n@keyframes hub-spin { to { transform: rotate(360deg); } }\n@container (max-width: 470px) {\n .hub-grid { grid-template-columns: 1fr; }\n .hub-topline { flex-wrap: wrap; }\n .hub-header-art { display: none; }\n .hub-results small { display: none; }\n .hub-stats { gap: 15px; }\n}\n@media (prefers-reduced-motion: reduce) { .spinning { animation: none; } }\n\n.hub-card-package { font-size: 10px; color: var(--dsw-alias-label-tertiary); overflow-wrap: anywhere; margin-top: 5px; }\n.hub-document-links { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 12px; }\n.hub-detail-actions { width: 100%; }\n.hub-detail-actions > div:first-child { display: flex; flex-wrap: wrap; gap: 8px; }\n\n.hub-source-label { display: block; margin-top: 8px; color: var(--dsw-alias-label-tertiary); font-size: 11px; }\n";
|
|
309
|
+
|
|
310
|
+
// src/client/index.jsx
|
|
311
|
+
var NS = "@zaimokuza/dsh-plugin-hub";
|
|
312
|
+
var MARKET_ID = "hub";
|
|
313
|
+
var BRAND = define_HUB_BRAND_default;
|
|
314
|
+
var request2 = (path, data, options) => request(path, data, { ...options, base: `/dsh-plugin-hub/${MARKET_ID}/api/` });
|
|
315
|
+
function Icon({ name: name2 = "box", size = 18, ...props }) {
|
|
316
|
+
const paths = {
|
|
317
|
+
search: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "10.5", cy: "10.5", r: "6.5" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "m16 16 4 4" })),
|
|
318
|
+
box: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "m12 3 9 5-9 5-9-5 9-5Z" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M3 8v9l9 5 9-5V8M12 13v9M7.5 5.5l9 5" })),
|
|
319
|
+
download: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 3v12m-5-5 5 5 5-5M4 16v5h16v-5" })),
|
|
320
|
+
arrow: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "M7 17 17 7M7 7h10v10" })),
|
|
321
|
+
refresh: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "M20 7v5h-5M4 17v-5h5" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M5.2 7A8 8 0 0 1 19 6l1 2M4 16l1 2a8 8 0 0 0 13.8-1" })),
|
|
322
|
+
clock: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("circle", { cx: "12", cy: "12", r: "9" }), /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 7v5l3 2" })),
|
|
323
|
+
check: /* @__PURE__ */ import_react.default.createElement("path", { d: "m5 12 4 4L19 6" }),
|
|
324
|
+
close: /* @__PURE__ */ import_react.default.createElement("path", { d: "m6 6 12 12M18 6 6 18" }),
|
|
325
|
+
code: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "m8 6-6 6 6 6m8-12 6 6-6 6m-3-15-2 18" })),
|
|
326
|
+
book: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "M12 5v16M3 4c4-1 6 0 9 2 3-2 5-3 9-2v15c-4-1-6 0-9 2-3-2-5-3-9-2V4Z" })),
|
|
327
|
+
plug: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "M8 2v5m8-5v5M6 7h12v4a6 6 0 0 1-12 0V7ZM12 17v5" })),
|
|
328
|
+
filter: /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("path", { d: "M4 7h16M7 12h10M10 17h4" }))
|
|
329
|
+
};
|
|
330
|
+
return /* @__PURE__ */ import_react.default.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props }, paths[name2] ?? paths.box);
|
|
331
|
+
}
|
|
332
|
+
function Picker({ label, value, items, onChange, disabled, icon, title }) {
|
|
333
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
334
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
335
|
+
import_dsh_client_ui_primitives.Menu,
|
|
336
|
+
{
|
|
337
|
+
open,
|
|
338
|
+
onClose: () => setOpen(false),
|
|
339
|
+
items,
|
|
340
|
+
selectedId: value,
|
|
341
|
+
portal: true,
|
|
342
|
+
align: "end",
|
|
343
|
+
onSelect: (id) => {
|
|
344
|
+
setOpen(false);
|
|
345
|
+
onChange(id);
|
|
346
|
+
},
|
|
347
|
+
anchor: /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", disabled, "aria-label": label, "aria-haspopup": "menu", "aria-expanded": open, icon, onClick: () => setOpen((v) => !v) }, title ?? items.find((item) => item.id === value)?.label, /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.IconChevronDownOutline14, null))
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
function Badge({ tone = "neutral", children }) {
|
|
352
|
+
const state = { green: "done", amber: "warning", red: "error", ongoing: "ongoing" }[tone];
|
|
353
|
+
return /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Pill, null, state && /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.StateDot, { state }), " ", children);
|
|
354
|
+
}
|
|
355
|
+
function status(plugin, release, t, hours) {
|
|
356
|
+
if (plugin.metadataLoading) return { label: t("\u6B63\u5728\u67E5\u8BE2\u7248\u672C"), tone: "ongoing" };
|
|
357
|
+
if (plugin.queryError) return { label: t(plugin.queryError.includes("\uFF08404\uFF09") ? "\u5F53\u524D\u4ED3\u5E93\u672A\u627E\u5230" : plugin.queryError.includes("\u4ED3\u5E93\u4E0E\u76EE\u5F55\u4E0D\u4E00\u81F4") ? "\u6765\u6E90\u4E0D\u5339\u914D" : plugin.queryError.includes("\u672A\u58F0\u660E\u53EF\u6838\u5BF9\u7684 GitHub \u6765\u6E90") ? "\u6765\u6E90\u672A\u6838\u5B9E" : "\u67E5\u8BE2\u5931\u8D25"), tone: "neutral" };
|
|
358
|
+
if (!release || release.compatibility === "unknown") return { label: t("\u517C\u5BB9\u6027\u672A\u77E5"), tone: "neutral" };
|
|
359
|
+
if (release.compatibility === "incompatible") return { label: t("\u7248\u672C\u4E0D\u517C\u5BB9"), tone: "red" };
|
|
360
|
+
if (release.age === "waiting") return { label: Number.isInteger(hours) ? t("\u672A\u6EE1 {hours} \u5C0F\u65F6", { hours }) : t("\u672A\u6EE1 {minutes} \u5206\u949F", { minutes: Math.round(hours * 60) }), tone: "amber" };
|
|
361
|
+
if (release.age === "unknown") return { label: t("\u53D1\u5E03\u65F6\u95F4\u672A\u77E5"), tone: "neutral" };
|
|
362
|
+
return release.canInstall ? { label: t("\u7B26\u5408\u5B89\u88C5\u6761\u4EF6"), tone: "green" } : { label: t("\u6682\u4E0D\u53EF\u5B89\u88C5"), tone: "neutral" };
|
|
363
|
+
}
|
|
364
|
+
function Market({ locale, t }) {
|
|
365
|
+
const language = (0, import_react.useSyncExternalStore)((listener) => locale.subscribe(listener), () => locale.getSnapshot().active);
|
|
366
|
+
const date = (value) => value ? new Date(value).toLocaleString(language.startsWith("zh") ? "zh-CN" : language, { month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false }) : t("\u65F6\u95F4\u672A\u77E5");
|
|
367
|
+
const explain = (value) => diagnostic(value, t, language);
|
|
368
|
+
const [data, setData] = (0, import_react.useState)(null);
|
|
369
|
+
const [error, setError] = (0, import_react.useState)("");
|
|
370
|
+
const [connectionError, setConnectionError] = (0, import_react.useState)("");
|
|
371
|
+
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
372
|
+
const [query, setQuery] = (0, import_react.useState)("");
|
|
373
|
+
const [tab, setTab] = (0, import_react.useState)("all");
|
|
374
|
+
const [tag, setTag] = (0, import_react.useState)("all");
|
|
375
|
+
const [visibleCount, setVisibleCount] = (0, import_react.useState)(40);
|
|
376
|
+
(0, import_react.useEffect)(() => setVisibleCount(40), [query, tab, tag]);
|
|
377
|
+
const [selected, setSelected] = (0, import_react.useState)({});
|
|
378
|
+
const [detailName, setDetailName] = (0, import_react.useState)(null);
|
|
379
|
+
const [showJobs, setShowJobs] = (0, import_react.useState)(false);
|
|
380
|
+
const [submitting, setSubmitting] = (0, import_react.useState)({});
|
|
381
|
+
(0, import_react.useEffect)(() => {
|
|
382
|
+
const controller = new AbortController();
|
|
383
|
+
let timer;
|
|
384
|
+
let failures = 0;
|
|
385
|
+
async function poll(first = false) {
|
|
386
|
+
try {
|
|
387
|
+
const value = await request2("state", void 0, { signal: controller.signal });
|
|
388
|
+
if (!controller.signal.aborted) {
|
|
389
|
+
setData(value);
|
|
390
|
+
setConnectionError("");
|
|
391
|
+
failures = 0;
|
|
392
|
+
}
|
|
393
|
+
} catch (err) {
|
|
394
|
+
if (!controller.signal.aborted) {
|
|
395
|
+
setConnectionError(err.message);
|
|
396
|
+
failures++;
|
|
397
|
+
}
|
|
398
|
+
} finally {
|
|
399
|
+
if (!controller.signal.aborted) {
|
|
400
|
+
if (first) setLoading(false);
|
|
401
|
+
timer = setTimeout(() => poll(), Math.min(1e4, 2e3 * 2 ** failures));
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
void poll(true);
|
|
406
|
+
return () => {
|
|
407
|
+
controller.abort();
|
|
408
|
+
clearTimeout(timer);
|
|
409
|
+
};
|
|
410
|
+
}, []);
|
|
411
|
+
const pendingVisible = (data?.lazyMetadata ? data.plugins.map((p) => localizePlugin(p, language)).filter((p) => inScope(p, resolveScope(tab, data.sources ?? [])) && (tag === "all" || p.tags.includes(tag)) && [p.displayName, p.packageName, p.description, p.owner, ...p.tags.map((id) => tagKeys[id] ? t(tagKeys[id]) : id)].join(" ").toLowerCase().includes(query.trim().toLowerCase())).slice(0, visibleCount).filter((p) => p.metadataLoading).slice(0, 40).map((p) => p.packageName) : []).join("|");
|
|
412
|
+
(0, import_react.useEffect)(() => {
|
|
413
|
+
if (!pendingVisible) return;
|
|
414
|
+
const controller = new AbortController();
|
|
415
|
+
void request2("releases", { packageNames: pendingVisible.split("|") }, { signal: controller.signal }).catch((error2) => {
|
|
416
|
+
if (!controller.signal.aborted) setError(error2.message);
|
|
417
|
+
});
|
|
418
|
+
return () => controller.abort();
|
|
419
|
+
}, [pendingVisible]);
|
|
420
|
+
function reportActionError(err) {
|
|
421
|
+
if (["\u8FDE\u63A5\u5DF2\u65AD\u5F00\uFF0C\u8BF7\u786E\u8BA4\u672C\u5730 DSH \u5B9E\u4F8B\u6B63\u5728\u8FD0\u884C\u3002\u6062\u590D\u540E\u9875\u9762\u4F1A\u81EA\u52A8\u91CD\u8FDE\u3002", "\u8BF7\u6C42\u8D85\u65F6\uFF0C\u6B63\u5728\u7B49\u5F85 DSH \u54CD\u5E94\u3002", "\u8BF7\u5148\u767B\u5F55\u5F53\u524D DSH \u5B9E\u4F8B", "\u670D\u52A1\u8FD4\u56DE\u4E86\u65E0\u6548\u54CD\u5E94\uFF0C\u8BF7\u5237\u65B0 DSH \u9875\u9762\u3002"].includes(err.message)) setConnectionError(err.message);
|
|
422
|
+
else setError(err.message);
|
|
423
|
+
}
|
|
424
|
+
async function update(path = "refresh", body = {}) {
|
|
425
|
+
setLoading(true);
|
|
426
|
+
setError("");
|
|
427
|
+
try {
|
|
428
|
+
setData(await request2(path === "refresh" ? "refresh-start" : path, body));
|
|
429
|
+
setConnectionError("");
|
|
430
|
+
} catch (err) {
|
|
431
|
+
reportActionError(err);
|
|
432
|
+
} finally {
|
|
433
|
+
setLoading(false);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async function install(plugin, release, action = "install") {
|
|
437
|
+
if (action === "install" && !release?.canInstall) return;
|
|
438
|
+
setSubmitting((previous) => ({ ...previous, [plugin.packageName]: true }));
|
|
439
|
+
setError("");
|
|
440
|
+
try {
|
|
441
|
+
await request2(action, { packageName: plugin.packageName, ...action === "install" ? { version: release.version } : {} });
|
|
442
|
+
setData(await request2("state"));
|
|
443
|
+
setShowJobs(true);
|
|
444
|
+
setConnectionError("");
|
|
445
|
+
} catch (err) {
|
|
446
|
+
reportActionError(err);
|
|
447
|
+
} finally {
|
|
448
|
+
setSubmitting((previous) => ({ ...previous, [plugin.packageName]: false }));
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
const releaseOf = (plugin) => plugin.versions.find((v) => v.version === selected[plugin.packageName]) ?? plugin.versions.find((v) => v.version === plugin.recommendedVersion) ?? plugin.versions[0];
|
|
452
|
+
const linkFor = (plugin, key) => plugin[key];
|
|
453
|
+
function documentLinks(plugin) {
|
|
454
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-document-links" }, [["documentationUrl", "\u4ECB\u7ECD\u6587\u6863"], ["troubleshootingUrl", "\u6392\u67E5\u6307\u5357"]].filter(([key]) => plugin[key]).map(([key, label]) => /* @__PURE__ */ import_react.default.createElement("a", { className: "hub-help-link", key, href: linkFor(plugin, key), target: "_blank", rel: "noopener noreferrer", title: plugin[key] }, t(label), " ", /* @__PURE__ */ import_react.default.createElement(Icon, { name: "arrow", size: 13 }))));
|
|
455
|
+
}
|
|
456
|
+
function uninstallButton(plugin) {
|
|
457
|
+
if (!plugin.installedVersion) return null;
|
|
458
|
+
const job = data.jobs.find((job2) => job2.packageName === plugin.packageName && ["queued", "installing"].includes(job2.status));
|
|
459
|
+
return /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", variant: "outline", disabled: Boolean(job) || submitting[plugin.packageName] || Boolean(connectionError), onClick: () => install(plugin, null, "uninstall") }, t(job?.action === "uninstall" ? "\u6B63\u5728\u5378\u8F7D\u2026" : "\u5378\u8F7D\u63D2\u4EF6"));
|
|
460
|
+
}
|
|
461
|
+
function installButton(plugin, release) {
|
|
462
|
+
const job = data.jobs.find((job2) => job2.packageName === plugin.packageName && ["queued", "installing"].includes(job2.status));
|
|
463
|
+
const installed = plugin.installedVersion === release?.version;
|
|
464
|
+
const key = job ? job.status === "queued" ? "\u5DF2\u52A0\u5165\u961F\u5217" : job.action === "uninstall" ? "\u6B63\u5728\u5378\u8F7D\u2026" : "\u6B63\u5728\u5B89\u88C5\u2026" : installed ? "\u5DF2\u5B89\u88C5" : !release?.canInstall ? "\u6682\u4E0D\u53EF\u5B89\u88C5" : "\u5B89\u88C5\u63D2\u4EF6";
|
|
465
|
+
return /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: installed ? "outline" : "primary", size: "sm", disabled: !release?.canInstall || installed || Boolean(job) || submitting[plugin.packageName] || Boolean(connectionError), onClick: () => install(plugin, release), icon: /* @__PURE__ */ import_react.default.createElement(Icon, { name: installed ? "check" : job ? "clock" : "download", size: 15 }) }, t(key));
|
|
466
|
+
}
|
|
467
|
+
if (!data) return /* @__PURE__ */ import_react.default.createElement("section", { className: "hub-market" }, /* @__PURE__ */ import_react.default.createElement("style", null, market_default), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-empty" }, /* @__PURE__ */ import_react.default.createElement(Icon, { name: "box", size: 38 }), /* @__PURE__ */ import_react.default.createElement("h2", null, BRAND.navTitle), /* @__PURE__ */ import_react.default.createElement("p", { role: error || connectionError ? "alert" : void 0 }, explain(error || connectionError) || t("\u6B63\u5728\u8BFB\u53D6\u63D2\u4EF6\u76EE\u5F55\u2026")), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: "outline", onClick: () => update() }, t("\u91CD\u65B0\u83B7\u53D6"))));
|
|
468
|
+
const all = data.plugins.map((plugin) => localizePlugin(plugin, language));
|
|
469
|
+
const tags = Object.fromEntries(Object.entries(tagKeys).map(([key, label]) => [key, t(label)]));
|
|
470
|
+
const sourceTabs = (data.sources ?? []).filter((source) => !source.primary);
|
|
471
|
+
const activeTab = resolveScope(tab, sourceTabs);
|
|
472
|
+
const selectedSource = sourceTabs.find((source) => activeTab === "source:" + source.id);
|
|
473
|
+
const tabs = [["all", "\u5168\u90E8\u63D2\u4EF6", all.length], ["installed", "\u5DF2\u5B89\u88C5", all.filter((p) => p.installedVersion).length], ...sourceTabs.map((source) => ["source:" + source.id, source.displayName, all.filter((p) => inScope(p, "source:" + source.id)).length])];
|
|
474
|
+
const filtered = all.filter((plugin) => inScope(plugin, activeTab) && (tag === "all" || plugin.tags.includes(tag)) && [plugin.displayName, plugin.packageName, plugin.description, plugin.owner, ...plugin.tags.map((item) => tags[item] ?? item)].join(" ").toLowerCase().includes(query.trim().toLowerCase()));
|
|
475
|
+
const detail = all.find((plugin) => plugin.packageName === detailName);
|
|
476
|
+
const pending = data.jobs.filter((job) => ["queued", "installing"].includes(job.status)).length;
|
|
477
|
+
const ready = all.filter((plugin) => plugin.recommendedVersion).length;
|
|
478
|
+
const brand = data.brand ?? BRAND;
|
|
479
|
+
return /* @__PURE__ */ import_react.default.createElement("section", { className: "hub-market", lang: language, style: { "--red": brand.primaryColor } }, /* @__PURE__ */ import_react.default.createElement("style", null, market_default), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-topline" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-brand" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-brandmark" }, brand.title.slice(0, 1)), brand.title, " ", /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-divider" }), " ", brand.subTitle), /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-runtime" }, /* @__PURE__ */ import_react.default.createElement("i", null), "DSH ", data.host.dsh)), /* @__PURE__ */ import_react.default.createElement("header", { className: "hub-header" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-eyebrow" }, t("\u63D2\u4EF6\u76EE\u5F55")), /* @__PURE__ */ import_react.default.createElement("h1", null, t("\u63D2\u4EF6\u5E02\u573A"), /* @__PURE__ */ import_react.default.createElement("span", null, t("\u3002"))), /* @__PURE__ */ import_react.default.createElement("p", null, t("\u627E\u5230\u9002\u5408\u5F53\u524D DSH \u7684\u5DE5\u5177\u3002"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-header-art" }, /* @__PURE__ */ import_react.default.createElement(Icon, { name: "box", size: 44 }), /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-art-plus" }, "+"), /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-art-dot" }))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-stats" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("strong", null, all.length.toString().padStart(2, "0")), /* @__PURE__ */ import_react.default.createElement("span", null, t("\u6536\u5F55\u63D2\u4EF6"))), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("strong", null, ready.toString().padStart(2, "0")), /* @__PURE__ */ import_react.default.createElement("span", null, t(data.lazyMetadata ? "\u5DF2\u786E\u8BA4\u53EF\u5B89\u88C5" : "\u6709\u53EF\u5B89\u88C5\u7248\u672C")))), /* @__PURE__ */ import_react.default.createElement("p", { className: "hub-footnote" }, t("\u51B7\u9759\u671F\uFF1A{minutes} \u5206\u949F \xB7 {source}", { minutes: data.minimumAgeMinutes, source: t(data.releaseAgeSource === "pnpm" ? "\u672C\u673A pnpm \u914D\u7F6E" : "\u9ED8\u8BA4 48 \u5C0F\u65F6") })), (data.lazyMetadata || data.metadataProgress?.running) && /* @__PURE__ */ import_react.default.createElement("p", null, t("\u5DF2\u67E5\u8BE2 {done} / {total} \u4E2A\u63D2\u4EF6\u7684\u7248\u672C", data.metadataProgress)), data.catalog.error && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-notice amber" }, /* @__PURE__ */ import_react.default.createElement(Icon, { name: "clock" }), /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement("b", null, t(data.catalog.stale ? "\u76EE\u5F55\u66F4\u65B0\u5931\u8D25\uFF0C\u7EE7\u7EED\u4F7F\u7528\u4E0A\u4E00\u4EFD\u6709\u6548\u6570\u636E" : "\u76EE\u5F55\u6682\u4E0D\u53EF\u7528")), /* @__PURE__ */ import_react.default.createElement("span", null, explain(data.catalog.error))), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", onClick: () => update() }, t("\u91CD\u8BD5"))), connectionError && /* @__PURE__ */ import_react.default.createElement("div", { role: "alert", className: "hub-notice red" }, /* @__PURE__ */ import_react.default.createElement("span", null, explain(connectionError)), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", onClick: () => update() }, t("\u91CD\u8BD5"))), error && error !== connectionError && /* @__PURE__ */ import_react.default.createElement("div", { role: "alert", className: "hub-notice red" }, /* @__PURE__ */ import_react.default.createElement("span", null, explain(error)), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", "aria-label": t("\u5173\u95ED\u9519\u8BEF"), onClick: () => setError(""), icon: /* @__PURE__ */ import_react.default.createElement(Icon, { name: "close" }) })), /* @__PURE__ */ import_react.default.createElement("nav", { className: "hub-tabs", "aria-label": t("\u63D2\u4EF6\u8303\u56F4") }, tabs.map(([key, label, count]) => /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { key, size: "sm", variant: activeTab === key ? "toolbar" : "ghost", "aria-pressed": activeTab === key, onClick: () => setTab(key) }, t(label), count !== null && /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-tab-count" }, count)))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-toolbar" }, /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Input, { className: "hub-search-input", icon: /* @__PURE__ */ import_react.default.createElement(Icon, { name: "search", size: 16 }), "aria-label": t("\u641C\u7D22\u63D2\u4EF6"), placeholder: t("\u641C\u7D22\u63D2\u4EF6\u3001\u7528\u9014\u6216\u7EF4\u62A4\u56E2\u961F"), value: query, onChange: (event) => setQuery(event.target.value) }), query && /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", "aria-label": t("\u6E05\u7A7A\u641C\u7D22"), onClick: () => setQuery(""), icon: /* @__PURE__ */ import_react.default.createElement(Icon, { name: "close", size: 14 }) }), /* @__PURE__ */ import_react.default.createElement(Picker, { label: t("\u6309\u6807\u7B7E\u7B5B\u9009"), value: tag, items: [{ id: "all", label: t("\u6240\u6709\u6807\u7B7E") }, ...Object.entries(tags).map(([id, label]) => ({ id, label }))], onChange: setTag, icon: /* @__PURE__ */ import_react.default.createElement(Icon, { name: "filter", size: 16 }) }), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", disabled: loading, onClick: () => update(), title: t("\u5237\u65B0\u76EE\u5F55\u4E0E\u7248\u672C"), icon: /* @__PURE__ */ import_react.default.createElement(Icon, { name: "refresh", size: 16, className: loading ? "spinning" : "" }) }, t("\u5237\u65B0"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-results" }, /* @__PURE__ */ import_react.default.createElement("span", null, query ? t("\u201C{query}\u201D \u7684\u641C\u7D22\u7ED3\u679C", { query }) : t(selectedSource?.displayName ?? (activeTab === "installed" ? "\u4F60\u7684\u5DE5\u4F5C\u5DE5\u5177" : "\u4E3A\u56E2\u961F\u7CBE\u9009")), " ", /* @__PURE__ */ import_react.default.createElement("b", null, filtered.length)), /* @__PURE__ */ import_react.default.createElement("small", null, t("\u7248\u672C\u4FE1\u606F\u6765\u81EA npm \xB7 \u6309\u5F53\u524D DSH \u68C0\u67E5\u58F0\u660E"))), selectedSource?.error && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-notice amber" }, /* @__PURE__ */ import_react.default.createElement("span", null, t(selectedSource.displayName), " \xB7 ", explain(selectedSource.error), selectedSource.stale && " \xB7 " + t("\u4F7F\u7528\u7F13\u5B58"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-grid" }, filtered.slice(0, visibleCount).map((plugin, index) => {
|
|
480
|
+
const release = releaseOf(plugin);
|
|
481
|
+
const state = status(plugin, release, t, data.minimumAgeHours);
|
|
482
|
+
return /* @__PURE__ */ import_react.default.createElement("article", { className: "hub-card", key: plugin.packageName, style: { "--card-index": index } }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-card-top" }, /* @__PURE__ */ import_react.default.createElement("span", { className: `hub-plugin-icon icon-${plugin.tags[0]}` }, /* @__PURE__ */ import_react.default.createElement(Icon, { name: plugin.tags.includes("agent") ? "plug" : plugin.tags[0] === "knowledge" ? "book" : plugin.tags.includes("developer-tools") ? "code" : "box", size: 25 })), /* @__PURE__ */ import_react.default.createElement(Badge, { tone: state.tone }, state.label)), /* @__PURE__ */ import_react.default.createElement("h2", { className: "hub-card-heading" }, /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", onClick: () => setDetailName(plugin.packageName) }, plugin.displayName, /* @__PURE__ */ import_react.default.createElement(Icon, { name: "arrow", size: 13 }))), /* @__PURE__ */ import_react.default.createElement("code", { className: "hub-card-package" }, plugin.packageName), (data.sources?.length ?? 0) > 1 && /* @__PURE__ */ import_react.default.createElement("small", { className: "hub-source-label" }, t("\u6765\u6E90"), " \xB7 ", t(plugin.catalogSource?.displayName ?? "")), /* @__PURE__ */ import_react.default.createElement("p", { className: "hub-description" }, plugin.description), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-tags" }, plugin.tags.map((item) => /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Pill, { key: item }, tags[item] ?? item))), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-version-row" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("\u9009\u62E9\u7248\u672C")), /* @__PURE__ */ import_react.default.createElement(Picker, { label: t("{name}\u7248\u672C", { name: plugin.displayName }), value: release?.version ?? "", disabled: !plugin.versions.length, items: plugin.versions.length ? plugin.versions.map((v) => ({ id: v.version, label: v.version + (v.version === plugin.recommendedVersion ? " \xB7 " + t("\u63A8\u8350") : "") })) : [{ id: "", label: t("\u6682\u4E0D\u53EF\u7528") }], onChange: (value) => setSelected((previous) => ({ ...previous, [plugin.packageName]: value })) })), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-version-note" }, plugin.queryError ? explain(plugin.queryError) : release?.canInstall ? t("\u53D1\u5E03\u4E8E {date}", { date: date(release.publishedAt) }) : explain(release?.reasons[0]) || t("\u6CA1\u6709\u53EF\u7528\u7248\u672C")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-card-actions" }, installButton(plugin, release), uninstallButton(plugin)), documentLinks(plugin));
|
|
483
|
+
})), filtered.length > visibleCount && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-pagination" }, /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: "outline", size: "sm", onClick: () => setVisibleCount((value) => value + 40) }, t("\u52A0\u8F7D\u66F4\u591A"))), !filtered.length && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-empty" }, /* @__PURE__ */ import_react.default.createElement(Icon, { name: "search", size: 32 }), /* @__PURE__ */ import_react.default.createElement("h3", null, t("\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u63D2\u4EF6")), /* @__PURE__ */ import_react.default.createElement("p", null, t("\u8BD5\u8BD5\u5176\u5B83\u5173\u952E\u8BCD\uFF0C\u6216\u6E05\u9664\u5F53\u524D\u7B5B\u9009\u6761\u4EF6\u3002")), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: "outline", onClick: () => {
|
|
484
|
+
setQuery("");
|
|
485
|
+
setTag("all");
|
|
486
|
+
setTab("all");
|
|
487
|
+
} }, t("\u67E5\u770B\u5168\u90E8\u63D2\u4EF6"))), /* @__PURE__ */ import_react.default.createElement("footer", { className: "hub-footer" }, /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement("i", null), t("\u76EE\u5F55 {version} \xB7 \u66F4\u65B0\u4E8E {date}", { version: data.catalog.version ?? t("\u672A\u52A0\u8F7D"), date: date(data.catalog.updatedAt) })), /* @__PURE__ */ import_react.default.createElement("span", null, t("\u5E02\u573A v{version}", { version: data.marketVersion }))), /* @__PURE__ */ import_react.default.createElement("p", { className: "hub-footnote" }, t("\u201C\u7B26\u5408\u5B89\u88C5\u6761\u4EF6\u201D\u4F9D\u636E\u7248\u672C\u58F0\u660E\u4E0E\u53D1\u5E03\u65F6\u95F4\uFF0C\u5B9E\u9645\u4E0B\u8F7D\u4ECD\u4EE5 Nexus \u4E3A\u51C6\u3002")), !!data.jobs.length && /* @__PURE__ */ import_react.default.createElement("aside", { className: "hub-queue" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-queue-summary" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "hub-queue-icon" }, /* @__PURE__ */ import_react.default.createElement(Icon, { name: pending ? "download" : "check" })), /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement("b", null, pending ? t("{count} \u4E2A\u63D2\u4EF6\u64CD\u4F5C\u6B63\u5728\u6267\u884C", { count: pending }) : t("\u63D2\u4EF6\u64CD\u4F5C\u5DF2\u5B8C\u6210")), /* @__PURE__ */ import_react.default.createElement("small", null, t("{count} \u9879\u5F85\u624B\u52A8\u91CD\u542F\u751F\u6548", { count: data.pendingRestart }))), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { size: "sm", onClick: () => setShowJobs(!showJobs), "aria-expanded": showJobs }, t(showJobs ? "\u6536\u8D77" : "\u67E5\u770B\u4EFB\u52A1"))), showJobs && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-jobs" }, data.jobs.slice().reverse().map((job) => /* @__PURE__ */ import_react.default.createElement("div", { key: job.id }, /* @__PURE__ */ import_react.default.createElement("span", null, /* @__PURE__ */ import_react.default.createElement("b", null, all.find((p) => p.packageName === job.packageName)?.displayName ?? job.packageName), /* @__PURE__ */ import_react.default.createElement("small", null, t(job.action === "uninstall" ? "\u5378\u8F7D" : "\u5B89\u88C5"), " \xB7 ", job.version)), /* @__PURE__ */ import_react.default.createElement(Badge, { tone: job.status === "completed" ? "green" : job.status === "failed" ? "red" : "amber" }, t({ queued: "\u6392\u961F\u4E2D", installing: job.action === "uninstall" ? "\u5378\u8F7D\u4E2D" : "\u5B89\u88C5\u4E2D", completed: "\u5F85\u91CD\u542F", failed: job.action === "uninstall" ? "\u5378\u8F7D\u5931\u8D25" : "\u5B89\u88C5\u5931\u8D25" }[job.status])), job.error && /* @__PURE__ */ import_react.default.createElement("p", null, explain(job.error)))))), /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Modal, { open: Boolean(detail), onClose: () => setDetailName(null), title: detail?.displayName ?? "", closeLabel: t("\u5173\u95ED\u8BE6\u60C5"), className: "hub-detail-dialog", contentClassName: "hub-detail-scroll", description: detail?.description, footer: detail && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-detail-actions" }, /* @__PURE__ */ import_react.default.createElement("div", null, installButton(detail, releaseOf(detail)), uninstallButton(detail)), documentLinks(detail)) }, detail && /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-detail-body" }, /* @__PURE__ */ import_react.default.createElement("code", { className: "hub-package-name" }, detail.packageName), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-detail-info" }, /* @__PURE__ */ import_react.default.createElement("span", null, t("\u7EF4\u62A4\u56E2\u961F"), /* @__PURE__ */ import_react.default.createElement("b", null, detail.owner)), /* @__PURE__ */ import_react.default.createElement("span", null, t("\u5F53\u524D\u5BBF\u4E3B"), /* @__PURE__ */ import_react.default.createElement("b", null, "DSH ", data.host.dsh))), /* @__PURE__ */ import_react.default.createElement("h3", null, t("\u53D1\u884C\u7248\u672C")), /* @__PURE__ */ import_react.default.createElement("div", { className: "hub-releases" }, detail.versions.map((release) => {
|
|
488
|
+
const state = status(detail, release, t, data.minimumAgeHours);
|
|
489
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { key: release.version, className: "hub-release" }, /* @__PURE__ */ import_react.default.createElement("div", null, /* @__PURE__ */ import_react.default.createElement(import_dsh_client_ui_primitives.Button, { variant: releaseOf(detail)?.version === release.version ? "toolbar" : "outline", size: "sm", "aria-pressed": releaseOf(detail)?.version === release.version, onClick: () => setSelected((previous) => ({ ...previous, [detail.packageName]: release.version })) }, release.version), /* @__PURE__ */ import_react.default.createElement(Badge, { tone: state.tone }, state.label)), /* @__PURE__ */ import_react.default.createElement("small", null, t("\u53D1\u5E03\u65F6\u95F4 {date} \xB7 DSH {range}", { date: date(release.publishedAt), range: release.dshRange ?? t(release.compatibilityBasis === "dshPluginHub.hostCompatibility" ? "\u4E0D\u6309\u7248\u672C\u9650\u5236\uFF0C\u8FD0\u884C\u65F6\u68C0\u67E5\u63A5\u53E3" : release.compatibilityBasis === "peerDependencies" ? "\u5BBF\u4E3B\u4F9D\u8D56\u58F0\u660E" : release.compatibilityBasis?.includes("dshReleases") ? "\u4F5C\u8005\u9010\u7248\u672C\u58F0\u660E" : "\u672A\u58F0\u660E") })), release.reasons.length > 0 && /* @__PURE__ */ import_react.default.createElement("p", null, release.reasons.map(explain).join(" \xB7 ")), release.age === "waiting" && /* @__PURE__ */ import_react.default.createElement("small", null, Number.isInteger(data.minimumAgeHours) ? t("\u9884\u8BA1\u6EE1 {hours} \u5C0F\u65F6\uFF1A{date}", { hours: data.minimumAgeHours, date: date(release.eligibleAt) }) : t("\u9884\u8BA1\u6EE1 {minutes} \u5206\u949F\uFF1A{date}", { minutes: data.minimumAgeMinutes, date: date(release.eligibleAt) })));
|
|
490
|
+
}), detail.queryError && /* @__PURE__ */ import_react.default.createElement("p", null, explain(detail.queryError))))));
|
|
491
|
+
}
|
|
492
|
+
var name = NS;
|
|
493
|
+
var inject = ["slots", "locale"];
|
|
494
|
+
function apply(ctx) {
|
|
495
|
+
ctx.effect(() => ctx.locale.register(NS, words), "Plugin Hub: dictionaries");
|
|
496
|
+
const t = ctx.locale.bind(NS);
|
|
497
|
+
ctx.slots.inject("settings.section", () => ctx.slots.register({ name: "settings.section", id: MARKET_ID, order: 39, label: () => BRAND.navTitle, locale: NS }, () => /* @__PURE__ */ import_react.default.createElement(Market, { locale: ctx.locale, t })));
|
|
498
|
+
}
|
|
499
|
+
return module.exports; } });
|
|
500
|
+
//# sourceMappingURL=client.js.map
|