#!/usr/bin/env node // @ts-check const { spawn } = require('child_process'); const electronPath = require('electron'); const { build, createLogger, createServer } = require('vite'); /** @type string */ const mode = process.env.MODE = process.env.MODE || 'development'; /** @type {import('vite').LogLevel} */ const LOG_LEVEL = 'info'; /** @type {import('vite').InlineConfig} */ const sharedConfig = { mode, build: { watch: {}, }, logLevel: LOG_LEVEL, }; /** * Messages on stderr that match any of the contained patterns will be stripped from output * * @type RegExp[] */ const stderrFilterPatterns = [ // warning about devtools extension // https://github.com/cawa-93/vite-electron-builder/issues/492 // https://github.com/MarshallOfSound/electron-devtools-installer/issues/143 /ExtensionLoadWarning/, ]; /** * @param {{name: string; configFile: string; writeBundle: import('rollup').OutputPlugin['writeBundle'] }} config * @returns {Promise | import('rollup').RollupWatcher>} */ function getWatcher({name, configFile, writeBundle}) { return build({ ...sharedConfig, configFile, plugins: [ { name, writeBundle, }, ], }); } /** * Start or restart App when source files are changed. * * @param {import('vite').ViteDevServer} viteDevServer * @returns {Promise | import('rollup').RollupWatcher>} */ function setupMainPackageWatcher(viteDevServer) { // Write a value to an environment variable to pass it to the main process. const protocol = `http${viteDevServer.config.server.https ? 's' : ''}:`; const host = viteDevServer.config.server.host || 'localhost'; const port = viteDevServer.config.server.port; const path = '/'; process.env.VITE_DEV_SERVER_URL = `${protocol}//${host}:${port}${path}`; const logger = createLogger( LOG_LEVEL, { prefix: '[main]', }, ); /** @type {import('child_process').ChildProcessWithoutNullStreams | null} */ let spawnProcess = null; return getWatcher({ name: 'reload-app-on-main-package-change', configFile: 'packages/main/vite.config.js', writeBundle() { if (spawnProcess !== null) { spawnProcess.kill('SIGINT'); spawnProcess = null; } spawnProcess = spawn(String(electronPath), ['.']); spawnProcess.stdout.on('data', (data) => { if (data.toString().trim() !== '') { logger.warn(data.toString(), {timestamp: true}) } }); spawnProcess.stderr.on('data', (data) => { const trimmedData = data.toString().trim(); if (trimmedData === '') { return; } const mayIgnore = stderrFilterPatterns.some((r) => r.test(data)); if (mayIgnore) { return; } logger.error(data, { timestamp: true }); }); }, }); } /** * Start or restart App when source files are changed. * * @param {import('vite').ViteDevServer} viteDevServer * @returns {Promise | import('rollup').RollupWatcher>} */ function setupPreloadPackageWatcher(viteDevServer) { return getWatcher({ name: 'reload-page-on-preload-package-change', configFile: 'packages/preload/vite.config.js', writeBundle() { viteDevServer.ws.send({ type: 'full-reload', }); }, }); } /** * @returns Promise */ async function setupDevEnvironment() { const viteDevServer = await createServer({ ...sharedConfig, configFile: 'packages/renderer/vite.config.js', }); await viteDevServer.listen(); await setupPreloadPackageWatcher(viteDevServer); return setupMainPackageWatcher(viteDevServer); } setupDevEnvironment().catch((err) => { console.error(err); process.exit(1); });