Local data and native APIs

Read and write the notes file

Create the data directory, handle a missing file, validate stored JSON, and write notes asynchronously.

12 minute lesson

~~~

Create src/notes-store.js. Keep file operations outside IPC registration so we can test them without Electron.

const fs = require('node:fs/promises')
const path = require('node:path')

async function readNotes(filePath, validateNotes) {
  try {
    const contents = await fs.readFile(filePath, 'utf8')
    return validateNotes(JSON.parse(contents))
  } catch (error) {
    if (error.code === 'ENOENT') return []
    throw error
  }
}

async function writeNotes(filePath, notes) {
  await fs.mkdir(path.dirname(filePath), { recursive: true })
  const temporaryPath = `${filePath}.tmp`

  await fs.writeFile(
    temporaryPath,
    JSON.stringify(notes, null, 2),
    'utf8'
  )
  await fs.rename(temporaryPath, filePath)
}

module.exports = { readNotes, writeNotes }

A missing file means the app has no notes yet. Invalid JSON is different: surface the error instead of silently erasing or replacing user data.

The asynchronous file APIs keep the main process responsive while the operating system works.

Writing a temporary file first reduces the chance of leaving a half-written JSON document when the process stops during a save. The rename replaces the visible file only after the complete temporary file exists.

This is not a complete backup system. Disk errors, external edits, and filesystem behavior can still fail. Keep the original error, preserve the unsaved renderer state, and consider versioned backups for important production data.

JSON parsing and data validation are separate steps. Valid JSON can still contain an invalid note shape, so readNotes() passes the parsed value through validateNotes() before returning it.

Test three files by hand: no file, valid notes, and truncated JSON. Only the missing file should become an empty list.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →