I'm trying to refactor an Electron app to be more secure and am struggling to figure out how to structure my preload.js file and renderer file (mainWindow.js).
Given a window created in my main.js file thus:
const win = new BrowserWindow({
title: app.name,
show: false,
width,
height,
webPreferences: {
nodeIntegration: false,
enableRemoteModule: false,
contextIsolation: true,
preload: path.join(__dirname, "./js/preload.js"),
},
});
...and a preload.js that's something like this:
const { ipcRenderer, contextBridge } = require("electron");
contextBridge.exposeInMainWorld("api", {
logStuff: (arg) => ipcRenderer.invoke("logStuff", arg),
});
How do I take code in mainWindow.js (renderer process) and move the require statements over to preload.js so the necessary modules are available in mainWindow.js. Specifically, I'm using the Dexie IndexedDB module which has to run in the render process.
mainWindow.js
const db = require("../js/database");
...
//create db if no data exists
function setup() {
db.transaction("rw", db.entries, function* () {
if ((yield db.entries.count()) === 0) {
yield db.entries.bulkPut(dlist());
}
}).catch((error) => {
console.error(error.stack);
});
}
Should I be adding this to preload.js...
window.db = require("../js/database");
(database.js is where Dexie gets required and sets up the db schema)
and then in mainWindow.js reference the module off the window object? eg
function setup() {
window.db.transaction("rw", window.db.entries, function* () {
if ((yield window.db.entries.count()) === 0) {
yield window.db.entries.bulkPut(dlist());
}
}).catch((error) => {
console.error(error.stack);
});
}
Or should all the db operations happen in the preload script? And is this really the optimal approach in terms of security?