How to persist data in an Electron app?

Electron

Electron Problem Overview


I've been scouring the Electron documentation to try and figure out how to persist data in an Electron app. For example, in iOS or OS X, you could use NSUserDefaults to store user settings and preferences. I would like to do something similar. How can I persist data in an Electron app?

Electron Solutions


Solution 1 - Electron

NeDB is the only suggested or featured tool as an embedded persistent database for Electron by Electron, currently. - http://electron.atom.io/community/

It's also could be useful to store user settings if settings are complex.

Why NeDB could be a better solution on this case?

> Embedded persistent or in memory database for Node.js, nw.js, Electron > and browsers, 100% JavaScript, no binary dependency. API is a subset > of MongoDB's and it's plenty fast. - NeDB

Creating or loading a database:

var Datastore = require('nedb')
  , db = new Datastore({ filename: 'path/to/datafile', autoload: true });
// You can issue commands right away

Inserting a document:

var doc = { hello: 'world'
               , n: 5
               , today: new Date()
               , nedbIsAwesome: true
               , notthere: null
               , notToBeSaved: undefined  // Will not be saved
               , fruits: [ 'apple', 'orange', 'pear' ]
               , infos: { name: 'nedb' }
               };

db.insert(doc, function (err, newDoc) {   // Callback is optional
  // newDoc is the newly inserted document, including its _id
  // newDoc has no key called notToBeSaved since its value was undefined
});

Finding documents:

// Finding all inhabited planets in the solar system
db.find({ system: 'solar', inhabited: true }, function (err, docs) {
  // docs is an array containing document Earth only
});

The list goes on...

Update - September 2019

As of 2019, this is no longer the valid answer. See the answers of @jviotti and @Tharanga below.

Solution 2 - Electron

There is an NPM module I wrote called electron-json-storage that is meant to abstract this out and provide a nice and easy interface to the developer.

The module internally reads/writes JSON to/from app.getPath('userData'):

const storage = require('electron-json-storage');

// Write
storage.set('foobar', { foo: 'bar' }).then(function() {

    // Read
    storage.get('foobar').then(function(object) {
        console.log(object.foo);
        // will print "bar"
    });

});

Solution 3 - Electron

There is a nice module for storing user data in elecron. It's called electron-store.

Installation

$ npm install electron-store

Sample usage (copied from github page)

const Store = require('electron-store');
const store = new Store();

store.set('unicorn', '🦄');
console.log(store.get('unicorn'));
//=> '🦄'

// Use dot-notation to access nested properties
store.set('foo.bar', true);
console.log(store.get('foo'));
//=> {bar: true}

store.delete('unicorn');
console.log(store.get('unicorn'));
//=> undefined

This module has many features and there are many advantages over window.localStorage

Solution 4 - Electron

Electron views are built with Webkit which gives you access to the web based localstorage api. Good for simple and easy settings storage.

If you need something more powerful or need storage access from the main script, you can use one of the numerous node based storage modules. Personally I like lowdb.

With most node storage modules, you will need to provide a file location. Try:

var app = require('app');
app.getPath('userData');

Solution 5 - Electron

Since NeDB's latest release was 4 years ago and there are many open issues, I would not recommend it. But there are many other alternatives you can use now.

https://github.com/pubkey/rxdb (many features, observable queries)

https://github.com/pouchdb/pouchdb (simple but many open issues)

https://github.com/techfort/LokiJS (only in-memory storage)

https://github.com/typicode/lowdb (good for simple, small datasets)

Solution 6 - Electron

There is a module that gives simple methods to get and set json files to this directory, creates subdirectories if needed and supports callbacks and promises:

https://github.com/ran-y/electron-storage

Readme:

Installation

$ npm install --save electron-storage

usage

const storage = require('electron-storage');

API

storage.get(filePath, cb)

storage.get(filePath, (err, data) => {
  if (err) {
    console.error(err)
  } else {
    console.log(data);
  }
});

storage.get(filePath)

storage.get(filePath)
.then(data => {
  console.log(data);
})
.catch(err => {
  console.error(err);
});

storage.set(filePath, data, cb)

storage.set(filePath, data, (err) => {
  if (err) {
    console.error(err)
  }
});

storage.set(filePath, data)

storage.set(filePath, data)
.then(data => {
  console.log(data);
})
.catch(err => {
  console.error(err);
});

storage.isPathExists(path, cb)

storage.isPathExists(path, (itDoes) => {
  if (itDoes) {
    console.log('pathDoesExists !')
  }
});

storage.isPathExists(path)

storage.isPathExists(path)
.then(itDoes => {
  if (itDoes) {
    console.log('pathDoesExists !')
  }
});

Solution 7 - Electron

You have multiple opions other than what mentioned in other answers.

If you want to store data in an SQL databse then you can https://github.com/mapbox/node-sqlite3

Or if you are storing configurations, You can store directly in OS's userData storage.

 const electron = require('electron');
 const fs = require('fs');
 const path = require('path');

 const dataPath = electron.app.getPath('userData');
 const filePath = path.join(dataPath, 'config.json');

 function writeData(key, value){
   let contents = parseData()
   contents[key] = value;
   fs.writeFileSync(filePath, JSON.stringify(contents));
 }

 function readData(key, value) {
  let contents = parseData()
  return contents[key]
 }

 function parseData(){
   const defaultData = {}
   try {
    return JSON.parse(fs.readFileSync(filePath));
  } catch(error) {
    return defaultData;
  }
 }

Solution 8 - Electron

You can go for Indexeddb, which is most likely suitable for client-side app needs due to:

  • Its built-in versioning mechanism. Client-side applications often face version fragmentation as users don't usually update to new version at the same time. So checking version of existing database and update accordingly is a good idea.
  • It's schemaless, which allows flexibility of adding more data to client's storage (which happen pretty often in my experience) without having to update database to a new version, unless you create new indices.
  • It support wide ranges of data: basic types as well as blob data (file, images)

All in all it's a good choice. The only caveat is that chromium cores may automatically wipe out indexeddb to reclaim disk space when storage is under strain if navigator.storage.persist is not set, or when the host machine is crashed leaving indexeddb in corrupted state.

Solution 9 - Electron

There are a plethora of ways for data persistence that can be used in Electron and choosing the right approach depends essentially on your use case(s). If it's only about saving application settings then you can use simple mechanisms such as flat files or HTML5 Storage APIs, for advanced data requirements you should opt for large scale database solutions such as MySQL or MongoDB (with or without ORMs).

You can check this list of methods/tools to persist data in Electron apps

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrewView Question on Stackoverflow
Solution 1 - ElectronmertyildiranView Answer on Stackoverflow
Solution 2 - ElectronjviottiView Answer on Stackoverflow
Solution 3 - ElectronTharangaView Answer on Stackoverflow
Solution 4 - ElectronTeakView Answer on Stackoverflow
Solution 5 - ElectronpubkeyView Answer on Stackoverflow
Solution 6 - ElectronYoniView Answer on Stackoverflow
Solution 7 - ElectronHaseeb AView Answer on Stackoverflow
Solution 8 - ElectronvuamitomView Answer on Stackoverflow
Solution 9 - ElectronAhmedView Answer on Stackoverflow