Local data and native APIs
Connect persistence to IPC
Wire validated load and save handlers to the notes store and report failures without leaking internal details.
We have a store, and we have IPC handlers that return an empty array. Time to connect them.
In src/index.js, import the store and replace the two handlers:
const { readNotes, writeNotes } = require('./notes-store')
ipcMain.handle('notes:load', async event => {
assertTrustedSender(event.senderFrame)
return readNotes(notesPath(), validateNotes)
})
ipcMain.handle('notes:save', async (event, value) => {
assertTrustedSender(event.senderFrame)
const notes = validateNotes(value)
await writeNotes(notesPath(), notes)
return { saved: notes.length }
})
Both handlers do the same two things first. They check the sender, then they validate the data.
Notice that validation runs in both directions. The load path validates what comes from disk. The save path validates what comes from the renderer. Neither side is trusted. A local file can be corrupted, or edited by another program. The renderer is a web page.
Register handlers once
ipcMain.handle() throws if you register the same channel twice. Register the handlers at module level or inside whenReady(), not inside createWindow(). Otherwise a second window, or a window reopened from the Dock on macOS, crashes the app with “Attempted to register a second handler”.
If you replace a handler during a development reload, call ipcMain.removeHandler('notes:save') first.
Report failures without leaking
In the renderer we already wrap the bridge call in try and catch. The message shown to the user is “Could not save notes”. That’s all they need.
The full error, with the file path and the stack trace, belongs in the main process terminal. Don’t forward it to the renderer. A path like /Users/flavio/Library/Application Support/... tells an attacker things about the machine, and it doesn’t help the user anyway.
Also, don’t claim success early. The status must say “Saving…” until the promise resolves. If the write fails, the edited note must stay visible so the user can copy it somewhere safe.
Prove it works
Seeing the array in renderer memory proves nothing. Run this sequence:
- Create a note and wait for the “Saved 1 notes” status.
- Quit the whole application, then reopen it.
- Confirm the note comes back from the
userDatafile we logged in the previous lesson. - Make the data folder unwritable (
chmod 500on macOS or Linux) and try to save again. - Confirm the renderer says “Could not save notes” and the edited text is still there.
Restore the permissions after the test. A successful write followed by a successful restart is the real test of persistence.
Lesson completed