bun_plugins 1.2.5 → 1.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -127
- package/dist/{src/PluginManager.d.ts → PluginManager.d.ts} +9 -20
- package/dist/PluginManager.d.ts.map +1 -0
- package/dist/{src/PluginManager.js → PluginManager.js} +189 -212
- package/dist/PluginManager.js.map +1 -0
- package/dist/{src/index.d.ts → index.d.ts} +1 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/{src/index.js → index.js} +0 -2
- package/dist/index.js.map +1 -0
- package/dist/{src/managers → managers}/ContextFactory.d.ts +1 -1
- package/dist/managers/ContextFactory.d.ts.map +1 -0
- package/dist/{src/managers → managers}/ContextFactory.js +26 -51
- package/dist/managers/ContextFactory.js.map +1 -0
- package/dist/managers/DependencyManager.d.ts.map +1 -0
- package/dist/{src/managers → managers}/DependencyManager.js +5 -7
- package/dist/managers/DependencyManager.js.map +1 -0
- package/dist/{src/managers → managers}/HooksManager.d.ts +1 -4
- package/dist/managers/HooksManager.d.ts.map +1 -0
- package/dist/{src/managers → managers}/HooksManager.js +8 -36
- package/dist/managers/HooksManager.js.map +1 -0
- package/dist/managers/ResourceManager.d.ts.map +1 -0
- package/dist/{src/managers → managers}/ResourceManager.js +3 -3
- package/dist/managers/ResourceManager.js.map +1 -0
- package/dist/{src/storage → storage}/JsonPluginStorage.d.ts +1 -2
- package/dist/storage/JsonPluginStorage.d.ts.map +1 -0
- package/dist/storage/JsonPluginStorage.js +63 -0
- package/dist/storage/JsonPluginStorage.js.map +1 -0
- package/dist/{src/types.d.ts → types.d.ts} +19 -60
- package/dist/types.d.ts.map +1 -0
- package/dist/{src/types.js → types.js} +0 -6
- package/dist/types.js.map +1 -0
- package/dist/utils/errorParser.d.ts.map +1 -0
- package/dist/{src/utils → utils}/errorParser.js +5 -2
- package/dist/utils/errorParser.js.map +1 -0
- package/dist/utils/pluginValidator.d.ts +93 -0
- package/dist/utils/pluginValidator.d.ts.map +1 -0
- package/dist/{src/utils → utils}/pluginValidator.js +14 -11
- package/dist/utils/pluginValidator.js.map +1 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/worker/WorkerRunner.d.ts.map +1 -0
- package/dist/{src/worker → worker}/WorkerRunner.js +13 -38
- package/dist/worker/WorkerRunner.js.map +1 -0
- package/package.json +6 -9
- package/LICENSE +0 -9
- package/dist/examples/action-registry-declarative.d.ts +0 -14
- package/dist/examples/action-registry-declarative.d.ts.map +0 -1
- package/dist/examples/action-registry-declarative.js +0 -130
- package/dist/examples/action-registry-declarative.js.map +0 -1
- package/dist/examples/action-registry-example.d.ts +0 -31
- package/dist/examples/action-registry-example.d.ts.map +0 -1
- package/dist/examples/action-registry-example.js +0 -84
- package/dist/examples/action-registry-example.js.map +0 -1
- package/dist/examples/index-declarative.d.ts +0 -32
- package/dist/examples/index-declarative.d.ts.map +0 -1
- package/dist/examples/index-declarative.js +0 -206
- package/dist/examples/index-declarative.js.map +0 -1
- package/dist/examples/logger-declarative.d.ts +0 -109
- package/dist/examples/logger-declarative.d.ts.map +0 -1
- package/dist/examples/logger-declarative.js +0 -330
- package/dist/examples/logger-declarative.js.map +0 -1
- package/dist/examples/logger-simple.d.ts +0 -8
- package/dist/examples/logger-simple.d.ts.map +0 -1
- package/dist/examples/logger-simple.js +0 -165
- package/dist/examples/logger-simple.js.map +0 -1
- package/dist/examples/server-declarative.d.ts +0 -46
- package/dist/examples/server-declarative.d.ts.map +0 -1
- package/dist/examples/server-declarative.js +0 -205
- package/dist/examples/server-declarative.js.map +0 -1
- package/dist/examples/shared/action-registry.d.ts +0 -45
- package/dist/examples/shared/action-registry.d.ts.map +0 -1
- package/dist/examples/shared/action-registry.js +0 -65
- package/dist/examples/shared/action-registry.js.map +0 -1
- package/dist/examples/shared/plugin-builder.d.ts +0 -41
- package/dist/examples/shared/plugin-builder.d.ts.map +0 -1
- package/dist/examples/shared/plugin-builder.js +0 -85
- package/dist/examples/shared/plugin-builder.js.map +0 -1
- package/dist/examples/storage-declarative.d.ts +0 -13
- package/dist/examples/storage-declarative.d.ts.map +0 -1
- package/dist/examples/storage-declarative.js +0 -203
- package/dist/examples/storage-declarative.js.map +0 -1
- package/dist/plugins/ActionRegistryPlugin.d.ts +0 -14
- package/dist/plugins/ActionRegistryPlugin.d.ts.map +0 -1
- package/dist/plugins/ActionRegistryPlugin.js +0 -52
- package/dist/plugins/ActionRegistryPlugin.js.map +0 -1
- package/dist/plugins/DynamicJSActionsPlugin.d.ts +0 -21
- package/dist/plugins/DynamicJSActionsPlugin.d.ts.map +0 -1
- package/dist/plugins/DynamicJSActionsPlugin.js +0 -57
- package/dist/plugins/DynamicJSActionsPlugin.js.map +0 -1
- package/dist/plugins/DynamicMathActionsPlugin.d.ts +0 -22
- package/dist/plugins/DynamicMathActionsPlugin.d.ts.map +0 -1
- package/dist/plugins/DynamicMathActionsPlugin.js +0 -64
- package/dist/plugins/DynamicMathActionsPlugin.js.map +0 -1
- package/dist/plugins/DynamicTextActionsPlugin.d.ts +0 -22
- package/dist/plugins/DynamicTextActionsPlugin.d.ts.map +0 -1
- package/dist/plugins/DynamicTextActionsPlugin.js +0 -58
- package/dist/plugins/DynamicTextActionsPlugin.js.map +0 -1
- package/dist/plugins/DynamicUtilityActionsPlugin.d.ts +0 -22
- package/dist/plugins/DynamicUtilityActionsPlugin.d.ts.map +0 -1
- package/dist/plugins/DynamicUtilityActionsPlugin.js +0 -75
- package/dist/plugins/DynamicUtilityActionsPlugin.js.map +0 -1
- package/dist/plugins/ExamplePlugin.d.ts +0 -3
- package/dist/plugins/ExamplePlugin.d.ts.map +0 -1
- package/dist/plugins/ExamplePlugin.js +0 -24
- package/dist/plugins/ExamplePlugin.js.map +0 -1
- package/dist/plugins/LifecycleDemoPlugin.d.ts +0 -20
- package/dist/plugins/LifecycleDemoPlugin.d.ts.map +0 -1
- package/dist/plugins/LifecycleDemoPlugin.js +0 -34
- package/dist/plugins/LifecycleDemoPlugin.js.map +0 -1
- package/dist/plugins/MathPlugin.d.ts +0 -16
- package/dist/plugins/MathPlugin.d.ts.map +0 -1
- package/dist/plugins/MathPlugin.js +0 -30
- package/dist/plugins/MathPlugin.js.map +0 -1
- package/dist/plugins/MyJSPlugin.d.ts +0 -7
- package/dist/plugins/MyJSPlugin.d.ts.map +0 -1
- package/dist/plugins/MyJSPlugin.js +0 -12
- package/dist/plugins/MyJSPlugin.js.map +0 -1
- package/dist/plugins/TypedExamplePlugin.d.ts +0 -10
- package/dist/plugins/TypedExamplePlugin.d.ts.map +0 -1
- package/dist/plugins/TypedExamplePlugin.js +0 -61
- package/dist/plugins/TypedExamplePlugin.js.map +0 -1
- package/dist/plugins/arktype/index.d.ts +0 -8
- package/dist/plugins/arktype/index.d.ts.map +0 -1
- package/dist/plugins/arktype/index.js +0 -25
- package/dist/plugins/arktype/index.js.map +0 -1
- package/dist/src/Plugin.d.ts +0 -28
- package/dist/src/Plugin.d.ts.map +0 -1
- package/dist/src/Plugin.js +0 -36
- package/dist/src/Plugin.js.map +0 -1
- package/dist/src/PluginManager.d.ts.map +0 -1
- package/dist/src/PluginManager.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/logger/LoggerAdapter.d.ts +0 -77
- package/dist/src/logger/LoggerAdapter.d.ts.map +0 -1
- package/dist/src/logger/LoggerAdapter.js +0 -242
- package/dist/src/logger/LoggerAdapter.js.map +0 -1
- package/dist/src/logger/LoggerFactory.d.ts +0 -73
- package/dist/src/logger/LoggerFactory.d.ts.map +0 -1
- package/dist/src/logger/LoggerFactory.js +0 -99
- package/dist/src/logger/LoggerFactory.js.map +0 -1
- package/dist/src/logger/index.d.ts +0 -3
- package/dist/src/logger/index.d.ts.map +0 -1
- package/dist/src/logger/index.js +0 -3
- package/dist/src/logger/index.js.map +0 -1
- package/dist/src/managers/ContextFactory.d.ts.map +0 -1
- package/dist/src/managers/ContextFactory.js.map +0 -1
- package/dist/src/managers/DependencyManager.d.ts.map +0 -1
- package/dist/src/managers/DependencyManager.js.map +0 -1
- package/dist/src/managers/HooksManager.d.ts.map +0 -1
- package/dist/src/managers/HooksManager.js.map +0 -1
- package/dist/src/managers/ResourceManager.d.ts.map +0 -1
- package/dist/src/managers/ResourceManager.js.map +0 -1
- package/dist/src/storage/JsonPluginStorage.d.ts.map +0 -1
- package/dist/src/storage/JsonPluginStorage.js +0 -75
- package/dist/src/storage/JsonPluginStorage.js.map +0 -1
- package/dist/src/types/plugin-registry-base.d.ts +0 -80
- package/dist/src/types/plugin-registry-base.d.ts.map +0 -1
- package/dist/src/types/plugin-registry-base.js +0 -6
- package/dist/src/types/plugin-registry-base.js.map +0 -1
- package/dist/src/types.d.ts.map +0 -1
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils/errorParser.d.ts.map +0 -1
- package/dist/src/utils/errorParser.js.map +0 -1
- package/dist/src/utils/pluginValidator.d.ts +0 -17
- package/dist/src/utils/pluginValidator.d.ts.map +0 -1
- package/dist/src/utils/pluginValidator.js.map +0 -1
- package/dist/src/utils/security.d.ts.map +0 -1
- package/dist/src/utils/security.js.map +0 -1
- package/dist/src/worker/WorkerRunner.d.ts.map +0 -1
- package/dist/src/worker/WorkerRunner.js.map +0 -1
- /package/dist/{src/managers → managers}/DependencyManager.d.ts +0 -0
- /package/dist/{src/managers → managers}/ResourceManager.d.ts +0 -0
- /package/dist/{src/utils → utils}/errorParser.d.ts +0 -0
- /package/dist/{src/utils → utils}/security.d.ts +0 -0
- /package/dist/{src/utils → utils}/security.js +0 -0
- /package/dist/{src/worker → worker}/WorkerRunner.d.ts +0 -0
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import { readdir, mkdir } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
3
|
+
import { join, dirname } from "node:path";
|
|
4
4
|
import { watch, existsSync } from "node:fs";
|
|
5
5
|
import { WorkerMessageType, PluginPermission, RPCMethod, HookType } from "./types";
|
|
6
6
|
import { validatePlugin } from "./utils/pluginValidator";
|
|
7
7
|
import { JsonPluginStorage } from "./storage/JsonPluginStorage";
|
|
8
|
-
import
|
|
8
|
+
import semver from "semver";
|
|
9
9
|
import { ResourceManager } from "./managers/ResourceManager";
|
|
10
10
|
import { DependencyManager } from "./managers/DependencyManager";
|
|
11
11
|
import { HooksManager } from "./managers/HooksManager";
|
|
12
12
|
import { createPluginContext } from "./managers/ContextFactory";
|
|
13
13
|
import { errorParser } from "./utils/errorParser";
|
|
14
14
|
import { checkNetworkPermission, checkPermission as checkGeneralPermission } from "./utils/security";
|
|
15
|
-
import { logger } from "./logger";
|
|
16
15
|
export class PluginManager extends EventEmitter {
|
|
17
16
|
plugins = new Map();
|
|
18
17
|
availablePlugins = new Map();
|
|
19
|
-
|
|
20
|
-
pluginApis = new Map();
|
|
18
|
+
pluginFiles = new Map(); // filePath -> pluginName
|
|
21
19
|
// Modules
|
|
22
20
|
resources;
|
|
23
21
|
dependencyManager;
|
|
@@ -27,6 +25,8 @@ export class PluginManager extends EventEmitter {
|
|
|
27
25
|
pluginLoadTimeout;
|
|
28
26
|
workerFactory;
|
|
29
27
|
workerRunnerPath;
|
|
28
|
+
hotReloadWatcher = null;
|
|
29
|
+
hotReloadTimer = null;
|
|
30
30
|
constructor(storageRoot = join(process.cwd(), "storage"), options) {
|
|
31
31
|
super();
|
|
32
32
|
this.storageRoot = storageRoot;
|
|
@@ -62,7 +62,7 @@ export class PluginManager extends EventEmitter {
|
|
|
62
62
|
throw new Error(`Plugin ${plugin.name} requires host version ${plugin.engines.host}, but found ${this.hostVersion}`);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
console.log(`Loading plugin: ${plugin.name} v${plugin.version}`);
|
|
66
66
|
// 1. Prepare Storage
|
|
67
67
|
const storage = new JsonPluginStorage(this.storageRoot, plugin.name);
|
|
68
68
|
// 2. Load & Validate Configuration
|
|
@@ -73,7 +73,8 @@ export class PluginManager extends EventEmitter {
|
|
|
73
73
|
}
|
|
74
74
|
catch (e) {
|
|
75
75
|
const error = errorParser(e, `Error in plugin ${plugin.name}`);
|
|
76
|
-
|
|
76
|
+
console.warn(`[SafeMode] Using default config, validation failed. Error: ${error.message}`);
|
|
77
|
+
config = {}; // Reset to empty config on validation failure to prevent downstream errors
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
// 3. Initialize Resources
|
|
@@ -83,57 +84,37 @@ export class PluginManager extends EventEmitter {
|
|
|
83
84
|
throw new Error(`Invalid plugin name: ${plugin.name}. Name cannot contain path traversal characters.`);
|
|
84
85
|
}
|
|
85
86
|
// 4. Context Creation
|
|
86
|
-
this
|
|
87
|
-
const context = createPluginContext(this, plugin, this.resources, storage);
|
|
87
|
+
const context = createPluginContext(this, plugin, this.resources, storage, config);
|
|
88
88
|
// 5. Setup Hooks with Performance Monitoring (Delegated to HooksManager via Builder)
|
|
89
89
|
if (plugin.setup) {
|
|
90
90
|
try {
|
|
91
|
-
await plugin.setup(this.hooksManager.getBuilder(plugin.name
|
|
91
|
+
await plugin.setup(this.hooksManager.getBuilder(plugin.name));
|
|
92
92
|
}
|
|
93
93
|
catch (e) {
|
|
94
|
-
|
|
94
|
+
console.error(`Error during setup for ${plugin.name}:`, e);
|
|
95
95
|
throw errorParser(e, `Error during setup for ${plugin.name}`);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
// 6. Lifecycle onLoad
|
|
99
99
|
try {
|
|
100
|
-
|
|
101
|
-
let timeoutError = null;
|
|
102
|
-
const timeoutId = setTimeout(() => {
|
|
103
|
-
if (!completed) {
|
|
104
|
-
completed = true;
|
|
105
|
-
timeoutError = new Error(`Plugin ${plugin.name} timed out (${this.pluginLoadTimeout}ms)`);
|
|
106
|
-
}
|
|
107
|
-
}, this.pluginLoadTimeout);
|
|
100
|
+
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Plugin ${plugin.name} timed out (${this.pluginLoadTimeout}ms)`)), this.pluginLoadTimeout));
|
|
108
101
|
const start = performance.now();
|
|
109
|
-
|
|
110
|
-
await plugin.onLoad(context);
|
|
111
|
-
}
|
|
112
|
-
finally {
|
|
113
|
-
completed = true;
|
|
114
|
-
clearTimeout(timeoutId);
|
|
115
|
-
}
|
|
116
|
-
// Check if timeout triggered
|
|
117
|
-
if (timeoutError) {
|
|
118
|
-
throw timeoutError;
|
|
119
|
-
}
|
|
102
|
+
await Promise.race([plugin.onLoad(context), timeoutPromise]);
|
|
120
103
|
const duration = performance.now() - start;
|
|
121
104
|
this.plugins.set(plugin.name, plugin);
|
|
122
|
-
|
|
105
|
+
console.log(`Plugin ${plugin.name} loaded successfully in ${duration.toFixed(2)}ms.`);
|
|
123
106
|
// Trigger onStarted after registration if provided
|
|
124
107
|
if (plugin.onStarted) {
|
|
125
108
|
try {
|
|
126
109
|
await plugin.onStarted();
|
|
127
110
|
}
|
|
128
111
|
catch (e) {
|
|
129
|
-
|
|
112
|
+
console.error(`Error in onStarted for ${plugin.name}:`, e);
|
|
130
113
|
}
|
|
131
114
|
}
|
|
132
|
-
// 7. Trigger onStart hooks registered via setup()
|
|
133
|
-
await this.hooksManager.runOnStart();
|
|
134
115
|
}
|
|
135
116
|
catch (error) {
|
|
136
|
-
|
|
117
|
+
console.error(`Failed to load plugin ${plugin.name}:`, error);
|
|
137
118
|
// Cleanup resources directly since plugin is not in this.plugins yet
|
|
138
119
|
this.resources.cleanup(plugin.name, this);
|
|
139
120
|
this.hooksManager.cleanup(plugin.name);
|
|
@@ -143,7 +124,7 @@ export class PluginManager extends EventEmitter {
|
|
|
143
124
|
async registerIsolated(pluginPath, pluginName) {
|
|
144
125
|
return new Promise((resolve, reject) => {
|
|
145
126
|
const workerScript = this.workerRunnerPath;
|
|
146
|
-
|
|
127
|
+
console.log("Worker Path:", workerScript);
|
|
147
128
|
const timeoutId = setTimeout(() => {
|
|
148
129
|
worker.terminate();
|
|
149
130
|
reject(new Error(`Isolated plugin ${pluginName} timed out during loading (${this.pluginLoadTimeout}ms)`));
|
|
@@ -224,28 +205,16 @@ export class PluginManager extends EventEmitter {
|
|
|
224
205
|
else if (type === HookType.ON_LOAD) {
|
|
225
206
|
this.hooksManager.registerOnLoad(filterRegExp, proxyCallback, pluginName, options?.order);
|
|
226
207
|
}
|
|
227
|
-
else if (type === HookType.ON_START) {
|
|
228
|
-
this.hooksManager.registerOnStart(() => proxyCallback({}), pluginName);
|
|
229
|
-
}
|
|
230
208
|
result = true;
|
|
231
209
|
}
|
|
232
210
|
else if (method === RPCMethod.ManagerGetPlugin) {
|
|
233
211
|
const targetName = args[0];
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (api) {
|
|
237
|
-
result = api;
|
|
238
|
-
}
|
|
239
|
-
else {
|
|
240
|
-
// Fallback to the plugin itself
|
|
241
|
-
const p = this.getPlugin(targetName);
|
|
242
|
-
result = api !== undefined ? api : p || undefined;
|
|
243
|
-
}
|
|
212
|
+
const p = this.getPlugin(targetName);
|
|
213
|
+
result = p?.getSharedApi ? p.getSharedApi() : undefined;
|
|
244
214
|
}
|
|
245
215
|
else if (method === RPCMethod.Log) {
|
|
246
216
|
const level = args[0];
|
|
247
|
-
|
|
248
|
-
logger.getLogger(pluginName)[level](msg, ...restArgs);
|
|
217
|
+
console[level](`[${pluginName}]`, ...args.slice(1));
|
|
249
218
|
result = true;
|
|
250
219
|
}
|
|
251
220
|
else if (method === RPCMethod.PermissionCheck) {
|
|
@@ -261,27 +230,13 @@ export class PluginManager extends EventEmitter {
|
|
|
261
230
|
const urlStr = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
|
|
262
231
|
checkPermission(PluginPermission.Network, urlStr);
|
|
263
232
|
const response = await fetch(input, init);
|
|
264
|
-
const responseHeaders = {};
|
|
265
|
-
response.headers.forEach((v, k) => { responseHeaders[k] = v; });
|
|
266
233
|
result = {
|
|
267
234
|
status: response.status,
|
|
268
235
|
statusText: response.statusText,
|
|
269
|
-
headers:
|
|
236
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
270
237
|
body: await response.text()
|
|
271
238
|
};
|
|
272
239
|
}
|
|
273
|
-
else if (method === RPCMethod.ConfigGet) {
|
|
274
|
-
result = this.getPluginConfig(pluginName);
|
|
275
|
-
}
|
|
276
|
-
else if (method === RPCMethod.StorageReload) {
|
|
277
|
-
await storage.reload();
|
|
278
|
-
result = true;
|
|
279
|
-
}
|
|
280
|
-
else if (method === RPCMethod.ManagerRegisterApi) {
|
|
281
|
-
const [api] = args;
|
|
282
|
-
this.registerApi(pluginName, api);
|
|
283
|
-
result = true;
|
|
284
|
-
}
|
|
285
240
|
worker.postMessage({ id, result });
|
|
286
241
|
}
|
|
287
242
|
catch (e) {
|
|
@@ -308,7 +263,7 @@ export class PluginManager extends EventEmitter {
|
|
|
308
263
|
else if (msg.type === WorkerMessageType.MANIFEST) {
|
|
309
264
|
const { metadata } = msg;
|
|
310
265
|
pluginMetadata = metadata;
|
|
311
|
-
|
|
266
|
+
console.log(`Metadata received for isolated plugin: ${metadata.name}`);
|
|
312
267
|
}
|
|
313
268
|
else if (msg.type === WorkerMessageType.LOAD_SUCCESS) {
|
|
314
269
|
clearTimeout(timeoutId); // Success, clear global timeout
|
|
@@ -331,24 +286,20 @@ export class PluginManager extends EventEmitter {
|
|
|
331
286
|
await new Promise(r => setTimeout(r, 200));
|
|
332
287
|
worker.terminate();
|
|
333
288
|
// Clear pending hooks on unload
|
|
334
|
-
for (const pending of
|
|
289
|
+
for (const pending of pendingHooks.values()) {
|
|
335
290
|
pending.reject(new Error("Plugin unloaded"));
|
|
336
291
|
}
|
|
337
292
|
pendingHooks.clear();
|
|
338
293
|
},
|
|
339
294
|
};
|
|
340
295
|
this.plugins.set(metadata.name, proxyPlugin);
|
|
341
|
-
|
|
342
|
-
if (metadata.api) {
|
|
343
|
-
this.registerApi(metadata.name, metadata.api);
|
|
344
|
-
}
|
|
345
|
-
logger.getLogger("PluginManager").info(`Isolated Plugin ${metadata.name} loaded in worker.`);
|
|
296
|
+
console.log(`Isolated Plugin ${metadata.name} loaded in worker.`);
|
|
346
297
|
resolve();
|
|
347
298
|
}
|
|
348
299
|
else if (msg.type === WorkerMessageType.LOAD_ERROR) {
|
|
349
300
|
clearTimeout(timeoutId);
|
|
350
301
|
// Cleanup pending hooks on load error
|
|
351
|
-
for (const pending of
|
|
302
|
+
for (const pending of pendingHooks.values()) {
|
|
352
303
|
pending.reject(new Error(`Load error: ${msg.error}`));
|
|
353
304
|
}
|
|
354
305
|
pendingHooks.clear();
|
|
@@ -359,9 +310,9 @@ export class PluginManager extends EventEmitter {
|
|
|
359
310
|
worker.addEventListener("message", (event) => rpcHandler(event.data));
|
|
360
311
|
worker.addEventListener("error", (err) => {
|
|
361
312
|
clearTimeout(timeoutId);
|
|
362
|
-
|
|
313
|
+
console.error(`[Isolated:${pluginName}] Worker Error:`, err);
|
|
363
314
|
// Reject all pending hooks on crash
|
|
364
|
-
for (const pending of
|
|
315
|
+
for (const pending of pendingHooks.values()) {
|
|
365
316
|
pending.reject(new Error("Worker terminated unexpectedly"));
|
|
366
317
|
}
|
|
367
318
|
pendingHooks.clear();
|
|
@@ -373,62 +324,36 @@ export class PluginManager extends EventEmitter {
|
|
|
373
324
|
const plugin = this.plugins.get(pluginName);
|
|
374
325
|
if (!plugin)
|
|
375
326
|
return;
|
|
376
|
-
for (const [name, p] of
|
|
327
|
+
for (const [name, p] of this.plugins.entries()) {
|
|
377
328
|
if (p.dependencies && p.dependencies[pluginName]) {
|
|
378
|
-
|
|
329
|
+
console.warn(`Warning: Plugin ${name} depends on ${pluginName} which is being unloaded.`);
|
|
379
330
|
}
|
|
380
331
|
}
|
|
381
332
|
try {
|
|
382
333
|
await plugin.onUnload();
|
|
383
334
|
}
|
|
384
335
|
catch (error) {
|
|
385
|
-
|
|
336
|
+
console.error(`Error unloading plugin ${pluginName}:`, error);
|
|
386
337
|
}
|
|
387
338
|
finally {
|
|
388
339
|
this.plugins.delete(pluginName);
|
|
389
340
|
this.resources.cleanup(pluginName, this);
|
|
390
341
|
this.hooksManager.cleanup(pluginName);
|
|
391
|
-
|
|
392
|
-
logger.getLogger("PluginManager").info(`Plugin ${pluginName} unloaded.`);
|
|
342
|
+
console.log(`Plugin ${pluginName} unloaded.`);
|
|
393
343
|
}
|
|
394
344
|
}
|
|
395
345
|
getPlugin(name) {
|
|
396
346
|
return this.plugins.get(name);
|
|
397
347
|
}
|
|
398
|
-
getApi(name) {
|
|
399
|
-
// Get the registered API
|
|
400
|
-
return this.getPluginApi(name);
|
|
401
|
-
}
|
|
402
|
-
getPluginConfig(name) {
|
|
403
|
-
return this.configs.get(name) || {};
|
|
404
|
-
}
|
|
405
348
|
listPlugins() {
|
|
406
349
|
return Array.from(this.plugins.keys());
|
|
407
350
|
}
|
|
408
|
-
// Método para registrar manualmente la API de un plugin
|
|
409
|
-
registerApi(pluginName, api) {
|
|
410
|
-
this.pluginApis.set(pluginName, api);
|
|
411
|
-
}
|
|
412
|
-
// Método para obtener la API de un plugin
|
|
413
|
-
getPluginApi(pluginName) {
|
|
414
|
-
return this.pluginApis.get(pluginName);
|
|
415
|
-
}
|
|
416
|
-
// Método para limpiar la API de un plugin al desregistrarlo
|
|
417
|
-
unregisterApi(pluginName) {
|
|
418
|
-
this.pluginApis.delete(pluginName);
|
|
419
|
-
}
|
|
420
351
|
emit(eventName, ...args) {
|
|
421
352
|
return super.emit(eventName, ...args);
|
|
422
353
|
}
|
|
423
354
|
on(eventName, listener) {
|
|
424
355
|
return super.on(eventName, listener);
|
|
425
356
|
}
|
|
426
|
-
once(eventName, listener) {
|
|
427
|
-
return super.once(eventName, listener);
|
|
428
|
-
}
|
|
429
|
-
off(eventName, listener) {
|
|
430
|
-
return super.off(eventName, listener);
|
|
431
|
-
}
|
|
432
357
|
async loadPluginsFromDirectory(directoryPath = join(process.cwd(), "plugins")) {
|
|
433
358
|
try {
|
|
434
359
|
const globalConfigPath = join(this.storageRoot, "plugins.json");
|
|
@@ -441,35 +366,15 @@ export class PluginManager extends EventEmitter {
|
|
|
441
366
|
}
|
|
442
367
|
}
|
|
443
368
|
catch (e) {
|
|
444
|
-
|
|
369
|
+
console.warn("Failed to load global plugin config", e);
|
|
445
370
|
}
|
|
446
|
-
const
|
|
371
|
+
const files = await readdir(directoryPath);
|
|
447
372
|
this.availablePlugins.clear();
|
|
448
|
-
for (const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
const pluginDir = join(directoryPath, entry.name);
|
|
452
|
-
const pkgPath = join(pluginDir, "package.json");
|
|
453
|
-
if (existsSync(pkgPath)) {
|
|
454
|
-
// Auto-install dependencies if node_modules missing
|
|
455
|
-
await this.ensureDependenciesInstalled(pluginDir);
|
|
456
|
-
fullPath = pluginDir;
|
|
457
|
-
}
|
|
458
|
-
else {
|
|
459
|
-
const distPath = join(pluginDir, "dist");
|
|
460
|
-
if (existsSync(distPath)) {
|
|
461
|
-
fullPath = distPath;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
else if ((entry.name.endsWith(".ts") || entry.name.endsWith(".js")) && !entry.name.endsWith(".d.ts")) {
|
|
466
|
-
fullPath = join(directoryPath, entry.name);
|
|
467
|
-
}
|
|
468
|
-
if (fullPath) {
|
|
373
|
+
for (const file of files) {
|
|
374
|
+
if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.endsWith(".d.ts")) {
|
|
375
|
+
const fullPath = join(directoryPath, file);
|
|
469
376
|
try {
|
|
470
|
-
|
|
471
|
-
const query = `?update=${Date.now()}`;
|
|
472
|
-
const module = await import(fullPath + query);
|
|
377
|
+
const module = await import(fullPath);
|
|
473
378
|
for (const key in module) {
|
|
474
379
|
const ExportedItem = module[key];
|
|
475
380
|
const validation = validatePlugin(ExportedItem);
|
|
@@ -477,23 +382,22 @@ export class PluginManager extends EventEmitter {
|
|
|
477
382
|
this.availablePlugins.set(validation.plugin.name, validation.plugin);
|
|
478
383
|
}
|
|
479
384
|
else {
|
|
480
|
-
|
|
481
|
-
logger.getLogger("PluginManager").warn(`Skipping invalid plugin item in ${entry.name}: ${errorMsg}`);
|
|
385
|
+
console.warn(`Skipping invalid plugin in ${file}: ${validation.error}`);
|
|
482
386
|
}
|
|
483
387
|
}
|
|
484
388
|
}
|
|
485
389
|
catch (err) {
|
|
486
|
-
|
|
390
|
+
console.error(`Error importing ${fullPath}:`, err);
|
|
487
391
|
}
|
|
488
392
|
}
|
|
489
393
|
}
|
|
490
394
|
const pluginsToLoad = [];
|
|
491
|
-
for (const plugin of
|
|
395
|
+
for (const plugin of this.availablePlugins.values()) {
|
|
492
396
|
if (!disabledPlugins.includes(plugin.name)) {
|
|
493
397
|
pluginsToLoad.push(plugin);
|
|
494
398
|
}
|
|
495
399
|
else {
|
|
496
|
-
|
|
400
|
+
console.log(`Plugin ${plugin.name} is disabled.`);
|
|
497
401
|
}
|
|
498
402
|
}
|
|
499
403
|
try {
|
|
@@ -504,7 +408,7 @@ export class PluginManager extends EventEmitter {
|
|
|
504
408
|
if (plugin.dependencies) {
|
|
505
409
|
for (const dep of Object.keys(plugin.dependencies)) {
|
|
506
410
|
if (!this.plugins.has(dep)) {
|
|
507
|
-
|
|
411
|
+
console.warn(`Skipping ${plugin.name}: Dependency ${dep} failed to load or is missing.`);
|
|
508
412
|
dependenciesOk = false;
|
|
509
413
|
break;
|
|
510
414
|
}
|
|
@@ -513,18 +417,13 @@ export class PluginManager extends EventEmitter {
|
|
|
513
417
|
if (!dependenciesOk)
|
|
514
418
|
continue;
|
|
515
419
|
try {
|
|
516
|
-
if (this.plugins.has(plugin.name)) {
|
|
517
|
-
logger.getLogger("PluginManager").info(`Updating plugin: ${plugin.name}`);
|
|
518
|
-
await this.reloadPlugin(plugin.name);
|
|
519
|
-
loadedPlugins.push(plugin);
|
|
520
|
-
}
|
|
521
|
-
else {
|
|
420
|
+
if (!this.plugins.has(plugin.name)) {
|
|
522
421
|
await this.register(plugin);
|
|
523
422
|
loadedPlugins.push(plugin);
|
|
524
423
|
}
|
|
525
424
|
}
|
|
526
425
|
catch (e) {
|
|
527
|
-
|
|
426
|
+
console.error(`Failed to load ${plugin.name}:`, e);
|
|
528
427
|
}
|
|
529
428
|
}
|
|
530
429
|
for (const plugin of loadedPlugins) {
|
|
@@ -533,23 +432,23 @@ export class PluginManager extends EventEmitter {
|
|
|
533
432
|
await plugin.onStarted();
|
|
534
433
|
}
|
|
535
434
|
catch (e) {
|
|
536
|
-
|
|
435
|
+
console.error(`Error in onStarted for ${plugin.name}:`, e);
|
|
537
436
|
}
|
|
538
437
|
}
|
|
539
438
|
}
|
|
540
439
|
}
|
|
541
440
|
catch (e) {
|
|
542
|
-
|
|
441
|
+
console.error("Failed to resolve plugin dependencies or load plugins:", e);
|
|
543
442
|
}
|
|
544
443
|
}
|
|
545
444
|
catch (error) {
|
|
546
|
-
|
|
445
|
+
console.error(`Failed to load plugins from ${directoryPath}`, error);
|
|
547
446
|
}
|
|
548
447
|
}
|
|
549
448
|
async disablePlugin(name) {
|
|
550
449
|
await this.unregister(name);
|
|
551
450
|
await this.updatePluginState(name, true);
|
|
552
|
-
|
|
451
|
+
console.log(`Plugin ${name} disabled.`);
|
|
553
452
|
}
|
|
554
453
|
async enablePlugin(name) {
|
|
555
454
|
await this.updatePluginState(name, false);
|
|
@@ -559,7 +458,7 @@ export class PluginManager extends EventEmitter {
|
|
|
559
458
|
if (plugin.dependencies) {
|
|
560
459
|
for (const dep of Object.keys(plugin.dependencies)) {
|
|
561
460
|
if (!this.plugins.has(dep)) {
|
|
562
|
-
|
|
461
|
+
console.warn(`Cannot enable ${name}: Dependency ${dep} is not loaded.`);
|
|
563
462
|
return;
|
|
564
463
|
}
|
|
565
464
|
}
|
|
@@ -567,33 +466,19 @@ export class PluginManager extends EventEmitter {
|
|
|
567
466
|
await this.register(plugin);
|
|
568
467
|
}
|
|
569
468
|
else {
|
|
570
|
-
|
|
469
|
+
console.warn(`Plugin ${name} enabled but not found in available plugins.`);
|
|
571
470
|
}
|
|
572
471
|
}
|
|
573
472
|
}
|
|
574
473
|
async reloadPlugin(name) {
|
|
575
|
-
const
|
|
576
|
-
if (
|
|
577
|
-
|
|
474
|
+
const plugin = this.plugins.get(name);
|
|
475
|
+
if (plugin) {
|
|
476
|
+
console.log(`Reloading plugin ${name}...`);
|
|
578
477
|
await this.unregister(name);
|
|
579
478
|
}
|
|
580
479
|
const definition = this.availablePlugins.get(name);
|
|
581
480
|
if (definition) {
|
|
582
481
|
await this.register(definition);
|
|
583
|
-
const newPlugin = this.plugins.get(name);
|
|
584
|
-
// If the new version has onReload, call it
|
|
585
|
-
if (newPlugin && newPlugin.onReload) {
|
|
586
|
-
// We need a context for onReload as well
|
|
587
|
-
const storage = new JsonPluginStorage(this.storageRoot, name);
|
|
588
|
-
const context = createPluginContext(this, newPlugin, this.resources, storage);
|
|
589
|
-
try {
|
|
590
|
-
await newPlugin.onReload(context);
|
|
591
|
-
}
|
|
592
|
-
catch (e) {
|
|
593
|
-
logger.getLogger("PluginManager").error(`Error in onReload for ${name}:`, e);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
this.emit("plugin:updated", { name: definition.name, version: definition.version });
|
|
597
482
|
}
|
|
598
483
|
else {
|
|
599
484
|
throw new Error(`Plugin ${name} not found in available plugins.`);
|
|
@@ -619,7 +504,7 @@ export class PluginManager extends EventEmitter {
|
|
|
619
504
|
await Bun.write(globalConfigPath, JSON.stringify(config, null, 2));
|
|
620
505
|
}
|
|
621
506
|
catch (e) {
|
|
622
|
-
|
|
507
|
+
console.error("Failed to update plugin state", e);
|
|
623
508
|
}
|
|
624
509
|
}
|
|
625
510
|
async runOnResolve(args) {
|
|
@@ -628,34 +513,158 @@ export class PluginManager extends EventEmitter {
|
|
|
628
513
|
async runOnLoad(args) {
|
|
629
514
|
return this.hooksManager.runOnLoad(args);
|
|
630
515
|
}
|
|
631
|
-
// Bun-like Aliases
|
|
632
|
-
async use(plugin) { return this.register(plugin); }
|
|
633
|
-
async plugin(plugin) { return this.register(plugin); }
|
|
634
|
-
async remove(pluginName) { return this.unregister(pluginName); }
|
|
635
516
|
toBunPlugin() {
|
|
636
517
|
return this.hooksManager.toBunPlugin();
|
|
637
518
|
}
|
|
638
|
-
hotReloadTimer = null;
|
|
639
519
|
enableHotReload(pluginDir) {
|
|
640
|
-
|
|
641
|
-
|
|
520
|
+
// Close existing watcher if any
|
|
521
|
+
if (this.hotReloadWatcher) {
|
|
522
|
+
this.hotReloadWatcher.close();
|
|
523
|
+
}
|
|
524
|
+
// Initial scan to build file map
|
|
525
|
+
this.scanAndTrackPlugins(pluginDir);
|
|
526
|
+
console.log(`[HotReload] Watching ${pluginDir} for changes...`);
|
|
527
|
+
this.hotReloadWatcher = watch(pluginDir, { recursive: true }, async (event, filename) => {
|
|
642
528
|
if (!filename || (!filename.endsWith(".ts") && !filename.endsWith(".js")))
|
|
643
529
|
return;
|
|
530
|
+
if (filename.endsWith(".d.ts"))
|
|
531
|
+
return; // Skip type definitions
|
|
532
|
+
const fullPath = join(pluginDir, filename);
|
|
644
533
|
if (this.hotReloadTimer)
|
|
645
534
|
clearTimeout(this.hotReloadTimer);
|
|
646
535
|
this.hotReloadTimer = setTimeout(async () => {
|
|
647
|
-
|
|
648
|
-
await this.loadPluginsFromDirectory(pluginDir);
|
|
536
|
+
await this.handleFileChange(event, fullPath, filename, pluginDir);
|
|
649
537
|
}, 300);
|
|
650
538
|
});
|
|
651
539
|
}
|
|
540
|
+
async scanAndTrackPlugins(pluginDir) {
|
|
541
|
+
this.pluginFiles.clear();
|
|
542
|
+
try {
|
|
543
|
+
const files = await readdir(pluginDir);
|
|
544
|
+
for (const file of files) {
|
|
545
|
+
if ((file.endsWith(".ts") || file.endsWith(".js")) && !file.endsWith(".d.ts")) {
|
|
546
|
+
const fullPath = join(pluginDir, file);
|
|
547
|
+
try {
|
|
548
|
+
const module = await import(fullPath);
|
|
549
|
+
for (const key in module) {
|
|
550
|
+
const ExportedItem = module[key];
|
|
551
|
+
const validation = validatePlugin(ExportedItem);
|
|
552
|
+
if (validation.valid) {
|
|
553
|
+
this.pluginFiles.set(fullPath, validation.plugin.name);
|
|
554
|
+
this.availablePlugins.set(validation.plugin.name, validation.plugin);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
catch (err) {
|
|
559
|
+
console.warn(`[HotReload] Failed to scan ${file}:`, err);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
catch (err) {
|
|
565
|
+
console.error(`[HotReload] Failed to scan plugin directory:`, err);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
async handleFileChange(event, fullPath, filename, pluginDir) {
|
|
569
|
+
const exists = existsSync(fullPath);
|
|
570
|
+
const previousName = this.pluginFiles.get(fullPath);
|
|
571
|
+
if (!exists && previousName) {
|
|
572
|
+
// File was removed - uninstall plugin
|
|
573
|
+
console.log(`[HotReload] Plugin file removed: ${filename}. Unloading plugin ${previousName}...`);
|
|
574
|
+
this.pluginFiles.delete(fullPath);
|
|
575
|
+
if (this.plugins.has(previousName)) {
|
|
576
|
+
await this.unregister(previousName);
|
|
577
|
+
console.log(`[HotReload] Plugin ${previousName} unloaded.`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else if (exists && !previousName) {
|
|
581
|
+
// New file added - install plugin
|
|
582
|
+
console.log(event, `[HotReload] New plugin file detected: ${filename}. Loading plugin...`);
|
|
583
|
+
try {
|
|
584
|
+
const module = await import(fullPath);
|
|
585
|
+
for (const key in module) {
|
|
586
|
+
const ExportedItem = module[key];
|
|
587
|
+
const validation = validatePlugin(ExportedItem);
|
|
588
|
+
if (validation.valid) {
|
|
589
|
+
const plugin = validation.plugin;
|
|
590
|
+
this.pluginFiles.set(fullPath, plugin.name);
|
|
591
|
+
this.availablePlugins.set(plugin.name, plugin);
|
|
592
|
+
// Check if not disabled and load it
|
|
593
|
+
const globalConfigPath = join(this.storageRoot, "plugins.json");
|
|
594
|
+
let disabledPlugins = [];
|
|
595
|
+
try {
|
|
596
|
+
const file = Bun.file(globalConfigPath);
|
|
597
|
+
if (await file.exists()) {
|
|
598
|
+
const data = await file.json();
|
|
599
|
+
disabledPlugins = data.disabled || [];
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
catch (e) { /* ignore */ }
|
|
603
|
+
if (!disabledPlugins.includes(plugin.name) && !this.plugins.has(plugin.name)) {
|
|
604
|
+
await this.register(plugin);
|
|
605
|
+
console.log(`[HotReload] Plugin ${plugin.name} loaded.`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
catch (err) {
|
|
611
|
+
console.error(`[HotReload] Failed to load new plugin ${filename}:`, pluginDir, err);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
else if (exists && previousName) {
|
|
615
|
+
// File was modified - reload plugin
|
|
616
|
+
console.log(`[HotReload] Plugin file modified: ${filename}. Reloading plugin ${previousName}...`);
|
|
617
|
+
try {
|
|
618
|
+
// Remove from module cache to force reimport
|
|
619
|
+
delete require.cache[fullPath];
|
|
620
|
+
// Unload existing plugin
|
|
621
|
+
if (this.plugins.has(previousName)) {
|
|
622
|
+
await this.unregister(previousName);
|
|
623
|
+
}
|
|
624
|
+
// Reload the plugin
|
|
625
|
+
const module = await import(fullPath);
|
|
626
|
+
for (const key in module) {
|
|
627
|
+
const ExportedItem = module[key];
|
|
628
|
+
const validation = validatePlugin(ExportedItem);
|
|
629
|
+
if (validation.valid) {
|
|
630
|
+
const plugin = validation.plugin;
|
|
631
|
+
this.availablePlugins.set(plugin.name, plugin);
|
|
632
|
+
// Check if not disabled and load it
|
|
633
|
+
const globalConfigPath = join(this.storageRoot, "plugins.json");
|
|
634
|
+
let disabledPlugins = [];
|
|
635
|
+
try {
|
|
636
|
+
const file = Bun.file(globalConfigPath);
|
|
637
|
+
if (await file.exists()) {
|
|
638
|
+
const data = await file.json();
|
|
639
|
+
disabledPlugins = data.disabled || [];
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
catch (e) { /* ignore */ }
|
|
643
|
+
if (!disabledPlugins.includes(plugin.name)) {
|
|
644
|
+
await this.register(plugin);
|
|
645
|
+
console.log(`[HotReload] Plugin ${plugin.name} reloaded.`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
catch (err) {
|
|
651
|
+
console.error(`[HotReload] Failed to reload plugin ${filename}:`, err);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
disableHotReload() {
|
|
656
|
+
if (this.hotReloadWatcher) {
|
|
657
|
+
this.hotReloadWatcher.close();
|
|
658
|
+
this.hotReloadWatcher = null;
|
|
659
|
+
console.log(`[HotReload] File watcher stopped.`);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
652
662
|
getMetrics() {
|
|
653
663
|
return {
|
|
654
664
|
totalPlugins: this.plugins.size,
|
|
655
665
|
activePlugins: Array.from(this.plugins.keys()),
|
|
656
666
|
resources: this.resources.getUsageSummary(),
|
|
657
667
|
hooks: {
|
|
658
|
-
onStart: this.hooksManager.getHookCount(HookType.ON_START),
|
|
659
668
|
onResolve: this.hooksManager.getHookCount(HookType.ON_RESOLVE),
|
|
660
669
|
onLoad: this.hooksManager.getHookCount(HookType.ON_LOAD)
|
|
661
670
|
}
|
|
@@ -663,7 +672,7 @@ export class PluginManager extends EventEmitter {
|
|
|
663
672
|
}
|
|
664
673
|
getPluginStatus() {
|
|
665
674
|
const status = {};
|
|
666
|
-
for (const [name, plugin] of
|
|
675
|
+
for (const [name, plugin] of this.plugins) {
|
|
667
676
|
const resources = this.resources.get(name);
|
|
668
677
|
status[name] = {
|
|
669
678
|
version: plugin.version,
|
|
@@ -677,37 +686,5 @@ export class PluginManager extends EventEmitter {
|
|
|
677
686
|
}
|
|
678
687
|
return status;
|
|
679
688
|
}
|
|
680
|
-
async ensureDependenciesInstalled(pluginPath) {
|
|
681
|
-
const nodeModulesPath = join(pluginPath, "node_modules");
|
|
682
|
-
if (!existsSync(nodeModulesPath)) {
|
|
683
|
-
// 1. Check if we are in production
|
|
684
|
-
const isProduction = process.env.NODE_ENV === "production";
|
|
685
|
-
if (isProduction) {
|
|
686
|
-
logger.getLogger("PluginManager").warn(`[PluginManager] Warning: Plugin at ${pluginPath} is missing node_modules. Auto-install is disabled in production.`);
|
|
687
|
-
return;
|
|
688
|
-
}
|
|
689
|
-
// 2. Check if 'bun' CLI is even available in the system
|
|
690
|
-
const bunPath = Bun.which("bun");
|
|
691
|
-
if (!bunPath) {
|
|
692
|
-
logger.getLogger("PluginManager").warn(`[PluginManager] Warning: node_modules missing in ${pluginPath}, but 'bun' CLI was not found. Cannot auto-install.`);
|
|
693
|
-
return;
|
|
694
|
-
}
|
|
695
|
-
logger.getLogger("PluginManager").info(`[PluginManager] Development mode detected. node_modules missing in ${pluginPath}. Installing deps...`);
|
|
696
|
-
try {
|
|
697
|
-
const proc = Bun.spawn([bunPath, "install"], {
|
|
698
|
-
cwd: pluginPath,
|
|
699
|
-
stdout: "inherit",
|
|
700
|
-
stderr: "inherit",
|
|
701
|
-
});
|
|
702
|
-
const exitCode = await proc.exited;
|
|
703
|
-
if (exitCode !== 0) {
|
|
704
|
-
logger.getLogger("PluginManager").error(`[PluginManager] Failed to install dependencies for ${pluginPath}. Exit code: ${exitCode}`);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
catch (e) {
|
|
708
|
-
logger.getLogger("PluginManager").error(`[PluginManager] Error running bun install for ${pluginPath}:`, e);
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
689
|
}
|
|
713
690
|
//# sourceMappingURL=PluginManager.js.map
|