@yumerijs/loader 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -7,6 +7,14 @@ interface Plugin {
7
7
  render?: string;
8
8
  config?: Schema<any>;
9
9
  }
10
+ export interface PluginConfigEntry {
11
+ id: string;
12
+ moduleName: string;
13
+ config: any;
14
+ configKey: string;
15
+ enabled: boolean;
16
+ legacy: boolean;
17
+ }
10
18
  export declare class PluginLoader {
11
19
  private pluginsDir;
12
20
  core: Core;
@@ -25,6 +33,13 @@ export declare class PluginLoader {
25
33
  private pluginContexts;
26
34
  private isDev;
27
35
  constructor(core?: Core, pluginsDir?: string);
36
+ /**
37
+ * Normalize both the legacy `{ "package-name": { ...config } }` form and
38
+ * the named instance form `{ "instance-id": { module, config } }`.
39
+ */
40
+ getPluginEntry(pluginId: string): PluginConfigEntry | undefined;
41
+ setPluginConfig(pluginId: string, config: any): boolean;
42
+ private getEnabledPluginEntries;
28
43
  /**
29
44
  * Reloads the config file from disk into memory and emits a 'config-reloaded' event.
30
45
  * This does NOT reload any plugins.
package/dist/index.js CHANGED
@@ -25,6 +25,55 @@ export class PluginLoader {
25
25
  this.isDev = process.env.NODE_ENV === 'development';
26
26
  Logger.setCore(this.core);
27
27
  }
28
+ /**
29
+ * Normalize both the legacy `{ "package-name": { ...config } }` form and
30
+ * the named instance form `{ "instance-id": { module, config } }`.
31
+ */
32
+ getPluginEntry(pluginId) {
33
+ const plugins = this.config?.plugins;
34
+ if (!plugins || typeof plugins !== 'object')
35
+ return undefined;
36
+ const configKey = Object.prototype.hasOwnProperty.call(plugins, pluginId)
37
+ ? pluginId
38
+ : Object.prototype.hasOwnProperty.call(plugins, `~${pluginId}`)
39
+ ? `~${pluginId}`
40
+ : undefined;
41
+ if (!configKey)
42
+ return undefined;
43
+ const enabled = !configKey.startsWith('~');
44
+ const id = enabled ? configKey : configKey.substring(1);
45
+ const value = plugins[configKey];
46
+ const isInstance = value && typeof value === 'object' && !Array.isArray(value)
47
+ && typeof value.module === 'string';
48
+ return {
49
+ id,
50
+ moduleName: isInstance ? value.module : id,
51
+ config: isInstance ? (value.config ?? {}) : (value ?? {}),
52
+ configKey,
53
+ enabled,
54
+ legacy: !isInstance,
55
+ };
56
+ }
57
+ setPluginConfig(pluginId, config) {
58
+ const entry = this.getPluginEntry(pluginId);
59
+ if (!entry)
60
+ return false;
61
+ if (entry.legacy) {
62
+ this.config.plugins[entry.configKey] = config;
63
+ }
64
+ else {
65
+ this.config.plugins[entry.configKey].config = config;
66
+ }
67
+ return true;
68
+ }
69
+ getEnabledPluginEntries() {
70
+ if (!this.config || typeof this.config.plugins !== 'object' || this.config.plugins === null) {
71
+ return [];
72
+ }
73
+ return Object.keys(this.config.plugins)
74
+ .map(key => this.getPluginEntry(key.startsWith('~') ? key.substring(1) : key))
75
+ .filter(entry => entry && entry.enabled);
76
+ }
28
77
  /**
29
78
  * Reloads the config file from disk into memory and emits a 'config-reloaded' event.
30
79
  * This does NOT reload any plugins.
@@ -84,18 +133,14 @@ export class PluginLoader {
84
133
  this.logger.info('No plugins configuration found. No plugins to load.');
85
134
  return;
86
135
  }
87
- const allPluginNames = Object.keys(this.config.plugins);
136
+ const allEntries = Object.keys(this.config.plugins)
137
+ .map(key => this.getPluginEntry(key.startsWith('~') ? key.substring(1) : key))
138
+ .filter(Boolean);
88
139
  this.pluginStatus = {}; // Reset status
89
- for (const name of allPluginNames) {
90
- if (name.startsWith('~')) {
91
- const actualName = name.substring(1);
92
- this.pluginStatus[actualName] = "disabled" /* PluginStatus.DISABLED */;
93
- }
94
- else {
95
- this.pluginStatus[name] = "pending" /* PluginStatus.PENDING */;
96
- }
140
+ for (const entry of allEntries) {
141
+ this.pluginStatus[entry.id] = entry.enabled ? "pending" /* PluginStatus.PENDING */ : "disabled" /* PluginStatus.DISABLED */;
97
142
  }
98
- const enabledPlugins = allPluginNames.filter(name => !name.startsWith('~'));
143
+ const enabledPlugins = allEntries.filter(entry => entry.enabled).map(entry => entry.id);
99
144
  const currentlyLoaded = Object.keys(this.plugins);
100
145
  for (const loadedName of currentlyLoaded) {
101
146
  if (!enabledPlugins.includes(loadedName)) {
@@ -170,13 +215,13 @@ export class PluginLoader {
170
215
  return false;
171
216
  }
172
217
  this.plugins[pluginName] = pluginInstance;
173
- // ### NEW CONFIG LOGIC ###
174
- const rawConfig = (this.config.plugins && this.config.plugins[pluginName]) || {};
175
- const schema = pluginInstance.config || Schema.object({}); // The schema is exported as 'config'
176
- const finalConfig = fallback(schema, rawConfig);
177
- // Update the in-memory config with the fully resolved one
178
- this.config.plugins[pluginName] = finalConfig;
179
- // ### END NEW CONFIG LOGIC ###
218
+ const entry = this.getPluginEntry(pluginName);
219
+ if (!entry) {
220
+ throw new Error(`Plugin configuration not found for instance "${pluginName}".`);
221
+ }
222
+ const schema = pluginInstance.config || Schema.object({});
223
+ const finalConfig = fallback(schema, entry.config);
224
+ this.setPluginConfig(pluginName, finalConfig);
180
225
  const context = this.getContext(pluginName, {});
181
226
  if (pluginInstance.render) {
182
227
  context.renderer = this.core.renderers.get(pluginInstance.render || '');
@@ -188,14 +233,15 @@ export class PluginLoader {
188
233
  }
189
234
  if (this.isDev) {
190
235
  let pluginPathToWatch = null;
236
+ const moduleName = entry.moduleName;
191
237
  try {
192
- const packageJsonUrl = import.meta.resolve(`${pluginName}/package.json`);
238
+ const packageJsonUrl = import.meta.resolve(`${moduleName}/package.json`);
193
239
  const pkgJsonPath = fileURLToPath(packageJsonUrl);
194
240
  pluginPathToWatch = path.dirname(pkgJsonPath);
195
241
  }
196
242
  catch (e) {
197
- const localPluginPath = path.resolve(process.cwd(), pluginName);
198
- const localPluginPathInPlugins = path.resolve(process.cwd(), 'plugins', pluginName);
243
+ const localPluginPath = path.resolve(process.cwd(), moduleName);
244
+ const localPluginPathInPlugins = path.resolve(process.cwd(), 'plugins', moduleName);
199
245
  if (fs.existsSync(localPluginPath)) {
200
246
  pluginPathToWatch = localPluginPath;
201
247
  }
@@ -315,10 +361,12 @@ export class PluginLoader {
315
361
  this.pluginWatchers[pluginName] = watcher;
316
362
  }
317
363
  async loadModule(pluginName) {
318
- const pluginModule = await import(pluginName);
364
+ const entry = this.getPluginEntry(pluginName);
365
+ if (!entry)
366
+ throw new Error(`Plugin configuration not found for instance "${pluginName}".`);
367
+ const pluginModule = await import(entry.moduleName);
319
368
  const context = this.getContext(pluginName, {});
320
- const rawConfig = (this.config.plugins && this.config.plugins[pluginName]) || {};
321
- return resolvePluginModule(pluginModule, context, rawConfig);
369
+ return resolvePluginModule(pluginModule, context, entry.config);
322
370
  }
323
371
  async checkPluginDependencies(pluginPath) {
324
372
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yumerijs/loader",
3
- "version": "3.0.1",
3
+ "version": "3.1.0",
4
4
  "description": "Module loader for yumeri",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "devDependencies": {
30
30
  "@types/js-yaml": "^4.0.9",
31
31
  "@types/node": "^22.13.10",
32
- "@yumerijs/core": "^3.0.0",
32
+ "@yumerijs/core": "^3.0.5",
33
33
  "esbuild-register": "^3.6.0",
34
34
  "typescript": "^6.0.3"
35
35
  },
@@ -41,6 +41,6 @@
41
41
  "js-yaml": "^4.1.0"
42
42
  },
43
43
  "peerDependencies": {
44
- "@yumerijs/core": "^3.0.0"
44
+ "@yumerijs/core": "^3.0.5"
45
45
  }
46
46
  }