Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

electron-settings

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

electron-settings - npm Package Compare versions

Comparing version 2.2.4 to 3.0.0

lib/settings-helpers.js

19

index.js
/**
* Electron Settings
* Electron Settings - User settings manager for Electron.
*
* A simple persistent user settings manager for Electron. Originally adapted
* from Atom's own configuration manager, electron-settings allows you to save
* user settings to the disk so that they can be loaded in the next time your
* app starts up.
*
* NOTE: v2 is not compatible with earlier versions of electron-settings.
*
* @version 2.2.2
* @version 3.0.0
* @author Nathan Buchar
* @copyright 2016 Nathan Buchar <hello@nathanbuchar.com>
* @copyright 2016-2017 Nathan Buchar <hello@nathanbuchar.com>
* @license ISC
*/
module.exports = require('./lib/settings');
'use strict';
const Settings = require('./lib/settings');
module.exports = new Settings();
'use strict';
const assert = require('assert');
const debug = require('debug')('electron-settings:main');
const deepExtend = require('deep-extend');
const clone = require('clone');
const electron = require('electron');
const exists = require('file-exists');
const events = require('events');
const fs = require('fs-extra');
const helpers = require('key-path-helpers');
const path = require('path');
const { EventEmitter } = require('events');
const Observer = require('./observer');
const Helpers = require('./settings-helpers');
const Observer = require('./settings-observer');
/**
* Obtain a reference to the Electron app. If electron-settings is required
* within the context of a renderer view, we need to import it via remote.
*
* @see http://electron.atom.io/docs/api/app
* @type {Object}
*/
const app = electron.app || electron.remote.app;
class Settings extends events.EventEmitter {
/**
* The user data path for the Electron app.
*
* @see http://electron.atom.io/docs/api/app/#appgetpathname
* @type {string}
*/
const USER_DATA_PATH = app.getPath('userData');
/**
* The default settings file name.
*
* @type {string}
*/
const SETTINGS_FILE_NAME = 'Settings';
/**
* The Settings class.
*
* @extends events.EventEmitter
*/
class Settings extends EventEmitter {
constructor() {

@@ -51,3 +18,3 @@ super();

/**
* The default settings Object.
* Local reference to the Electron app.
*

@@ -57,82 +24,52 @@ * @type {Object}

*/
this._defaults = {};
this._app = electron.app || electron.remote.app;
/**
* The FSWatcher instance. This will watch if the settings file changes
* and notify key path observers.
* The path to the user data folder for the current app.
*
* @type {FSWatcher}
* @default null
* @type {string}
* @private
*/
this._fsWatcher = null;
this._userDataPath = this._app.getPath('userData');
/**
* Called when the settings file has been created for the first time.
* The absolute path to the settings file.
*
* @type {Function}
* @type {string}
* @private
*/
this._handleSettingsCreate = this._onSettingsCreate.bind(this);
this._settingsPath = path.join(this._userDataPath, 'Settings');
/**
* Called when the file has been changed.
* The FSWatcher instance. This will watch if the settings file and
* notify key path observers.
*
* @type {Function}
* @type {FSWatcher}
* @default null
* @private
*/
this._handleFileChange = this._onFileChange.bind(this);
this._fsWatcher = null;
this._init();
/**
* Called when the settings file is changed or renamed.
*
* @type {Object}
* @private
*/
this._handleSettingsChange = this._onSettingsChange.bind(this);
}
/**
* Initializes the Settings instance.
* Watches the settings file for changes using the native `FSWatcher`
* class in case the settings file is changed outside of
* ElectronSettings' jursidiction.
*
* @private
*/
_init() {
this._registerEvents();
this._observeSettingsFile();
}
/**
* Registers internal event handlers.
*
* @private
*/
_registerEvents() {
this.addListener(Settings.Events.CREATE, this._handleSettingsCreate);
}
/**
* Observes the settings file for changes. It is possible that the settings
* file may be changed from a system outside of electron-settings' control or
* possible a separate electron-settings instance. If this happens, it would
* be nice to trigger key path changes.
*
* @see https://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener
* @param {boolean} [reset=false] Reset the FSWatcher if it already exists.
* @returns {boolean}
* @private
*/
_observeSettingsFile(reset=false) {
const pathToSettings = this.getSettingsFilePath();
// Close the FSWatcher and nullify its reference.
if (reset && this._fsWatcher) {
this._fsWatcher.close();
this._fsWatcher = null;
debug('settings file observer reset');
}
_watchSettings() {
if (!this._fsWatcher) {
try {
this._fsWatcher = fs.watch(pathToSettings, this._handleFileChange);
debug('observing settings file');
} catch (e) {
// File may not yet exist or possible user permissions error.
debug('could not observe settings file at this time');
this._fsWatcher = fs.watch(this._settingsPath, this._handleSettingsChange);
} catch(err) {
// File may not exist yet or possible user permissions error.
}

@@ -143,61 +80,16 @@ }

/**
* Configures electron-settings global default options.
* Writes the given settings object to the disk.
*
* @param {Object} options
* @param {Object} [obj={}]
* @param {Object} [opts={}]
* @private
*/
_configureGlobalSettings(options) {
const opts = this._extendDefaultOptions(options);
Settings.DefaultOptions = opts;
debug(`global configuration set to ${JSON.stringify(opts)}`);
}
/**
* Parses save options and ensures that default values are set if they are
* not provided.
*
* @param {Object} [options]
* @param {boolean} [options.atomicSaving=true]
* @param {boolean} [options.prettify=false]
* @param {boolean} [options.overwrite=false]
* @param {string} [options.settingsDir=USER_DATA_PATH]
* @param {string} [options.settingsFileName=Settings]
* @returns {Object}
* @private
*/
_extendDefaultOptions(options={}) {
return Object.assign({}, Settings.DefaultOptions, options);
}
/**
* Sets electron-settings default settings. These will be applied upon
* settings file creation, as well as `applyDefaults()` and
* `resetToDefaults()`.
*
* @param {Object} obj
* @private
*/
_setDefaults(obj) {
this._defaults = clone(obj);
debug(`defaults set to ${JSON.stringify(this._defaults)}`);
}
/**
* Deletes the settings file. This may occur if the data has become corrupted
* and can no longer be read.
*
* @private
*/
_unlinkSettingsFileSync() {
const pathToSettings = this.getSettingsFilePath();
_writeSettings(obj={}, opts={}) {
try {
fs.unlinkSync(pathToSettings);
debug(`settings file deleted at ${pathToSettings}`);
} catch (e) {
// Do nothing.
fs.outputJsonSync(this._settingsPath, obj, {
spaces: opts.prettify ? 2 : 0
});
this._watchSettings();
} catch(err) {
// Something went wrong.
}

@@ -207,106 +99,14 @@ }

/**
* Deletes the settings file and re-ensures its existence with default
* settings if possible. This is the doomsday scenario.
* Returns the settings from the settings file, or creates the file
* if it does not yet exist.
*
* @private
*/
_resetSettingsFileSync() {
debug('resetting settings file...');
this._unlinkSettingsFileSync();
this._ensureSettingsFileSync();
}
/**
* Checks if the settings file exists on the disk. If it does not, it is
* created with an empty object as its contents.
*
* @returns {Promise}
* @private
*/
_ensureSettingsFile() {
debug('ensuring settings file...');
return new Promise((resolve, reject) => {
if (!this.settingsFileExists()) {
const defaults = this._defaults;
this._writeSettingsFile(defaults).then(() => {
this._emitCreateEvents();
resolve();
}, reject);
} else {
resolve();
}
});
}
/**
* The synchronous version of `_ensureSettingsFile()`.
*
* @see _ensureSettingsFile
* @private
*/
_ensureSettingsFileSync() {
debug('ensuring settings file...');
if (!this.settingsFileExists()) {
const defaults = this._defaults;
this._writeSettingsFileSync(defaults);
this._emitCreateEvents();
}
}
/**
* Reads the settings file from the disk and parses the contents as JSON.
*
* @returns {Promise}
* @private
*/
_readSettingsFile() {
return new Promise((resolve, reject) => {
this._ensureSettingsFile().then(() => {
const pathToSettings = this.getSettingsFilePath();
debug('reading settings...');
fs.readJson(pathToSettings, (err, obj) => {
if (err) {
debug(`ERROR: malformed JSON detected at ${pathToSettings}`);
this._resetSettingsFileSync();
this._readSettingsFile().then(resolve, reject);
} else {
resolve(obj);
}
});
}, reject);
});
}
/**
* The synchronous version of `_readSettingsFile()`.
*
* @see _readSettingsFile
* @returns {Object}
* @private
*/
_readSettingsFileSync() {
this._ensureSettingsFileSync();
const pathToSettings = this.getSettingsFilePath();
_readSettings() {
try {
debug('reading settings...');
const obj = fs.readJsonSync(pathToSettings);
return obj;
} catch (e) {
debug(`ERROR: malformed JSON detected at ${pathToSettings}`);
this._resetSettingsFileSync();
return this._readSettingsFileSync();
return fs.readJsonSync(this._settingsPath);
} catch(err) {
this._writeSettings();
return {};
}

@@ -316,169 +116,48 @@ }

/**
* Parses the given object to a JSON string and saves it to the disk. If
* atomic saving is enabled, then we firt save a temp file, and once it has
* been successfully written, we overwrite the old settings file.
* Called when the settings file has been changed or
* renamed (moved/deleted).
*
* @param {Object} obj
* @param {Object} [options]
* @returns {Promise}
* @type {string} eventType
* @private
*/
_writeSettingsFile(obj, options) {
debug('writing settings file...');
const opts = this._extendDefaultOptions(options);
const pathToSettings = this.getSettingsFilePath();
const spaces = opts.prettify ? 2 : 0;
return new Promise((resolve, reject) => {
if (opts.atomicSaving) {
const tmpFilePath = `${pathToSettings}-tmp`;
fs.outputJson(tmpFilePath, obj, { spaces }, err => {
if (!err) {
fs.rename(tmpFilePath, pathToSettings, err => {
if (err) {
reject(err);
} else {
this._observeSettingsFile(true);
this._emitWriteEvents();
resolve();
}
});
} else {
fs.unlink(tmpFilePath, () => {
this._resetSettingsFileSync();
reject(err);
});
}
});
} else {
fs.outputJson(pathToSettings, obj, { spaces }, err => {
if (err) {
reject(err);
} else {
this._observeSettingsFile(true);
this._emitWriteEvents();
resolve();
}
});
_onSettingsChange(eventType) {
switch (eventType) {
case 'change': {
this.emit(Settings.Events.CHANGE);
break;
}
});
}
/**
* The synchronous version of `_writeSettingsFile()`.
*
* @see _writeSettingsFile
* @private
*/
_writeSettingsFileSync(obj, options) {
debug('writing settings file...');
const opts = this._extendDefaultOptions(options);
const pathToSettings = this.getSettingsFilePath();
const spaces = opts.prettify ? 2 : 0;
if (opts.atomicSaving) {
const tmpFilePath = `${pathToSettings}-tmp`;
try {
fs.outputJsonSync(tmpFilePath, obj, { spaces });
fs.renameSync(tmpFilePath, pathToSettings);
} catch (e) {
try {
fs.unlinkSync(tmpFilePath);
} catch (e) {
// Do nothing.
}
return;
case 'rename': {
this._fsWatcher.close();
this._fsWatcher = null;
break;
}
this._observeSettingsFile(true);
} else {
fs.outputJsonSync(pathToSettings, obj, { spaces });
this._observeSettingsFile();
}
this._emitWriteEvents();
}
/**
* Emits the internal and public "create" events.
* Watches the given key path for changes and calls the given handler
* if the value changes. To unsubscribe from changes, call `dispose()`
* on the Observer instance that is returned.
*
* @emits Settings#create
* @param {string} keyPath
* @param {Function} handler
* @returns {Observer}
* @public
*/
_emitCreateEvents() {
this.emit(Settings.InternalEvents.CREATE, this.getSettingsFilePath());
this.emit(Settings.Events.CREATE, this.getSettingsFilePath());
watch(keyPath, handler) {
return new Observer(this, keyPath, handler);
}
/**
* Emits the internal and public "write" events.
* Returns a boolean indicating whether the settings object contains
* the given key path.
*
* @emits Settings#save
*/
_emitWriteEvents() {
this.emit(Settings.InternalEvents.WRITE);
this.emit(Settings.Events.WRITE);
}
/**
* Called when the "create" event fires.
*
* @private
*/
_onSettingsCreate() {
debug(`settings file created at ${this.getSettingsFilePath()}`);
}
/**
* Called when the settings file has changed.
*
* @param {string} eventType Either "rename" or "change".
* @param {string} filename The name of the file that triggered the event.
*/
_onFileChange(eventType, filename) {
if (eventType === Settings.FSWatcherEventTypes.CHANGE) {
debug(`detected change to settings file`);
this._emitWriteEvents();
}
}
/**
* Checks if the chosen key path exists within the settings object.
*
* @throws if key path is not a string.
* @param {string} keyPath
* @returns {Promise}
* @returns {boolean}
* @public
*/
has(keyPath) {
debug(`called has() at "${keyPath}"`);
const obj = this._readSettings();
const keyPathExists = Helpers.hasKeyPath(obj, keyPath);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
return new Promise((resolve, reject) => {
this._readSettingsFile().then(obj => {
const keyPathExists = helpers.hasKeyPath(obj, keyPath);
resolve(keyPathExists);
}, reject);
});
}
/**
* The synchronous version of `has()`.
*
* @see has
*/
hasSync(keyPath) {
debug(`called hasSync() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
const obj = this._readSettingsFileSync();
const keyPathExists = helpers.hasKeyPath(obj, keyPath);
return keyPathExists;

@@ -488,340 +167,94 @@ }

/**
* Gets the value at the chosen key path.
* Returns the value at the given key path, or sets the value at that key
* path to the default value, if provided, if the key does not exist.
*
* @param {string} [keyPath]
* @returns {Promise}
* @param {string} keyPath
* @param {any} [defaultValue]
* @returns {any}
* @public
*/
get(keyPath) {
debug(`called get() at "${keyPath}"`);
get(keyPath, defaultValue) {
const obj = this._readSettings();
const keyPathExists = Helpers.hasKeyPath(obj, keyPath);
const value = Helpers.getValueAtKeyPath(obj, keyPath);
return new Promise((resolve, reject) => {
this._readSettingsFile().then(obj => {
let value = obj;
if (!keyPathExists && typeof defaultValue !== 'undefined') {
Helpers.setValueAtKeyPath(obj, keyPath, defaultValue);
if (typeof keyPath === 'string') {
value = helpers.getValueAtKeyPath(obj, keyPath);
}
resolve(value);
}, reject);
});
}
/**
* The synchronous version of `get()`.
*
* @see get
*/
getSync(keyPath) {
debug(`called getSync() at "${keyPath}"`);
let value = this._readSettingsFileSync();
if (typeof keyPath === 'string') {
value = helpers.getValueAtKeyPath(value, keyPath);
return clone(defaultValue);
} else {
return value;
}
return value;
}
/**
* Sets the value at the chosen key path.
* Returns all settings.
*
* @throws if key path is not a string.
* @throws if options is not an object.
* @param {string} keyPath
* @param {any} [value]
* @param {Object} [options]
* @returns {Promise}
* @returns {Object}
* @public
*/
set(keyPath, value={}, options={}) {
debug(`called set() at "${keyPath}"`);
getAll() {
const obj = this._readSettings();
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
return new Promise((resolve, reject) => {
this._readSettingsFile().then(obj => {
helpers.setValueAtKeyPath(obj, keyPath, value);
this._writeSettingsFile(obj, options).then(resolve, reject);
}, reject);
});
return obj;
}
/**
* The synchronous version of `set()`.
* Sets the value at the given key path.
*
* @see set
*/
setSync(keyPath, value={}, options={}) {
debug(`called setSync() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
const obj = this._readSettingsFileSync();
helpers.setValueAtKeyPath(obj, keyPath, value);
this._writeSettingsFileSync(obj, options);
}
/**
* Deletes the key and value at the chosen key path.
*
* @throws if key path is not a string.
* @throws if options is not an object.
* @param {string} keyPath
* @param {Object} [options]
* @returns {Promise}
* @param {any} value
* @param {Object} [opts]
* @public
*/
delete(keyPath, options={}) {
debug(`called delete() at "${keyPath}"`);
set(keyPath, value, opts) {
const obj = this._readSettings();
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
return new Promise((resolve, reject) => {
this._readSettingsFile().then(obj => {
helpers.deleteValueAtKeyPath(obj, keyPath);
this._writeSettingsFile(obj, options).then(resolve, reject);
}, reject);
});
Helpers.setValueAtKeyPath(obj, keyPath, value);
this._writeSettings(obj, opts);
}
/**
* The synchronous version of `delete()`.
* Sets all settings.
*
* @see delete
* @param {Object}
* @param {Object} [opts]
* @public
*/
deleteSync(keyPath, options={}) {
debug(`called deleteSync() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
const obj = this._readSettingsFileSync();
helpers.deleteValueAtKeyPath(obj, keyPath);
this._writeSettingsFileSync(obj, options);
}
/**
* Clears all settings and replaces the file contents with an empty object.
*
* @throws if options is not an object.
* @param {Object} [options]
* @param {boolean} [options.atomicSaving=true]
* @param {boolean} [options.prettify=false]
* @returns {Promise}
*/
clear(options={}) {
debug('called clear()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
return this._writeSettingsFile({}, options);
}
/**
* The synchronous version of `clear()`.
*
* @see clear
*/
clearSync(options={}) {
debug('called clearSync()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
this._writeSettingsFileSync({}, options);
}
/**
* Sets default settings.
*
* @throws if defaults is not an object.
* @param {Object} [options={}
* @returns {Promise}
*/
defaults(defaults) {
assert.strictEqual(typeof defaults, 'object', 'Defaults must be an object');
this._setDefaults(defaults);
}
/**
* Extends the current settings with the default settings. Optionally, you
* may overwrite pre-existing settings with their repsective defaults by
* setting `options.overwrite` to true. Set defaults using the `defaults()`
* method.
*
* @throws if options is not an object.
* @param {Object} [options]
* @returns {Promise}
*/
applyDefaults(options={}) {
debug('called applyDefaults()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
return new Promise((resolve, reject) => {
this._readSettingsFile().then(obj => {
let newObj;
if (options.overwrite === true) {
newObj = deepExtend({}, obj, this._defaults);
} else {
newObj = deepExtend({}, this._defaults, obj);
}
this._writeSettingsFile(newObj, options).then(resolve, reject);
});
});
}
/**
* The synchronous version of `applyDefaults()`.
*
* @see applyDefaults
*/
applyDefaultsSync(options={}) {
debug('called applyDefaultsSync()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
let obj = this._readSettingsFileSync();
let newObj;
if (options.overwrite === true) {
newObj = deepExtend({}, obj, this._defaults);
} else {
newObj = deepExtend({}, this._defaults, obj);
setAll(obj, opts) {
if (typeof obj === 'object') {
this._writeSettings(obj, opts);
}
this._writeSettingsFileSync(newObj, options);
}
/**
* Resets the settings to defaults. Set defaults using the `defaults()`
* method.
* Deletes the key and value at the given key path.
*
* @throws if options is not an object.
* @param {Object} [options]
* @returns {Promise}
*/
resetToDefaults(options={}) {
debug('called resetToDefaults()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
const defaults = this._defaults;
return this._writeSettingsFile(defaults, options);
}
/**
* The synchronous version of `resetToDefaults()`.
*
* @see resetToDefaults
*/
resetToDefaultsSync(options={}) {
debug('called resetToDefaultsSync()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');
const defaults = this._defaults;
this._writeSettingsFileSync(defaults, options);
}
/**
* Observes the chosen key path for changes and calls the handler if the
* value changes. Returns an Observer instance which has a `dispose` method.
* To unsubscribe, simply call `dispose()` on the returned key path observer.
*
* @throws if key path is not a string.
* @throws if handler is not a function.
* @param {string} keyPath
* @param {Function} handler
* @returns {Observer} The key path observer.
* @param {Object} [opts]
* @public
*/
observe(keyPath, handler) {
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');
assert.strictEqual(typeof handler, 'function', 'Handler must be a function');
delete(keyPath, opts) {
const obj = this._readSettings();
const keyPathExists = Helpers.hasKeyPath(obj, keyPath);
const observer = new Observer(this, keyPath, handler);
return observer;
if (keyPathExists) {
Helpers.deleteValueAtKeyPath(obj, keyPath);
this._writeSettings(obj, opts);
}
}
/**
* Globally configure electron-settings options.
* Deletes all settings.
*
* @throws if options is not an object.
* @param {Object} options
* @param {boolean} [options.atomicSaving=true]
* @param {boolean} [options.prettify=false]
* @param {Object} [options.defaults]
* @public
*/
configure(options) {
assert.strictEqual(typeof options, 'object', 'Options must be an object');
this._configureGlobalSettings(options);
deleteAll() {
this._writeSettings({});
}
/**
* Returns the path to the settings file on the disk,
*
* @returns {string}
*/
getSettingsFilePath() {
const settingsDir = Settings.DefaultOptions.settingsDir;
const settingsFileName = Settings.DefaultOptions.settingsFileName;
const settingsFilePath = path.join(settingsDir, settingsFileName);
return settingsFilePath;
}
/**
* Checks if the settings file currently exists on the disk.
*
* @returns {boolean}
*/
settingsFileExists() {
const pathToSettings = this.getSettingsFilePath();
const fileExists = exists(pathToSettings);
return fileExists;
}
/**
* Why doesn't this exist?
*
* @alias EventListener.removeListener
*/
off() {
return this.removeListener.apply(this, arguments);
}
}
/**
* Default save options.
* ElectronSettings event names.
*
* @type {Object}
* @readonly
*/
Settings.DefaultOptions = {
atomicSaving: true,
prettify: false,
settingsDir: USER_DATA_PATH,
settingsFileName: SETTINGS_FILE_NAME,
overwrite: false
};
/**
* Settings event names.
*
* @enum {string}

@@ -831,38 +264,5 @@ * @readonly

Settings.Events = {
CREATE: 'create',
WRITE: 'write',
CHANGE: 'change'
};
/**
* Settings internal event names.
*
* @enum {string}
* @readonly
*/
Settings.InternalEvents = {
CREATE: '_create',
WRITE: '_write',
CHANGE: '_change'
};
/**
* FSWatcher event types.
*
* @enum {string}
* @readonly
*/
Settings.FSWatcherEventTypes = {
CHANGE: 'change',
RENAME: 'rename'
};
/**
* The Settings instance.
*
* @type {Settings}
* @readonly
*/
Settings.Instance = new Settings();
module.exports = Settings.Instance;
module.exports = Settings;
ISC License
Copyright (c) 2016, Nathan Buchar
Copyright (c) 2017, Nathan Buchar

@@ -5,0 +5,0 @@ Permission to use, copy, modify, and/or distribute this software for any

{
"name": "electron-settings",
"version": "2.2.4",
"version": "3.0.0",
"description": "A simple persistent user settings manager for Electron.",

@@ -11,2 +11,8 @@ "main": "index.js",

},
"repository": {
"type": "git",
"url": "https://github.com/nathanbuchar/electron-settings"
},
"author": "Nathan Buchar <hello@nathanbuchar.com>",
"license": "ISC",
"keywords": [

@@ -18,46 +24,25 @@ "electron",

"settings",
"manager",
"config",
"storage",
"json",
"storage",
"promise",
"has",
"get",
"getAll",
"set",
"setAll",
"delete",
"reset",
"clear"
"deleteAll",
"watch"
],
"repository": {
"type": "git",
"url": "https://github.com/nathanbuchar/electron-settings"
},
"author": "Nathan Buchar <hello@nathanbuchar.com>",
"contributors": [
{
"name": "Nathan Buchar",
"email": "hello@nathanbuchar.com",
"web": "http://nathanbuchar,com/"
},
{
"name": "Kai Eichinger",
"email": "kai.eichinger@outlook.com"
}
],
"license": "ISC",
"dependencies": {
"clone": "^1.0.2",
"debug": "^2.2.0",
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"deep-extend": "^0.4.1",
"file-exists": "^2.0.0",
"fs-extra": "^0.30.0",
"key-path-helpers": "^0.4.0"
"fs-extra": "^2.1.2"
},
"devDependencies": {
"chai": "^3.5.0",
"electron-mocha": "^3.0.0",
"electron-prebuilt": "^1.2.6",
"mocha": "^3.0.2"
"electron-mocha": "^3.4.0",
"electron-prebuilt": "^1.4.13",
"mocha": "^3.2.0"
}
}

@@ -1,14 +0,9 @@

electron-settings
=================
# electron-settings
**:warning: Sorry, project not currently in active development. Try [electron-json-storage](https://www.npmjs.com/package/electron-json-storage) :warning:**
A simple persistent user settings manager for [Electron][external_electron].
***
Originally adapted from Atom's own configuration manager, electron-settings allows you to save your users' settings to the disk so that they can be loaded in the next time your app starts without skipping a beat.
A simple persistent user settings manager for [Electron][external_electron]. Originally adapted from [Atom's own configuration manager][external_atom-config], electron-settings allows you to save user settings to the disk so that they can be loaded in the next time your app starts.
Also, you can [subscribe to settings and get notified when their value changes][section_methods_watch]. So that's pretty neat.
Also, you can [observe key paths][method_observe] and get notified if their value changes. So that's pretty neat.
**Note:** v2 is not compatible with earlier versions of electron-settings.
[![npm version](https://badge.fury.io/js/electron-settings.svg)](http://badge.fury.io/js/electron-settings)

@@ -25,12 +20,10 @@ [![dependencies](https://david-dm.org/nathanbuchar/electron-settings.svg)](https://david-dm.org/nathanbuchar/electron-settings)

Install
---------
## Install
```
$ npm install electron-settings
$ npm install --save electron-settings
```
Quick Start
-----------
## Demo

@@ -43,94 +36,382 @@ ```js

last: 'Kramer'
}).then(() => {
settings.get('name.first').then(val => {
console.log(val);
// => "Cosmo"
});
});
settings.getSettingsFilePath();
// => /Users/You/Library/Application Support/YourApp/Settings
settings.get('name.first');
// => "Cosmo"
settings.has('name.middle');
// => false
```
Default Settings
----------------
## FAQ
You can configure default settings by using [`settings.defaults()`][method_defaults]. This will set the defaults object globally. If this is the first time the settings file is being accessed, the defaults will be applied automatically.
* **What is a "key path"?**
```js
settings.defaults({
foo: 'bar'
});
With electron-settings, you are not just setting keys like you would with local storage. Instead, you are working with a JSON object, and a key path is a string that points to a specific key within that object—essentially using object dot notation in string form.
settings.get('foo').then(val => {
console.log(val);
// => 'bar'
});
```
For example, in the JSON object below the value at the key path `"foo"` is the object `{ bar: 'baz' }`, and the value at the key path `"foo.bar"` is the string `"baz"`.
Additionally, you can use [`applyDefaults()`][method_apply-defaults] or [`resetToDefaults()`][method_reset-to-defaults] to fit your needs.
```json
{
"foo": {
"bar": "baz"
}
}
```
* **What data types may be stored?**
You may set a key path to any value supported by JSON: an **object**, **array**, **string**, **number**, **boolean**, or **`null`**.
FAQ
---
Unfortunately, dates and other special object types will be type converted and lost, because JSON does not support anything other than the aforementioned data types.
* **What is a "key path"?**
* **Where is the settings file saved?**
With electron-settings, you are not just setting keys like you would with local storage. Instead, you are working with a JSON object, and a key path is a string that points to a specific key within that object—essentially object dot notation in string form.
Settings are saved in your app's [user data directory](http://electron.atom.io/docs/api/app/#appgetpathname) in a file called `Settings`.
For example, in the JSON object below the value at the key path `"foo.bar"` is `"baz"`.
* `~/Library/Application Support/YourApp` on MacOS.
* `%APPDATA%/YourApp` on Windows.
* `$XDG_CONFIG_HOME/YourApp` or `~/.config/YourApp` on Linux.
```json
{
"foo": {
"bar": "baz"
* **Can I use electron-settings in both the main and renderer processes?**
You bet!
***
## Methods
* [`has()`][section_methods_has]
* [`get()`][section_methods_get]
* [`getAll()`][section_methods_get-all]
* [`set()`][section_methods_set]
* [`setAll()`][section_methods_set-all]
* [`delete()`][section_methods_delete]
* [`deleteAll()`][section_methods_delete-all]
* [`watch()`][section_methods_watch]
***
* ### has()
**`settings.has(keyPath):boolean`**
Returns a boolean indicating whether the settings object contains the given key path.
***
**Parameters**
* **`keyPath`** *String*
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
}
```
```
* **Can I use electron-settings in both the main and renderer processes?**
Checks if the settings contains the key path `"foo.bar"`.
```js
settings.has('foo.bar');
// => true
```
Yes! Just be aware that if the window closes during an async operation, data may be lost.
Checks if the settings contains the key path `"qux"`.
```js
settings.has('qux');
// => false
```
* **What data types may be stored?**
You may set a key path to any value supported by JSON: an object, array, string, number, boolean, or `null`.
* ### get()
* **Why do I have to use promises?**
**`settings.get(keyPath[, defaultValue]):any`**
electron-settings reads and writes to the file system asynchronously. In order to ensure data integrity, you should use promises. Alternatively, all methods have a synchronous counterpart that you may use instead.
Returns the value at the given key path, or sets the value at that key path to the default value, if provided, if the key does not exist. See also: [`getAll()`][section_methods_get-all].
* **Where is the settings file saved?**
***
The settings file is named `Settings` and is saved in your app's [user data directory](http://electron.atom.io/docs/api/app/#appgetpathname):
**Parameters**
* `~/Library/Application Support/YourApp` on MacOS.
* `%APPDATA%/YourApp` on Windows.
* `$XDG_CONFIG_HOME/YourApp` or `~/.config/YourApp` on Linux.
* **`keyPath`** *String*
* **`defaultValue`** *Any* - The value to apply if the setting does not already exist.
You can use [`getSettingsFilePath()`][method_get-settings-file-path] to get the full path to the settings file.
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
***
Gets the value at `"foo"`.
```js
settings.get('foo');
// => { "bar": "baz" }
```
Gets the value at `"foo.bar"`.
```js
settings.get('foo.bar');
// => "baz"
```
Gets the value at `"qux"`.
```js
settings.get('qux');
// => undefined
```
Documentation
-------------
* [Events][docs_events]
* [Methods][docs_methods]
Gets the value at `"qux"`, with a default fallback.
```js
settings.get('qux', 'aqpw');
// => "aqpw"
```
Contributors
-------
* [Nathan Buchar](mailto:hello@nathanbuchar.com) (Owner)
* [Kai Eichinger](mailto:kai.eichinger@outlook.com)
* *You?*
* ### getAll()
**`settings.getAll():Object`**
License
-------
Returns all settings. See also: [`get()`][section_methods_get].
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
Gets all settings.
```js
settings.getAll();
// => { "foo": { "bar": "baz" } }
```
* ### set()
**`settings.set(keyPath, value[, options])`**
Sets the value at the given key path. See also: [`setAll()`][section_methods_set-all].
***
**Parameters**
* **`keyPath`** *String* - The path to the key whose value we wish to set. This key need not already exist.
* **`value`** *Any* - The value to set the key at the chosen key path to. This must be a data type supported by JSON: an object, array, string, number, boolean, or `null`.
* **`options`** *Object* (optional)
* `prettify` *Boolean* (optional) - Prettify the JSON output. Defaults to `false`.
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
Changing the value at the key path `"foo.bar"` from `"baz"` to `"qux"`.
```js
settings.set('foo.bar', 'qux');
settings.get('foo.bar');
// => "qux"
```
Setting the value at the key path `"new.key"`.
```js
settings.set('new', 'hotness');
settings.get('new');
// => "hotness"
```
* ### setAll()
**`settings.setAll(obj[, options])`**
Sets all settings. See also: [`set()`][section_methods_set].
***
**Parameters**
* **`obj`** *Object* - The new settings object.
* **`options`** *Object* (optional)
* `prettify` *Boolean* (optional) - Prettify the JSON output. Defaults to `false`.
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
Sets all settings.
```js
settings.setAll({ new: 'hotness' });
settings.getAll();
// => { "new": "hotness" }
```
* ### delete()
**`settings.delete(keyPath[, options])`**
Deletes the key and value at the given key path. See also: [`deleteAll()`][section_methods_delete-all].
***
**Parameters**
* **`keyPath`** *String*
* **`options`** *Object* (optional)
* `prettify` *Boolean* (optional) - Prettify the JSON output. Defaults to `false`.
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
Deleting `"foo.bar"`.
```js
settings.delete('foo.bar');
settings.get('foo');
// => {}
```
* ### deleteAll()
**`settings.deleteAll([options])`**
Deletes all settings. See also: [`delete()`][section_methods_delete].
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
Deletes all settings.
```js
settings.deleteAll();
settings.getAll();
// => {}
```
* ### watch()
**`settings.watch(keyPath, handler):Function`**
Watches the given key path for changes and calls the given handler if the value changes. To unsubscribe from changes, call `dispose()` on the Observer instance that is returned.
***
**Parameters**
* **`keyPath`** *String* - The path to the key that we wish to watch for changes.
* **`handler`** *Function* - The callback that will be invoked if the value at the chosen key path changes. Passes the following as arguments:
* `newValue` *Any*
* `oldValue` *Any*
***
**Examples**
Given:
```json
{
"foo": {
"bar": "baz"
}
}
```
Watch `"foo.bar"`.
```js
settings.watch('foo', (newValue, oldValue) => {
console.log(newValue);
// => "qux"
});
settings.set('foo.bar', 'qux');
```
Dispose the key path watcher after the value has changed once.
```js
const observer = settings.watch('foo', newValue => {
observer.dispose();
});
settings.set('foo', 'qux');
});
```
## Authors
* [Nathan Buchar] (Owner)
## License
[ISC][license]

@@ -140,5 +421,4 @@

***
<small>Last updated **Aug. 16th, 2016** by [Nathan Buchar].</small>
**Having trouble?** [Get help on Gitter][external_gitter].</small>
<small>**Having trouble?** [Get help on Gitter][external_gitter].</small>

@@ -149,3 +429,2 @@

[license]: ./LICENSE.md

@@ -156,20 +435,18 @@

[section_install]: #install
[section_quick-start]: #quick-start
[section_default-settings]: #default-settings
[section_demo]: #demo
[section_faq]: #faq
[section_documentation]: #documentation
[section_contributors]: #contributors
[section_methods]: #methods
[section_authors]: #authors
[section_license]: #license
[docs_events]: ./docs/events.md
[docs_methods]: ./docs/methods.md
[section_methods_has]: #has
[section_methods_get]: #get
[section_methods_get-all]: #getall
[section_methods_set]: #set
[section_methods_set-all]: #setall
[section_methods_delete]: #delete
[section_methods_delete-all]: #deleteall
[section_methods_watch]: #watch
[method_get-settings-file-path]: ./docs/methods.md#getsettingsfilepath
[method_observe]: ./docs/methods.md#observe
[method_defaults]: ./docs/methods.md#defaults
[method_apply-defaults]: ./docs/methods.md#applydefaults
[method_reset-to-defaults]: ./docs/methods.md#resettodefaults
[external_electron]: https://electron.atom.com
[external_atom-config]: https://github.com/atom/atom/blob/master/src/config.coffee
[external_electron]: https://electron.atom.io
[external_gitter]: https://gitter.im/nathanbuchar/electron-settings

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc