Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a .getSync() function #163

Merged
merged 1 commit into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ electron-json-storage
[![Build Status](https://travis-ci.org/electron-userland/electron-json-storage.svg?branch=master)](https://travis-ci.org/electron-userland/electron-json-storage)
[![Build status](https://ci.appveyor.com/api/projects/status/ulwk1nnh7l8209xg/branch/master?svg=true)](https://ci.appveyor.com/project/electron-userland/electron-json-storage/branch/master)

[Electron](http://electron.atom.io) lacks an easy way to persist and read user settings for your application. `electron-json-storage` implements an API somehow similar to [localStorage](https://developer.mozilla.org/en/docs/Web/API/Window/localStorage) to write and read JSON objects to/from the operating system application data directory, as defined by `app.getPath('userData')`.
[Electron](http://electron.atom.io) lacks an easy way to persist and read user settings for your application. `electron-json-storage` implements an API somewhat similar to [localStorage](https://developer.mozilla.org/en/docs/Web/API/Window/localStorage) to write and read JSON objects to/from the operating system application data directory, as defined by `app.getPath('userData')`.

Related modules:

Expand All @@ -35,7 +35,7 @@ When loaded in renderer processes, this module will try to make use of

Electron 10 now [defaults `enableRemoteModule` to
false](https://www.electronjs.org/docs/breaking-changes#default-changed-enableremotemodule-defaults-to-false),
which means that `electron-json-storage` will not be able to calculate a data path by default.
which means that `electron-json-storage` will be able to calculate a data path by default.

The solution is to manually call `storage.setDataPath()` before reading or
writing any values or setting `enableRemoteModule` to `true`.
Expand All @@ -49,6 +49,7 @@ Documentation
* [.setDataPath(directory)](#module_storage.setDataPath)
* [.getDataPath()](#module_storage.getDataPath) ⇒ <code>String</code>
* [.get(key, [options], callback)](#module_storage.get)
* [.getSync(key, [options])](#module_storage.getSync)
* [.getMany(keys, [options], callback)](#module_storage.getMany)
* [.getAll([options], callback)](#module_storage.getAll)
* [.set(key, json, [options], callback)](#module_storage.set)
Expand Down Expand Up @@ -142,6 +143,28 @@ storage.get('foobar', function(error, data) {
console.log(data);
});
```
<a name="module_storage.getSync"></a>

### storage.getSync(key, [options])
See `.get()`.

**Kind**: static method of [<code>storage</code>](#module_storage)
**Summary**: Read user data (sync)
**Access**: public

| Param | Type | Description |
| --- | --- | --- |
| key | <code>String</code> | key |
| [options] | <code>Object</code> | options |
| [options.dataPath] | <code>String</code> | data path |

**Example**
```js
const storage = require('electron-json-storage');

var data = storage.getSync('foobar');
console.log(data);
```
<a name="module_storage.getMany"></a>

### storage.getMany(keys, [options], callback)
Expand Down
2 changes: 1 addition & 1 deletion doc/README.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ electron-json-storage
[![Build Status](https://travis-ci.org/electron-userland/electron-json-storage.svg?branch=master)](https://travis-ci.org/electron-userland/electron-json-storage)
[![Build status](https://ci.appveyor.com/api/projects/status/ulwk1nnh7l8209xg/branch/master?svg=true)](https://ci.appveyor.com/project/electron-userland/electron-json-storage/branch/master)

[Electron](http://electron.atom.io) lacks an easy way to persist and read user settings for your application. `electron-json-storage` implements an API somehow similar to [localStorage](https://developer.mozilla.org/en/docs/Web/API/Window/localStorage) to write and read JSON objects to/from the operating system application data directory, as defined by `app.getPath('userData')`.
[Electron](http://electron.atom.io) lacks an easy way to persist and read user settings for your application. `electron-json-storage` implements an API somewhat similar to [localStorage](https://developer.mozilla.org/en/docs/Web/API/Window/localStorage) to write and read JSON objects to/from the operating system application data directory, as defined by `app.getPath('userData')`.

Related modules:

Expand Down
55 changes: 53 additions & 2 deletions lib/lock.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ exports.lock = function(file, callback, times) {
lockFile.lock(file, lockOptions, function(error) {
if (error && error.code === 'EPERM' && times < 10) {
setTimeout(function() {
exports.unlock(file, callback, times + 1);
exports.lock(file, callback, times + 1);
}, 1000);
return;
}
Expand All @@ -68,7 +68,34 @@ exports.lock = function(file, callback, times) {
};

/**
* @summary Unlock a lock file
* @summary Create a lock file (sync)
* @function
* @public
*
* @param {String} file - lock file
*
* @example
* lock.lockSync('foo.lock');
*/
exports.lockSync = function(file, times) {
times = times || 0;

try {
lockFile.lockSync(file, {
stale: lockOptions.stale,
retries: lockOptions.retries
});
} catch (error) {
if (error && error.code === 'EPERM' && times < 10) {
return exports.lockSync(file, times + 1);
}

throw error;
}
};

/**
* @summary Unlock a locked file
* @function
* @public
*
Expand Down Expand Up @@ -96,3 +123,27 @@ exports.unlock = function(file, callback, times) {
return callback(error);
});
};

/**
* @summary Unlock a locked file (sync)
* @function
* @public
*
* @param {String} file - lock file
*
* @example
* lock.unlockSync('foo.lock');
*/
exports.unlockSync = function(file, times) {
times = times || 0;

try {
lockFile.unlockSync(file);
} catch (error) {
if (error && error.code === 'EPERM' && times < 10) {
return exports.unlockSync(file, times + 1);
}

throw error;
}
};
63 changes: 63 additions & 0 deletions lib/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ const readFile = function(fileName, callback, times) {
});
};

const readFileSync = function(fileName, times) {
times = times || 0;
try {
return fs.readFileSync(fileName);
} catch (error) {
if (error.code === 'ENOENT') {
return JSON.stringify({});
}

if (error.code === 'EPERM' && times < 10) {
return readFileSync(fileName, times + 1);
}

throw error;
}
};

/**
* @summary Get the default data path
* @function
Expand Down Expand Up @@ -193,6 +210,52 @@ exports.get = function(key, options, callback) {
});
};

/**
* @summary Read user data (sync)
* @function
* @public
*
* @description
* See `.get()`.
*
* @param {String} key - key
* @param {Object} [options] - options
* @param {String} [options.dataPath] - data path
*
* @example
* const storage = require('electron-json-storage');
*
* var data = storage.getSync('foobar');
* console.log(data);
*/
exports.getSync = function(key, options) {
options = options || {};
var fileName = utils.getFileName(key, {
dataPath: options.dataPath
});

mkdirp.sync(path.dirname(fileName));

try {
lock.lockSync(utils.getLockFileName(fileName));
} catch (error) {
if (error && error.code === 'EEXIST') {
return exports.getSync(key, options);
}

throw error;
}

var object = readFileSync(fileName);
lock.unlockSync(utils.getLockFileName(fileName));

try {
return JSON.parse(object);
} catch (error) {
throw new Error('Invalid data: ' + object);
}
};

/**
* @summary Read many user data keys
* @function
Expand Down
96 changes: 96 additions & 0 deletions tests/storage.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield an error if no key (sync)', function(done) {
chai.expect(() => {
storage.getSync(null);
}).to.throw('Missing key');
done();
});

it('should yield an error if key is not a string', function(done) {
storage.get(123, function(error, data) {
chai.expect(error).to.be.an.instanceof(Error);
Expand All @@ -169,6 +176,13 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield an error if key is not a string (sync)', function(done) {
chai.expect(() => {
storage.getSync(123);
}).to.throw('Invalid key');
done();
});

it('should yield an error if key is a blank string', function(done) {
storage.get(' ', function(error, data) {
chai.expect(error).to.be.an.instanceof(Error);
Expand All @@ -178,6 +192,13 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield an error if key is a blank string (sync)', function(done) {
chai.expect(() => {
storage.getSync(' ');
}).to.throw('Invalid key');
done();
});

describe('given the user data path does not exist', function() {

beforeEach(function(done) {
Expand All @@ -196,6 +217,12 @@ describe('Electron JSON Storage', function() {
});
});

it('should return an empty object for any key (sync)', function(done) {
var data = storage.getSync('foobarbaz');
chai.expect(data).to.deep.equal({});
done();
});

});

describe('given the same key stored in multiple data paths', function(done) {
Expand Down Expand Up @@ -233,6 +260,15 @@ describe('Electron JSON Storage', function() {
});
});

it('should initially return the key in the default location (sync)', function(done) {
var data = storage.getSync('foo');
chai.expect(data).to.deep.equal({
location: 'default'
});

done();
});

it('should return the new value given the right data path', function(done) {
storage.setDataPath(this.newDataPath);
storage.get('foo', function(error, data) {
Expand All @@ -245,6 +281,16 @@ describe('Electron JSON Storage', function() {
});
});

it('should return the new value given the right data path (sync)', function(done) {
storage.setDataPath(this.newDataPath);
var data = storage.getSync('foo');
chai.expect(data).to.deep.equal({
location: 'new'
});

done();
});

it('should return nothing given the wrong data path', function(done) {
if (os.platform() === 'win32') {
storage.setDataPath('C:\\tmp\\electron-json-storage');
Expand All @@ -263,6 +309,25 @@ describe('Electron JSON Storage', function() {
done();
});
});

it('should return nothing given the wrong data path (sync)', function(done) {
if (os.platform() === 'win32') {
storage.setDataPath('C:\\tmp\\electron-json-storage');
} else {
storage.setDataPath('/tmp/electron-json-storage');
}

async.waterfall([
storage.clear,
function(callback) {
callback(null, storage.getSync('foo'));
}
], function(error, data) {
chai.expect(error).to.not.exist;
chai.expect(data).to.deep.equal({});
done();
});
});
});

describe('given stored keys with a colon', function() {
Expand Down Expand Up @@ -301,6 +366,12 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield the data (sync)', function(done) {
var data = storage.getSync('foo');
chai.expect(data).to.deep.equal({ data: 'hello world' });
done();
});

it('should yield the data if explicitly passing the extension', function(done) {
storage.get('foo.json', function(error, data) {
chai.expect(error).to.not.exist;
Expand All @@ -309,6 +380,12 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield the data if explicitly passing the extension (sync)', function(done) {
var data = storage.getSync('foo.json');
chai.expect(data).to.deep.equal({ data: 'hello world' });
done();
});

it('should yield an empty object given an incorrect key', function(done) {
storage.get('foobarbaz', function(error, data) {
chai.expect(error).to.not.exist;
Expand All @@ -317,6 +394,12 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield an empty object given an incorrect key (sync)', function(done) {
var data = storage.getSync('foobarbaz');
chai.expect(data).to.deep.equal({});
done();
});

});

describe('given invalid stored JSON', function() {
Expand All @@ -340,6 +423,13 @@ describe('Electron JSON Storage', function() {
});
});

it('should yield an error (sync)', function(done) {
chai.expect(() => {
return storage.getSync('foo');
}).to.throw('Invalid data: Foo{bar}123');
done();
});

});

describe('given a non-existent user data path', function() {
Expand All @@ -365,6 +455,12 @@ describe('Electron JSON Storage', function() {
});
});

it('should return an empty object for any key (sync)', function(done) {
var result = storage.getSync('foo');
chai.expect(result).to.deep.equal({});
done();
});

});

});
Expand Down