const fs = require('fs'); const path = require('path'); console.log('Starting electron build process...'); // Copy web files const webDistPath = path.join(__dirname, '..', 'dist'); const electronDistPath = path.join(__dirname, '..', 'dist-electron'); const wwwPath = path.join(electronDistPath, 'www'); // Create www directory if it doesn't exist if (!fs.existsSync(wwwPath)) { fs.mkdirSync(wwwPath, { recursive: true }); } // Copy web files to www directory fs.cpSync(webDistPath, wwwPath, { recursive: true }); // Fix asset paths in index.html const indexPath = path.join(wwwPath, 'index.html'); let indexContent = fs.readFileSync(indexPath, 'utf8'); // Fix asset paths indexContent = indexContent .replace(/\/assets\//g, './assets/') .replace(/href="\//g, 'href="./') .replace(/src="\//g, 'src="./'); fs.writeFileSync(indexPath, indexContent); // Check for remaining /assets/ paths console.log('After path fixing, checking for remaining /assets/ paths:', indexContent.includes('/assets/')); console.log('Sample of fixed content:', indexContent.substring(0, 500)); console.log('Copied and fixed web files in:', wwwPath); // Copy main process files console.log('Copying main process files...'); // Create the main process file with inlined logger const mainContent = `const { app, BrowserWindow } = require("electron"); const path = require("path"); const fs = require("fs"); // Inline logger implementation const logger = { log: (...args) => console.log(...args), error: (...args) => console.error(...args), info: (...args) => console.info(...args), warn: (...args) => console.warn(...args), debug: (...args) => console.debug(...args), }; // Check if running in dev mode const isDev = process.argv.includes("--inspect"); function createWindow() { // Add before createWindow function const preloadPath = path.join(__dirname, "preload.js"); logger.log("Checking preload path:", preloadPath); logger.log("Preload exists:", fs.existsSync(preloadPath)); // Create the browser window. const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, webSecurity: true, allowRunningInsecureContent: false, preload: path.join(__dirname, "preload.js"), }, }); // Always open DevTools for now mainWindow.webContents.openDevTools(); // Intercept requests to fix asset paths mainWindow.webContents.session.webRequest.onBeforeRequest( { urls: [ "file://*/*/assets/*", "file://*/assets/*", "file:///assets/*", // Catch absolute paths "", // Catch all URLs as a fallback ], }, (details, callback) => { let url = details.url; // Handle paths that don't start with file:// if (!url.startsWith("file://") && url.includes("/assets/")) { url = \`file://\${path.join(__dirname, "www", url)}\`; } // Handle absolute paths starting with /assets/ if (url.includes("/assets/") && !url.includes("/www/assets/")) { const baseDir = url.includes("dist-electron") ? url.substring( 0, url.indexOf("/dist-electron") + "/dist-electron".length, ) : \`file://\${__dirname}\`; const assetPath = url.split("/assets/")[1]; const newUrl = \`\${baseDir}/www/assets/\${assetPath}\`; callback({ redirectURL: newUrl }); return; } callback({}); // No redirect for other URLs }, ); if (isDev) { // Debug info logger.log("Debug Info:"); logger.log("Running in dev mode:", isDev); logger.log("App is packaged:", app.isPackaged); logger.log("Process resource path:", process.resourcesPath); logger.log("App path:", app.getAppPath()); logger.log("__dirname:", __dirname); logger.log("process.cwd():", process.cwd()); } const indexPath = path.join(__dirname, "www", "index.html"); if (isDev) { logger.log("Loading index from:", indexPath); logger.log("www path:", path.join(__dirname, "www")); logger.log("www assets path:", path.join(__dirname, "www", "assets")); } if (!fs.existsSync(indexPath)) { logger.error(\`Index file not found at: \${indexPath}\`); throw new Error("Index file not found"); } // Add CSP headers to allow API connections, Google Fonts, and zxing-wasm mainWindow.webContents.session.webRequest.onHeadersReceived( (details, callback) => { callback({ responseHeaders: { ...details.responseHeaders, "Content-Security-Policy": [ "default-src 'self';" + "connect-src 'self' https://api.endorser.ch https://*.timesafari.app https://*.jsdelivr.net;" + "img-src 'self' data: https: blob:;" + "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://*.jsdelivr.net;" + "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;" + "font-src 'self' data: https://fonts.gstatic.com;" + "style-src-elem 'self' 'unsafe-inline' https://fonts.googleapis.com;" + "worker-src 'self' blob:;", ], }, }); }, ); // Load the index.html mainWindow .loadFile(indexPath) .then(() => { logger.log("Successfully loaded index.html"); if (isDev) { mainWindow.webContents.openDevTools(); logger.log("DevTools opened - running in dev mode"); } }) .catch((err) => { logger.error("Failed to load index.html:", err); logger.error("Attempted path:", indexPath); }); // Listen for console messages from the renderer mainWindow.webContents.on("console-message", (_event, _level, message) => { logger.log("Renderer Console:", message); }); // Add right after creating the BrowserWindow mainWindow.webContents.on( "did-fail-load", (_event, errorCode, errorDescription) => { logger.error("Page failed to load:", errorCode, errorDescription); }, ); mainWindow.webContents.on("preload-error", (_event, preloadPath, error) => { logger.error("Preload script error:", preloadPath, error); }); mainWindow.webContents.on( "console-message", (_event, _level, message, line, sourceId) => { logger.log("Renderer Console:", line, sourceId, message); }, ); // Enable remote debugging when in dev mode if (isDev) { mainWindow.webContents.openDevTools(); } } // Handle app ready app.whenReady().then(createWindow); // Handle all windows closed app.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); } }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); // Handle any errors process.on("uncaughtException", (error) => { logger.error("Uncaught Exception:", error); }); `; // Write the main process file const mainDest = path.join(electronDistPath, 'main.js'); fs.writeFileSync(mainDest, mainContent); // Copy preload script if it exists const preloadSrc = path.join(__dirname, '..', 'src', 'electron', 'preload.js'); const preloadDest = path.join(electronDistPath, 'preload.js'); if (fs.existsSync(preloadSrc)) { console.log(`Copying ${preloadSrc} to ${preloadDest}`); fs.copyFileSync(preloadSrc, preloadDest); } // Verify build structure console.log('\nVerifying build structure:'); console.log('Files in dist-electron:', fs.readdirSync(electronDistPath)); console.log('Build completed successfully!');