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.1.1 to 2.2.0

9

CHANGELOG.md

@@ -8,2 +8,11 @@ Changelog

2.2.0 - Aug. 31, 2016
---------------------
* Improved internal debugger.
* Adds tests to test non-atomic saving.
* Adds tests for the `create` and `write` events.
* Add FSWatcher to trigger write events if the settings file is changed externally.
* Adds `options.settingsDir` and `options.settingsFileName` (needs tests).
* Updates dev dependencies.
2.1.1 - Aug. 3, 2016

@@ -10,0 +19,0 @@ --------------------

138

docs/methods.md

@@ -12,3 +12,2 @@ [Electron Settings] » **Methods**

* [`defaults()`][method_defaults]
* [`observe()`][method_observe]
* [`has()`][method_has] [*sync*][method_has-sync]

@@ -21,2 +20,3 @@ * [`get()`][method_get] [*sync*][method_get-sync]

* [`resetToDefaults()`][method_reset-to-defaults] [*sync*][method_reset-to-defaults-sync]
* [`observe()`][method_observe]
* [`getSettingsFilePath()`][method_get-settings-file-path]

@@ -86,2 +86,3 @@

settings.get('name.first').then(val => {
console.log(val);
// => Joe

@@ -95,56 +96,2 @@ });

observe()
---------
**`settings.observe(keyPath, handler):Function`**
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.
**Arguments**
* **`keyPath`** *String* - The path to the key that we wish to observe.
* **`handler`** *Function* - The callback that will be invoked if the value at the chosen key path changes. Returns:
* `evt` *Object*
* `oldValue` *Any*
* `newValue` *Any*
**Examples**
Given:
```json
{
"foo": "bar"
}
```
Observe `"foo"`.
```js
settings.observe('foo', evt => {
// => {
// oldValue: 'bar',
// newValue: 'qux'
// }
});
settings.set('foo', 'qux');
```
Dispose the key path observer.
```js
const observer = settings.observe('foo', evt => {
// => {
// oldValue: 'bar',
// newValue: 'qux'
// }
});
settings.set('foo', 'qux').then(() => {
observer.dispose();
});
```
***
has()

@@ -175,2 +122,3 @@ -----

settings.has('foo.bar').then(exists => {
console.log(exists);
// => true

@@ -183,2 +131,3 @@ });

settings.has('grizzknuckle').then(exists => {
console.log(exists);
// => false

@@ -250,3 +199,4 @@ });

