import { spawn } from 'node:child_process' const host = '127.0.0.1' const port = '43117' let printedLinks = false let collectedLines = [] const maxCollectedLines = 400 const nuxtProcess = spawn('nuxt', [ 'dev', '--dotenv', '.env.development', '--host', host, '--port', port ], { shell: true, stdio: ['inherit', 'pipe', 'pipe'] }) /** * 개발 서버 링크 출력 * @returns {void} */ const printDevLinks = () => { const origin = `http://${host}:${port}` console.log('') console.log('sori.studio 개발 서버') console.log(`- 개발 서버: ${origin}`) console.log(`- Admin: ${origin}/admin`) console.log(`- Tailwind Viewer: ${origin}/_tailwind/`) console.log('') } /** * Nuxt 로그 처리 * @param {Buffer} chunk - 로그 버퍼 * @returns {void} */ const handleNuxtLog = (chunk) => { const text = chunk.toString() for (const line of text.split('\n')) { if (line) { collectedLines.push(line) if (collectedLines.length > maxCollectedLines) { collectedLines = collectedLines.slice(-maxCollectedLines) } } const localMatch = line.match(/Local:\s+(https?:\/\/[^\s]+)/) if (localMatch && !printedLinks) { printedLinks = true printDevLinks() continue } if (/(^|\s)(error:|warn:|warning:|failed|fatal|eaddrinuse|cannot|emfile|epipe|eacces|eperm)\b/i.test(line) || /\bat\s.+\(.+\)/.test(line) || /Object\.\$resolve/.test(line)) { console.log(line) } } } nuxtProcess.stdout.on('data', handleNuxtLog) nuxtProcess.stderr.on('data', handleNuxtLog) nuxtProcess.on('close', (code) => { if (code && collectedLines.length) { console.log('') console.log('--- Nuxt 종료 로그 (최근) ---') for (const line of collectedLines) { console.log(line) } console.log('--- 종료 로그 끝 ---') console.log('') } process.exit(code || 0) }) process.on('SIGINT', () => { nuxtProcess.kill('SIGINT') }) process.on('SIGTERM', () => { nuxtProcess.kill('SIGTERM') })