Skip to content

Commit

Permalink
add config.getDir, loads all files in a directory (#18)
Browse files Browse the repository at this point in the history
* add config.getDir, loads all files in a directory
* add directory watching support
* add test for invalid dir (error handling)
  • Loading branch information
msimerson committed Mar 7, 2017
1 parent 888f0dd commit b4f65b0
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 13 deletions.
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

0 comments on commit b4f65b0

Please sign in to comment.