```js
settings.get().then(value => {
settings.get().then(val => {
console.log(val);
// => { foo: { bar: 'baz' } }

@@ -258,3 +208,4 @@ });

```js
settings.get('foo.bar').then(value => {
settings.get('foo.bar').then(val => {
console.log(val);
// => 'baz'

@@ -266,3 +217,4 @@ });

```js
settings.get('snap').then(value => {
settings.get('snap').then(val => {
console.log(val);
// => undefined

@@ -342,3 +294,4 @@ });

}).then(() => {
settings.get('user.name.first').then(value => {
settings.get('user.name.first').then(val => {
console.log(val);
// => 'Cosmo'

@@ -410,3 +363,4 @@ });

settings.delete('foo.bar').then(() => {
settings.get('foo').then(value => {
settings.get('foo').then(val => {
console.log(val);
// => { foo: {} }

@@ -459,3 +413,4 @@ });

settings.clear(() => {
settings.get(value => {
settings.get(val => {
console.log(val);
// => {}

@@ -530,2 +485,3 @@ });

settings.get().then(obj => {
console.log(obj);
// => {

@@ -552,2 +508,3 @@ // user: {

settings.get().then(obj => {
console.log(obj);
// => {

@@ -616,2 +573,3 @@ // user: {

settings.get().then(obj => {
console.log(obj);
// => {

@@ -639,2 +597,58 @@ // foo: 'bar'

observe()
---------
**`settings.observe(keyPath, handler):Function`**
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.
**Arguments**
* **`keyPath`** *String* - The path to the key that we wish to observe.
* **`handler`** *Function* - The callback that will be invoked if the value at the chosen key path changes. Returns:
* `evt` *Object*
* `oldValue` *Any*
* `newValue` *Any*
**Examples**
Given:
```json
{
"foo": "bar"
}
```
Observe `"foo"`.
```js
settings.observe('foo', evt => {
console.log(evt);
// => {
// oldValue: 'bar',
// newValue: 'qux'
// }
});
settings.set('foo', 'qux');
```
Dispose the key path observer.
```js
const observer = settings.observe('foo', evt => {
console.log(evt);
// => {
// oldValue: 'bar',
// newValue: 'qux'
// }
});
settings.set('foo', 'qux').then(() => {
observer.dispose();
});
```
***
getSettingsFilePath()

@@ -660,3 +674,3 @@ ------------------------

***
<small>Last updated **Aug. 2nd, 2016** by [Nathan Buchar].</small>
<small>Last updated **Aug. 16th, 2016** by [Nathan Buchar].</small>

@@ -663,0 +677,0 @@ <small>**Having trouble?** [Get help on Gitter](https://gitter.im/nathanbuchar/electron-settings).</small>

'use strict';
const clone = require('clone');
const equal = require('deep-equal');
const debug = require('debug')('electron-settings:observer');
const deepEqual = require('deep-equal');

@@ -14,5 +15,8 @@ class Observer {

* @param {Function} handler
* @returns {Object} this
*/
constructor(settings, keyPath, handler) {
debug(`new key path observer for "${keyPath}"`);
/**

@@ -49,3 +53,3 @@ * Reference to the settings instance.

*/
this._currentValue = this._settings.getSync(keyPath);
this._currentValue = this._getCurrentValue();

@@ -58,17 +62,24 @@ /**

*/
this._handleWrite = this._onWrite.bind(this);
this._handleSettingsWrite = this._onSettingsChange.bind(this);
return this._init();
/**
* Bind write listener.
*/
this._settings.on('write', this._handleSettingsWrite);
return this;
}
/**
* Initializes the key path observer.
* Returns the current value of the observed key path.
*
* @returns {Object} this
* @returns {any} value
* @private
*/
_init() {
this._settings.on('write', this._handleWrite);
_getCurrentValue() {
const settings = this._settings;
const keyPath = this._keyPath;
const value = settings.getSync(keyPath);
return this;
return value;
}

@@ -81,7 +92,9 @@

*/
_onWrite() {
_onSettingsChange() {
const oldValue = this._currentValue;
const newValue = this._settings.getSync(this._keyPath);
const newValue = this._getCurrentValue();
if (!equal(newValue, oldValue)) {
if (!deepEqual(newValue, oldValue)) {
debug(`detected change at "${this._keyPath}"`);
this._currentValue = clone(newValue);

@@ -96,7 +109,9 @@ this._handler.call(this, {

/**
* Disposes of the key path observer.
* Disposes of the key path observer by unbinding the event listener and
* nullifying all internal references.
*/
dispose() {
this._settings.off('write', this._handleWrite);
const keyPath = this._keyPath;
this._settings.removeListener('write', this._handleSettingsWrite);
this._settings = null;

@@ -106,3 +121,5 @@ this._keyPath = null;

this._currentValue = null;
this._handleWrite = null;
this._handleSettingsWrite = null;
debug(`key path observer for "${keyPath}" disposed`);
}

@@ -109,0 +126,0 @@ }

'use strict';
const assert = require('assert');
const debug = require('debug')('electron-settings');
const debug = require('debug')('electron-settings:main');
const deepExtend = require('deep-extend');

@@ -26,2 +26,17 @@ const clone = require('clone');

/**
* 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.

@@ -37,3 +52,3 @@ *

/**
* Default settings.
* The default settings Object.
*

@@ -45,33 +60,96 @@ * @type Object

// Handle "create" events.
this.addListener(Settings.Events.CREATE, this._onCreate.bind(this));
/**
* The FSWatcher instance. This will watch if the settings file changes
* and notify key path observers.
*
* @type fs.FSWatcher
* @default null
* @private
*/
this._fsWatcher = null;
// Handle "write" events.
this.addListener(Settings.Events.WRITE, this._onWrite.bind(this));
/**
* Called when the settings file has been created for the first time.
*
* @type Function
* @private
*/
this._handleSettingsCreate = this._onSettingsCreate.bind(this);
/**
* Called when the file has been changed.
*
* @type Function
* @private
*/
this._handleFileChange = this._onFileChange.bind(this);
this._init();
}
/**
* Configures electron-settings global default options.
* Initializes the Settings instance.
*
* @param {Object} options
* @private
*/
_configureGlobalSettings(options) {
const opts = this._extendDefaultOptions(options);
_init() {
this._registerEvents();
this._observeSettingsFile();
}
Settings.DefaultOptions = opts;
/**
* Registers internal event handlers.
*
* @private
*/
_registerEvents() {
this.addListener(Settings.Events.CREATE, this._handleSettingsCreate);
}
debug(`global settings configured to ${JSON.stringify(opts)}`);
/**
* 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');
}
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');
}
}
}
/**
* Sets electron-settings default settings. These will be applied upon
* settings file creation, as well as `applyDefaults()` and
* `resetToDefaults()`.
* Configures electron-settings global default options.
*
* @param {Object} obj
* @param {Object} options
* @private
*/
_setDefaults(obj) {
this._defaults = clone(obj);
_configureGlobalSettings(options) {
const opts = this._extendDefaultOptions(options);
Settings.DefaultOptions = opts;
debug(`global configuration set to ${JSON.stringify(opts)}`);
}

@@ -87,2 +165,4 @@

* @param {boolean} [options.overwrite=false]
* @param {string} [options.settingsDir=USER_DATA_PATH]
* @param {string} [options.settingsFileName=Settings]
* @returns {Object}

@@ -96,2 +176,16 @@ * @private

/**
* 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

@@ -110,4 +204,3 @@ * and can no longer be read.

} catch (e) {
// Either the file doesn't exist, or you're totally fucked.
// But probably the former.. ¯\_(ツ)_/¯
// Do nothing.
}

@@ -123,2 +216,4 @@ }

_resetSettingsFileSync() {
debug('resetting settings file...');
this._unlinkSettingsFileSync();

@@ -136,2 +231,4 @@ this._ensureSettingsFileSync();

_ensureSettingsFile() {
debug('ensuring settings file...');
return new Promise((resolve, reject) => {

@@ -158,2 +255,4 @@ if (!this.settingsFileExists()) {

_ensureSettingsFileSync() {
debug('ensuring settings file...');
if (!this.settingsFileExists()) {

@@ -178,2 +277,4 @@ const defaults = this._defaults;

debug('reading settings...');
fs.readJson(pathToSettings, (err, obj) => {

@@ -184,4 +285,3 @@ if (err) {

this._resetSettingsFileSync();
reject(err);
this._readSettingsFile().then(resolve, reject);
} else {

@@ -208,2 +308,4 @@ resolve(obj);

try {
debug('reading settings...');
const obj = fs.readJsonSync(pathToSettings);

@@ -216,2 +318,4 @@

this._resetSettingsFileSync();
return this._readSettingsFileSync();
}

@@ -231,2 +335,4 @@ }

_writeSettingsFile(obj, options) {
debug('writing settings file...');
const opts = this._extendDefaultOptions(options);

@@ -246,2 +352,3 @@ const pathToSettings = this.getSettingsFilePath();

} else {
this._observeSettingsFile(true);
this._emitWriteEvent();

@@ -253,4 +360,4 @@ resolve();

fs.unlink(tmpFilePath, () => {
this._resetSettingsFile();
return reject(err);
this._resetSettingsFileSync();
reject(err);
});

@@ -264,2 +371,3 @@ }

} else {
this._observeSettingsFile(true);
this._emitWriteEvent();

@@ -280,2 +388,4 @@ resolve();

_writeSettingsFileSync(obj, options) {
debug('writing settings file...');
const opts = this._extendDefaultOptions(options);

@@ -290,2 +400,3 @@ const pathToSettings = this.getSettingsFilePath();

fs.outputJsonSync(tmpFilePath, obj, { spaces });
fs.renameSync(tmpFilePath, pathToSettings);
} catch (e) {

@@ -295,3 +406,3 @@ try {

} catch (e) {
// No operation.
// Do nothing.
}

@@ -302,5 +413,6 @@

fs.renameSync(tmpFilePath, pathToSettings);
this._observeSettingsFile(true);
} else {
fs.outputJsonSync(pathToSettings, obj, { spaces });
this._observeSettingsFile();
}

@@ -334,3 +446,3 @@

*/
_onCreate() {
_onSettingsCreate() {
debug(`settings file created at ${this.getSettingsFilePath()}`);

@@ -340,8 +452,13 @@ }

/**
* Called when the "write" event fires.
* Called when the settings file has changed.
*
* @private
* @param {string} eventType - Either "rename" or "change".
* @param {string} filename - The name of the file that triggered the event.
*/
_onWrite() {
debug(`settings file written to ${this.getSettingsFilePath()}`);
_onFileChange(eventType, filename) {
if (eventType === Settings.FSWatcherEventTypes.CHANGE) {
debug(`detected change to settings file`);
this._emitWriteEvent();
}
}

@@ -357,2 +474,4 @@

has(keyPath) {
debug(`called has() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');

@@ -375,2 +494,4 @@

hasSync(keyPath) {
debug(`called hasSync() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');

@@ -391,2 +512,4 @@

get(keyPath) {
debug(`called get() at "${keyPath}"`);
return new Promise((resolve, reject) => {

@@ -411,2 +534,4 @@ this._readSettingsFile().then(obj => {

getSync(keyPath) {
debug(`called getSync() at "${keyPath}"`);
let value = this._readSettingsFileSync();

@@ -432,2 +557,4 @@

set(keyPath, value={}, options={}) {
debug(`called set() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');

@@ -451,2 +578,4 @@ assert.strictEqual(typeof options, 'object', 'Options must be an object');

setSync(keyPath, value={}, options={}) {
debug(`called setSync() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');

@@ -472,2 +601,4 @@ assert.strictEqual(typeof options, 'object', 'Options must be an object');

delete(keyPath, options={}) {
debug(`called delete() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');

@@ -491,2 +622,4 @@ assert.strictEqual(typeof options, 'object', 'Options must be an object');

deleteSync(keyPath, options={}) {
debug(`called deleteSync() at "${keyPath}"`);
assert.strictEqual(typeof keyPath, 'string', 'Key path must be a string');

@@ -512,2 +645,4 @@ assert.strictEqual(typeof options, 'object', 'Options must be an object');

clear(options={}) {
debug('called clear()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');

@@ -524,2 +659,4 @@

clearSync(options={}) {
debug('called clearSync()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');

@@ -554,2 +691,4 @@

applyDefaults(options={}) {
debug('called applyDefaults()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');

@@ -578,2 +717,4 @@

applyDefaultsSync(options={}) {
debug('called applyDefaultsSync()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');

@@ -602,2 +743,4 @@

resetToDefaults(options={}) {
debug('called resetToDefaults()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');

@@ -616,2 +759,4 @@

resetToDefaultsSync(options={}) {
debug('called resetToDefaultsSync()');
assert.strictEqual(typeof options, 'object', 'Options must be an object');

@@ -622,4 +767,2 @@

this._writeSettingsFileSync(defaults, options);
this._readSettingsFileSync();
}

@@ -636,3 +779,3 @@

* @param {Function} handler
* @returns {Observer}
* @returns {Observer} observer
*/

@@ -643,3 +786,5 @@ observe(keyPath, handler) {

return new Observer(this, keyPath, handler);
const observer = new Observer(this, keyPath, handler);
return observer;
}

@@ -668,4 +813,5 @@

getSettingsFilePath() {
const userDataPath = app.getPath('userData');
const settingsFilePath = path.join(userDataPath, Settings.FileName);
const settingsDir = Settings.DefaultOptions.settingsDir;
const settingsFileName = Settings.DefaultOptions.settingsFileName;
const settingsFilePath = path.join(settingsDir, settingsFileName);

@@ -695,3 +841,3 @@ return settingsFilePath;

}
};
}

@@ -707,2 +853,4 @@ /**

prettify: false,
settingsDir: USER_DATA_PATH,
settingsFileName: SETTINGS_FILE_NAME,
overwrite: false

@@ -719,12 +867,16 @@ };

CREATE: 'create',
WRITE: 'write'
WRITE: 'write',
CHANGE: 'change'
};
/**
* The file name for the settings file.
* FSWatcher event types.
*
* @type string
* @enum {string}
* @readonly
*/
Settings.FileName = 'Settings';
Settings.FSWatcherEventTypes = {
CHANGE: 'change',
RENAME: 'rename'
};

@@ -731,0 +883,0 @@ /**

{
"name": "electron-settings",
"version": "2.1.1",
"version": "2.2.0",
"description": "A simple persistent user settings manager for Electron.",
"main": "index.js",
"scripts": {
"test": "electron-mocha test && electron-mocha --renderer test"
"test": "npm run test:main && npm run test:renderer",
"test:main": "electron-mocha test",
"test:renderer": "electron-mocha test --renderer"
},

@@ -55,6 +57,6 @@ "keywords": [

"chai": "^3.5.0",
"electron-mocha": "^2.3.0",
"electron-mocha": "^3.0.0",
"electron-prebuilt": "^1.2.6",
"mocha": "^2.5.3"
"mocha": "^3.0.2"
}
}

@@ -40,2 +40,3 @@ electron-settings

settings.get('name.first').then(val => {
console.log(val);
// => "Cosmo"

@@ -61,2 +62,3 @@ });

settings.get('foo').then(val => {
console.log(val);
// => 'bar'

@@ -134,3 +136,3 @@ });

***
<small>Last updated **Aug. 2nd, 2016** by [Nathan Buchar].</small>
<small>Last updated **Aug. 16th, 2016** by [Nathan Buchar].</small>

@@ -160,2 +162,3 @@ <small>**Having trouble?** [Get help on Gitter][external_gitter].</small>

[method_get-settings-file-path]: ./docs/methods.md#getsettingsfilepath
[method_observe]: ./docs/methods.md#observe
[method_defaults]: ./docs/methods.md#defaults

@@ -162,0 +165,0 @@ [method_apply-defaults]: ./docs/methods.md#applydefaults

@@ -16,2 +16,10 @@ /* global it, describe, before, after, beforeEach, afterEach */

beforeEach('configure electron-settings', () => {
settings.configure({
atomicSaving: false,
prettify: false,
overwrite: false
});
});
beforeEach('set electron-settings defaults', () => {
settings.defaults({

@@ -28,470 +36,616 @@ foo: 'bar'

describe('has()', () => {
describe('methods', () => {
it('should return true if the key path exists', done => {
settings.has('foo').then(exists => {
expect(exists).to.be.true;
done();
describe('has()', () => {
it('should return true if the key path exists', done => {
settings.has('foo').then(exists => {
expect(exists).to.be.true;
done();
});
});
it('should return false if the key path does not exist', done => {
settings.has('snap').then(exists => {
expect(exists).to.be.false;
done();
});
});
it('should throw if no key path is given', () => {
expect(() => {
settings.has();
}).to.throw(/Key path must be a string/);
});
it('should throw if key path is given but is not a string', () => {
expect(() => {
settings.has(false);
}).to.throw(/Key path must be a string/);
});
});
it('should return false if the key path does not exist', done => {
settings.has('snap').then(exists => {
describe('hasSync()', () => {
it('should return true if the key path exists', () => {
const exists = settings.hasSync('foo');
expect(exists).to.be.true;
});
it('should return false if the key path does not exist', () => {
const exists = settings.hasSync('snap');
expect(exists).to.be.false;
done();
});
});
it('should throw if no key path is given', () => {
expect(() => {
settings.has();
}).to.throw(/Key path must be a string/);
});
it('should throw if no key path is given', () => {
expect(() => {
settings.hasSync();
}).to.throw(/Key path must be a string/);
});
it('should throw if key path is given but is not a string', () => {
expect(() => {
settings.has(false);
}).to.throw(/Key path must be a string/);
it('should throw if key path is not a string', () => {
expect(() => {
settings.hasSync(false);
}).to.throw(/Key path must be a string/);
});
});
});
describe('hasSync()', () => {
describe('get()', () => {
it('should return true if the key path exists', () => {
const exists = settings.hasSync('foo');
it('should return the value at the chosen key path', done => {
settings.get('foo').then(value => {
expect(value).to.deep.equal('bar');
done();
});
});
expect(exists).to.be.true;
});
it('should return undefined if the key path does not exist', done => {
settings.get('snap').then(value => {
expect(value).to.be.undefined;
done();
});
});
it('should return false if the key path does not exist', () => {
const exists = settings.hasSync('snap');
it('should return the entire settings object if no key path is given', done => {
settings.get().then(value => {
expect(value).to.deep.equal({ foo: 'bar' });
done();
});
});
expect(exists).to.be.false;
});
it('should reset the settings file if the data is malformed', done => {
const pathToSettings = settings.getSettingsFilePath();
it('should throw if no key path is given', () => {
expect(() => {
settings.hasSync();
}).to.throw(/Key path must be a string/);
});
fs.outputFileSync(pathToSettings, 'not valid json');
it('should throw if key path is not a string', () => {
expect(() => {
settings.hasSync(false);
}).to.throw(/Key path must be a string/);
settings.get().then(value => {
expect(value).to.deep.equal({ foo: 'bar' });
done();
});
});
});
});
describe('get()', () => {
describe('getSync()', () => {
it('should return the value at the chosen key path', done => {
settings.get('foo').then(value => {
it('should return the value at the chosen key path', () => {
const value = settings.getSync('foo');
expect(value).to.deep.equal('bar');
done();
});
});
it('should return undefined if the key path does not exist', done => {
settings.get('snap').then(value => {
it('should return undefined if the key path does not exist', () => {
const value = settings.getSync('snap');
expect(value).to.be.undefined;
done();
});
});
it('should return the entire settings object if no key path is given', done => {
settings.get().then(value => {
it('should return the entire settings object if no key path is given', () => {
const value = settings.getSync();
expect(value).to.deep.equal({ foo: 'bar' });
done();
});
});
});
describe('getSync()', () => {
describe('set()', () => {
it('should return the value at the chosen key path', () => {
const value = settings.getSync('foo');
it('should set the value at the chosen key path to a string (atomic)', done => {
settings.set('snap', 'crackle').then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal('crackle');
done();
});
});
});
expect(value).to.deep.equal('bar');
});
it('should set the value at the chosen key path to a string (non-atomic)', done => {
settings.set('snap', 'crackle', { atomicSaving: false }).then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal('crackle');
done();
});
});
});
it('should return undefined if the key path does not exist', () => {
const value = settings.getSync('snap');
it('should set the value at the chosen key path to a number', done => {
settings.set('snap', 10).then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal(10);
done();
});
});
});
expect(value).to.be.undefined;
});
it('should set the value at the chosen key path to a boolean', done => {
settings.set('snap', false).then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal(false);
done();
});
});
});
it('should return the entire settings object if no key path is given', () => {
const value = settings.getSync();
it('should set the value at the chosen key path to an object', done => {
settings.set('snap', {
foo: 'bar'
}).then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal({ foo: 'bar' });
done();
});
});
});
expect(value).to.deep.equal({ foo: 'bar' });
});
});
describe('set()', () => {
it('should set the value at the chosen key path', done => {
settings.set('snap', 'crackle').then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal('crackle');
done();
it('should set the value at the chosen key path to null', done => {
settings.set('snap', null).then(() => {
settings.get('snap').then(value => {
expect(value).to.deep.equal(null);
done();
});
});
});
});
it('should overwrite a pre-existing value', done => {
settings.set('foo', 'qux').then(() => {
settings.get('foo').then(value => {
expect(value).to.deep.equal('qux');
done();
it('should overwrite a pre-existing value', done => {
settings.set('foo', 'qux').then(() => {
settings.get('foo').then(value => {
expect(value).to.deep.equal('qux');
done();
});
});
});
});
it('should throw if no key path is given', () => {
expect(() => {
settings.set();
}).to.throw(/Key path must be a string/);
});
it('should throw if no key path is given', () => {
expect(() => {
settings.set();
}).to.throw(/Key path must be a string/);
});
it('should throw if key path is not a string', () => {
expect(() => {
settings.set(false);
}).to.throw(/Key path must be a string/);
});
it('should throw if key path is not a string', () => {
expect(() => {
settings.set(false);
}).to.throw(/Key path must be a string/);
});
it('should throw if options is not an object', () => {
expect(() => {
settings.set('foo', 'bar', false);
}).to.throw(/Options must be an object/);
it('should throw if options is not an object', () => {
expect(() => {
settings.set('foo', 'bar', false);
}).to.throw(/Options must be an object/);
});
});
});
describe('setSync()', () => {
describe('setSync()', () => {
it('should set the value at the chosen key path', () => {
settings.setSync('snap', 'crackle');
it('should set the value at the chosen key path to a string (atomic)', () => {
settings.setSync('snap', 'crackle');
const value = settings.getSync('snap');
const value = settings.getSync('snap');
expect(value).to.deep.equal('crackle');
});
expect(value).to.deep.equal('crackle');
});
it('should overwrite a pre-existing value', () => {
settings.setSync('foo', 'qux');
it('should set the value at the chosen key path to a string (non-atomic)', () => {
settings.setSync('snap', 'crackle', { atomicSaving: false });
const value = settings.getSync('foo');
const value = settings.getSync('snap');
expect(value).to.deep.equal('qux');
});
expect(value).to.deep.equal('crackle');
});
it('should throw if no key path is given', () => {
expect(() => {
settings.setSync();
}).to.throw(/Key path must be a string/);
});
it('should set the value at the chosen key path to a number', () => {
settings.setSync('snap', 10);
it('should throw if key path is not a string', () => {
expect(() => {
settings.setSync(false);
}).to.throw(/Key path must be a string/);
});
const value = settings.getSync('snap');
it('should throw if options is not an object', () => {
expect(() => {
settings.setSync('foo', 'bar', false);
}).to.throw(/Options must be an object/);
});
});
expect(value).to.deep.equal(10);
});
describe('delete()', () => {
it('should set the value at the chosen key path to a boolean', () => {
settings.setSync('snap', false);
it('should delete the value at the chosen key path', done => {
settings.delete('foo').then(() => {
settings.get('foo').then(value => {
expect(value).to.be.undefined;
done();
});
const value = settings.getSync('snap');
expect(value).to.deep.equal(false);
});
});
it('should throw if no key path is given', () => {
expect(() => {
settings.delete();
}).to.throw(/Key path must be a string/);
});
it('should set the value at the chosen key path to an object', () => {
settings.setSync('snap', { foo: 'bar' });
it('should throw if key path is not a string', () => {
expect(() => {
settings.delete(false);
}).to.throw(/Key path must be a string/);
});
const value = settings.getSync('snap');
it('should throw if options is not an object', () => {
expect(() => {
settings.delete('foo', false);
}).to.throw(/Options must be an object/);
});
});
expect(value).to.deep.equal({ foo: 'bar' });
});
describe('deleteSync()', () => {
it('should set the value at the chosen key path to null', () => {
settings.setSync('snap', null);
it('should delete the value at the chosen key path', () => {
settings.deleteSync('foo');
const value = settings.getSync('snap');
const value = settings.getSync('foo');
expect(value).to.deep.equal(null);
});
expect(value).to.be.undefined;
});
it('should overwrite a pre-existing value', () => {
settings.setSync('foo', 'qux');
it('should throw if no key path is given', () => {
expect(() => {
settings.deleteSync();
}).to.throw(/Key path must be a string/);
});
const value = settings.getSync('foo');
it('should throw if key path not a string', () => {
expect(() => {
settings.deleteSync(false);
}).to.throw(/Key path must be a string/);
});
expect(value).to.deep.equal('qux');
});
it('should throw if options is not an object', () => {
expect(() => {
settings.deleteSync('foo', false);
}).to.throw(/Options must be an object/);
it('should throw if no key path is given', () => {
expect(() => {
settings.setSync();
}).to.throw(/Key path must be a string/);
});
it('should throw if key path is not a string', () => {
expect(() => {
settings.setSync(false);
}).to.throw(/Key path must be a string/);
});
it('should throw if options is not an object', () => {
expect(() => {
settings.setSync('foo', 'bar', false);
}).to.throw(/Options must be an object/);
});
});
});
describe('clear()', () => {
describe('delete()', () => {
it('should clear the entire settings object', done => {
settings.clear().then(() => {
settings.get().then(value => {
expect(value).to.be.empty;
done();
it('should delete the value at the chosen key path', done => {
settings.delete('foo').then(() => {
settings.get('foo').then(value => {
expect(value).to.be.undefined;
done();
});
});
});
});
it('should throw if options is not an object', () => {
expect(() => {
settings.clear(false);
}).to.throw(/Options must be an object/);
it('should throw if no key path is given', () => {
expect(() => {
settings.delete();
}).to.throw(/Key path must be a string/);
});
it('should throw if key path is not a string', () => {
expect(() => {
settings.delete(false);
}).to.throw(/Key path must be a string/);
});
it('should throw if options is not an object', () => {
expect(() => {
settings.delete('foo', false);
}).to.throw(/Options must be an object/);
});
});
});
describe('clearSync()', () => {
describe('deleteSync()', () => {
it('should clear the entire settings object', () => {
settings.clearSync();
it('should delete the value at the chosen key path', () => {
settings.deleteSync('foo');
const value = settings.getSync();
const value = settings.getSync('foo');
expect(value).to.be.empty;
});
expect(value).to.be.undefined;
});
it('should throw if options is not an object', () => {
expect(() => {
settings.clearSync(false);
}).to.throw(/Options must be an object/);
});
});
it('should throw if no key path is given', () => {
expect(() => {
settings.deleteSync();
}).to.throw(/Key path must be a string/);
});
describe('defaults()', () => {
it('should throw if key path not a string', () => {
expect(() => {
settings.deleteSync(false);
}).to.throw(/Key path must be a string/);
});
it('should set global defaults', done => {
settings.defaults({
snap: 'crackle'
it('should throw if options is not an object', () => {
expect(() => {
settings.deleteSync('foo', false);
}).to.throw(/Options must be an object/);
});
});
settings.resetToDefaults().then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ snap: 'crackle' });
done();
describe('clear()', () => {
it('should clear the entire settings object', done => {
settings.clear().then(() => {
settings.get().then(value => {
expect(value).to.be.empty;
done();
});
});
});
});
it('should throw if defaults is not an object', () => {
expect(() => {
settings.defaults(false);
}).to.throw(/Defaults must be an object/);
it('should throw if options is not an object', () => {
expect(() => {
settings.clear(false);
}).to.throw(/Options must be an object/);
});
});
});
describe('applyDefaults()', () => {
describe('clearSync()', () => {
it('should apply defaults', done => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
it('should clear the entire settings object', () => {
settings.clearSync();
const value = settings.getSync();
expect(value).to.be.empty;
});
settings.applyDefaults().then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ foo: 'bar', snap: 'crackle' });
done();
});
it('should throw if options is not an object', () => {
expect(() => {
settings.clearSync(false);
}).to.throw(/Options must be an object/);
});
});
it('should apply defaults and overwrite pre-existing values', done => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
});
describe('defaults()', () => {
settings.applyDefaults({ overwrite: true }).then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ foo: 'qux', snap: 'crackle' });
done();
it('should set global defaults', done => {
settings.defaults({
snap: 'crackle'
});
settings.resetToDefaults().then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ snap: 'crackle' });
done();
});
});
});
});
it('should throw if options is not an object', () => {
expect(() => {
settings.applyDefaults(false);
}).to.throw(/Options must be an object/);
it('should throw if defaults is not an object', () => {
expect(() => {
settings.defaults(false);
}).to.throw(/Defaults must be an object/);
});
});
});
describe('applyDefaultsSync()', () => {
describe('applyDefaults()', () => {
it('should apply defaults', () => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
it('should apply defaults', done => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
});
settings.applyDefaults().then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ foo: 'bar', snap: 'crackle' });
done();
});
});
});
settings.applyDefaultsSync();
it('should apply defaults and overwrite pre-existing values', done => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
});
const val = settings.getSync();
settings.applyDefaults({ overwrite: true }).then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ foo: 'qux', snap: 'crackle' });
done();
});
});
});
expect(val).to.deep.equal({ foo: 'bar', snap: 'crackle' });
it('should throw if options is not an object', () => {
expect(() => {
settings.applyDefaults(false);
}).to.throw(/Options must be an object/);
});
});
it('should apply defaults and overwrite pre-existing values', () => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
describe('applyDefaultsSync()', () => {
it('should apply defaults', () => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
});
settings.applyDefaultsSync();
const val = settings.getSync();
expect(val).to.deep.equal({ foo: 'bar', snap: 'crackle' });
});
settings.applyDefaultsSync({ overwrite: true });
it('should apply defaults and overwrite pre-existing values', () => {
settings.defaults({
foo: 'qux',
snap: 'crackle'
});
const val = settings.getSync();
settings.applyDefaultsSync({ overwrite: true });
expect(val).to.deep.equal({ foo: 'qux', snap: 'crackle' });
});
const val = settings.getSync();
it('should throw if options is not an object', () => {
expect(() => {
settings.applyDefaults(false);
}).to.throw(/Options must be an object/);
expect(val).to.deep.equal({ foo: 'qux', snap: 'crackle' });
});
it('should throw if options is not an object', () => {
expect(() => {
settings.applyDefaults(false);
}).to.throw(/Options must be an object/);
});
});
});
describe('resetToDefaults()', () => {
describe('resetToDefaults()', () => {
it('should reset to defaults', done => {
settings.set('foo', 'qux').then(() => {
settings.resetToDefaults().then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ foo: 'bar' });
done();
it('should reset to defaults', done => {
settings.set('foo', 'qux').then(() => {
settings.resetToDefaults().then(() => {
settings.get().then(obj => {
expect(obj).to.deep.equal({ foo: 'bar' });
done();
});
});
});
});
});
it('should throw if options is not an object', () => {
expect(() => {
settings.resetToDefaults(false);
}).to.throw(/Options must be an object/);
it('should throw if options is not an object', () => {
expect(() => {
settings.resetToDefaults(false);
}).to.throw(/Options must be an object/);
});
});
});
describe('resetToDefaultsSync()', () => {
describe('resetToDefaultsSync()', () => {
it('should reset to defaults', () => {
settings.setSync('foo', 'qux');
settings.resetToDefaultsSync();
it('should reset to defaults', () => {
settings.setSync('foo', 'qux');
settings.resetToDefaultsSync();
const val = settings.getSync();
const val = settings.getSync();
expect(val).to.deep.equal({ foo: 'bar' });
});
expect(val).to.deep.equal({ foo: 'bar' });
});
it('should throw if options is not an object', () => {
expect(() => {
settings.resetToDefaultsSync(false);
}).to.throw(/Options must be an object/);
it('should throw if options is not an object', () => {
expect(() => {
settings.resetToDefaultsSync(false);
}).to.throw(/Options must be an object/);
});
});
});
describe('observe()', () => {
describe('observe()', () => {
it('should observe the given key path', done => {
const observer = settings.observe('foo', evt => {
expect(evt.oldValue).to.deep.equal('bar');
expect(evt.newValue).to.deep.equal('qux');
it('should observe the given key path', done => {
const observer = settings.observe('foo', evt => {
expect(evt.oldValue).to.deep.equal('bar');
expect(evt.newValue).to.deep.equal('qux');
observer.dispose();
done();
});
settings.setSync('foo', 'qux');
});
it('should dispose the key path observer', done => {
const observer = settings.observe('foo', evt => {
expect(evt).to.not.exist;
});
observer.dispose();
settings.setSync('foo', 'baz');
done();
});
settings.setSync('foo', 'qux');
});
it('should throw if no key path is given', () => {
expect(() => {
settings.observe();
}).to.throw(/Key path must be a string/);
});
it('should dispose the key path observer', done => {
const observer = settings.observe('foo', evt => {
expect(evt).to.not.exist;
it('should throw if key path is given but is not a string', () => {
expect(() => {
settings.observe(false);
}).to.throw(/Key path must be a string/);
});
observer.dispose();
settings.setSync('foo', 'baz');
it('should throw if no handler is given', () => {
expect(() => {
settings.observe('foo');
}).to.throw(/Handler must be a function/);
});
done();
it('should throw if handler is given but is not a function', () => {
expect(() => {
settings.observe('foo', false);
}).to.throw(/Handler must be a function/);
});
});
it('should throw if no key path is given', () => {
expect(() => {
settings.observe();
}).to.throw(/Key path must be a string/);
});
describe('configure()', () => {
it('should throw if key path is given but is not a string', () => {
expect(() => {
settings.observe(false);
}).to.throw(/Key path must be a string/);
it('should globally configure electron-settings options', () => {
settings.configure({
prettify: true
});
});
});
it('should throw if no handler is given', () => {
expect(() => {
settings.observe('foo');
}).to.throw(/Handler must be a function/);
});
describe('getSettingsFilePath()', () => {
it('should throw if handler is given but is not a function', () => {
expect(() => {
settings.observe('foo', false);
}).to.throw(/Handler must be a function/);
it('should return the path to the settings file', () => {
expect(settings.getSettingsFilePath()).to.be.a.string;
});
});
});
describe('configure()', () => {
describe('events', () => {
it('should globally configure electron-settings options', () => {
settings.configure({
prettify: true
describe('create', () => {
it('should emit when the settings file is created', done => {
const pathToSettings = settings.getSettingsFilePath();
const handler = settingsFilePath => {
expect(settingsFilePath).to.equal(pathToSettings);
settings.removeListener('create', handler);
done();
};
// Delete the settings file.
fs.unlinkSync(pathToSettings);
settings.on('create', handler);
settings.getSync('foo');
});
});
});
describe('getSettingsFilePath()', () => {
describe('write', () => {
it('should return the path to the settings file', () => {
expect(settings.getSettingsFilePath()).to.be.a.string;
it('should emit when the settings file is written to', done => {
const handler = () => {
settings.removeListener('write', handler);
done();
};
settings.on('write', handler);
settings.set('foo', 'bar');
});
it('should emit when the settings file is written to from an external source', done => {
const pathToSettings = settings.getSettingsFilePath();
const handler = () => {
settings.removeListener('write', handler);
done();
};
settings.on('write', handler);
fs.outputJsonSync(pathToSettings, { foo: 'bar' });
});
});
});
});
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