/** * Step: service — Generate and load service manager config. * Replaces 08-setup-service.sh * * Supports the unified EJClaw service: * - ejclaw — always installed */ import { execSync } from 'child_process'; import fs from 'fs'; import os from 'os'; import path from 'path'; import { logger } from '../src/logger.js'; import { getPlatform, getNodePath, getServiceManager } from './platform.js'; import { detectLegacyServiceIssues, formatLegacyServiceFailureMessage, } from './legacy-service-guard.js'; import { getServiceDefs } from './service-defs.js'; import { setupLaunchd, setupLinux } from './service-installers.js'; import { emitStatus } from './status.js'; /* ------------------------------------------------------------------ */ /* Entry point */ /* ------------------------------------------------------------------ */ export async function run(_args: string[]): Promise { const projectRoot = process.cwd(); const platform = getPlatform(); const nodePath = getNodePath(); const homeDir = os.homedir(); const serviceManager = getServiceManager(); logger.info({ platform, nodePath, projectRoot }, 'Setting up service'); const legacyServiceIssues = detectLegacyServiceIssues( projectRoot, serviceManager, homeDir, ); if (legacyServiceIssues.length > 0) { const errorMessage = formatLegacyServiceFailureMessage({ projectRoot, serviceManager, homeDir, services: legacyServiceIssues, }); logger.error( { legacyServiceIssues, serviceManager }, 'Legacy multi-service install detected during setup', ); emitStatus('SETUP_SERVICE', { SERVICE_TYPE: serviceManager, NODE_PATH: nodePath, PROJECT_PATH: projectRoot, STATUS: 'failed', ERROR: 'legacy_services_detected', LEGACY_SERVICES: legacyServiceIssues .map((service) => `${service.name}:${service.status}`) .join(','), LOG: 'logs/setup.log', }); console.error(errorMessage); process.exit(1); } // Build first logger.info('Building TypeScript'); try { execSync('bun run build', { cwd: projectRoot, stdio: ['ignore', 'pipe', 'pipe'], }); logger.info('Build succeeded'); } catch { logger.error('Build failed'); emitStatus('SETUP_SERVICE', { SERVICE_TYPE: 'unknown', NODE_PATH: nodePath, PROJECT_PATH: projectRoot, STATUS: 'failed', ERROR: 'build_failed', LOG: 'logs/setup.log', }); process.exit(1); } fs.mkdirSync(path.join(projectRoot, 'logs'), { recursive: true }); const serviceDefs = getServiceDefs(projectRoot); if (platform === 'macos') { for (const def of serviceDefs) { setupLaunchd(def, projectRoot, nodePath, homeDir); } } else if (platform === 'linux') { setupLinux(serviceDefs, projectRoot, nodePath, homeDir); } else { emitStatus('SETUP_SERVICE', { SERVICE_TYPE: 'unknown', NODE_PATH: nodePath, PROJECT_PATH: projectRoot, STATUS: 'failed', ERROR: 'unsupported_platform', LOG: 'logs/setup.log', }); process.exit(1); } }