or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-electron-store

Simple data persistence for Electron apps using JSON storage with atomic writes

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/electron-store@10.1.x

To install, run

npx @tessl/cli install tessl/npm-electron-store@10.1.0

index.mddocs/

Electron Store

Electron Store provides simple data persistence for Electron applications, handling user settings, app state, cache, and other data using JSON files stored in the app's userData directory. It extends the 'conf' package with Electron-specific functionality and supports both main and renderer processes.

Package Information

  • Package Name: electron-store
  • Package Type: npm
  • Language: JavaScript (ESM)
  • Installation: npm install electron-store
  • Requires: Electron 30 or later

Core Imports

import Store from "electron-store";

For TypeScript:

import Store, { Schema } from "electron-store";

Basic Usage

import Store from "electron-store";

const store = new Store();

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

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

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

Architecture

Electron Store is built around several key components:

  • Cross-Process Support: Works in both main and renderer processes with automatic IPC setup
  • Atomic Writes: Prevents data corruption during crashes by writing atomically to disk
  • JSON Storage: Uses human-readable JSON files in Electron's userData directory
  • Schema Validation: Optional JSON Schema validation with AJV validator
  • Configuration Management: Extends 'conf' package with Electron-specific path and version handling
  • Migration System: Supports data migrations between versions

Internal Implementation Details

Process Type Detection:

  • Automatically detects renderer vs main process using process.type
  • Renderer processes communicate with main process via IPC channel 'electron-store-get-data'
  • Main process handles userData path and app version resolution

Path Resolution Logic:

  • If cwd option provided: resolves relative paths against Electron's userData directory
  • If no cwd: defaults to app.getPath('userData')
  • Absolute paths in cwd are used as-is

Option Transformation:

  • name option becomes configName internally (conf requirement)
  • projectVersion defaults to app.getVersion() if not specified
  • All other conf options pass through unchanged

Electron-Store vs Conf Package

