126 lines
4.0 KiB
JavaScript
126 lines
4.0 KiB
JavaScript
/**
|
|
* Module Registry
|
|
* Manages module registration and dependency tracking
|
|
*/
|
|
export class ModuleRegistry {
|
|
constructor() {
|
|
this.modules = {};
|
|
this.readyPromises = {};
|
|
this.moduleDependencies = new Map(); // Track module dependencies
|
|
}
|
|
|
|
/**
|
|
* Register a module
|
|
* @param {BaseModule} module - Module to register
|
|
* @param {Array<string>} [dependencies] - Optional array of module dependencies
|
|
*/
|
|
register(module, dependencies = null) {
|
|
if (!module || !module.id) {
|
|
console.error('Invalid module - must have an id property');
|
|
return;
|
|
}
|
|
|
|
// Store the module
|
|
this.modules[module.id] = module;
|
|
|
|
// Store dependencies if provided, otherwise use module.dependencies
|
|
if (dependencies) {
|
|
this.moduleDependencies.set(module.id, dependencies);
|
|
|
|
// Also set them on the module itself for backwards compatibility
|
|
if (module.dependencies === undefined) {
|
|
module.dependencies = [...dependencies];
|
|
}
|
|
} else if (module.dependencies) {
|
|
// Use the module's own dependencies property
|
|
this.moduleDependencies.set(module.id, [...module.dependencies]);
|
|
} else {
|
|
// No dependencies
|
|
this.moduleDependencies.set(module.id, []);
|
|
}
|
|
|
|
// Create a promise that will resolve when this module is ready
|
|
this.readyPromises[module.id] = new Promise((resolve) => {
|
|
// Set up a state change listener for this module
|
|
document.addEventListener('module:stateChange', (event) => {
|
|
if (event.detail.moduleId === module.id &&
|
|
(event.detail.state === 'FINISHED' || event.detail.state === 'ERROR')) {
|
|
resolve(event.detail.state === 'FINISHED');
|
|
}
|
|
});
|
|
|
|
// Check if already in finished state
|
|
if (module.state === 'FINISHED') {
|
|
resolve(true);
|
|
} else if (module.state === 'ERROR') {
|
|
resolve(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get a module by id
|
|
* @param {string} id - Module id
|
|
* @returns {BaseModule} - The module, or null if not found
|
|
*/
|
|
getModule(id) {
|
|
return this.modules[id] || null;
|
|
}
|
|
|
|
/**
|
|
* Get all registered modules
|
|
* @returns {Object} - Map of modules
|
|
*/
|
|
getAllModules() {
|
|
return this.modules;
|
|
}
|
|
|
|
/**
|
|
* Get dependencies for a module
|
|
* @param {string} id - Module id
|
|
* @returns {Array<string>} - Array of dependencies
|
|
*/
|
|
getDependencies(id) {
|
|
return this.moduleDependencies.get(id) || [];
|
|
}
|
|
|
|
/**
|
|
* Wait for a module to be ready (in FINISHED state)
|
|
* @param {string} id - Module id to wait for
|
|
* @param {number} timeout - Optional timeout in ms
|
|
* @returns {Promise} - Resolves when the module is ready
|
|
*/
|
|
waitForModule(id, timeout = null) {
|
|
if (!this.readyPromises[id]) {
|
|
return Promise.resolve(false);
|
|
}
|
|
|
|
if (timeout) {
|
|
// Add timeout logic
|
|
return Promise.race([
|
|
this.readyPromises[id],
|
|
new Promise(resolve => setTimeout(() => resolve(false), timeout))
|
|
]);
|
|
}
|
|
|
|
return this.readyPromises[id];
|
|
}
|
|
|
|
/**
|
|
* Wait for multiple modules to be ready
|
|
* @param {Array<string>} ids - Array of module ids to wait for
|
|
* @param {number} timeout - Optional timeout in ms
|
|
* @returns {Promise} - Resolves when all modules are ready
|
|
*/
|
|
waitForModules(ids, timeout = null) {
|
|
const promises = ids.map(id => this.waitForModule(id, timeout));
|
|
return Promise.all(promises);
|
|
}
|
|
}
|
|
|
|
// Create and export a singleton instance
|
|
export const moduleRegistry = new ModuleRegistry();
|
|
|
|
// Make registry accessible globally
|
|
window.moduleRegistry = moduleRegistry;
|