@yumerijs/loader 2.0.0 → 2.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.
- package/dist/index.d.ts +34 -16
- package/dist/index.js +269 -88
- package/package.json +6 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,45 @@
|
|
|
1
|
-
import { Core, Config, Logger, Context } from '@yumerijs/core';
|
|
1
|
+
import { Core, Config, Logger, Context, PluginStatus } from '@yumerijs/core';
|
|
2
|
+
import 'esbuild-register';
|
|
2
3
|
interface Plugin {
|
|
3
4
|
apply: (ctx: Context, config: Config) => Promise<void>;
|
|
4
5
|
disable: (ctx: Context) => Promise<void>;
|
|
5
6
|
depend: Array<string>;
|
|
6
7
|
provide: Array<string>;
|
|
7
8
|
}
|
|
8
|
-
|
|
9
|
-
load(pluginName: string): Promise<Plugin>;
|
|
10
|
-
unloadPlugin(pluginName: string): Promise<void>;
|
|
11
|
-
checkPluginDependencies(pluginPath: string): Promise<boolean>;
|
|
12
|
-
installPluginDependencies(pluginName: string): Promise<void>;
|
|
13
|
-
logger: Logger;
|
|
14
|
-
}
|
|
15
|
-
declare class PluginLoader {
|
|
16
|
-
private pluginCache;
|
|
17
|
-
private core;
|
|
18
|
-
private config;
|
|
19
|
-
private isDev;
|
|
9
|
+
export declare class PluginLoader {
|
|
20
10
|
private pluginsDir;
|
|
11
|
+
core: Core;
|
|
12
|
+
config: any;
|
|
21
13
|
logger: Logger;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
plugins: {
|
|
15
|
+
[name: string]: Plugin & {
|
|
16
|
+
depend?: string[];
|
|
17
|
+
provide?: string[];
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
pluginStatus: Record<string, PluginStatus>;
|
|
21
|
+
private pluginWatchers;
|
|
22
|
+
private pluginModules;
|
|
23
|
+
private configPath;
|
|
24
|
+
private pluginContexts;
|
|
25
|
+
private isDev;
|
|
26
|
+
constructor(core?: Core, pluginsDir?: string);
|
|
27
|
+
getCore(): Core;
|
|
28
|
+
getContext(pluginName: string): Context;
|
|
29
|
+
unregall(pluginName: string): void;
|
|
30
|
+
loadConfig(configPath: string): Promise<void>;
|
|
31
|
+
private watchConfig;
|
|
32
|
+
getPluginConfig(pluginName: string): Promise<Config>;
|
|
33
|
+
loadPlugins(): Promise<void>;
|
|
34
|
+
loadSinglePlugin(pluginName: string, triggerPendingCheck?: boolean, onlypending?: boolean): Promise<boolean>;
|
|
35
|
+
private _loadPendingPlugins;
|
|
36
|
+
unloadPlugin(pluginNameToUnload: string, ispending?: boolean): Promise<void>;
|
|
37
|
+
private _unloadSinglePlugin;
|
|
38
|
+
reloadPlugin(pluginName: string): Promise<void>;
|
|
39
|
+
private watchPlugin;
|
|
40
|
+
loadModule(pluginName: string): Promise<Plugin>;
|
|
25
41
|
private clearRequireCache;
|
|
42
|
+
checkPluginDependencies(pluginPath: string): Promise<boolean>;
|
|
43
|
+
installPluginDependencies(pluginName: string): Promise<void>;
|
|
26
44
|
}
|
|
27
45
|
export default PluginLoader;
|
package/dist/index.js
CHANGED
|
@@ -33,147 +33,327 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PluginLoader = void 0;
|
|
36
37
|
const path = __importStar(require("path"));
|
|
37
38
|
const core_1 = require("@yumerijs/core");
|
|
38
39
|
const fs = __importStar(require("fs"));
|
|
39
40
|
const util_1 = require("util");
|
|
40
41
|
const child_process_1 = require("child_process");
|
|
41
|
-
const
|
|
42
|
+
const yaml = __importStar(require("js-yaml"));
|
|
43
|
+
const chokidar = __importStar(require("chokidar"));
|
|
44
|
+
require("esbuild-register");
|
|
42
45
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
43
46
|
class PluginLoader {
|
|
44
|
-
|
|
45
|
-
core
|
|
47
|
+
pluginsDir;
|
|
48
|
+
core;
|
|
46
49
|
config = null;
|
|
47
|
-
isDev = false;
|
|
48
|
-
pluginsDir = 'plugins'; // Default plugins directory
|
|
49
50
|
logger = new core_1.Logger('loader');
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
plugins = {};
|
|
52
|
+
pluginStatus = {};
|
|
53
|
+
pluginWatchers = {};
|
|
54
|
+
pluginModules = {};
|
|
55
|
+
configPath = '';
|
|
56
|
+
pluginContexts = {};
|
|
57
|
+
isDev = false;
|
|
58
|
+
constructor(core, pluginsDir = 'plugins') {
|
|
55
59
|
this.pluginsDir = pluginsDir;
|
|
60
|
+
this.core = core || new core_1.Core(undefined, false);
|
|
61
|
+
this.isDev = process.env.NODE_ENV === 'development';
|
|
62
|
+
core_1.Logger.setCore(this.core); // Set the core instance for the logger
|
|
56
63
|
}
|
|
57
|
-
|
|
58
|
-
this.core
|
|
59
|
-
this.config = config;
|
|
64
|
+
getCore() {
|
|
65
|
+
return this.core;
|
|
60
66
|
}
|
|
61
|
-
|
|
62
|
-
if (this.
|
|
63
|
-
|
|
67
|
+
getContext(pluginName) {
|
|
68
|
+
if (!this.pluginContexts[pluginName]) {
|
|
69
|
+
this.pluginContexts[pluginName] = new core_1.Context(this.core, pluginName);
|
|
64
70
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
return this.pluginContexts[pluginName];
|
|
72
|
+
}
|
|
73
|
+
unregall(pluginName) {
|
|
74
|
+
const ctx = this.pluginContexts[pluginName];
|
|
75
|
+
if (ctx) {
|
|
76
|
+
ctx.dispose();
|
|
77
|
+
delete this.pluginContexts[pluginName];
|
|
72
78
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
}
|
|
80
|
+
async loadConfig(configPath) {
|
|
81
|
+
try {
|
|
82
|
+
this.configPath = configPath;
|
|
83
|
+
const doc = yaml.load(fs.readFileSync(configPath, 'utf8'));
|
|
84
|
+
this.config = doc;
|
|
85
|
+
this.logger.info('Config loaded.');
|
|
86
|
+
if (this.isDev) {
|
|
87
|
+
this.watchConfig(configPath);
|
|
88
|
+
}
|
|
89
|
+
this.core.coreConfig = this.config.core || {};
|
|
90
|
+
this.core.i18n = new (require('@yumerijs/core').I18n)(this.core.coreConfig.lang || ['zh', 'en']);
|
|
76
91
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
92
|
+
catch (e) {
|
|
93
|
+
this.logger.error('Failed to load config:', e);
|
|
94
|
+
throw e;
|
|
80
95
|
}
|
|
81
|
-
|
|
96
|
+
}
|
|
97
|
+
watchConfig(configPath) {
|
|
98
|
+
const watcher = chokidar.watch(configPath, {
|
|
99
|
+
persistent: true,
|
|
100
|
+
ignoreInitial: true,
|
|
101
|
+
awaitWriteFinish: {
|
|
102
|
+
stabilityThreshold: 300,
|
|
103
|
+
pollInterval: 100,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
watcher.on('change', async () => {
|
|
82
107
|
try {
|
|
83
|
-
|
|
108
|
+
const doc = yaml.load(fs.readFileSync(configPath, 'utf8'));
|
|
109
|
+
if (doc && doc.plugins) {
|
|
110
|
+
this.config.plugins = doc.plugins;
|
|
111
|
+
}
|
|
112
|
+
await this.core.emit('config-changed', this.config);
|
|
84
113
|
}
|
|
85
|
-
catch (
|
|
86
|
-
|
|
87
|
-
|
|
114
|
+
catch (error) {
|
|
115
|
+
this.logger.error('Failed to reload config:', error);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
this.logger.info(`Watching for config changes at ${configPath}`);
|
|
119
|
+
}
|
|
120
|
+
async getPluginConfig(pluginName) {
|
|
121
|
+
const actualPluginName = pluginName.startsWith('~') ? pluginName.substring(1) : pluginName;
|
|
122
|
+
if (this.configPath && this.isDev) {
|
|
123
|
+
try {
|
|
124
|
+
const doc = yaml.load(fs.readFileSync(this.configPath, 'utf8'));
|
|
125
|
+
if (doc && doc.plugins) {
|
|
126
|
+
this.config.plugins = doc.plugins;
|
|
88
127
|
}
|
|
89
|
-
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
this.logger.warn('Failed to refresh config for hot reload:', error);
|
|
90
131
|
}
|
|
91
132
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
133
|
+
if (!this.config.plugins[actualPluginName]) {
|
|
134
|
+
return new core_1.Config(actualPluginName);
|
|
135
|
+
}
|
|
136
|
+
return new core_1.Config(actualPluginName, this.config.plugins[actualPluginName]);
|
|
137
|
+
}
|
|
138
|
+
async loadPlugins() {
|
|
139
|
+
if (!this.config || typeof this.config.plugins !== 'object' || this.config.plugins === null) {
|
|
140
|
+
this.logger.info('No plugins configuration found. No plugins to load.');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const allPluginNames = Object.keys(this.config.plugins);
|
|
144
|
+
this.pluginStatus = {}; // Reset status
|
|
145
|
+
for (const name of allPluginNames) {
|
|
146
|
+
if (name.startsWith('~')) {
|
|
147
|
+
const actualName = name.substring(1);
|
|
148
|
+
this.pluginStatus[actualName] = "disabled" /* PluginStatus.DISABLED */;
|
|
97
149
|
}
|
|
98
150
|
else {
|
|
99
|
-
|
|
100
|
-
return plugin.default || plugin;
|
|
151
|
+
this.pluginStatus[name] = "pending" /* PluginStatus.PENDING */;
|
|
101
152
|
}
|
|
102
153
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
154
|
+
const enabledPlugins = allPluginNames.filter(name => !name.startsWith('~'));
|
|
155
|
+
const currentlyLoaded = Object.keys(this.plugins);
|
|
156
|
+
for (const loadedName of currentlyLoaded) {
|
|
157
|
+
if (!enabledPlugins.includes(loadedName)) {
|
|
158
|
+
await this.unloadPlugin(loadedName);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (enabledPlugins.length === 0) {
|
|
162
|
+
this.logger.info('No enabled plugins found in configuration.');
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
let loadedInLastPass = true;
|
|
166
|
+
while (loadedInLastPass) {
|
|
167
|
+
loadedInLastPass = false;
|
|
168
|
+
for (const pluginName of enabledPlugins) {
|
|
169
|
+
if (this.pluginStatus[pluginName] === "enabled" /* PluginStatus.ENABLED */) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
const success = await this.loadSinglePlugin(pluginName, false);
|
|
173
|
+
if (success) {
|
|
174
|
+
loadedInLastPass = true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
await this._loadPendingPlugins();
|
|
179
|
+
const pendingPlugins = Object.keys(this.pluginStatus).filter(p => this.pluginStatus[p] === "pending" /* PluginStatus.PENDING */);
|
|
180
|
+
if (pendingPlugins.length > 0) {
|
|
181
|
+
// this.logger.warn('Some plugins could not be loaded due to unresolved dependencies:', pendingPlugins);
|
|
106
182
|
}
|
|
107
183
|
}
|
|
108
|
-
async
|
|
184
|
+
async loadSinglePlugin(pluginName, triggerPendingCheck = true, onlypending = false) {
|
|
185
|
+
if (!this.pluginStatus[pluginName]) {
|
|
186
|
+
this.pluginStatus[pluginName] = "pending" /* PluginStatus.PENDING */;
|
|
187
|
+
}
|
|
188
|
+
if (this.pluginStatus[pluginName] !== "pending" /* PluginStatus.PENDING */ && onlypending) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
109
191
|
try {
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
192
|
+
const pluginInstance = await this.loadModule(pluginName);
|
|
193
|
+
if (!pluginInstance) {
|
|
194
|
+
throw new Error('Plugin loader returned no instance.');
|
|
195
|
+
}
|
|
196
|
+
const deps = pluginInstance.depend || [];
|
|
197
|
+
const unmetDependencies = deps.filter(dep => !this.core.components[dep]);
|
|
198
|
+
if (unmetDependencies.length > 0) {
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
this.plugins[pluginName] = pluginInstance;
|
|
202
|
+
const pluginConfig = await this.getPluginConfig(pluginName);
|
|
203
|
+
const context = this.getContext(pluginName);
|
|
204
|
+
// The new API
|
|
205
|
+
await this.core.plugin(pluginInstance, context, pluginConfig);
|
|
206
|
+
this.pluginStatus[pluginName] = "enabled" /* PluginStatus.ENABLED */;
|
|
207
|
+
if (triggerPendingCheck) {
|
|
208
|
+
await this._loadPendingPlugins();
|
|
209
|
+
}
|
|
210
|
+
if (this.isDev) {
|
|
211
|
+
let pluginPathToWatch = null;
|
|
212
|
+
try {
|
|
213
|
+
const pkgJsonPath = require.resolve(`${pluginName}/package.json`);
|
|
214
|
+
pluginPathToWatch = path.dirname(pkgJsonPath);
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
const localPluginPath = path.resolve(process.cwd(), pluginName);
|
|
218
|
+
const localPluginPathInPlugins = path.resolve(process.cwd(), 'plugins', pluginName);
|
|
219
|
+
if (fs.existsSync(localPluginPath)) {
|
|
220
|
+
pluginPathToWatch = localPluginPath;
|
|
118
221
|
}
|
|
119
|
-
else if (
|
|
120
|
-
|
|
222
|
+
else if (fs.existsSync(localPluginPathInPlugins)) {
|
|
223
|
+
pluginPathToWatch = localPluginPathInPlugins;
|
|
121
224
|
}
|
|
122
225
|
}
|
|
226
|
+
if (pluginPathToWatch) {
|
|
227
|
+
this.watchPlugin(pluginName, pluginPathToWatch);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
this.logger.warn(`Could not resolve path for plugin ${pluginName} to watch for changes.`);
|
|
231
|
+
}
|
|
123
232
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
catch (err) {
|
|
236
|
+
this.logger.error(`Failed to load plugin "${pluginName}":`, err);
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
async _loadPendingPlugins() {
|
|
241
|
+
const pendingPlugins = Object.keys(this.pluginStatus).filter(p => this.pluginStatus[p] === "pending" /* PluginStatus.PENDING */);
|
|
242
|
+
if (pendingPlugins.length === 0)
|
|
243
|
+
return;
|
|
244
|
+
for (const pluginName of pendingPlugins) {
|
|
245
|
+
await this.loadSinglePlugin(pluginName, false);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async unloadPlugin(pluginNameToUnload, ispending = false) {
|
|
249
|
+
const dependents = [];
|
|
250
|
+
const pluginsToCheck = [pluginNameToUnload];
|
|
251
|
+
while (pluginsToCheck.length > 0) {
|
|
252
|
+
const currentPluginName = pluginsToCheck.shift();
|
|
253
|
+
const provided = this.plugins[currentPluginName]?.provide || [];
|
|
254
|
+
if (provided.length === 0)
|
|
255
|
+
continue;
|
|
256
|
+
for (const pluginName in this.plugins) {
|
|
257
|
+
if (dependents.includes(pluginName) || pluginName === pluginNameToUnload)
|
|
258
|
+
continue;
|
|
259
|
+
const deps = this.plugins[pluginName].depend || [];
|
|
260
|
+
if (provided.some(p => deps.includes(p))) {
|
|
261
|
+
if (!dependents.includes(pluginName)) {
|
|
262
|
+
dependents.push(pluginName);
|
|
263
|
+
pluginsToCheck.push(pluginName);
|
|
264
|
+
}
|
|
131
265
|
}
|
|
132
|
-
const module = require(resolvedPath);
|
|
133
|
-
return module.default || module;
|
|
134
266
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
267
|
+
}
|
|
268
|
+
for (const dependentName of dependents) {
|
|
269
|
+
await this.unloadPlugin(dependentName, true);
|
|
270
|
+
}
|
|
271
|
+
await this._unloadSinglePlugin(pluginNameToUnload, ispending);
|
|
272
|
+
}
|
|
273
|
+
async _unloadSinglePlugin(pluginName, ispending = false) {
|
|
274
|
+
if (this.pluginStatus[pluginName] !== "enabled" /* PluginStatus.ENABLED */) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
this.logger.info(`Unloading plugin "${pluginName}"...`);
|
|
278
|
+
try {
|
|
279
|
+
const plugin = this.plugins[pluginName];
|
|
280
|
+
if (plugin && plugin.disable)
|
|
281
|
+
await plugin.disable(this.getContext(pluginName));
|
|
282
|
+
this.unregall(pluginName);
|
|
283
|
+
delete this.plugins[pluginName];
|
|
284
|
+
delete this.pluginModules[pluginName];
|
|
285
|
+
this.pluginStatus[pluginName] = ispending ? "pending" /* PluginStatus.PENDING */ : "disabled" /* PluginStatus.DISABLED */;
|
|
286
|
+
if (this.pluginWatchers[pluginName]) {
|
|
287
|
+
this.pluginWatchers[pluginName].close();
|
|
288
|
+
delete this.pluginWatchers[pluginName];
|
|
140
289
|
}
|
|
290
|
+
this.core.emit('plugin-unloaded', pluginName);
|
|
141
291
|
}
|
|
142
|
-
catch (
|
|
143
|
-
this.logger.error(`
|
|
144
|
-
|
|
292
|
+
catch (error) {
|
|
293
|
+
this.logger.error(`Failed to unload plugin "${pluginName}":`, error);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async reloadPlugin(pluginName) {
|
|
297
|
+
await this.unloadPlugin(pluginName);
|
|
298
|
+
const success = await this.loadSinglePlugin(pluginName);
|
|
299
|
+
if (success) {
|
|
300
|
+
this.core.emit('plugin-reloaded', pluginName);
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
this.logger.error(`Failed to reload plugin "${pluginName}". It may have unmet dependencies.`);
|
|
145
304
|
}
|
|
146
305
|
}
|
|
306
|
+
watchPlugin(pluginName, pluginPath) {
|
|
307
|
+
if (this.pluginWatchers[pluginName]) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const logger = new core_1.Logger('hmr');
|
|
311
|
+
const watcher = chokidar.watch(pluginPath, {
|
|
312
|
+
ignored: /(^|[\/])\../,
|
|
313
|
+
persistent: true,
|
|
314
|
+
ignoreInitial: true,
|
|
315
|
+
awaitWriteFinish: {
|
|
316
|
+
stabilityThreshold: 200,
|
|
317
|
+
pollInterval: 100,
|
|
318
|
+
},
|
|
319
|
+
});
|
|
320
|
+
watcher.on('change', async (changePath) => {
|
|
321
|
+
logger.info(`Plugin file changed: ${changePath}`);
|
|
322
|
+
await this.reloadPlugin(pluginName);
|
|
323
|
+
});
|
|
324
|
+
watcher.on('add', async (changePath) => {
|
|
325
|
+
logger.info(`New file added to plugin ${pluginName}: ${changePath}`);
|
|
326
|
+
await this.reloadPlugin(pluginName);
|
|
327
|
+
});
|
|
328
|
+
watcher.on('unlink', async (changePath) => {
|
|
329
|
+
logger.info(`File removed from plugin ${pluginName}: ${changePath}`);
|
|
330
|
+
await this.reloadPlugin(pluginName);
|
|
331
|
+
});
|
|
332
|
+
this.pluginWatchers[pluginName] = watcher;
|
|
333
|
+
}
|
|
334
|
+
async loadModule(pluginName) {
|
|
335
|
+
if (this.isDev) {
|
|
336
|
+
this.clearRequireCache(pluginName, new Set());
|
|
337
|
+
}
|
|
338
|
+
const plugin = await require(pluginName);
|
|
339
|
+
return plugin.default || plugin;
|
|
340
|
+
}
|
|
147
341
|
clearRequireCache(moduleId, visited) {
|
|
148
342
|
if (visited.has(moduleId)) {
|
|
149
|
-
return;
|
|
343
|
+
return;
|
|
150
344
|
}
|
|
151
345
|
visited.add(moduleId);
|
|
152
346
|
const module = require.cache[moduleId];
|
|
153
347
|
if (!module)
|
|
154
348
|
return;
|
|
155
|
-
// Recursively clear children's cache
|
|
156
349
|
if (module.children) {
|
|
157
350
|
for (const child of module.children) {
|
|
158
351
|
this.clearRequireCache(child.id, visited);
|
|
159
352
|
}
|
|
160
353
|
}
|
|
161
|
-
// Delete the module from cache
|
|
162
354
|
delete require.cache[moduleId];
|
|
163
355
|
}
|
|
164
|
-
async unloadPlugin(pluginName) {
|
|
165
|
-
if (!this.pluginCache[pluginName]) {
|
|
166
|
-
return; // Plugin not loaded
|
|
167
|
-
}
|
|
168
|
-
delete this.pluginCache[pluginName];
|
|
169
|
-
// With dynamic import, there's no direct equivalent of require.cache to clear.
|
|
170
|
-
// The timestamp query in dev mode handles fresh loading.
|
|
171
|
-
// For production, modules are cached intentionally.
|
|
172
|
-
this.core?.unregall(pluginName);
|
|
173
|
-
// this.logger.info(`Plugin unloaded: ${pluginName}`);
|
|
174
|
-
}
|
|
175
356
|
async checkPluginDependencies(pluginPath) {
|
|
176
|
-
// TODO: Implement dependency checking from package.json
|
|
177
357
|
return true;
|
|
178
358
|
}
|
|
179
359
|
async installPluginDependencies(pluginName) {
|
|
@@ -192,4 +372,5 @@ class PluginLoader {
|
|
|
192
372
|
}
|
|
193
373
|
}
|
|
194
374
|
}
|
|
375
|
+
exports.PluginLoader = PluginLoader;
|
|
195
376
|
exports.default = PluginLoader;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yumerijs/loader",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Module loader for yumeri",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -25,12 +25,16 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/yumerijs/yumeri#readme",
|
|
27
27
|
"devDependencies": {
|
|
28
|
+
"@types/js-yaml": "^4.0.9",
|
|
28
29
|
"@types/node": "^22.13.10",
|
|
29
30
|
"esbuild": "^0.25.9",
|
|
30
31
|
"esbuild-register": "^3.6.0",
|
|
31
32
|
"typescript": "^5.8.2"
|
|
32
33
|
},
|
|
33
34
|
"dependencies": {
|
|
34
|
-
"@
|
|
35
|
+
"@types/js-yaml": "^4.0.9",
|
|
36
|
+
"@yumerijs/core": "^2.0.1",
|
|
37
|
+
"chokidar": "^4.0.3",
|
|
38
|
+
"js-yaml": "^4.1.0"
|
|
35
39
|
}
|
|
36
40
|
}
|