electron-store

repository·main·Indexed 26 days ago

https://github.com/sindresorhus/electron-store

Simple data persistence for Electron apps or modules to save and load user settings, app state, and cache into a JSON file. Version 11.0.2 requires Electron 30 or later and is a native ESM module. It features JSON Schema validation, data migrations, encryption/obfuscation, and support for custom serialization formats like YAML. Designed for small datasets, it provides methods for dot-notation access, array appending, and change watching via .onDidChange and .onDidAnyChange.

Tokens
3K
Snippets
11
Records
21
Agent score
85%

What's inside electron-store

  1. Basic usage of electron-store

    main

    Use electron-store to save and load small amounts of data (like user settings or app state) in a JSON file located at app.getPath('userData')/config.json.

    Warning: This is not a database. The entire JSON file is read and written on every change, so it is best suited for small data. For large datasets, use SQLite or a similar solution.

    import Store from '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
  2. Access store values in the renderer process

    main

    Because electron-store is not a singleton, a store instance initialized in the main process is not automatically available in the renderer process. To access values in the renderer, use Electron's ipcMain.handle and ipcRenderer.invoke pattern to pass values between processes.

    // In the Main process
    ipcMain.handle('getStoreValue', (event, key) => {
    	return store.get(key);
    });
    
    // In the Renderer process
    const foo = await ipcRenderer.invoke('getStoreValue', 'foo');
  3. Configure encryption and obfuscation

    main

    To deter users from manually editing the JSON config file, you can provide an encryptionKey. This obfuscates the file using the specified encryptionAlgorithm.

    Warning: This is not intended for high-security purposes as the key is easily found in plain-text Node.js apps.

    Available algorithms:

    • aes-256-cbc (Default): Supports reading existing plaintext files.
    • aes-256-gcm: Provides authentication; decryption fails if the file is tampered with.
    • aes-256-ctr

    Note: Using aes-256-gcm or aes-256-ctr requires existing plaintext files to be deleted or migrated first.

  4. Initialize Electron Store in the Renderer process

    main
    If you are using electron-store in a renderer process, you must first call ElectronStore.initRenderer() from the main process. This sets up the IPC listener required for the renderer to retrieve necessary application data (like userData path and app version) to locate the configuration file.
  5. Data size limitations

    main

    Do not use electron-store for large amounts of data. The package reads and writes the entire JSON file on every change, which causes performance degradation with even moderately large data (e.g., 1 MB+).

    Recommended use cases: Small amounts of data like user settings, value caching, or state. Recommended alternatives for large data: Use SQLite or save files to disk and store the file path in the store.

  6. Use YAML or other serialization formats

    main

    You can customize the configuration file format by providing serialize and deserialize options. The chosen format must be compatible with utf8 encoding. For example, you can use js-yaml to store configuration as YAML instead of JSON.

    import Store from 'electron-store';
    import yaml from 'js-yaml';
    
    const store = new Store({
    	fileExtension: 'yaml',
    	serialize: yaml.safeDump,
    	deserialize: yaml.safeLoad
    });
  7. Perform data migrations

    main

    Use the migrations option to perform operations whenever the store version is upgraded. The migrations object maps version strings (which can be semver ranges) to handler functions.

    Note: This feature is provided without official support and may contain known bugs.

    import Store from 'electron-store';
    
    const store = new Store({
    	migrations: {
    		'0.0.1': store => {
    			store.set('debugPhase', true);
    		},
    		'1.0.0': store => {
    			store.delete('debugPhase');
    			store.set('phase', '1.0.0');
    		},
    		'1.0.2': store => {
    			store.set('phase', '1.0.2');
    		},
    		'>=2.0.0': store => {
    			store.set('phase', '>=2.0.0');
    		}
    	}
    });
  8. Configure data validation with schema

    main

    You can validate your configuration data using a JSON Schema. electron-store uses ajv and supports JSON Schema draft-2020-12. Define your schema as an object where each key is a property name and each value is a JSON schema for that property. Note that values in the defaults option will overwrite the default key in the schema option.

    import Store from 'electron-store';
    
    const schema = {
    	foo: {
    		type: 'number',
    		maximum: 100,
    		minimum: 1,
    		default: 50
    	},
    	bar: {
    		type: 'string',
    		format: 'url'
    	}
    };
    
    const store = new Store({schema});
    
    console.log(store.get('foo'));
    //=> 50
    
    store.set('foo', '1');
    // [Error: Config schema violation: `foo` should be number]
  9. Use beforeEachMigration for migration lifecycle hooks

    main

    The beforeEachMigration callback is executed before every migration step. It receives the store instance and a context object containing fromVersion, toVersion, finalVersion, and versions. This is useful for logging or preparing data.

    import Store from 'electron-store';
    
    const mainConfig = new Store({
    	beforeEachMigration: (store, context) => {
    		console.log(`[main-config] migrate from ${context.fromVersion} → ${context.toVersion}`);
    	},
    	migrations: {
    		'0.4.0': store => {
    			store.set('debugPhase', true);
    		}
    	}
    });
  10. Append items to an array

    main

    The .appendToArray(key, value) method adds an item to an array at the specified key. If the key does not exist, it creates a new array. If the existing value at the key is not an array, it throws a TypeError.

    store.set('items', [{name: 'foo'}]);
    store.appendToArray('items', {name: 'bar'});
    console.log(store.get('items'));
    //=> [{name: 'foo'}, {name: 'bar'}]
    
    // Creates array if key doesn't exist
    store.appendToArray('newItems', 'first');
    console.log(store.get('newItems'));
    //=> ['first']