@yumerijs/loader 3.1.1 → 3.1.2
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 +3 -1
- package/dist/index.js +23 -22
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ interface Plugin {
|
|
|
3
3
|
apply: (ctx: Context, config: Config) => Promise<void>;
|
|
4
4
|
disable: (ctx: Context) => Promise<void>;
|
|
5
5
|
depend: Array<string>;
|
|
6
|
+
optional?: Array<string>;
|
|
6
7
|
provide: Array<string>;
|
|
7
8
|
render?: string;
|
|
8
9
|
config?: Schema<any>;
|
|
@@ -23,6 +24,7 @@ export declare class PluginLoader {
|
|
|
23
24
|
plugins: {
|
|
24
25
|
[name: string]: Plugin & {
|
|
25
26
|
depend?: string[];
|
|
27
|
+
optional?: string[];
|
|
26
28
|
provide?: string[];
|
|
27
29
|
};
|
|
28
30
|
};
|
|
@@ -51,7 +53,7 @@ export declare class PluginLoader {
|
|
|
51
53
|
unregall(pluginName: string): void;
|
|
52
54
|
loadConfig(configPath: string): Promise<void>;
|
|
53
55
|
loadPlugins(): Promise<void>;
|
|
54
|
-
loadSinglePlugin(pluginName: string, triggerPendingCheck?: boolean, onlypending?: boolean): Promise<boolean>;
|
|
56
|
+
loadSinglePlugin(pluginName: string, triggerPendingCheck?: boolean, onlypending?: boolean, requireOptionalDependencies?: boolean): Promise<boolean>;
|
|
55
57
|
private _loadPendingPlugins;
|
|
56
58
|
unloadPlugin(pluginNameToUnload: string, ispending?: boolean): Promise<void>;
|
|
57
59
|
private _unloadSinglePlugin;
|
package/dist/index.js
CHANGED
|
@@ -153,26 +153,20 @@ export class PluginLoader {
|
|
|
153
153
|
this.logger.info('No enabled plugins found in configuration.');
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
|
-
|
|
157
|
-
while (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
const success = await this.loadSinglePlugin(pluginName, false);
|
|
164
|
-
if (success) {
|
|
165
|
-
loadedInLastPass = true;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
156
|
+
// 第一阶段:将 optional 与 depend 一样处理,尽量让可选服务先完成加载并注入。
|
|
157
|
+
while (await this._loadPendingPlugins(true)) {
|
|
158
|
+
// Continue scanning until no plugin can satisfy all required and optional dependencies.
|
|
159
|
+
}
|
|
160
|
+
// 第二阶段:严格扫描无法推进后,忽略尚未提供的 optional;depend 仍必须满足。
|
|
161
|
+
while (await this._loadPendingPlugins(false)) {
|
|
162
|
+
// Continue scanning in relaxed mode until only genuinely missing dependencies remain.
|
|
168
163
|
}
|
|
169
|
-
await this._loadPendingPlugins();
|
|
170
164
|
const pendingPlugins = Object.keys(this.pluginStatus).filter(p => this.pluginStatus[p] === "pending" /* PluginStatus.PENDING */);
|
|
171
165
|
if (pendingPlugins.length > 0) {
|
|
172
|
-
|
|
166
|
+
this.logger.warn('Some plugins could not be loaded due to unresolved required dependencies:', pendingPlugins);
|
|
173
167
|
}
|
|
174
168
|
}
|
|
175
|
-
async loadSinglePlugin(pluginName, triggerPendingCheck = true, onlypending = false) {
|
|
169
|
+
async loadSinglePlugin(pluginName, triggerPendingCheck = true, onlypending = false, requireOptionalDependencies = true) {
|
|
176
170
|
if (!this.pluginStatus[pluginName]) {
|
|
177
171
|
this.pluginStatus[pluginName] = "pending" /* PluginStatus.PENDING */;
|
|
178
172
|
}
|
|
@@ -211,7 +205,10 @@ export class PluginLoader {
|
|
|
211
205
|
}
|
|
212
206
|
}
|
|
213
207
|
}
|
|
214
|
-
const deps =
|
|
208
|
+
const deps = [
|
|
209
|
+
...(pluginInstance.depend || []),
|
|
210
|
+
...(requireOptionalDependencies ? (pluginInstance.optional || []) : []),
|
|
211
|
+
];
|
|
215
212
|
const unmetDependencies = deps.filter(dep => !this.core.components[dep] && !this.core.services[dep]);
|
|
216
213
|
if (unmetDependencies.length > 0) {
|
|
217
214
|
return false;
|
|
@@ -231,7 +228,7 @@ export class PluginLoader {
|
|
|
231
228
|
await this.core.plugin(pluginInstance, context, finalConfig);
|
|
232
229
|
this.pluginStatus[pluginName] = "enabled" /* PluginStatus.ENABLED */;
|
|
233
230
|
if (triggerPendingCheck) {
|
|
234
|
-
await this._loadPendingPlugins();
|
|
231
|
+
await this._loadPendingPlugins(requireOptionalDependencies);
|
|
235
232
|
}
|
|
236
233
|
if (this.isDev) {
|
|
237
234
|
let pluginPathToWatch = null;
|
|
@@ -265,13 +262,14 @@ export class PluginLoader {
|
|
|
265
262
|
return false;
|
|
266
263
|
}
|
|
267
264
|
}
|
|
268
|
-
async _loadPendingPlugins() {
|
|
265
|
+
async _loadPendingPlugins(requireOptionalDependencies = true) {
|
|
269
266
|
const pendingPlugins = Object.keys(this.pluginStatus).filter(p => this.pluginStatus[p] === "pending" /* PluginStatus.PENDING */);
|
|
270
|
-
|
|
271
|
-
return;
|
|
267
|
+
let loadedAny = false;
|
|
272
268
|
for (const pluginName of pendingPlugins) {
|
|
273
|
-
await this.loadSinglePlugin(pluginName, false);
|
|
269
|
+
const loaded = await this.loadSinglePlugin(pluginName, false, true, requireOptionalDependencies);
|
|
270
|
+
loadedAny ||= loaded;
|
|
274
271
|
}
|
|
272
|
+
return loadedAny;
|
|
275
273
|
}
|
|
276
274
|
async unloadPlugin(pluginNameToUnload, ispending = false) {
|
|
277
275
|
const dependents = [];
|
|
@@ -325,7 +323,10 @@ export class PluginLoader {
|
|
|
325
323
|
this.logger.info(`Reloading plugin: "${pluginName}"...`);
|
|
326
324
|
await this.reloadConfigFile();
|
|
327
325
|
await this.unloadPlugin(pluginName, true);
|
|
328
|
-
|
|
326
|
+
let success = await this.loadSinglePlugin(pluginName, true, false, true);
|
|
327
|
+
if (!success) {
|
|
328
|
+
success = await this.loadSinglePlugin(pluginName, true, false, false);
|
|
329
|
+
}
|
|
329
330
|
if (success) {
|
|
330
331
|
this.logger.info(`Plugin "${pluginName}" reloaded successfully.`);
|
|
331
332
|
this.core.emit('plugin-reloaded', pluginName);
|