{"version":3,"sources":["../src/dev-server/index.ts","../src/dev-server/process-runner.ts","../src/dev-server/dev-server.ts","../src/dev-server/proxy.ts"],"sourcesContent":["export * from './dev-server';\nexport * from './process-runner';\nexport * from './proxy';\n","import { spawn, ChildProcess } from 'child_process';\nimport { logger } from '../core/logger';\nimport * as pc from 'picocolors';\n\nexport interface ProcessConfig {\n    name: string;\n    command: string;\n    args: string[];\n    cwd: string;\n    color: 'cyan' | 'green' | 'yellow' | 'magenta' | 'blue';\n    env?: Record<string, string>;\n}\n\n/**\n * Run multiple processes concurrently with colored output\n */\nexport class ProcessRunner {\n    private processes: Map<string, ChildProcess> = new Map();\n    private colors = {\n        cyan: pc.cyan,\n        green: pc.green,\n        yellow: pc.yellow,\n        magenta: pc.magenta,\n        blue: pc.blue,\n    };\n\n    async run(configs: ProcessConfig[]): Promise<void> {\n        logger.info('🚀 Starting development servers...\\n');\n\n        for (const config of configs) {\n            this.startProcess(config);\n        }\n\n        // Handle graceful shutdown\n        process.on('SIGINT', () => this.stopAll());\n        process.on('SIGTERM', () => this.stopAll());\n    }\n\n    private startProcess(config: ProcessConfig): void {\n        const { name, command, args, cwd, color, env } = config;\n\n        const colorFn = this.colors[color];\n        const prefix = colorFn(`[${name}]`);\n\n        logger.info(`${prefix} Starting...`);\n\n        const proc = spawn(command, args, {\n            cwd,\n            stdio: 'pipe',\n            shell: true,\n            env: { ...process.env, ...env },\n        });\n\n        this.processes.set(name, proc);\n\n        // Handle stdout\n        proc.stdout?.on('data', (data) => {\n            const lines = data.toString().split('\\n').filter((l: string) => l.trim());\n            lines.forEach((line: string) => {\n                console.log(`${prefix} ${line}`);\n            });\n        });\n\n        // Handle stderr\n        proc.stderr?.on('data', (data) => {\n            const lines = data.toString().split('\\n').filter((l: string) => l.trim());\n            lines.forEach((line: string) => {\n                console.error(`${prefix} ${pc.red(line)}`);\n            });\n        });\n\n        // Handle exit\n        proc.on('exit', (code) => {\n            if (code !== 0 && code !== null) {\n                logger.error(`${prefix} Exited with code ${code}`);\n            }\n            this.processes.delete(name);\n        });\n\n        // Handle errors\n        proc.on('error', (error) => {\n            logger.error(`${prefix} Error:`, error.message);\n        });\n    }\n\n    stopAll(): void {\n        logger.info('\\n🛑 Stopping all processes...');\n\n        for (const [name, proc] of this.processes.entries()) {\n            logger.info(`Stopping ${name}...`);\n            proc.kill('SIGTERM');\n        }\n\n        setTimeout(() => {\n            process.exit(0);\n        }, 1000);\n    }\n\n    isRunning(name: string): boolean {\n        return this.processes.has(name);\n    }\n}\n","import { ProcessRunner, ProcessConfig } from './process-runner';\nimport { logger } from '../core/logger';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport interface DevServerConfig {\n    apiPath: string;\n    webPath: string;\n    webPort?: number;\n    apiPort?: number;\n    useProxy?: boolean;\n}\n\n/**\n * Unified development server for Fusion projects\n */\nexport class FusionDevServer {\n    private processRunner: ProcessRunner;\n\n    constructor() {\n        this.processRunner = new ProcessRunner();\n    }\n\n    async start(config: DevServerConfig): Promise<void> {\n        const {\n            apiPath,\n            webPath,\n            webPort = 3000,\n            apiPort = 5050,\n            useProxy = false,\n        } = config;\n\n        if (useProxy) {\n            throw new Error('The legacy dev proxy is disabled because it conflicts with the Next.js port. Use the production runtime for single-port serving.');\n        }\n\n        // Validate paths\n        if (!fs.existsSync(apiPath)) {\n            throw new Error(`API path not found: ${apiPath}`);\n        }\n        if (!fs.existsSync(webPath)) {\n            throw new Error(`Web path not found: ${webPath}`);\n        }\n\n        const processes: ProcessConfig[] = [];\n\n        // Add API server\n        processes.push({\n            name: 'API',\n            command: 'npm',\n            args: ['run', 'start:dev'],\n            cwd: path.resolve(apiPath),\n            color: 'cyan',\n            env: {\n                PORT: apiPort.toString(),\n            },\n        });\n\n        // Add Web server\n        processes.push({\n            name: 'Web',\n            command: 'npm',\n            args: ['run', 'dev', '--', '-p', webPort.toString()],\n            cwd: path.resolve(webPath),\n            color: 'green',\n            env: {\n                NEXT_PUBLIC_API_URL: `http://localhost:${apiPort}`,\n            },\n        });\n\n        // Start processes\n        await this.processRunner.run(processes);\n\n        // Log info\n        logger.info('╔═══════════════════════════════════════╗');\n        logger.info('║   Fusion Development Server Ready    ║');\n        logger.info('╚═══════════════════════════════════════╝\\n');\n        logger.info(`🌐 Web:  http://localhost:${webPort}`);\n        logger.info(`🔌 API:  http://localhost:${apiPort}`);\n        logger.info('\\n');\n    }\n\n    stop(): void {\n        this.processRunner.stopAll();\n    }\n}\n","import http from 'http';\nimport httpProxy from 'http-proxy';\nimport { logger } from '../core/logger';\nimport * as pc from 'picocolors';\n\nexport interface ProxyConfig {\n    port: number;\n    apiTarget: string;\n    apiPrefix: string;\n}\n\n/**\n * Proxy server to forward API requests from Next.js to NestJS\n */\nexport class ProxyServer {\n    private server: http.Server | null = null;\n    private proxy: httpProxy | null = null;\n\n    async start(config: ProxyConfig): Promise<void> {\n        const { port, apiTarget, apiPrefix } = config;\n\n        this.proxy = httpProxy.createProxyServer({\n            target: apiTarget,\n            changeOrigin: true,\n            ws: true, // WebSocket support\n        });\n\n        // Handle proxy errors\n        this.proxy.on('error', (err, req, res) => {\n            logger.error('Proxy error:', err.message);\n            if (res && 'headersSent' in res && !(res as any).headersSent) {\n                (res as http.ServerResponse).writeHead(502, { 'Content-Type': 'text/plain' });\n                (res as http.ServerResponse).end('Bad Gateway - API server unavailable');\n            }\n        });\n\n        this.server = http.createServer((req, res) => {\n            // Check if request is for API\n            if (req.url?.startsWith(apiPrefix)) {\n                // Remove prefix before forwarding\n                const newUrl = req.url.substring(apiPrefix.length) || '/';\n                req.url = newUrl;\n\n                logger.info(pc.gray(`→ ${req.method} ${apiPrefix}${newUrl}`));\n                this.proxy!.web(req, res);\n            } else {\n                // Not an API request - should not happen\n                res.writeHead(404);\n                res.end('Not Found');\n            }\n        });\n\n        // Handle WebSocket upgrade\n        this.server.on('upgrade', (req, socket, head) => {\n            if (req.url?.startsWith(apiPrefix)) {\n                const newUrl = req.url.substring(apiPrefix.length) || '/';\n                req.url = newUrl;\n                this.proxy!.ws(req, socket, head);\n            }\n        });\n\n        return new Promise((resolve) => {\n            this.server!.listen(port, () => {\n                logger.success(`✅ Proxy server running on port ${port}`);\n                logger.info(`   Forwarding ${pc.cyan(apiPrefix + '/*')} → ${pc.cyan(apiTarget)}\\n`);\n                resolve();\n            });\n        });\n    }\n\n    stop(): void {\n        if (this.server) {\n            this.server.close();\n            this.server = null;\n        }\n        if (this.proxy) {\n            this.proxy.close();\n            this.proxy = null;\n        }\n    }\n}\n"],"mappings":"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","names":["spawn","pc","ProcessRunner","processes","Map","colors","cyan","green","yellow","magenta","blue","run","configs","logger","info","config","startProcess","process","on","stopAll","name","command","args","cwd","color","env","colorFn","prefix","proc","spawn","stdio","shell","set","stdout","data","lines","toString","split","filter","l","trim","forEach","line","console","log","stderr","error","red","code","delete","message","entries","kill","setTimeout","exit","isRunning","has","path","fs","FusionDevServer","processRunner","ProcessRunner","start","config","apiPath","webPath","webPort","apiPort","useProxy","Error","existsSync","processes","push","name","command","args","cwd","resolve","color","env","PORT","toString","NEXT_PUBLIC_API_URL","run","logger","info","stop","stopAll","http","httpProxy","pc","ProxyServer","server","proxy","start","config","port","apiTarget","apiPrefix","httpProxy","createProxyServer","target","changeOrigin","ws","on","err","req","res","logger","error","message","headersSent","writeHead","end","http","createServer","url","startsWith","newUrl","substring","length","info","gray","method","web","socket","head","Promise","resolve","listen","success","cyan","stop","close"]}