Electron-Store Specific Features:

  • static initRenderer(): Sets up IPC for renderer-only usage
  • openInEditor(): Opens config file in system editor (uses Electron's shell.openPath)
  • Automatic Electron app integration (userData path, app version)
  • Cross-process support with IPC communication
  • Options interface tailored for Electron (excludes conf's project-specific options)

Inherited from Conf Package:

  • All data storage methods: set(), get(), has(), delete(), clear(), reset()
  • Change watching: onDidChange(), onDidAnyChange()
  • Properties: size, store, path
  • Schema validation, migrations, encryption, serialization
  • Atomic file operations and dot-notation support

Capabilities

Store Constructor

Creates a new store instance with Electron-specific configuration.

/**
 * Creates a new ElectronStore instance with optional configuration
 * Inherits all conf package options except configName, projectName, projectVersion, projectSuffix
 * @param options - Configuration options for the store
 */
constructor<T extends Record<string, any>>(options?: Options<T>): ElectronStore<T>;

/**
 * Options interface extends conf's ConfigOptions with exclusions
 * Excludes: configName, projectName, projectVersion, projectSuffix (handled internally)
 */
type Options<T extends Record<string, any>> = Except<ConfigOptions<T>, 'configName' | 'projectName' | 'projectVersion' | 'projectSuffix'> & {
  /** Name of the storage file (without extension). Default: 'config' */
  readonly name?: string;
};

/**
 * Inherited ConfigOptions from conf package include:
 * - defaults: Default values for store items
 * - schema: JSON Schema for validation  
 * - rootSchema: Top-level schema properties
 * - ajvOptions: JSON Schema validator options
 * - migrations: Version-based migration handlers
 * - cwd: Custom config directory (auto-resolved to userData by electron-store)
 * - encryptionKey: Optional encryption key for obfuscation
 * - fileExtension: Config file extension (default: 'json')
 * - clearInvalidConfig: Clear config on syntax errors (default: false)
 * - serialize: Custom serialization function
 * - deserialize: Custom deserialization function
 * - accessPropertiesByDotNotation: Enable dot notation (default: true)
 * - watch: Watch config file for changes (default: false)
 * - configFileMode: File permissions for config file
 */

interface MigrationContext {
  fromVersion: string;
  toVersion: string; 
  finalVersion: string;
  versions: string[];
}

Static Methods

Renderer Process Initialization

Initializes IPC communication channels when using store only in renderer process.

/**
 * Initializer to set up required IPC communication channels
 * Call this from the main process when creating Store instances only in renderer process
 */
static initRenderer(): void;

Instance Methods

Note: All methods below are inherited from the conf package, with ElectronStore providing Electron-specific initialization and path handling.

Data Access Methods

Core methods for getting, setting, and managing stored data (inherited from conf).

/**
 * Set a single item in the store
 * @param key - Property key (supports dot-notation for nested properties)
 * @param value - Value to store (must be JSON serializable)
 */
set(key: string, value: any): void;

/**
 * Set multiple items at once
 * @param object - Object with key-value pairs to store
 */
set(object: Partial<T>): void;

/**
 * Get an item from the store
 * @param key - Property key (supports dot-notation)
 * @param defaultValue - Default value if key doesn't exist
 * @returns The stored value or defaultValue
 */
get(key: string, defaultValue?: any): any;

/**
 * Check if an item exists in the store
 * @param key - Property key to check
 * @returns true if key exists, false otherwise
 */
has(key: string): boolean;

/**
 * Delete an item from the store
 * @param key - Property key to delete
 */
delete(key: string): void;

/**
 * Delete all items from the store
 * Resets known items to their default values if defined by defaults or schema
 */
clear(): void;

/**
 * Reset items to their default values
 * @param keys - Keys to reset to default values
 */
reset(...keys: string[]): void;

Change Watching Methods

Methods for observing changes to stored data (inherited from conf).

/**
 * Watch for changes on a specific key
 * @param key - Key to watch for changes
 * @param callback - Function called when key changes
 * @returns Function to unsubscribe from changes
 */
onDidChange(key: string, callback: (newValue: any, oldValue: any) => void): () => void;

/**
 * Watch for any changes to the store
 * @param callback - Function called when any value changes
 * @returns Function to unsubscribe from changes  
 */
onDidAnyChange(callback: (newValue: T, oldValue: T) => void): () => void;

Editor Integration

Method for opening the storage file in an external editor.

/**
 * Open the storage file in the user's default editor
 * @returns Promise that resolves when editor opens or rejects on failure
 */
openInEditor(): Promise<void>;

Instance Properties

Properties providing access to store metadata and data (inherited from conf).

/**
 * Get the number of items in the store
 */
readonly size: number;

/**
 * Get or set all data as an object
 * Setting this property replaces all store data
 */
store: T;

/**
 * Get the path to the storage file
 */
readonly path: string;

Types

Schema Export

Re-exported type from the 'conf' package for JSON Schema validation.

/**
 * JSON Schema type for validation configuration
 * Re-exported from 'conf' package
 */
export { Schema } from 'conf';

Usage Examples

Basic Store Operations

import Store from "electron-store";

const store = new Store();

// Store different data types
store.set('user.name', 'Alice');
store.set('user.preferences', { theme: 'dark', language: 'en' });
store.set('recentFiles', ['file1.txt', 'file2.txt']);

// Check and retrieve data
if (store.has('user.name')) {
  console.log(`Hello, ${store.get('user.name')}!`);
}

// Get with default value
const theme = store.get('user.preferences.theme', 'light');

Store with Schema Validation

import Store from "electron-store";

const schema = {
  user: {
    type: 'object',
    properties: {
      name: { type: 'string', minLength: 1 },
      age: { type: 'number', minimum: 0 }
    },
    required: ['name']
  },
  settings: {
    type: 'object',
    properties: {
      theme: { type: 'string', enum: ['light', 'dark'] }
    },
    default: { theme: 'light' }
  }
};

const store = new Store({ schema });

// This will work
store.set('user', { name: 'Bob', age: 25 });

// This will throw an error due to schema validation
// store.set('user', { age: 25 }); // Missing required 'name'

Cross-Process Usage

In the main process:

import Store from "electron-store";

// Option 1: Create store in main process (accessible anywhere)
const store = new Store();

// Option 2: Initialize for renderer-only usage
Store.initRenderer();

In the renderer process:

import Store from "electron-store";

// If using option 1, create another instance
const store = new Store();

// If using option 2, this works without main process store
const store = new Store();

store.set('renderer-data', 'Hello from renderer!');

Change Watching

import Store from "electron-store";

const store = new Store({ watch: true });

// Watch specific key changes
const unsubscribe = store.onDidChange('user.theme', (newValue, oldValue) => {
  console.log(`Theme changed from ${oldValue} to ${newValue}`);
  // Update UI theme
});

// Watch all changes
const unsubscribeAll = store.onDidAnyChange((newStore, oldStore) => {
  console.log('Store updated:', newStore);  
});

// Unsubscribe when no longer needed
unsubscribe();
unsubscribeAll();

Migration Example

import Store from "electron-store";

const store = new Store({
  migrations: {
    '0.1.0': store => {
      // Migration from version 0.1.0
      store.set('newFeatureEnabled', true);
    },
    '1.0.0': store => {
      // Migration from version 1.0.0
      const oldData = store.get('deprecatedKey');
      if (oldData) {
        store.set('newKey', oldData);
        store.delete('deprecatedKey');
      }
    }
  },
  beforeEachMigration: (store, context) => {
    console.log(`Migrating from ${context.fromVersion} to ${context.toVersion}`);
  }
});

Custom Storage Location and Encryption

import Store from "electron-store";
import path from "node:path";

const store = new Store({
  name: 'user-settings',
  cwd: path.join(__dirname, 'custom-config'),
  encryptionKey: 'my-secret-key', // For obfuscation only
  fileExtension: 'conf'
});

// Storage file will be at: custom-config/user-settings.conf
console.log('Config stored at:', store.path);

Error Handling

Common Errors

Renderer Process Without Initialization: This error occurs when creating a Store instance in renderer process without proper IPC setup:

Error: Electron Store: You need to call `.initRenderer()` from the main process.

Solution: Call Store.initRenderer() in main process before creating Store instances in renderer.

IPC Communication Failures: When renderer process cannot communicate with main process:

// Renderer process gets null from IPC call
const appData = electron.ipcRenderer.sendSync('electron-store-get-data');
if (!appData) {
  throw new Error('Electron Store: You need to call `.initRenderer()` from the main process.');
}

Schema Validation Errors: When data doesn't match defined JSON schema:

Error: Config schema violation: `propertyName` should be string

Note: Validation uses AJV with JSON Schema draft-2020-12

Editor Opening Failures: When openInEditor() fails to open the storage file:

try {
  await store.openInEditor();
} catch (error) {
  // Error comes from Electron's shell.openPath()
  console.error('Failed to open editor:', error.message);
}

File System Errors: Inherited from conf package - file permission issues, disk full, etc.

Debug Information

IPC Channel Name: 'electron-store-get-data' (used for renderer-main communication)

Type Safety Considerations

  • Values must be JSON serializable (no undefined, function, or symbol)
  • Schema validation occurs on set() operations
  • Migration functions receive the store instance as first parameter
  • TypeScript generic <T> provides compile-time type safety for store data