UNPKG

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.

255 lines (254 loc) 10.2 kB
"use strict"; /** * @fileoverview Setup Orchestrator - Coordinates the entire setup process * @version 1.0.0 * @since 2025-07-31 * @module SetupOrchestrator * @description Coordinates setup wizard execution and integration with server startup * @contributors Claude Code Agent */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SetupOrchestrator = void 0; const AsciiAnimations_1 = __importDefault(require("./AsciiAnimations")); const MinimalSetupWizard_1 = require("./MinimalSetupWizard"); class SetupOrchestrator { constructor(config = {}) { this.config = { mode: 'interactive', force: false, skipValidation: false, ...config, }; // Initialize setup wizard this.wizard = new MinimalSetupWizard_1.MinimalSetupWizard(); } /** * Check if setup is required based on configuration and current state */ async isSetupRequired() { if (this.config.force) { return true; } const isComplete = await this.wizard.isSetupComplete(); return !isComplete; } /** * Run setup process and return integration result */ async runSetup() { try { console.log('🎯 MCP Quiz Server Setup Starting...\n'); // Check if setup is needed const setupRequired = await this.isSetupRequired(); if (!setupRequired) { return { setupRan: false, result: null, integrationSuccess: true, message: 'Setup already completed, proceeding with server startup', }; } // Run the setup wizard const setupResult = await this.wizard.runIfNeeded(); if (!setupResult) { return { setupRan: false, result: null, integrationSuccess: true, message: 'No setup required', }; } // Validate setup result await this.validateSetupResult(setupResult); return { setupRan: true, result: setupResult, integrationSuccess: true, message: 'Setup completed successfully, server ready to start', }; } catch (error) { console.error('❌ Setup failed:', error.message); AsciiAnimations_1.default.displayError(`Setup orchestration failed: ${error.message}`); return { setupRan: false, result: null, integrationSuccess: false, message: `Setup failed: ${error.message}`, }; } } /** * Validate that setup result is complete and valid */ async validateSetupResult(result) { if (this.config.skipValidation) { return; } // Validate admin configuration if (!result.admin.username || !result.admin.password) { throw new Error('Invalid admin configuration'); } // Validate server configuration if (!result.server.port || result.server.port < 1024 || result.server.port > 65535) { throw new Error('Invalid server port configuration'); } // Validate security configuration if (!result.security.jwtSecret || result.security.jwtSecret.length < 32) { throw new Error('Invalid security configuration'); } // Validate features configuration if (!result.features.userAuth) { console.warn('⚠️ Warning: User authentication is disabled'); } console.log('✅ Setup validation passed'); } /** * Get configuration object suitable for server integration */ static createServerConfig(setupResult) { return { server: { port: setupResult.server.port, host: setupResult.server.host, environment: setupResult.server.environment, }, features: setupResult.features, security: { jwtSecret: setupResult.security.jwtSecret, sessionTimeout: setupResult.security.sessionTimeout, maxSessions: setupResult.security.maxSessions, enableRotation: setupResult.security.enableRotation, }, admin: { username: setupResult.admin.username, email: setupResult.admin.email, // Note: password hash should be computed separately for security passwordHash: MinimalSetupWizard_1.MinimalSetupWizard.hashPassword(setupResult.admin.password), }, setup: { completed: true, timestamp: setupResult.setupTimestamp, version: '1.0.0', }, }; } /** * Run silent setup with minimal prompts (for CI/CD) */ async runSilentSetup(defaults = {}) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; console.log('🤖 Running silent setup with defaults...'); try { const setupResult = { admin: { username: ((_a = defaults.admin) === null || _a === void 0 ? void 0 : _a.username) || 'admin', password: ((_b = defaults.admin) === null || _b === void 0 ? void 0 : _b.password) || MinimalSetupWizard_1.MinimalSetupWizard.generateJenkinsStylePassword(), email: ((_c = defaults.admin) === null || _c === void 0 ? void 0 : _c.email) || 'admin@localhost', }, server: { port: ((_d = defaults.server) === null || _d === void 0 ? void 0 : _d.port) || 3000, host: ((_e = defaults.server) === null || _e === void 0 ? void 0 : _e.host) || '0.0.0.0', environment: ((_f = defaults.server) === null || _f === void 0 ? void 0 : _f.environment) || 'production', }, security: { jwtSecret: ((_g = defaults.security) === null || _g === void 0 ? void 0 : _g.jwtSecret) || require('crypto').randomBytes(64).toString('hex'), sessionTimeout: ((_h = defaults.security) === null || _h === void 0 ? void 0 : _h.sessionTimeout) || 30, maxSessions: ((_j = defaults.security) === null || _j === void 0 ? void 0 : _j.maxSessions) || 3, enableRotation: ((_k = defaults.security) === null || _k === void 0 ? void 0 : _k.enableRotation) || true, }, features: defaults.features || { userAuth: true, cloudSync: false, multiUser: false, analytics: false, localQuizzes: true, timerFeature: true, mcpProtocol: true, }, setupTimestamp: new Date(), }; // Save the setup result using the wizard's save method await this.wizard.saveSetupResult(setupResult); console.log('✅ Silent setup completed'); console.log(`📋 Admin credentials: ${setupResult.admin.username} / ${setupResult.admin.password}`); console.log('📁 Configuration saved to .setup/ directory'); return { setupRan: true, result: setupResult, integrationSuccess: true, message: 'Silent setup completed successfully', }; } catch (error) { return { setupRan: false, result: null, integrationSuccess: false, message: `Silent setup failed: ${error.message}`, }; } } /** * Reset setup (for development/testing) */ async resetSetup() { console.log('🔄 Resetting setup...'); const fs = require('fs'); const path = require('path'); const setupDir = path.join(process.cwd(), '.setup'); const configDir = path.join(process.cwd(), 'config'); try { // Remove setup files const setupCompleteFile = path.join(setupDir, 'setup-complete.json'); const passwordFile = path.join(setupDir, 'initial-admin-password.txt'); const configFile = path.join(configDir, 'setup-config.json'); [setupCompleteFile, passwordFile, configFile].forEach(file => { if (fs.existsSync(file)) { fs.unlinkSync(file); console.log(`✅ Removed: ${file}`); } }); console.log('🔄 Setup reset completed'); } catch (error) { console.error('❌ Setup reset failed:', error.message); throw error; } } /** * Get setup status for health checks */ async getSetupStatus() { const setupComplete = await this.wizard.isSetupComplete(); if (!setupComplete) { return { setupComplete: false, configExists: false, }; } try { const fs = require('fs'); const path = require('path'); const setupFile = path.join(process.cwd(), '.setup', 'setup-complete.json'); const configFile = path.join(process.cwd(), 'config', 'setup-config.json'); const setupData = JSON.parse(fs.readFileSync(setupFile, 'utf8')); return { setupComplete: true, configExists: fs.existsSync(configFile), timestamp: setupData.timestamp, version: setupData.version, }; } catch (_a) { return { setupComplete: false, configExists: false, }; } } } exports.SetupOrchestrator = SetupOrchestrator;