npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@limbusfoundation/electronsave

v4.0.2

Published

Save Electron app data locally

Downloads

68

Readme

ElectronSave

ElectronSave

Save Electron (or any other Node.js app) data locally using JSON, YAML, or TOML.

Installation

Install ElectronSave using npm:

npm install @limbusfoundation/electronsave

Usage

ElectronSave uses ES Modules and provides a named ElectronSave export:

import { ElectronSave } from "@limbusfoundation/electronsave";

const config = new ElectronSave();

By default, the configuration file is stored in the user's home directory as appConfig.json.

You can specify a custom path and file format:

const config = new ElectronSave("./config.json", {
    type: "json"
});

Supported file types:

  • json
  • yaml
  • toml

You can also configure a schema and encryption key when creating the instance:

const config = new ElectronSave("./config.json", {
    type: "json",
    schema: {
        type: "object"
    },
    encryptionKey: "0123456789abcdef0123456789abcdef"
});

Methods

setPath(newPath)

Sets a custom path for the configuration file.

  • newPath (string) - Path to the configuration file.
config.setPath("./config.json");

getPath()

Returns the current configuration file path.

const path = config.getPath();

console.log(path);

setEncryptionKey(key)

Sets the encryption key used by mask() and unmask().

  • key (string) - Must contain exactly 32 characters.
config.setEncryptionKey("0123456789abcdef0123456789abcdef");

setSchema(schema)

Sets a JSON Schema used to validate the configuration data.

  • schema (object) - JSON Schema object.
config.setSchema({
    type: "object",
    properties: {
        name: { type: "string" },
        age: { type: "integer" }
    },
    required: ["name", "age"]
});

set(key, value)

Saves a value to the configuration file.

  • key (string) - Property name or nested property path.
  • value (any) - Value to store.

Nested keys can be accessed using . as a separator. Missing intermediate objects are created automatically.

config.set("theme", "dark");

config.set("user", {
    name: "John",
    age: 30
});

config.set("user.preferences.language", "en");
config.set("user.preferences.notifications", true);

The resulting configuration can be:

{
    "theme": "dark",
    "user": {
        "name": "John",
        "age": 30,
        "preferences": {
            "language": "en",
            "notifications": true
        }
    }
}

set() persists data without automatically validating the entire document against the schema.

get(key, defaultValue)

Retrieves a value from the configuration file.

  • key (string) - Property name or nested property path.
  • defaultValue (any) - Value returned when the key does not exist.
const theme = config.get("theme", "light");

const language = config.get("user.preferences.language", "en");

console.log(theme);
console.log(language);

Nested array items can also be accessed using numeric path segments:

const firstItem = config.get("items.0");
const firstItemName = config.get("items.0.name");

delete(key)

Removes a property from the configuration file.

  • key (string) - Property name or nested property path.
config.delete("theme");

config.delete("user.preferences.notifications");

Array items can also be removed using nested paths:

config.delete("items.0");

When deleting an array item through a numeric path, the remaining items are shifted automatically.

clear()

Removes all data from the configuration file.

config.clear();

push(key, index, value)

Inserts a value into an array at a specific index.

  • key (string) - Property name or nested property path containing an array.
  • index (number) - Index where the value should be inserted.
  • value (any) - Value to insert.
config.set("items", []);

config.push("items", 0, {
    id: "1",
    name: "First Item"
});

config.push("items", 1, {
    id: "2",
    name: "Second Item"
});

Nested arrays are supported:

config.set("user.preferences.tags", []);

config.push("user.preferences.tags", 0, "javascript");
config.push("user.preferences.tags", 1, "electron");

The index can be anywhere from 0 to the current array length.

pop(key, index)

Removes and returns a value from an array at a specific index.

  • key (string) - Property name or nested property path containing an array.
  • index (number) - Index of the value to remove.
const removedItem = config.pop("items", 0);

console.log(removedItem);

Nested arrays are supported:

const removedTag = config.pop("user.preferences.tags", 0);

console.log(removedTag);

If the index is invalid, pop() returns undefined.

validate()

Validates the current configuration data against the schema configured with setSchema().

Returns:

  • null when the data is valid or no schema is configured.
  • An array of AJV ErrorObjects when validation fails.
const errors = config.validate();

if(errors) {
    console.log("Validation error:", errors);
} else {
    console.log("Validation successful!");
}

Example:

const config = new ElectronSave("./config.json");

config.setSchema({
    type: "object",
    properties: {
        name: { type: "string" },
        age: { type: "integer", minimum: 18 }
    },
    required: ["name", "age"]
});

config.set("name", "Rhyan");
config.set("age", 23);

const errors = config.validate();

if(errors) {
    console.log("Validation error:", errors);
}

