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 config.getDir, loads all files in a directory #18

Merged
merged 5 commits into from
Mar 7, 2017
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
4 changes: 2 additions & 2 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# 1.0.11 - 2017-0_-_
# 1.0.11 - 2017-03-04

-
- add config.getDir, loads all files in a directory

# 1.0.10 - 2017-02-05

Expand Down
15 changes: 10 additions & 5 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,25 @@ Config.prototype.get = function (name, type, cb, options) {
return results;
};

Config.prototype.getDir = function (name, opts, done) {
cfreader.read_dir(path.resolve(this.root_path, name), opts, done);
};

function merge_config (defaults, overrides, type) {
if (type === 'ini' || type === 'json' || type === 'yaml') {
return merge_struct(JSON.parse(JSON.stringify(defaults)), overrides);
}
else if (Array.isArray(overrides) && Array.isArray(defaults) &&

if (Array.isArray(overrides) && Array.isArray(defaults) &&
overrides.length > 0) {
return overrides;
}
else if (overrides != null) {

if (overrides != null) {
return overrides;
}
else {
return defaults;
}

return defaults;
}

function merge_struct (defaults, overrides) {
Expand Down
77 changes: 73 additions & 4 deletions configfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,11 @@ cfreader.on_watch_event = function (name, type, options, cb) {
};

cfreader.watch_dir = function () {
// NOTE: This only works on Linux and Windows
// NOTE: Has OS platform limitations:
// https://nodejs.org/api/fs.html#fs_fs_watch_filename_options_listener
var cp = cfreader.config_path;
if (cfreader._watchers[cp]) return;

var watcher = function (fse, filename) {
if (!filename) return;
var full_path = path.join(cp, filename);
Expand Down Expand Up @@ -181,9 +183,10 @@ cfreader.get_cache_key = function (name, options) {
};

cfreader.read_config = function (name, type, cb, options) {
// Store arguments used so we can re-use them by filename later
// and so we know which files we've attempted to read so that
// we can ignore any other files written to the same directory.
// Store arguments used so we can:
// 1. re-use them by filename later
// 2. to know which files we've read, so we can ignore
// other files written to the same directory.

cfreader._read_args[name] = {
type: type,
Expand Down Expand Up @@ -221,6 +224,72 @@ cfreader.read_config = function (name, type, cb, options) {
return result;
};

function isDirectory (filepath) {
return new Promise(function (resolve, reject) {
fs.stat(filepath, function (err, stat) {
if (err) return reject(err);
resolve(stat.isDirectory());
})
})
}

function fsReadDir (filepath) {
return new Promise(function (resolve, reject) {
fs.readdir(filepath, function (err, fileList) {
if (err) return reject(err);
resolve(fileList);
})
})
}

function fsWatchDir (dirPath) {

if (cfreader._watchers[dirPath]) return;

cfreader._watchers[dirPath] = fs.watch(dirPath, { persistent: false }, function (fse, filename) {
// console.log('event: ' + fse + ', ' + filename);
if (!filename) return;
var full_path = path.join(dirPath, filename);
var args = cfreader._read_args[dirPath];
// console.log(args);
if (cfreader._sedation_timers[full_path]) {
clearTimeout(cfreader._sedation_timers[full_path]);
}
cfreader._sedation_timers[full_path] = setTimeout(function () {
delete cfreader._sedation_timers[full_path];
args.opts.watchCb();
}, 2 * 1000);
});
}

cfreader.read_dir = function (name, opts, done) {

cfreader._read_args[name] = { opts: opts }
var type = opts.type || 'binary';

isDirectory(name)
.then((result) => {
return fsReadDir(name);
})
.then((result2) => {
var reader = require('./readers/' + type);
var promises = [];
result2.forEach(function (file) {
promises.push(reader.loadPromise(path.resolve(name, file)))
});
return Promise.all(promises);
})
.then((fileList) => {
// console.log(fileList);
done(null, fileList);
})
.catch((error) => {
done(error);
})

if (opts.watchCb) fsWatchDir(name);
};

cfreader.ensure_enoent_timer = function () {
if (cfreader._enoent_timer) return;
// Create timer
Expand Down
11 changes: 10 additions & 1 deletion readers/binary.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@

var fs = require('fs');

exports.load = function(name) {
exports.load = function (name) {
return fs.readFileSync(name);
};

exports.loadPromise = function (name) {
return new Promise(function (resolve, reject) {
fs.readFile(name, function (err, content) {
if (err) return reject(err);
resolve({ path: name, data: content });
});
});
};

exports.empty = function () {
return null;
};
64 changes: 63 additions & 1 deletion test/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

process.env.NODE_ENV = 'test'

var fs = require('fs');
var path = require('path');

var cb = function () { return false; };
Expand Down Expand Up @@ -203,7 +204,7 @@ var yamlRes = {
}
};

function _test_get(test, name, type, callback, options, expected) {
function _test_get (test, name, type, callback, options, expected) {
test.expect(1);
var config = require('../config');
var cfg = config.get(name, type, callback, options);
Expand Down Expand Up @@ -335,3 +336,64 @@ exports.merged = {
test.done();
},
}

exports.getDir = {
'setUp' : setUp,
'tearDown' : function (done) {
fs.unlink(path.resolve('test','config','dir', '4.ext'), function () {
done();
})
},
'loads all files in dir' : function (test) {
test.expect(4);
this.config.getDir('dir', { type: 'binary' }, function (err, files) {
// console.log(files);
test.equal(err, null);
test.equal(files.length, 3);
test.equal(files[0].data, 'contents1\n');
test.equal(files[2].data, 'contents3\n');
test.done();
})
},
'errs on invalid dir' : function (test) {
test.expect(1);
this.config.getDir('dirInvalid', { type: 'binary' }, function (err, files) {
// console.log(arguments);
test.equal(err.code, 'ENOENT');
test.done();
})
},
'reloads when file in dir is touched' : function (test) {
test.expect(6);
var self = this;
var tmpFile = path.resolve('test','config','dir', '4.ext');
var callCount = 0;
var getDirDone = function (err, files) {
// console.log('Loading: test/config/dir');
if (err) console.error(err);
callCount++;
if (callCount === 1) {
// console.log(files);
test.equal(err, null);
test.equal(files.length, 3);
test.equal(files[0].data, 'contents1\n');
test.equal(files[2].data, 'contents3\n');
fs.writeFile(tmpFile, 'contents4\n', function (err, res) {
test.equal(err, null);
// console.log('file touched, waiting for callback');
// console.log(res);
});
return;
}
if (callCount === 2) {
test.equal(files[3].data, 'contents4\n');
test.done();
}
}
var getDir = function () {
var opts = { type: 'binary', watchCb: getDir };
self.config.getDir('dir', opts, getDirDone);
};
getDir();
}
}
1 change: 1 addition & 0 deletions test/config/dir/1.ext
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contents1
1 change: 1 addition & 0 deletions test/config/dir/2.ext
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contents2
1 change: 1 addition & 0 deletions test/config/dir/3.ext
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
contents3