Comparing version
var path = require('path'); | ||
var fs = require('fs'); | ||
var Config = require('./config'); | ||
var ConfigLoader = require('./config-loader'); | ||
module.exports = exports = function(configDirPath, defaultsDirPath, callback) { | ||
return new ConfigLoader(configDirPath, defaultsDirPath, callback); | ||
module.exports = exports = function(configDirPath, defaultsDirPath) { | ||
return new Config(configDirPath, defaultsDirPath); | ||
}; | ||
exports.Config = Config; | ||
exports.ConfigLoader = ConfigLoader; | ||
exports.Config = Config; |
var util = require('util'); | ||
// modules | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var tools = require('primitive'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var JSONStream = require('JSONStream'); | ||
function Config(path, callback) { | ||
function Config(configPath, defaultsPath) { | ||
var _this = this; | ||
EventEmitter.call(this); | ||
// set the path | ||
this.path = path; | ||
if(typeof configPath != 'string') { throw new Error('configPath is not a string'); } | ||
if(defaultsPath && typeof defaultsPath != 'string') { throw new Error('defaultsPath is not a string'); } | ||
// setup the instance | ||
this._proxiedEvents = []; | ||
this._reservedProperties = []; | ||
for(var property in this) { | ||
this._reservedProperties.push(property); | ||
} | ||
this._readStream = fs.createReadStream(this.path, { | ||
encoding: 'utf8' | ||
}); | ||
this.defaultsPath = defaultsPath || null; | ||
this.configPath = configPath; | ||
// if a callback is given then buffer parse | ||
// the read stream, then, once complete, | ||
// callback with the full config object. | ||
if(typeof callback == 'function') { | ||
// when the read stream is finished then return | ||
// the data. | ||
var data = ''; | ||
this._readStream.on('error', callback); | ||
this._readStream.on('data', function(chunk) { | ||
data += chunk; | ||
}); | ||
this._readStream.on('end', function() { | ||
// load the config | ||
var config = this._getConfigSet(this.configPath); | ||
// attempt to parse as JSON | ||
try { | ||
data = JSON.parse(data); | ||
} catch(err) { | ||
callback(err); | ||
return; | ||
} | ||
// load defaults | ||
if(this.defaultsPath) { | ||
var defaults = this._getConfigSet(this.defaultsPath); | ||
config = tools.merge(defaults, config, true); | ||
} | ||
// emit a ready event and call the callback | ||
// with the full data. | ||
this.emit('ready', data); | ||
callback(undefined, data); | ||
}); | ||
for(var prop in config) { | ||
this[prop] = config[prop]; | ||
} | ||
// proxy JSON paths as events on the readStream. | ||
this.on('newListener', function(event) { | ||
if(_this._proxiedEvents.indexOf(event) > -1) { return; } | ||
_this._proxiedEvents.push(event); | ||
_this._readStream | ||
.pipe(JSONStream.parse(event)) | ||
.on('data', function(data) { | ||
_this.emit(event, data); | ||
}); | ||
}); | ||
} | ||
util.inherits(Config, EventEmitter); | ||
Config.prototype._getConfigSet = function(configPath) { | ||
if(!fs.existsSync(configPath)) { | ||
throw new Error('Config not found at ' + configPath); | ||
} | ||
// if the path is a file then load its as a | ||
// single config, otherwise load it as a config | ||
// set (directory of configs). | ||
var stat = fs.statSync(configPath); | ||
if(stat.isFile()) { | ||
return this._getConfig(configPath); | ||
} else if(stat.isDirectory()) { | ||
var configSet = {}; | ||
var dir = fs.readdirSync(configPath); | ||
for(var i = 0; i < dir.length; i += 1) { | ||
var filename = dir[i]; | ||
var namespace = this._getNamespace(filename); | ||
var _configPath = path.join(configPath, filename); | ||
configSet[namespace] = this._getConfigSet(_configPath); | ||
} | ||
return configSet; | ||
} | ||
try { | ||
return JSON.parse(fs.readFileSync(configPath)); | ||
} catch(err) { | ||
throw new Error('Cannot parse json config file ' + configPath); | ||
} | ||
}; | ||
Config.prototype._getConfig = function(configPath) { | ||
if(!fs.existsSync(configPath)) { | ||
throw new Error('Config not found at ' + configPath); | ||
} | ||
try { | ||
return JSON.parse(fs.readFileSync(configPath)); | ||
} catch(err) { | ||
throw new Error('Cannot parse json config file ' + configPath); | ||
} | ||
}; | ||
Config.prototype._getNamespace = function(filename) { | ||
var extname = path.extname(filename); | ||
var basename = path.basename(filename, extname); | ||
return tools.camelize(basename); | ||
}; | ||
module.exports = Config; |
{ | ||
"name": "ambiente", | ||
"version": "0.0.2", | ||
"version": "1.0.0", | ||
"description": "", | ||
@@ -23,5 +23,4 @@ "main": "./lib/ambiente", | ||
"dependencies": { | ||
"primitive": "0.0.5", | ||
"JSONStream": "~0.7.1" | ||
"primitive": "0.4.2" | ||
} | ||
} |
@@ -7,3 +7,2 @@ | ||
var ambiente = require('../'); | ||
var ConfigLoader = require('../lib/config-loader'); | ||
var Config = require('../lib/config'); | ||
@@ -18,3 +17,3 @@ | ||
var config = ambiente(CONFIG_PATH); | ||
config.should.be.an.instanceOf(ConfigLoader); | ||
config.should.be.an.instanceOf(Config); | ||
}); | ||
@@ -30,10 +29,2 @@ | ||
}); | ||
describe('ambiente.ConfigLoader', function() { | ||
it('references the ConfigLoader class', function() { | ||
ambiente.ConfigLoader.should.equal(ConfigLoader); | ||
}); | ||
}); |
@@ -9,60 +9,38 @@ | ||
// constants | ||
var TEST_CONFIG_PATH = path.resolve( | ||
__dirname, | ||
'fixtures/app/test.json' | ||
); | ||
var CONFIG_PATH = path.resolve(__dirname, './fixtures/dev'); | ||
var DEFAULTS_PATH = path.resolve(__dirname, './fixtures/app'); | ||
describe('config', function() { | ||
it('accepts a path', function() { | ||
new Config(TEST_CONFIG_PATH); | ||
it('accepts a config path', function() { | ||
var config = new Config(CONFIG_PATH); | ||
}); | ||
it('accepts a path and callback it calls when ready', function(done) { | ||
new Config(TEST_CONFIG_PATH, function(err, config) { | ||
if(err) { throw err; } | ||
config.should.be.OK; | ||
config.name.should.equal('app'); | ||
config.a.should.be.OK; | ||
config.a.foo.should.equal('bar'); | ||
config.b.should.be.OK; | ||
config.b.baz.should.equal('ack'); | ||
done(); | ||
}); | ||
it('accepts a config path and defaults path', function() { | ||
var config = new Config(CONFIG_PATH, DEFAULTS_PATH); | ||
}); | ||
it('emits an event for root each key in the config', function(done) { | ||
var _config = require(TEST_CONFIG_PATH); | ||
var config = new Config(TEST_CONFIG_PATH); | ||
config.on('a', function(a) { | ||
a.should.eql(_config.a); | ||
done(); | ||
}); | ||
it('sets the config namespaces on its instance', function() { | ||
var config = new Config(CONFIG_PATH); | ||
config.test.should.be.OK; | ||
config.test.file.should.equal('dev'); | ||
config.namespace.should.be.OK; | ||
config.namespace.subTest.should.be.OK; | ||
config.namespace.subTest.sub.should.equal('val'); | ||
}); | ||
it('applies all of the config data to itself upon a ready event', function() { | ||
var _config = require(TEST_CONFIG_PATH); | ||
var config = new Config(TEST_CONFIG_PATH); | ||
config.on('ready', function(config) { | ||
config.a.should.eql(_config.a); | ||
config.b.should.eql(_config.b); | ||
}); | ||
it('sets the config namespaces on its instance', function() { | ||
var config = new Config(CONFIG_PATH, DEFAULTS_PATH); | ||
config.test.should.be.OK; | ||
config.test.name.should.equal('app'); | ||
config.test.file.should.equal('dev'); | ||
config.test.a.should.OK; | ||
config.test.a.foo.should.equal('bar'); | ||
config.test.b.should.OK; | ||
config.test.b.baz.should.equal('ack'); | ||
config.namespace.should.be.OK; | ||
config.namespace.subTest.should.be.OK; | ||
config.namespace.subTest.sub.should.equal('val'); | ||
}); | ||
it('applies all of the config data to itself upon the callback', function() { | ||
var _config = require(TEST_CONFIG_PATH); | ||
new Config(TEST_CONFIG_PATH, function(err, config) { | ||
config.a.should.eql(_config.a); | ||
config.b.should.eql(_config.b); | ||
}); | ||
}); | ||
}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
-50%1
-50%1
-83.33%4944
-54.64%10
-16.67%134
-55.92%1
Infinity%+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
Updated