- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
209 lines
7.9 KiB
JavaScript
209 lines
7.9 KiB
JavaScript
import { moduleConfig } from './config.js';
|
|
import { Logger } from '../core/logger.js';
|
|
import { moduleErrorBoundary } from '../core/ModuleErrorBoundary.js';
|
|
import { stateManager } from '../core/StateManager.js';
|
|
import { dependencyManager } from '../core/DependencyManager.js';
|
|
|
|
export const activeModules = new Map(); // key: modulename → { mod, config, state }
|
|
|
|
export async function registerModules() {
|
|
// Use EAGER loading for single bundle - all modules in one chunk
|
|
let modules;
|
|
if (typeof global !== 'undefined' && global.importMeta?.glob) {
|
|
modules = global.importMeta.glob('./*/index.js', { eager: true });
|
|
} else {
|
|
modules = import.meta.glob('./*/index.js', { eager: true });
|
|
}
|
|
|
|
Logger.info('[Modules] Found modules:', Object.keys(modules));
|
|
|
|
const domModules = new Set(
|
|
Array.from(document.querySelectorAll('[data-module]')).map(el => el.dataset.module).filter(Boolean)
|
|
);
|
|
|
|
// Always load these core modules
|
|
const coreModules = new Set(['spa-router', 'form-handling', 'api-manager', 'image-manager']);
|
|
|
|
const usedModules = new Set([...domModules, ...coreModules]);
|
|
const fallbackMode = usedModules.size === coreModules.size && domModules.size === 0;
|
|
|
|
Logger.info('[Modules] DOM modules found:', [...domModules]);
|
|
Logger.info('[Modules] Core modules:', [...coreModules]);
|
|
Logger.info('[Modules] Used modules:', [...usedModules]);
|
|
Logger.info('[Modules] Fallback mode:', fallbackMode);
|
|
|
|
// Phase 1: Register only USED modules with dependency manager
|
|
console.log('🔍 [Modules] Starting Phase 1 - Module Registration');
|
|
console.log('🔍 [Modules] All discovered modules:', Object.keys(modules));
|
|
console.log('🔍 [Modules] Used modules:', [...usedModules]);
|
|
console.log('🔍 [Modules] Fallback mode:', fallbackMode);
|
|
|
|
Object.entries(modules).forEach(([path, mod]) => {
|
|
const name = path.split('/').slice(-2, -1)[0];
|
|
console.log(`🔍 [Module] Processing: ${name} from ${path}`);
|
|
console.log(`🔍 [Module] Used modules has ${name}:`, usedModules.has(name));
|
|
|
|
if(!fallbackMode && !usedModules.has(name)) {
|
|
console.log(`⏭️ [Module] Skipping unused module: ${name}`);
|
|
return;
|
|
}
|
|
|
|
console.log(`✅ [Module] Registering ${name} with dependency manager`);
|
|
|
|
// Register module definition if provided
|
|
if (typeof mod.definition === 'object') {
|
|
Logger.info(`📋 [Module] Using definition for ${name}:`, mod.definition);
|
|
dependencyManager.register(mod.definition);
|
|
} else {
|
|
// Create default definition for modules without explicit dependencies
|
|
const defaultDef = {
|
|
name,
|
|
version: '1.0.0',
|
|
dependencies: [],
|
|
provides: [],
|
|
priority: 0
|
|
};
|
|
Logger.info(`📋 [Module] Using default definition for ${name}:`, defaultDef);
|
|
dependencyManager.register(defaultDef);
|
|
}
|
|
});
|
|
|
|
// Phase 2: Calculate initialization order
|
|
const initOrder = dependencyManager.calculateInitializationOrder();
|
|
console.log('🔍 [Modules] Phase 2 - Initialization Order:', initOrder);
|
|
|
|
// Phase 3: Initialize modules in dependency order
|
|
for (const name of initOrder) {
|
|
console.log(`🔍 [Module] Phase 3 - Processing ${name} for initialization`);
|
|
console.log(`🔍 [Module] Used modules has ${name}:`, usedModules.has(name));
|
|
console.log(`🔍 [Module] Fallback mode:`, fallbackMode);
|
|
|
|
if(!fallbackMode && !usedModules.has(name)) {
|
|
console.log(`⏭️ [Module] Skipped (not used in DOM): ${name}`);
|
|
continue;
|
|
}
|
|
|
|
const modulePath = Object.keys(modules).find(path =>
|
|
path.split('/').slice(-2, -1)[0] === name
|
|
);
|
|
|
|
console.log(`🔍 [Module] Looking for module path for ${name}, found:`, modulePath);
|
|
|
|
if (!modulePath) {
|
|
console.log(`⛔ [Module] No implementation found for: ${name}`);
|
|
continue;
|
|
}
|
|
|
|
const mod = modules[modulePath];
|
|
const config = moduleConfig[name] || {};
|
|
|
|
console.log(`🔍 [Module] Module ${name} object:`, mod);
|
|
console.log(`🔍 [Module] Config for ${name}:`, config);
|
|
|
|
// Check dependencies before initialization
|
|
const depCheck = dependencyManager.checkDependencies(name);
|
|
console.log(`🔍 [Module] Dependency check for ${name}:`, depCheck);
|
|
|
|
if (!depCheck.satisfied) {
|
|
console.log(`❌ [Module] Cannot initialize ${name}: ${depCheck.reason}`);
|
|
activeModules.set(name, { mod: null, config, error: new Error(depCheck.reason), original: mod });
|
|
continue;
|
|
}
|
|
|
|
console.log(`🔍 [Module] Checking init function for ${name}:`, typeof mod.init, mod.init);
|
|
console.log(`🔍 [Module] Module object keys for ${name}:`, Object.keys(mod));
|
|
console.log(`🔍 [Module] Full module object for ${name}:`, mod);
|
|
|
|
if (typeof mod.init === 'function') {
|
|
try {
|
|
Logger.info(`🚀 [Module] Starting initialization for ${name}`);
|
|
dependencyManager.markInitializing(name);
|
|
|
|
// Create scoped state manager for module
|
|
const scopedState = stateManager.createScope(name);
|
|
|
|
// Wrap module with error boundary
|
|
const protectedMod = moduleErrorBoundary.wrapModule(mod, name);
|
|
|
|
// Initialize module with config and state
|
|
await protectedMod.init(config, scopedState);
|
|
|
|
dependencyManager.markInitialized(name);
|
|
activeModules.set(name, {
|
|
mod: protectedMod,
|
|
config,
|
|
state: scopedState,
|
|
original: mod
|
|
});
|
|
Logger.info(`✅ [Module] Initialized: ${name}`);
|
|
} catch (error) {
|
|
Logger.error(`❌ [Module] Failed to initialize ${name}:`, error);
|
|
activeModules.set(name, { mod: null, config, error, original: mod });
|
|
}
|
|
} else {
|
|
Logger.warn(`⛔ [Module] No init() in ${name} - typeof:`, typeof mod.init);
|
|
Logger.warn(`⛔ [Module] Available properties:`, Object.getOwnPropertyNames(mod));
|
|
}
|
|
}
|
|
|
|
if (fallbackMode) {
|
|
Logger.info('⚠️ [Module] No data-module usage detected, fallback to full init mode');
|
|
}
|
|
}
|
|
|
|
export function destroyModules() {
|
|
for (const [name, { mod, state }] of activeModules.entries()) {
|
|
if (mod && typeof mod.destroy === 'function') {
|
|
try {
|
|
mod.destroy();
|
|
Logger.info(`🧹 [Module] Destroyed: ${name}`);
|
|
} catch (error) {
|
|
Logger.error(`❌ [Module] Failed to destroy ${name}:`, error);
|
|
}
|
|
}
|
|
|
|
// Clean up state subscriptions
|
|
if (state && typeof state.cleanup === 'function') {
|
|
state.cleanup();
|
|
}
|
|
}
|
|
activeModules.clear();
|
|
moduleErrorBoundary.reset();
|
|
stateManager.reset();
|
|
dependencyManager.reset();
|
|
}
|
|
|
|
/**
|
|
* Gets health status of all active modules
|
|
* @returns {Object} Module health report
|
|
*/
|
|
export function getModuleHealth() {
|
|
const health = {
|
|
total: activeModules.size,
|
|
active: 0,
|
|
failed: 0,
|
|
modules: {},
|
|
errorBoundary: moduleErrorBoundary.getHealthStatus()
|
|
};
|
|
|
|
for (const [name, { mod, error }] of activeModules.entries()) {
|
|
if (error) {
|
|
health.failed++;
|
|
health.modules[name] = { status: 'failed', error: error.message };
|
|
} else if (mod) {
|
|
health.active++;
|
|
health.modules[name] = { status: 'active' };
|
|
} else {
|
|
health.modules[name] = { status: 'unknown' };
|
|
}
|
|
}
|
|
|
|
return health;
|
|
}
|
|
|
|
// Debug function - access via console
|
|
if (typeof window !== 'undefined') {
|
|
window.moduleHealth = getModuleHealth;
|
|
window.activeModules = activeModules;
|
|
}
|