/* eslint-disable no-console */ import { spawn } from 'child_process' import path from 'path' import fs, { existsSync } from 'fs-extra' import { Command } from '@oclif/command' import chokidar from 'chokidar' import chalk from 'chalk' import { dotSalesAppDir, salesAppMonorepoSrcDir, webpackBinPath, } from '../utils/directory' import { createDotSalesAppDir } from '../utils/createDotSalesAppDir' const defaultIgnored = [ '.DS_Store', 'README.md', '.gitignore', 'node_modules/**', '**/node_modules/**', '.git/**', 'package.json', ] export default class Dev extends Command { public async run() { if (!existsSync(salesAppMonorepoSrcDir)) { console.error( `${chalk.red( 'Error' )} - Sales App project not initialized. Please run "sales-app-cli init" first` ) return } await createDotSalesAppDir() console.log( `${chalk.blue( 'Info' )} - Watching for changes in ${salesAppMonorepoSrcDir}` ) const watcher = chokidar.watch(salesAppMonorepoSrcDir, { persistent: true, ignored: defaultIgnored, }) const webpackProcess = this.runWebpackServe() const proxyServerProcess = this.runProxyServer() watcher .on('add', (filePath) => { console.log(`${chalk.green('Added')} - File added: ${filePath}`) const destFilePath = path.join( dotSalesAppDir, 'src', path.relative(salesAppMonorepoSrcDir, filePath) ) fs.copyFileSync(filePath, destFilePath) console.log( `${chalk.green('Copied')} - Copied ${filePath} to ${destFilePath}` ) }) .on('change', (filePath) => { console.log(`${chalk.yellow('Changed')} - File changed: ${filePath}`) const destFilePath = path.join( dotSalesAppDir, 'src', path.relative(salesAppMonorepoSrcDir, filePath) ) fs.copyFileSync(filePath, destFilePath) console.log( `${chalk.yellow('Copied')} - Copied ${filePath} to ${destFilePath}` ) }) .on('unlink', (filePath) => { const destFilePath = path.join( dotSalesAppDir, 'src', path.relative(salesAppMonorepoSrcDir, filePath) ) try { if (existsSync(destFilePath)) { fs.unlinkSync(destFilePath) console.log(`${chalk.red('Deleted')} - Deleted ${destFilePath}`) } } catch (error) { console.error( `${chalk.red( 'Error' )} - Error deleting file ${destFilePath}: ${error}` ) } }) .on('error', (error) => { console.error(`${chalk.red('Watcher Error')} - ${error}`) process.exit() }) const terminateProcesses = () => { console.log( `${chalk.yellow('Warning')} - Received termination signal. Stopping...` ) webpackProcess.kill() proxyServerProcess.kill() process.exit() } process.on('SIGINT', terminateProcesses) process.on('SIGTERM', terminateProcesses) } private runWebpackServe() { const child = spawn(webpackBinPath, ['serve', '--mode', 'development'], { cwd: dotSalesAppDir, stdio: 'inherit', shell: true, }) child.on('error', (err) => { console.error( `${chalk.red('Error')} - Error starting webpack serve: ${err}` ) process.exit() }) child.on('close', (code) => { if (code !== 0) { console.error( `${chalk.red('Error')} - webpack serve exited with code ${code}` ) } process.exit() }) return child } private runProxyServer() { const child = spawn('node', ['dist/server/index'], { cwd: dotSalesAppDir, stdio: 'inherit', shell: true, }) child.on('error', (err) => { console.error( `${chalk.red('Error')} - Error starting proxy server: ${err}` ) process.exit() }) child.on('close', (code) => { if (code !== 0) { console.error( `${chalk.red('Error')} - proxy server exited with code ${code}` ) } process.exit() }) return child } }