import { ChildProcess, SpawnOptions, spawn } from "child_process"; import path from "path"; import { TemplateFramework } from "./types"; const createProcess = ( command: string, args: string[], options: SpawnOptions, ) => { return spawn(command, args, { ...options, shell: true, }) .on("exit", function (code) { if (code !== 0) { console.log(`Child process exited with code=${code}`); process.exit(1); } }) .on("error", function (err) { console.log("Error when running chill process: ", err); process.exit(1); }); }; // eslint-disable-next-line max-params export async function runApp( appPath: string, frontend: boolean, framework: TemplateFramework, port?: number, externalPort?: number, ): Promise<any> { let backendAppProcess: ChildProcess; let frontendAppProcess: ChildProcess | undefined; const frontendPort = port || 3000; let backendPort = externalPort || 8000; // Callback to kill app processes process.on("exit", () => { console.log("Killing app processes..."); backendAppProcess.kill(); frontendAppProcess?.kill(); }); let backendCommand = ""; let backendArgs: string[]; if (framework === "fastapi") { backendCommand = "poetry"; backendArgs = [ "run", "uvicorn", "main:app", "--host=0.0.0.0", "--port=" + backendPort, ]; } else if (framework === "nextjs") { backendCommand = "npm"; backendArgs = ["run", "dev"]; backendPort = frontendPort; } else { backendCommand = "npm"; backendArgs = ["run", "dev"]; } if (frontend) { return new Promise((resolve, reject) => { backendAppProcess = createProcess(backendCommand, backendArgs, { stdio: "inherit", cwd: path.join(appPath, "backend"), env: { ...process.env, PORT: `${backendPort}` }, }); frontendAppProcess = createProcess("npm", ["run", "dev"], { stdio: "inherit", cwd: path.join(appPath, "frontend"), env: { ...process.env, PORT: `${frontendPort}` }, }); }); } else { return new Promise((resolve, reject) => { backendAppProcess = createProcess(backendCommand, backendArgs, { stdio: "inherit", cwd: path.join(appPath), env: { ...process.env, PORT: `${backendPort}` }, }); }); } }