#!/usr/bin/env node const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const COLORS = { reset: '\x1b[0m', bright: '\x1b[1m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', }; function log(message, color = COLORS.reset) { console.log(`${color}${message}${COLORS.reset}`); } function logStep(step, message) { console.log(`\n${COLORS.cyan}[${step}]${COLORS.reset} ${message}`); } function logSuccess(message) { console.log(`${COLORS.green}✅${COLORS.reset} ${message}`); } function logError(message) { console.log(`${COLORS.red}❌${COLORS.reset} ${message}`); } function logWarning(message) { console.log(`${COLORS.yellow}⚠️${COLORS.reset} ${message}`); } function executeCommand(command, description) { try { logStep('EXEC', description); const result = execSync(command, { encoding: 'utf8', stdio: 'inherit' }); logSuccess(description); return true; } catch (error) { logError(`${description} failed: ${error.message}`); return false; } } function checkFileExists(filePath, description) { try { const exists = fs.existsSync(filePath); if (exists) { logSuccess(`${description} exists`); } else { logError(`${description} not found`); } return exists; } } function checkDirectoryStructure() { logStep(1, 'Checking Directory Structure'); const requiredDirectories = [ 'server/src', 'dashboard/src', 'client/src', 'extension/src', 'docs', '.trae/rules' ]; let allExist = true; requiredDirectories.forEach(dir => { const exists = checkFileExists(dir, `Directory ${dir}`); if (!exists) allExist = false; }); return allExist; } function checkConfigurationFiles() { logStep(2, 'Checking Configuration Files'); const requiredConfigs = [ 'server/package.json', 'dashboard/package.json', 'client/package.json', 'extension/package.json', 'server/tsconfig.json', 'dashboard/tsconfig.json', 'server/.eslintrc.js' ]; let allExist = true; requiredConfigs.forEach(config => { const exists = checkFileExists(config, `Config ${config}`); if (!exists) allExist = false; }); return allExist; } function checkDatabaseSchema() { logStep(3, 'Checking Database Schema'); const schemaFile = 'server/src/database/DatabaseSchema.ts'; const exists = checkFileExists(schemaFile, 'Database Schema'); if (exists) { const schema = require(path.join(process.cwd(), schemaFile)); const requiredTables = [ 'cf_product', 'cf_order', 'cf_customer', 'cf_tenant', 'cf_shop', 'cf_invoice', 'cf_settlement' ]; let allTablesExist = true; requiredTables.forEach(table => { if (schema.tables && schema.tables[table]) { logSuccess(`Table ${table} exists in schema`); } else { logError(`Table ${table} missing from schema`); allTablesExist = false; } }); return allTablesExist; } return false; } function checkCoreServices() { logStep(4, 'Checking Core Services'); const requiredServices = [ 'server/src/core/auth/RBACEngine.ts', 'server/src/core/cache/RedisService.ts', 'server/src/core/engine/CoreEngineService.ts', 'server/src/core/runtime/DomainEventBus.ts', 'server/src/core/telemetry/AlertService.ts' ]; let allExist = true; requiredServices.forEach(service => { const exists = checkFileExists(service, `Service ${service}`); if (!exists) allExist = false; }); return allExist; } function checkAPIControllers() { logStep(5, 'Checking API Controllers'); const requiredControllers = [ 'server/src/api/controllers/AuthController.ts', 'server/src/api/controllers/ProductController.ts', 'server/src/api/controllers/OrderController.ts', 'server/src/api/controllers/PricingController.ts', 'server/src/api/controllers/BillingController.ts', 'server/src/api/controllers/AnalyticsController.ts' ]; let allExist = true; requiredControllers.forEach(controller => { const exists = checkFileExists(controller, `Controller ${controller}`); if (!exists) allExist = false; }); return allExist; } function checkFrontendPages() { logStep(6, 'Checking Frontend Pages'); const requiredPages = [ 'dashboard/src/pages/DashboardPage.tsx', 'dashboard/src/pages/Product/index.tsx', 'dashboard/src/pages/Orders/index.tsx', 'dashboard/src/pages/TaskCenter/index.tsx', 'dashboard/src/pages/Compliance/index.tsx', 'dashboard/src/pages/Settings/SystemSettings.tsx', 'dashboard/src/pages/Analytics/index.tsx', 'dashboard/src/pages/Reports/index.tsx' ]; let allExist = true; requiredPages.forEach(page => { const exists = checkFileExists(page, `Page ${page}`); if (!exists) allExist = false; }); return allExist; } function checkDocumentation() { logStep(7, 'Checking Documentation'); const requiredDocs = [ 'docs/00_Business/Business_Blueprint.md', 'docs/00_Business/Business_ClosedLoops.md', 'docs/01_Architecture/System_Architecture.md', 'docs/01_Architecture/SERVICE_MAP.md', 'docs/01_Architecture/STATE_MACHINE.md', 'docs/02_Backend/API_Specs/Data_API_Specs.md', 'docs/03_Frontend/Frontend_Design.md', 'docs/05_AI/AI_Strategy.md', '.trae/rules/project-specific-rules.md' ]; let allExist = true; requiredDocs.forEach(doc => { const exists = checkFileExists(doc, `Documentation ${doc}`); if (!exists) allExist = false; }); return allExist; } function checkSecurityConfiguration() { logStep(8, 'Checking Security Configuration'); const securityFiles = [ 'server/src/core/guards/rbac.guard.ts', 'server/src/core/guards/service.guard.ts', 'server/src/core/guards/sla.guard.ts', 'server/src/core/security/SecurityProfilingService.ts', 'server/src/core/security/DataComplianceService.ts' ]; let allExist = true; securityFiles.forEach(file => { const exists = checkFileExists(file, `Security ${file}`); if (!exists) allExist = false; }); return allExist; } function checkPluginSystem() { logStep(9, 'Checking Plugin System'); const pluginFiles = [ 'server/src/core/runtime/PluginManager.ts', 'server/src/core/connectors/AmazonConnector.ts', 'server/src/core/connectors/eBayConnector.ts', 'server/src/core/connectors/ShopifyConnector.ts', 'extension/src/background/DOMParser.ts', 'extension/src/background/FingerprintManager.ts' ]; let allExist = true; pluginFiles.forEach(file => { const exists = checkFileExists(file, `Plugin ${file}`); if (!exists) allExist = false; }); return allExist; } function checkTestingInfrastructure() { logStep(10, 'Checking Testing Infrastructure'); const testFiles = [ 'server/src/tests/system-integration.test.ts', 'dashboard/src/tests/frontend.functional.test.ts', 'dashboard/src/tests/frontend.integration.test.ts' ]; let allExist = true; testFiles.forEach(file => { const exists = checkFileExists(file, `Test ${file}`); if (!exists) allExist = false; }); return allExist; } function checkRuntimeComponents() { logStep(11, 'Checking Runtime Components'); const runtimeFiles = [ 'server/src/core/runtime/DomainEventBus.ts', 'server/src/core/scheduler/AdaptiveScheduler.ts', 'server/src/core/telemetry/GlobalTracingService.ts', 'server/src/core/workers/WorkerHub.ts' ]; let allExist = true; runtimeFiles.forEach(file => { const exists = checkFileExists(file, `Runtime ${file}`); if (!exists) allExist = false; }); return allExist; } function checkDeploymentReadiness() { logStep(12, 'Checking Deployment Readiness'); const deploymentFiles = [ '.github/workflows/ci-cd.yml', 'scripts/db-init.sql', 'scripts/env-config.sh', 'server/package.json', 'dashboard/package.json' ]; let allExist = true; deploymentFiles.forEach(file => { const exists = checkFileExists(file, `Deployment ${file}`); if (!exists) allExist = false; }); return allExist; } function generateDeploymentReport() { logStep(13, 'Generating Deployment Report'); const report = { timestamp: new Date().toISOString(), system: { name: 'Crawlful Hub', version: '1.0.0', environment: process.env.NODE_ENV || 'development' }, checks: { directoryStructure: checkDirectoryStructure(), configurationFiles: checkConfigurationFiles(), databaseSchema: checkDatabaseSchema(), coreServices: checkCoreServices(), apiControllers: checkAPIControllers(), frontendPages: checkFrontendPages(), documentation: checkDocumentation(), securityConfiguration: checkSecurityConfiguration(), pluginSystem: checkPluginSystem(), testingInfrastructure: checkTestingInfrastructure(), runtimeComponents: checkRuntimeComponents(), deploymentReadiness: checkDeploymentReadiness() }, summary: { totalChecks: 12, passedChecks: 0, failedChecks: 0, readiness: 'unknown' } }; report.summary.passedChecks = Object.values(report.checks).filter(Boolean).length; report.summary.failedChecks = Object.values(report.checks).filter(val => !val).length; report.summary.readiness = report.summary.passedChecks === report.summary.totalChecks ? 'READY' : 'NOT_READY'; const reportPath = path.join(process.cwd(), 'deployment-report.json'); fs.writeFileSync(reportPath, JSON.stringify(report, null, 2)); logSuccess(`Deployment report generated: ${reportPath}`); if (report.summary.readiness === 'READY') { logSuccess('🚀 System is READY for deployment!'); } else { logWarning(`⚠️ System is NOT ready for deployment. ${report.summary.failedChecks} checks failed.`); } return report.summary.readiness === 'READY'; } function main() { console.log(`${COLORS.bright}${COLORS.cyan} ╔════════════════════════════════════════════════════════════╗ ║ ║ ║ CRAWLFUL HUB - SYSTEM DEPLOYMENT CHECKER ║ ║ ║ ║ Comprehensive System Validation & Deployment Prep ║ ║ ║ ╚════════════════════════════════════════════════════════════╝ ${COLORS.reset}`); logStep('START', 'Starting comprehensive system validation...\n'); const isReady = generateDeploymentReport(); console.log(`\n${COLORS.bright}${COLORS.cyan} ════════════════════════════════════════════════════════════ VALIDATION COMPLETE ════════════════════════════════════════════════════════════ ${COLORS.reset}`); process.exit(isReady ? 0 : 1); } if (require.main === module) { main(); } module.exports = { checkDirectoryStructure, checkConfigurationFiles, checkDatabaseSchema, checkCoreServices, checkAPIControllers, checkFrontendPages, checkDocumentation, checkSecurityConfiguration, checkPluginSystem, checkTestingInfrastructure, checkRuntimeComponents, checkDeploymentReadiness, generateDeploymentReport };