TibixDev_winboat/scripts/dev-server.ts
waffles-dev 155a5660e8
Chore: Update .prettierrc and run formatter on all files (#367)
* Chore: Update .prettierrc and run formatter on all files

* chore: Add .prettierignore rule for xel

* Add prettier version to dev dependencies and freeze version

---------

Co-authored-by: waffles-dev <waffles-dev@outlook.com>
Co-authored-by: levev <levvevv@gmail.com>
2025-10-20 22:19:20 +08:00

126 lines
3.4 KiB
TypeScript

process.env.NODE_ENV = "development";
import * as Vite from "vite";
import ChildProcess, { type ChildProcessWithoutNullStreams } from "child_process";
import Path from "path";
import Chalk from "chalk";
import Chokidar from "chokidar";
import Electron from "electron";
import compileTs from "./private/tsc.ts";
// ^ Extension needed because no TSConfig in the root
import FileSystem from "fs";
import { EOL } from "os";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = Path.dirname(__filename);
let viteServer: Vite.ViteDevServer | null = null;
let electronProcess: ChildProcessWithoutNullStreams | null = null;
let electronProcessLocker = false;
let rendererPort = 0;
async function startRenderer() {
viteServer = await Vite.createServer({
configFile: Path.join(__dirname, "..", "vite.config.ts"),
mode: "development",
});
return viteServer.listen();
}
async function startElectron() {
if (electronProcess) {
// single instance lock
return;
}
try {
await compileTs(Path.join(__dirname, "..", "src", "main"));
} catch {
console.log(Chalk.redBright("Could not start Electron because of the above typescript error(s)."));
electronProcessLocker = false;
return;
}
const args = [Path.join(__dirname, "..", "build", "main", "main.js"), String(rendererPort)];
electronProcess = ChildProcess.spawn(String(Electron), args);
electronProcessLocker = false;
electronProcess!.stdout.on("data", data => {
if (data == EOL) {
return;
}
process.stdout.write(Chalk.blueBright(`[electron] `) + Chalk.white(data.toString()));
});
electronProcess!.stderr.on("data", data =>
process.stderr.write(Chalk.blueBright(`[electron] `) + Chalk.white(data.toString())),
);
electronProcess!.on("exit", () => stop());
}
function restartElectron() {
if (electronProcess) {
electronProcess.removeAllListeners("exit");
electronProcess.kill();
electronProcess = null;
}
if (!electronProcessLocker) {
electronProcessLocker = true;
startElectron();
}
}
function copyStaticFiles() {
copy("static");
}
/*
The working dir of Electron is build/main instead of src/main because of TS.
tsc does not copy static files, so copy them over manually for dev server.
*/
function copy(path) {
FileSystem.cpSync(
Path.join(__dirname, "..", "src", "main", path),
Path.join(__dirname, "..", "build", "main", path),
{ recursive: true },
);
}
function stop() {
viteServer!.close();
process.exit();
}
async function start() {
console.log(`${Chalk.greenBright("=======================================")}`);
console.log(`${Chalk.greenBright("Starting Electron + Vite Dev Server...")}`);
console.log(`${Chalk.greenBright("=======================================")}`);
const devServer = await startRenderer();
rendererPort = devServer.config.server.port;
copyStaticFiles();
startElectron();
const path = Path.join(__dirname, "..", "src", "main");
Chokidar.watch(path, {
cwd: path,
}).on("change", path => {
console.log(Chalk.blueBright(`[electron] `) + `Change in ${path}. reloading... 🚀`);
if (path.startsWith(Path.join("static", "/"))) {
copy(path);
}
restartElectron();
});
}
start();