@bundy-lmw/hive-server 1.0.1

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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +211 -0
  3. package/dist/bootstrap.d.ts +36 -0
  4. package/dist/bootstrap.d.ts.map +1 -0
  5. package/dist/bootstrap.js +86 -0
  6. package/dist/bootstrap.js.map +1 -0
  7. package/dist/cli/index.d.ts +8 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +125 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/config.d.ts +93 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +156 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/gateway/auth.d.ts +16 -0
  16. package/dist/gateway/auth.d.ts.map +1 -0
  17. package/dist/gateway/auth.js +50 -0
  18. package/dist/gateway/auth.js.map +1 -0
  19. package/dist/gateway/http.d.ts +9 -0
  20. package/dist/gateway/http.d.ts.map +1 -0
  21. package/dist/gateway/http.js +178 -0
  22. package/dist/gateway/http.js.map +1 -0
  23. package/dist/gateway/websocket.d.ts +18 -0
  24. package/dist/gateway/websocket.d.ts.map +1 -0
  25. package/dist/gateway/websocket.js +197 -0
  26. package/dist/gateway/websocket.js.map +1 -0
  27. package/dist/gateway/ws/admin-handler.d.ts +68 -0
  28. package/dist/gateway/ws/admin-handler.d.ts.map +1 -0
  29. package/dist/gateway/ws/admin-handler.js +573 -0
  30. package/dist/gateway/ws/admin-handler.js.map +1 -0
  31. package/dist/gateway/ws/data-types.d.ts +130 -0
  32. package/dist/gateway/ws/data-types.d.ts.map +1 -0
  33. package/dist/gateway/ws/data-types.js +7 -0
  34. package/dist/gateway/ws/data-types.js.map +1 -0
  35. package/dist/gateway/ws/log-buffer.d.ts +29 -0
  36. package/dist/gateway/ws/log-buffer.d.ts.map +1 -0
  37. package/dist/gateway/ws/log-buffer.js +58 -0
  38. package/dist/gateway/ws/log-buffer.js.map +1 -0
  39. package/dist/gateway/ws/types.d.ts +67 -0
  40. package/dist/gateway/ws/types.d.ts.map +1 -0
  41. package/dist/gateway/ws/types.js +68 -0
  42. package/dist/gateway/ws/types.js.map +1 -0
  43. package/dist/heartbeat-scheduler.d.ts +43 -0
  44. package/dist/heartbeat-scheduler.d.ts.map +1 -0
  45. package/dist/heartbeat-scheduler.js +118 -0
  46. package/dist/heartbeat-scheduler.js.map +1 -0
  47. package/dist/main.d.ts +23 -0
  48. package/dist/main.d.ts.map +1 -0
  49. package/dist/main.js +120 -0
  50. package/dist/main.js.map +1 -0
  51. package/dist/plugin-manager/cli.d.ts +6 -0
  52. package/dist/plugin-manager/cli.d.ts.map +1 -0
  53. package/dist/plugin-manager/cli.js +115 -0
  54. package/dist/plugin-manager/cli.js.map +1 -0
  55. package/dist/plugin-manager/constants.d.ts +24 -0
  56. package/dist/plugin-manager/constants.d.ts.map +1 -0
  57. package/dist/plugin-manager/constants.js +58 -0
  58. package/dist/plugin-manager/constants.js.map +1 -0
  59. package/dist/plugin-manager/index.d.ts +11 -0
  60. package/dist/plugin-manager/index.d.ts.map +1 -0
  61. package/dist/plugin-manager/index.js +10 -0
  62. package/dist/plugin-manager/index.js.map +1 -0
  63. package/dist/plugin-manager/installer.d.ts +19 -0
  64. package/dist/plugin-manager/installer.d.ts.map +1 -0
  65. package/dist/plugin-manager/installer.js +256 -0
  66. package/dist/plugin-manager/installer.js.map +1 -0
  67. package/dist/plugin-manager/manager.d.ts +39 -0
  68. package/dist/plugin-manager/manager.d.ts.map +1 -0
  69. package/dist/plugin-manager/manager.js +171 -0
  70. package/dist/plugin-manager/manager.js.map +1 -0
  71. package/dist/plugin-manager/registry.d.ts +31 -0
  72. package/dist/plugin-manager/registry.d.ts.map +1 -0
  73. package/dist/plugin-manager/registry.js +63 -0
  74. package/dist/plugin-manager/registry.js.map +1 -0
  75. package/dist/plugin-manager/searcher.d.ts +18 -0
  76. package/dist/plugin-manager/searcher.d.ts.map +1 -0
  77. package/dist/plugin-manager/searcher.js +50 -0
  78. package/dist/plugin-manager/searcher.js.map +1 -0
  79. package/dist/plugin-manager/types.d.ts +71 -0
  80. package/dist/plugin-manager/types.d.ts.map +1 -0
  81. package/dist/plugin-manager/types.js +5 -0
  82. package/dist/plugin-manager/types.js.map +1 -0
  83. package/dist/plugins.d.ts +18 -0
  84. package/dist/plugins.d.ts.map +1 -0
  85. package/dist/plugins.js +198 -0
  86. package/dist/plugins.js.map +1 -0
  87. package/package.json +54 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Plugin Installer — 多来源安装
