112 lines
2.8 KiB
JavaScript
112 lines
2.8 KiB
JavaScript
|
'use strict';
|
||
|
var path = require('path');
|
||
|
var fs = require('graceful-fs');
|
||
|
var osenv = require('osenv');
|
||
|
var assign = require('object-assign');
|
||
|
var mkdirp = require('mkdirp');
|
||
|
var uuid = require('uuid');
|
||
|
var xdgBasedir = require('xdg-basedir');
|
||
|
var osTmpdir = require('os-tmpdir');
|
||
|
var writeFileAtomic = require('write-file-atomic');
|
||
|
var dotProp = require('dot-prop');
|
||
|
|
||
|
var user = (osenv.user() || uuid.v4()).replace(/\\/g, '');
|
||
|
var configDir = xdgBasedir.config || path.join(osTmpdir(), user, '.config');
|
||
|
var permissionError = 'You don\'t have access to this file.';
|
||
|
var defaultPathMode = parseInt('0700', 8);
|
||
|
var writeFileOptions = {mode: parseInt('0600', 8)};
|
||
|
|
||
|
function Configstore(id, defaults, opts) {
|
||
|
opts = opts || {};
|
||
|
|
||
|
var pathPrefix = opts.globalConfigPath ?
|
||
|
path.join(id, 'config.json') :
|
||
|
path.join('configstore', id + '.json');
|
||
|
|
||
|
this.path = path.join(configDir, pathPrefix);
|
||
|
|
||
|
this.all = assign({}, defaults || {}, this.all || {});
|
||
|
}
|
||
|
|
||
|
Configstore.prototype = Object.create(Object.prototype, {
|
||
|
all: {
|
||
|
get: function () {
|
||
|
try {
|
||
|
return JSON.parse(fs.readFileSync(this.path, 'utf8'));
|
||
|
} catch (err) {
|
||
|
// create dir if it doesn't exist
|
||
|
if (err.code === 'ENOENT') {
|
||
|
mkdirp.sync(path.dirname(this.path), defaultPathMode);
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
// improve the message of permission errors
|
||
|
if (err.code === 'EACCES') {
|
||
|
err.message = err.message + '\n' + permissionError + '\n';
|
||
|
}
|
||
|
|
||
|
// empty the file if it encounters invalid JSON
|
||
|
if (err.name === 'SyntaxError') {
|
||
|
writeFileAtomic.sync(this.path, '', writeFileOptions);
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
throw err;
|
||
|
}
|
||
|
},
|
||
|
set: function (val) {
|
||
|
try {
|
||
|
// make sure the folder exists as it
|
||
|
// could have been deleted in the meantime
|
||
|
mkdirp.sync(path.dirname(this.path), defaultPathMode);
|
||
|
|
||
|
writeFileAtomic.sync(this.path, JSON.stringify(val, null, '\t'), writeFileOptions);
|
||
|
} catch (err) {
|
||
|
// improve the message of permission errors
|
||
|
if (err.code === 'EACCES') {
|
||
|
err.message = err.message + '\n' + permissionError + '\n';
|
||
|
}
|
||
|
|
||
|
throw err;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
size: {
|
||
|
get: function () {
|
||
|
return Object.keys(this.all || {}).length;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
Configstore.prototype.get = function (key) {
|
||
|
return dotProp.get(this.all, key);
|
||
|
};
|
||
|
|
||
|
Configstore.prototype.set = function (key, val) {
|
||
|
var config = this.all;
|
||
|
if (arguments.length === 1) {
|
||
|
Object.keys(key).forEach(function (k) {
|
||
|
dotProp.set(config, k, key[k]);
|
||
|
});
|
||
|
} else {
|
||
|
dotProp.set(config, key, val);
|
||
|
}
|
||
|
this.all = config;
|
||
|
};
|
||
|
|
||
|
Configstore.prototype.has = function (key) {
|
||
|
return dotProp.has(this.all, key);
|
||
|
};
|
||
|
|
||
|
Configstore.prototype.delete = Configstore.prototype.del = function (key) {
|
||
|
var config = this.all;
|
||
|
dotProp.delete(config, key);
|
||
|
this.all = config;
|
||
|
};
|
||
|
|
||
|
Configstore.prototype.clear = function () {
|
||
|
this.all = {};
|
||
|
};
|
||
|
|
||
|
module.exports = Configstore;
|