mirror of
https://github.com/litruv/AudioSort.git
synced 2026-07-24 02:36:01 +10:00
Initial
This commit is contained in:
121
scripts/start-electron.mjs
Normal file
121
scripts/start-electron.mjs
Normal file
@@ -0,0 +1,121 @@
|
||||
/** @typedef {import('node:child_process').ChildProcess} ChildProcess */
|
||||
import { spawn } from 'node:child_process';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import treeKill from 'tree-kill';
|
||||
import electronPath from 'electron';
|
||||
|
||||
const filename = fileURLToPath(import.meta.url);
|
||||
const dirname = path.dirname(filename);
|
||||
const distMainEntry = path.resolve(dirname, '../dist/main/main/index.js');
|
||||
const distMainDir = path.dirname(distMainEntry);
|
||||
let child = /** @type {ChildProcess | null} */ (null);
|
||||
let restartTimer = /** @type {NodeJS.Timeout | null} */ (null);
|
||||
let isStarting = false;
|
||||
|
||||
/**
|
||||
* Simple debounce helper to avoid rapid restarts.
|
||||
* @param {() => void} fn
|
||||
* @param {number} delayMs
|
||||
*/
|
||||
function schedule(fn, delayMs) {
|
||||
if (restartTimer) {
|
||||
clearTimeout(restartTimer);
|
||||
}
|
||||
restartTimer = setTimeout(() => {
|
||||
restartTimer = null;
|
||||
fn();
|
||||
}, delayMs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits until the compiled main bundle exists before attempting to launch Electron.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function waitForBundle() {
|
||||
if (fs.existsSync(distMainEntry)) {
|
||||
return;
|
||||
}
|
||||
await new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
if (fs.existsSync(distMainEntry)) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts Electron pointing at the compiled JavaScript main entry.
|
||||
*/
|
||||
function launchElectron() {
|
||||
if (child) {
|
||||
return;
|
||||
}
|
||||
isStarting = true;
|
||||
const spawnOptions = {
|
||||
stdio: 'inherit',
|
||||
env: { ...process.env },
|
||||
windowsHide: false
|
||||
};
|
||||
child = spawn(electronPath, [distMainEntry], spawnOptions);
|
||||
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
console.error(`Electron exited with code ${code ?? 'unknown'}`);
|
||||
}
|
||||
child = null;
|
||||
isStarting = false;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
isStarting = false;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kills the current Electron process if it is running.
|
||||
*/
|
||||
function disposeElectron() {
|
||||
if (child?.pid) {
|
||||
try {
|
||||
treeKill(child.pid, 'SIGTERM');
|
||||
} catch (error) {
|
||||
console.warn('Failed to terminate Electron process', error);
|
||||
}
|
||||
}
|
||||
child = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the dev runner by waiting for the bundle, launching Electron, and watching for rebuilds.
|
||||
*/
|
||||
async function bootstrap() {
|
||||
await waitForBundle();
|
||||
launchElectron();
|
||||
|
||||
const watcher = fs.watch(distMainDir, { recursive: true }, (eventType, filename) => {
|
||||
if (!filename || isStarting || child === null) {
|
||||
return;
|
||||
}
|
||||
if (filename.endsWith('.js') || filename.endsWith('.js.map')) {
|
||||
schedule(() => {
|
||||
disposeElectron();
|
||||
launchElectron();
|
||||
}, 500);
|
||||
}
|
||||
});
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
watcher.close();
|
||||
disposeElectron();
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
bootstrap().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
37
scripts/start-electron.ts
Normal file
37
scripts/start-electron.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
/// <reference types="node" />
|
||||
import { spawn } from 'node:child_process';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const filename = fileURLToPath(import.meta.url);
|
||||
const dirname = path.dirname(filename);
|
||||
|
||||
/**
|
||||
* Resolves the Electron binary path based on the current platform.
|
||||
* @returns {string} Absolute path to the Electron executable.
|
||||
*/
|
||||
function resolveElectronBinary(): string {
|
||||
const base = path.resolve(dirname, '../node_modules/.bin');
|
||||
if (process.platform === 'win32') {
|
||||
return path.join(base, 'electron.cmd');
|
||||
}
|
||||
return path.join(base, 'electron');
|
||||
}
|
||||
|
||||
/**
|
||||
* Boots Electron pointing at the TypeScript main entry so tsx can transpile on the fly.
|
||||
*/
|
||||
function launchElectron(): void {
|
||||
const electronBinary = resolveElectronBinary();
|
||||
const mainEntry = path.resolve(dirname, '../src/main/index.ts');
|
||||
const child = spawn(electronBinary, [mainEntry], {
|
||||
stdio: 'inherit',
|
||||
env: { ...process.env }
|
||||
});
|
||||
|
||||
child.on('close', (code?: number) => {
|
||||
process.exit(code ?? 0);
|
||||
});
|
||||
}
|
||||
|
||||
launchElectron();
|
||||
Reference in New Issue
Block a user