mcp-quiz-server
Version:
🧠 AI-Powered Quiz Management via Model Context Protocol (MCP) - Create, manage, and take quizzes directly from VS Code, Claude, and other AI agents.
268 lines (219 loc) • 8.36 kB
text/typescript
/**
* @moduleName: Application Initializer - Bootstrap & Startup Service
* @version: 1.0.0
* @since: 2025-07-25
* @lastUpdated: 2025-07-27
* @projectSummary: Enhanced MCP Quiz Server - Application startup orchestration and component initialization
* @techStack: TypeScript, Async/Await, Service Composition, DOM Ready Events
* @dependency: SettingsManager, DemoConfigService, AppStore, DOM initialization
* @interModuleDependency: All core services, components, and store initialization
* @requirementsTraceability:
* {@link Requirements.REQ_ARCH_001} (System Bootstrap)
* {@link Requirements.REQ_INTEGRATION_001} (Component Orchestration)
* @briefDescription: Static service coordinating complete application startup with proper dependency order
* @methods: initialize, initializeServices, initializeComponents, loadInitialData
* @contributors: GitHub Copilot, Full Stack Wizard Mega Architect
* @examples:
* - await AppInitializer.initialize() // Complete app startup
* - AppInitializer.isInitialized() // Check initialization state
* @vulnerabilitiesAssessment: Initialization order validation, error boundary during startup, graceful degradation
*/
import { AppStore } from '../store/AppStore';
import { DemoConfigService } from './DemoConfigService';
import { SettingsManager } from './SettingsManager';
/**
* Service for initializing the application with all necessary components
*/
export class AppInitializer {
private static initialized = false;
/**
* Initialize the complete application
*/
static async initialize(): Promise<void> {
if (this.initialized) {
console.log('⚡ Application already initialized');
return;
}
console.log('🚀 Initializing Quiz Platform application...');
try {
// Initialize settings management
await this.initializeSettings();
// Initialize demo configuration system
await this.initializeDemoConfigs();
// Initialize application state
await this.initializeAppState();
// Set up error handling
this.setupGlobalErrorHandling();
// Set up performance monitoring
this.setupPerformanceMonitoring();
this.initialized = true;
console.log('✅ Quiz Platform application initialized successfully');
// Emit initialization complete event
window.dispatchEvent(new CustomEvent('app:initialized'));
} catch (error) {
console.error('❌ Failed to initialize application:', error);
throw error;
}
}
/**
* Initialize settings management system
*/
private static async initializeSettings(): Promise<void> {
console.log('⚙️ Initializing settings management...');
// Initialize settings manager (singleton)
const settingsManager = SettingsManager.getInstance();
// Subscribe to settings changes for app-wide updates
settingsManager.subscribe(settings => {
console.log('⚙️ Settings updated globally:', settings);
// Apply theme changes
if (settings.ui.theme) {
document.documentElement.setAttribute('data-theme', settings.ui.theme);
}
// Apply reduced motion preference
if (settings.ui.reducedMotion) {
document.documentElement.style.setProperty('--animation-duration', '0ms');
} else {
document.documentElement.style.removeProperty('--animation-duration');
}
// Apply font size preference
document.documentElement.setAttribute('data-font-size', settings.ui.fontSize);
});
console.log('✅ Settings management initialized');
}
/**
* Initialize demo configuration system
*/
private static async initializeDemoConfigs(): Promise<void> {
console.log('🎬 Initializing demo configuration system...');
await DemoConfigService.initialize();
console.log('✅ Demo configuration system initialized');
}
/**
* Initialize application state management
*/
private static async initializeAppState(): Promise<void> {
console.log('🏪 Initializing application state...');
// Get app store instance (singleton)
const appStore = AppStore.getInstance();
// Subscribe to critical state changes
appStore.subscribe(state => {
// Update submit bar visibility when relevant state changes
if (state.currentQuiz || state.ui.showWelcome || state.ui.showResults) {
appStore.updateSubmitBarVisibility();
}
});
console.log('✅ Application state initialized');
}
/**
* Set up global error handling
*/
private static setupGlobalErrorHandling(): void {
console.log('🛡️ Setting up global error handling...');
window.addEventListener('error', event => {
console.error('🚨 Global error:', event.error);
// Show user-friendly error message for critical errors
if (event.error?.name === 'ChunkLoadError') {
this.showReloadPrompt('A new version is available. Please reload the page.');
}
});
window.addEventListener('unhandledrejection', event => {
console.error('🚨 Unhandled promise rejection:', event.reason);
// Prevent default browser error handling for known recoverable errors
if (event.reason?.name === 'NetworkError') {
event.preventDefault();
console.warn('⚠️ Network error handled gracefully');
}
});
console.log('✅ Global error handling set up');
}
/**
* Set up performance monitoring
*/
private static setupPerformanceMonitoring(): void {
console.log('📊 Setting up performance monitoring...');
// Monitor long tasks
if ('PerformanceObserver' in window) {
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
if (entry.duration > 50) {
console.warn('⚠️ Long task detected:', entry.duration, 'ms');
}
});
});
try {
observer.observe({ entryTypes: ['longtask'] });
} catch (error) {
console.warn('Performance monitoring not fully supported:', error);
}
}
// Monitor page load performance
window.addEventListener('load', () => {
setTimeout(() => {
const navigation = performance.getEntriesByType(
'navigation'
)[0] as PerformanceNavigationTiming;
if (navigation) {
const loadTime = navigation.loadEventEnd - navigation.loadEventStart;
console.log(`📊 Page load time: ${loadTime}ms`);
if (loadTime > 3000) {
console.warn('⚠️ Slow page load detected');
}
}
}, 0);
});
console.log('✅ Performance monitoring set up');
}
/**
* Show reload prompt to user
*/
private static showReloadPrompt(message: string): void {
const shouldReload = confirm(`${message}\n\nReload now?`);
if (shouldReload) {
window.location.reload();
}
}
/**
* Get initialization status
*/
static isInitialized(): boolean {
return this.initialized;
}
/**
* Reset initialization (for testing)
*/
static reset(): void {
this.initialized = false;
console.log('🔄 Application initialization reset');
}
/**
* Initialize with custom configuration
*/
static async initializeWithConfig(
config: {
skipDemos?: boolean;
skipErrorHandling?: boolean;
skipPerformanceMonitoring?: boolean;
} = {}
): Promise<void> {
if (this.initialized) return;
console.log('🚀 Initializing with custom configuration...', config);
try {
await this.initializeSettings();
if (!config.skipDemos) {
await this.initializeDemoConfigs();
}
await this.initializeAppState();
if (!config.skipErrorHandling) {
this.setupGlobalErrorHandling();
}
if (!config.skipPerformanceMonitoring) {
this.setupPerformanceMonitoring();
}
this.initialized = true;
console.log('✅ Custom initialization complete');
} catch (error) {
console.error('❌ Custom initialization failed:', error);
throw error;
}
}
}