backup()

Creates a backup of the current configuration file.

Backups are stored in an appBackup directory next to the configuration file.

The filename uses the following format:

backup-MM-DD-YYYY-HH-MM-SS.<fileType>

For example:

appBackup/backup-09-24-2026-03-05-58.json
const backupPath = config.backup();

console.log("Backup created at:", backupPath);

restore(timestamp)

Restores a backup using its timestamp.

  • timestamp (string) - Timestamp portion of the backup filename.
config.restore("09-24-2026-03-05-58");

The backup extension automatically follows the configured file type.

onChange(key, callback)

Adds an observer for a specific key.

  • key (string) - Property name or nested property path.
  • callback (function) - Function called when the key is updated.
config.onChange("theme", (newValue) => {
    console.log(`Theme changed to: ${newValue}`);
});

config.set("theme", "dark");

Nested keys are also supported:

config.onChange("user.preferences.language", (newValue) => {
    console.log("Language changed to:", newValue);
});

config.set("user.preferences.language", "pt-BR");

mask(data)

Encrypts data using AES-256-CBC.

  • data (any) - Data to encrypt.

An encryption key must be configured before using this method.

config.setEncryptionKey("0123456789abcdef0123456789abcdef");

const encryptedData = config.mask({
    sensitive: "data"
});

console.log(encryptedData);

unmask(encryptedData)

Decrypts data previously encrypted with mask().

  • encryptedData (string) - Encrypted data.
const decryptedData = config.unmask(encryptedData);

console.log(decryptedData);

Nested Keys

ElectronSave supports dot-separated paths for accessing nested properties.

config.set("profile.username", "rhyan");
config.set("profile.preferences.language", "en");
config.set("profile.preferences.notifications", true);

console.log(config.get("profile.username"));
console.log(config.get("profile.preferences.language"));
console.log(config.get("profile.preferences.notifications"));

This produces:

{
    "profile": {
        "username": "rhyan",
        "preferences": {
            "language": "en",
            "notifications": true
        }
    }
}

Nested paths also work with arrays:

config.set("items", []);

config.push("items", 0, {
    id: "1",
    name: "First Item"
});

config.set("items.0.name", "Updated Item");

console.log(config.get("items.0.name"));

Nested paths are supported by:

  • set()
  • get()
  • delete()
  • push()
  • pop()
  • onChange()

A . in a key is interpreted as a path separator and cannot currently be used as part of a literal property name.

Schema Validation

ElectronSave uses AJV for JSON Schema validation.

Schemas can be used to validate:

  • Strings
  • Numbers
  • Integers
  • Booleans
  • Objects
  • Arrays
  • Null values
  • Required properties
  • String lengths
  • Numeric ranges
  • Regular expressions
  • Array sizes
  • Unique array items
  • Enumerations
  • Conditional schemas
  • Additional properties

Example Schema

const schema = {
    type: "object",
    properties: {
        theme: {
            type: "string"
        },
        user: {
            type: "object",
            properties: {
                name: {
                    type: "string"
                },
                age: {
                    type: "integer"
                }
            },
            required: ["name", "age"]
        }
    },
    required: ["theme", "user"]
};

config.setSchema(schema);

Validation

Schema validation is performed explicitly using validate().

config.set("theme", "dark");

config.set("user", {
    name: "John",
    age: 30
});

const errors = config.validate();

if(errors) {
    console.log("Validation error:", errors);
} else {
    console.log("Validation successful!");
}

This allows data to be built incrementally before validating the complete configuration.

File Formats

ElectronSave supports three configuration formats.

JSON

const config = new ElectronSave("./config.json", {
    type: "json"
});

YAML

const config = new ElectronSave("./config.yaml", {
    type: "yaml"
});

TOML

const config = new ElectronSave("./config.toml", {
    type: "toml"
});

Backups automatically use the configured file extension.

Notes

  • The default configuration path is <user-home>/appConfig.json.
  • Custom paths can be provided through the constructor or setPath().
  • JSON, YAML, and TOML are supported.
  • Dot-separated paths can be used to access nested objects and arrays.
  • set() automatically creates missing intermediate objects for nested paths.
  • set() persists data without performing schema validation.
  • get() supports default values when a path does not exist.
  • push() inserts values into arrays at a specific index.
  • pop() removes and returns a value from an array at a specific index.
  • validate() explicitly validates the current configuration against the configured schema.
  • Backups are stored inside an appBackup directory next to the configuration file.
  • Restoring a backup completely replaces the current configuration file.
  • An encryption key must contain exactly 32 characters before using mask() or unmask().
  • mask() and unmask() use AES-256-CBC.
  • A . in a key is interpreted as a nested path separator.

License

This project is licensed under the MIT License.