3
+ *
4
+ * 安全措施:
5
+ * - 使用 execFileSync 替代 execSync 防止命令注入
6
+ * - 路径穿越检查(isPathSafe)
7
+ * - Git URL 域名白名单(isGitUrlTrusted)
8
+ * - 安装失败自动回滚
9
+ */
10
+ import { execFileSync } from 'child_process';
11
+ import { existsSync, readFileSync, cpSync, rmSync, mkdirSync, readdirSync } from 'fs';
12
+ import { resolve } from 'path';
13
+ import { PLUGINS_DIR, CONFIG_PATH, isPathSafe, isGitUrlTrusted, atomicWriteJSON } from './constants.js';
14
+ import { addPlugin } from './registry.js';
15
+ /**
16
+ * 自动识别来源类型
17
+ */
18
+ export function resolveSource(input) {
19
+ // Git URL: https://*, git://*, git@*
20
+ if (/^https?:\/\//i.test(input) || /^git@/i.test(input) || /^git:\/\//i.test(input)) {
21
+ const name = input.split('/').pop()?.replace(/\.git$/, '') ?? 'unknown';
22
+ return { type: 'git', raw: input, resolved: input, targetName: name };
23
+ }
24
+ // Local path: ./*, ../*, /absolute
25
+ if (/^\.\//i.test(input) || /^\.\.\//i.test(input) || /^\//i.test(input)) {
26
+ const name = input.split('/').pop() ?? 'unknown';
27
+ return { type: 'local', raw: input, resolved: resolve(input), targetName: name };
28
+ }
29
+ // npm package: @bundy-lmw/hive-plugin-xxx or name
30
+ const name = input.replace(/^@bundy-lmw\/hive-plugin-/, '');
31
+ return { type: 'npm', raw: input, resolved: input, targetName: name };
32
+ }
33
+ /**
34
+ * 安装插件(统一入口)
35
+ */
36
+ export async function installPlugin(input) {
37
+ const source = resolveSource(input);
38
+ // 路径穿越检查
39
+ if (!isPathSafe(source.targetName)) {
40
+ return { success: false, name: source.targetName, error: `Invalid plugin name: ${source.targetName}` };
41
+ }
42
+ const targetDir = resolve(PLUGINS_DIR, source.targetName);
43
+ // 检查是否已安装
44
+ const { hasPlugin } = await import('./registry.js');
45
+ if (hasPlugin(source.targetName)) {
46
+ return {
47
+ success: false,
48
+ name: source.targetName,
49
+ error: 'Plugin already installed. Use `hive plugin update <name>` to upgrade.',
50
+ };
51
+ }
52
+ try {
53
+ switch (source.type) {
54
+ case 'npm':
55
+ return await installFromNpm(source, targetDir);
56
+ case 'git':
57
+ return await installFromGit(source, targetDir);
58
+ case 'local':
59
+ return await installFromLocal(source, targetDir);
60
+ }
61
+ }
62
+ catch (error) {
63
+ cleanupDir(targetDir);
64
+ return {
65
+ success: false,
66
+ name: source.targetName,
67
+ error: error instanceof Error ? error.message : String(error),
68
+ };
69
+ }
70
+ }
71
+ /**
72
+ * npm 包安装(使用 execFileSync 防止命令注入)
73
+ */
74
+ async function installFromNpm(source, targetDir) {
75
+ if (!existsSync(PLUGINS_DIR)) {
76
+ mkdirSync(PLUGINS_DIR, { recursive: true });
77
+ }
78
+ console.log(` Installing ${source.resolved}...`);
79
+ execFileSync('npm', ['install', '--prefix', targetDir, source.resolved], {
80
+ stdio: 'pipe',
81
+ timeout: 120_000,
82
+ });
83
+ const pluginInfo = validateInstalledPlugin(targetDir, source.resolved);
84
+ if (!pluginInfo) {
85
+ cleanupDir(targetDir);
86
+ return { success: false, name: source.targetName, error: 'Not a valid Hive plugin (missing hive.plugin in package.json)' };
87
+ }
88
+ addPlugin(source.targetName, {
89
+ source: `npm:${source.resolved}@${pluginInfo.version}`,
90
+ installedAt: new Date().toISOString(),
91
+ resolvedVersion: pluginInfo.version,
92
+ });
93
+ appendToConfig(source.resolved);
94
+ return { success: true, name: source.targetName, version: pluginInfo.version };
95
+ }
96
+ /**
97
+ * Git URL 安装
98
+ */
99
+ async function installFromGit(source, targetDir) {
100
+ if (!isGitUrlTrusted(source.resolved)) {
101
+ return {
102
+ success: false,
103
+ name: source.targetName,
104
+ error: `Untrusted git host. Only these are allowed: ${['github.com', 'gitlab.com', 'bitbucket.org', 'gitee.com', 'code.aliyun.com'].join(', ')}`,
105
+ };
106
+ }
107
+ console.log(` Cloning from ${source.resolved}`);
108
+ console.log(' Press Ctrl+C to cancel, or Enter to continue...');
109
+ await waitForEnter();
110
+ const tmpDir = resolve(PLUGINS_DIR, `.tmp-${source.targetName}-${Date.now()}`);
111
+ try {
112
+ execFileSync('git', ['clone', '--depth', '1', source.resolved, tmpDir], {
113
+ stdio: 'pipe',
114
+ timeout: 60_000,
115
+ });
116
+ const pluginInfo = validateInstalledPlugin(tmpDir);
117
+ if (!pluginInfo) {
118
+ return { success: false, name: source.targetName, error: 'Not a valid Hive plugin (missing hive.plugin in package.json)' };
119
+ }
120
+ if (existsSync(resolve(tmpDir, 'package.json'))) {
121
+ console.log(' Installing dependencies...');
122
+ execFileSync('npm', ['install', '--production'], { cwd: tmpDir, stdio: 'pipe', timeout: 120_000 });
123
+ }
124
+ if (!existsSync(PLUGINS_DIR)) {
125
+ mkdirSync(PLUGINS_DIR, { recursive: true });
126
+ }
127
+ cpSync(tmpDir, targetDir, { recursive: true });
128
+ addPlugin(source.targetName, {
129
+ source: `git:${source.resolved}`,
130
+ installedAt: new Date().toISOString(),
131
+ resolvedVersion: pluginInfo.version,
132
+ });
133
+ appendToConfig(source.targetName);
134
+ return { success: true, name: source.targetName, version: pluginInfo.version };
135
+ }
136
+ finally {
137
+ cleanupDir(tmpDir);
138
+ }
139
+ }
140
+ /**
141
+ * 本地路径安装
142
+ */
143
+ async function installFromLocal(source, targetDir) {
144
+ if (!existsSync(source.resolved)) {
145
+ return { success: false, name: source.targetName, error: 'Path not found' };
146
+ }
147
+ const pluginInfo = validateInstalledPlugin(source.resolved);
148
+ if (!pluginInfo) {
149
+ return { success: false, name: source.targetName, error: 'Not a valid Hive plugin (missing hive.plugin in package.json)' };
150
+ }
151
+ if (!existsSync(PLUGINS_DIR)) {
152
+ mkdirSync(PLUGINS_DIR, { recursive: true });
153
+ }
154
+ cpSync(source.resolved, targetDir, { recursive: true });
155
+ addPlugin(source.targetName, {
156
+ source: `local:${source.raw}`,
157
+ installedAt: new Date().toISOString(),
158
+ resolvedVersion: pluginInfo.version,
159
+ });
160
+ appendToConfig(source.targetName);
161
+ return { success: true, name: source.targetName, version: pluginInfo.version };
162
+ }
163
+ /**
164
+ * 验证已安装的插件是否合法
165
+ */
166
+ function validateInstalledPlugin(dir, npmPkg) {
167
+ // 1. 直接目录下的 package.json
168
+ const directPkgPath = resolve(dir, 'package.json');
169
+ if (existsSync(directPkgPath)) {
170
+ const pkg = tryParsePkgJson(directPkgPath);
171
+ if (pkg)
172
+ return pkg;
173
+ }
174
+ // 2. npm --prefix 安装:检查 node_modules/ 下的包
175
+ const nmDir = resolve(dir, 'node_modules');
176
+ if (!existsSync(nmDir))
177
+ return null;
178
+ return findPluginInNodeModules(nmDir);
179
+ }
180
+ /**
181
+ * 在 node_modules 中查找合法插件
182
+ */
183
+ function findPluginInNodeModules(nmDir) {
184
+ const entries = readdirSync(nmDir, { withFileTypes: true });
185
+ for (const entry of entries) {
186
+ if (!entry.isDirectory())
187
+ continue;
188
+ if (entry.name.startsWith('@')) {
189
+ const scopeDir = resolve(nmDir, entry.name);
190
+ if (!existsSync(scopeDir))
191
+ continue;
192
+ const scopeEntries = readdirSync(scopeDir, { withFileTypes: true });
193
+ for (const pkg of scopeEntries) {
194
+ if (!pkg.isDirectory())
195
+ continue;
196
+ const result = tryParsePkgJson(resolve(scopeDir, pkg.name, 'package.json'));
197
+ if (result)
198
+ return result;
199
+ }
200
+ }
201
+ else {
202
+ const result = tryParsePkgJson(resolve(nmDir, entry.name, 'package.json'));
203
+ if (result)
204
+ return result;
205
+ }
206
+ }
207
+ return null;
208
+ }
209
+ function tryParsePkgJson(pkgPath) {
210
+ try {
211
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
212
+ if (!pkg.hive?.plugin)
213
+ return null;
214
+ return { version: pkg.version || '0.0.0', description: pkg.description, homepage: pkg.homepage };
215
+ }
216
+ catch {
217
+ return null;
218
+ }
219
+ }
220
+ /**
221
+ * 将插件添加到 hive.config.json(原子写入)
222
+ */
223
+ function appendToConfig(pluginName) {
224
+ if (!existsSync(CONFIG_PATH))
225
+ return;
226
+ try {
227
+ const content = readFileSync(CONFIG_PATH, 'utf-8');
228
+ const config = JSON.parse(content);
229
+ if (!config.plugins) {
230
+ config.plugins = {};
231
+ }
232
+ if (!(pluginName in config.plugins)) {
233
+ atomicWriteJSON(CONFIG_PATH, config);
234
+ }
235
+ }
236
+ catch {
237
+ console.warn('[plugin-installer] Failed to update hive.config.json');
238
+ }
239
+ }
240
+ function cleanupDir(dir) {
241
+ if (existsSync(dir)) {
242
+ rmSync(dir, { recursive: true, force: true });
243
+ }
244
+ }
245
+ function waitForEnter() {
246
+ return new Promise((resolve) => {
247
+ const onData = () => {
248
+ process.stdin.removeListener('data', onData);
249
+ process.stdin.pause();
250
+ resolve();
251
+ };
252
+ process.stdin.resume();
253
+ process.stdin.once('data', onData);
254
+ });
255
+ }
256
+ //# sourceMappingURL=installer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installer.js","sourceRoot":"","sources":["../../src/plugin-manager/installer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Plugin Manager — list / remove / info / update
3
+ */
4
+ import type { PluginInfo } from './types.js';
5
+ /**
6
+ * 列出所有已安装插件
7
+ */
8
+ export declare function listPlugins(): string;
9
+ /**
10
+ * 卸载插件(含路径安全检查)
11
+ */
12
+ export declare function removePlugin(name: string): {
13
+ success: boolean;
14
+ error?: string;
15
+ };
16
+ export interface PluginInfoResult {
17
+ success: true;
18
+ info: PluginInfo;
19
+ }
20
+ export interface PluginInfoError {
21
+ success: false;
22
+ error: string;
23
+ }
24
+ /**
25
+ * 查看插件详情
26
+ */
27
+ export declare function showPluginInfo(name: string): PluginInfoResult | PluginInfoError;
28
+ /**
29
+ * 更新插件
30
+ */
31
+ export declare function updatePlugin(name?: string): Promise<{
32
+ updated: string[];
33
+ skipped: string[];
34
+ errors: Array<{
35
+ name: string;
36
+ error: string;
37
+ }>;
38
+ }>;
39
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugin-manager/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,YAAY,CAAA;AAE3D;;GAEG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAuBpC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAuB/E;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,IAAI,CAAA;IACb,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,eAAe,CA8C/E;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA+CnJ"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Plugin Manager — list / remove / info / update
3
+ */
4
+ import { existsSync, readFileSync, rmSync } from 'fs';
5
+ import { resolve } from 'path';
6
+ import { PLUGINS_DIR, CONFIG_PATH, isPathSafe, atomicWriteJSON, sep } from './constants.js';
7
+ import { loadRegistry, removePlugin as removeFromRegistry, getPlugin } from './registry.js';
8
+ /**
9
+ * 列出所有已安装插件
10
+ */
11
+ export function listPlugins() {
12
+ const registry = loadRegistry();
13
+ const entries = Object.entries(registry);
14
+ if (entries.length === 0) {
15
+ return 'No plugins installed.\n\nUse `hive plugin search <keyword>` to discover plugins.';
16
+ }
17
+ const lines = [''];
18
+ for (const [name, entry] of entries) {
19
+ const pluginDir = resolve(PLUGINS_DIR, name);
20
+ const status = existsSync(pluginDir) ? '' : ' (missing)';
21
+ const sourceType = entry.source.split(':')[0];
22
+ const date = new Date(entry.installedAt).toLocaleDateString();
23
+ lines.push(` ${name.padEnd(20)} v${entry.resolvedVersion.padEnd(10)} ${sourceType.padEnd(6)} ${date}${status}`);
24
+ }
25
+ lines.push('');
26
+ lines.push(` ${entries.length} plugin(s) installed.`);
27
+ lines.push('');
28
+ return lines.join('\n');
29
+ }
30
+ /**
31
+ * 卸载插件(含路径安全检查)
32
+ */
33
+ export function removePlugin(name) {
34
+ if (!getPlugin(name)) {
35
+ return { success: false, error: 'Plugin not installed' };
36
+ }
37
+ if (!isPathSafe(name)) {
38
+ return { success: false, error: `Invalid plugin name: ${name}` };
39
+ }
40
+ const pluginDir = resolve(PLUGINS_DIR, name);
41
+ if (!pluginDir.startsWith(PLUGINS_DIR + sep)) {
42
+ return { success: false, error: 'Path safety check failed' };
43
+ }
44
+ removeFromRegistry(name);
45
+ if (existsSync(pluginDir)) {
46
+ rmSync(pluginDir, { recursive: true, force: true });
47
+ }
48
+ removeFromConfig(name);
49
+ return { success: true };
50
+ }
51
+ /**
52
+ * 查看插件详情
53
+ */
54
+ export function showPluginInfo(name) {
55
+ if (!isPathSafe(name)) {
56
+ return { success: false, error: `Invalid plugin name: ${name}` };
57
+ }
58
+ const entry = getPlugin(name);
59
+ if (!entry) {
60
+ return { success: false, error: 'Plugin not installed' };
61
+ }
62
+ const lines = [''];
63
+ lines.push(` Name: ${name}`);
64
+ lines.push(` Version: ${entry.resolvedVersion}`);
65
+ lines.push(` Source: ${entry.source}`);
66
+ lines.push(` Installed: ${new Date(entry.installedAt).toLocaleString()}`);
67
+ const pkgPath = resolve(PLUGINS_DIR, name, 'package.json');
68
+ if (existsSync(pkgPath)) {
69
+ try {
70
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
71
+ if (pkg.description)
72
+ lines.push(` Desc: ${pkg.description}`);
73
+ if (pkg.homepage)
74
+ lines.push(` Homepage: ${pkg.homepage}`);
75
+ }
76
+ catch {
77
+ console.warn(`[plugin-manager] Failed to read ${name}/package.json`);
78
+ }
79
+ }
80
+ const config = readPluginConfig();
81
+ const pluginConfig = config[name];
82
+ if (pluginConfig && Object.keys(pluginConfig).length > 0) {
83
+ lines.push(` Config: ${JSON.stringify(pluginConfig)}`);
84
+ }
85
+ lines.push('');
86
+ const info = {
87
+ name,
88
+ version: entry.resolvedVersion,
89
+ source: entry.source,
90
+ installedAt: entry.installedAt,
91
+ description: undefined,
92
+ homepage: undefined,
93
+ config: pluginConfig,
94
+ };
95
+ return { success: true, info };
96
+ }
97
+ /**
98
+ * 更新插件
99
+ */
100
+ export async function updatePlugin(name) {
101
+ const registry = loadRegistry();
102
+ const names = name ? [name] : Object.keys(registry);
103
+ const updated = [];
104
+ const skipped = [];
105
+ const errors = [];
106
+ for (const pluginName of names) {
107
+ const entry = registry[pluginName];
108
+ if (!entry)
109
+ continue;
110
+ if (!entry.source.startsWith('npm:')) {
111
+ skipped.push(pluginName);
112
+ continue;
113
+ }
114
+ const npmPackage = entry.source.replace(/^npm:/, '').replace(/@\d+\.\d+\.\d+.*$/, '');
115
+ try {
116
+ const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(npmPackage)}/latest`);
117
+ if (!res.ok) {
118
+ errors.push({ name: pluginName, error: `npm Registry returned ${res.status}` });
119
+ continue;
120
+ }
121
+ const latest = (await res.json());
122
+ if (latest.version === entry.resolvedVersion) {
123
+ skipped.push(pluginName);
124
+ continue;
125
+ }
126
+ console.log(` Updating ${pluginName}: ${entry.resolvedVersion} → ${latest.version}`);
127
+ const { installPlugin } = await import('./installer.js');
128
+ const result = await installPlugin(`${npmPackage}@${latest.version}`);
129
+ if (result.success) {
130
+ updated.push(pluginName);
131
+ }
132
+ else {
133
+ errors.push({ name: pluginName, error: result.error || 'Install failed' });
134
+ }
135
+ }
136
+ catch (error) {
137
+ errors.push({ name: pluginName, error: error instanceof Error ? error.message : String(error) });
138
+ }
139
+ }
140
+ return { updated, skipped, errors };
141
+ }
142
+ /**
143
+ * 从 hive.config.json 移除插件配置(原子写入)
144
+ */
145
+ function removeFromConfig(pluginName) {
146
+ if (!existsSync(CONFIG_PATH))
147
+ return;
148
+ try {
149
+ const content = readFileSync(CONFIG_PATH, 'utf-8');
150
+ const config = JSON.parse(content);
151
+ if (config.plugins && pluginName in config.plugins) {
152
+ atomicWriteJSON(CONFIG_PATH, config);
153
+ }
154
+ }
155
+ catch {
156
+ console.warn('[plugin-manager] Failed to update hive.config.json');
157
+ }
158
+ }
159
+ function readPluginConfig() {
160
+ if (!existsSync(CONFIG_PATH))
161
+ return {};
162
+ try {
163
+ const config = JSON.parse(readFileSync(CONFIG_PATH, 'utf-8'));
164
+ return config.plugins || {};
165
+ }
166
+ catch {
167
+ console.warn('[plugin-manager] Failed to read hive.config.json');
168
+ return {};
169
+ }
170
+ }
171
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/plugin-manager/manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Plugin Registry — .registry.json 读写
3
+ *
4
+ * 使用原子写入防止竞态条件。
5
+ */
6
+ import type { PluginRegistry, RegistryEntry } from './types.js';
7
+ /**
8
+ * 加载注册表
9
+ */
10
+ export declare function loadRegistry(): PluginRegistry;
11
+ /**
12
+ * 保存注册表(原子写入)
13
+ */
14
+ export declare function saveRegistry(registry: PluginRegistry): void;
15
+ /**
16
+ * 添加插件到注册表
17
+ */
18
+ export declare function addPlugin(name: string, entry: RegistryEntry): void;
19
+ /**
20
+ * 从注册表移除插件
21
+ */
22
+ export declare function removePlugin(name: string): boolean;
23
+ /**
24
+ * 获取单个插件记录
25
+ */
26
+ export declare function getPlugin(name: string): RegistryEntry | undefined;
27
+ /**
28
+ * 检查插件是否已安装
29
+ */
30
+ export declare function hasPlugin(name: string): boolean;
31
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugin-manager/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/D;;GAEG;AACH,wBAAgB,YAAY,IAAI,cAAc,CAY7C;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAE3D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAIlE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CASlD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEjE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/C"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Plugin Registry — .registry.json 读写
3
+ *
4
+ * 使用原子写入防止竞态条件。
5
+ */
6
+ import { existsSync, readFileSync } from 'fs';
7
+ import { REGISTRY_PATH, atomicWriteJSON } from './constants.js';
8
+ /**
9
+ * 加载注册表
10
+ */
11
+ export function loadRegistry() {
12
+ if (!existsSync(REGISTRY_PATH)) {
13
+ return {};
14
+ }
15
+ try {
16
+ const content = readFileSync(REGISTRY_PATH, 'utf-8');
17
+ return JSON.parse(content);
18
+ }
19
+ catch {
20
+ console.warn(`[plugin-registry] ${REGISTRY_PATH} is corrupted, treating as empty`);
21
+ return {};
22
+ }
23
+ }
24
+ /**
25
+ * 保存注册表(原子写入)
26
+ */
27
+ export function saveRegistry(registry) {
28
+ atomicWriteJSON(REGISTRY_PATH, registry);
29
+ }
30
+ /**
31
+ * 添加插件到注册表
32
+ */
33
+ export function addPlugin(name, entry) {
34
+ const registry = loadRegistry();
35
+ registry[name] = entry;
36
+ saveRegistry(registry);
37
+ }
38
+ /**
39
+ * 从注册表移除插件
40
+ */
41
+ export function removePlugin(name) {
42
+ const registry = loadRegistry();
43
+ if (!(name in registry)) {
44
+ return false;
45
+ }
46
+ const updated = { ...registry };
47
+ delete updated[name];
48
+ saveRegistry(updated);
49
+ return true;
50
+ }
51
+ /**
52
+ * 获取单个插件记录
53
+ */
54
+ export function getPlugin(name) {
55
+ return loadRegistry()[name];
56
+ }
57
+ /**
58
+ * 检查插件是否已安装
59
+ */
60
+ export function hasPlugin(name) {
61
+ return name in loadRegistry();
62
+ }
63
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/plugin-manager/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAG/D;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,qBAAqB,aAAa,kCAAkC,CAAC,CAAA;QAClF,OAAO,EAAE,CAAA;IACX,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAwB;IACnD,eAAe,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAoB;IAC1D,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAA;IAC/B,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;IACtB,YAAY,CAAC,QAAQ,CAAC,CAAA;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAA;IAC/B,IAAI,CAAC,CAAC,IAAI,IAAI,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,OAAO,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAA;IAC/B,OAAO,OAAO,CAAC,IAAI,CAAC,CAAA;IACpB,YAAY,CAAC,OAAO,CAAC,CAAA;IACrB,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,YAAY,EAAE,CAAC,IAAI,CAAC,CAAA;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,IAAI,YAAY,EAAE,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Plugin Searcher — npm Registry Search API
3
+ */
4
+ import type { NpmSearchPackage } from './types.js';
5
+ interface SearchResult {
6
+ packages: NpmSearchPackage[];
7
+ total: number;
8
+ }
9
+ /**
10
+ * 搜索 npm 上的 hive plugin 插件
11
+ */
12
+ export declare function searchPlugins(keyword?: string, size?: number): Promise<SearchResult>;
13
+ /**
14
+ * 格式化搜索结果为终端表格
15
+ */
16
+ export declare function formatSearchResults(packages: NpmSearchPackage[], total: number): string;
17
+ export {};
18
+ //# sourceMappingURL=searcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"searcher.d.ts","sourceRoot":"","sources":["../../src/plugin-manager/searcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAqB,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIrE,UAAU,YAAY;IACpB,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,OAAO,CAAC,YAAY,CAAC,CAqBtF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBvF"}