First Push
This commit is contained in:
282
node_modules/config-chain/index.js
generated
vendored
Normal file
282
node_modules/config-chain/index.js
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
var ProtoList = require('proto-list')
|
||||
, path = require('path')
|
||||
, fs = require('fs')
|
||||
, ini = require('ini')
|
||||
, EE = require('events').EventEmitter
|
||||
, url = require('url')
|
||||
, http = require('http')
|
||||
|
||||
var exports = module.exports = function () {
|
||||
var args = [].slice.call(arguments)
|
||||
, conf = new ConfigChain()
|
||||
|
||||
while(args.length) {
|
||||
var a = args.shift()
|
||||
if(a) conf.push
|
||||
( 'string' === typeof a
|
||||
? json(a)
|
||||
: a )
|
||||
}
|
||||
|
||||
return conf
|
||||
}
|
||||
|
||||
//recursively find a file...
|
||||
|
||||
var find = exports.find = function () {
|
||||
var rel = path.join.apply(null, [].slice.call(arguments))
|
||||
|
||||
function find(start, rel) {
|
||||
var file = path.join(start, rel)
|
||||
try {
|
||||
fs.statSync(file)
|
||||
return file
|
||||
} catch (err) {
|
||||
if(path.dirname(start) !== start) // root
|
||||
return find(path.dirname(start), rel)
|
||||
}
|
||||
}
|
||||
return find(__dirname, rel)
|
||||
}
|
||||
|
||||
var parse = exports.parse = function (content, file, type) {
|
||||
content = '' + content
|
||||
// if we don't know what it is, try json and fall back to ini
|
||||
// if we know what it is, then it must be that.
|
||||
if (!type) {
|
||||
try { return JSON.parse(content) }
|
||||
catch (er) { return ini.parse(content) }
|
||||
} else if (type === 'json') {
|
||||
if (this.emit) {
|
||||
try { return JSON.parse(content) }
|
||||
catch (er) { this.emit('error', er) }
|
||||
} else {
|
||||
return JSON.parse(content)
|
||||
}
|
||||
} else {
|
||||
return ini.parse(content)
|
||||
}
|
||||
}
|
||||
|
||||
var json = exports.json = function () {
|
||||
var args = [].slice.call(arguments).filter(function (arg) { return arg != null })
|
||||
var file = path.join.apply(null, args)
|
||||
var content
|
||||
try {
|
||||
content = fs.readFileSync(file,'utf-8')
|
||||
} catch (err) {
|
||||
return
|
||||
}
|
||||
return parse(content, file, 'json')
|
||||
}
|
||||
|
||||
var env = exports.env = function (prefix, env) {
|
||||
env = env || process.env
|
||||
var obj = {}
|
||||
var l = prefix.length
|
||||
for(var k in env) {
|
||||
if(k.indexOf(prefix) === 0)
|
||||
obj[k.substring(l)] = env[k]
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
exports.ConfigChain = ConfigChain
|
||||
function ConfigChain () {
|
||||
EE.apply(this)
|
||||
ProtoList.apply(this, arguments)
|
||||
this._awaiting = 0
|
||||
this._saving = 0
|
||||
this.sources = {}
|
||||
}
|
||||
|
||||
// multi-inheritance-ish
|
||||
var extras = {
|
||||
constructor: { value: ConfigChain }
|
||||
}
|
||||
Object.keys(EE.prototype).forEach(function (k) {
|
||||
extras[k] = Object.getOwnPropertyDescriptor(EE.prototype, k)
|
||||
})
|
||||
ConfigChain.prototype = Object.create(ProtoList.prototype, extras)
|
||||
|
||||
ConfigChain.prototype.del = function (key, where) {
|
||||
// if not specified where, then delete from the whole chain, scorched
|
||||
// earth style
|
||||
if (where) {
|
||||
var target = this.sources[where]
|
||||
target = target && target.data
|
||||
if (!target) {
|
||||
return this.emit('error', new Error('not found '+where))
|
||||
}
|
||||
delete target[key]
|
||||
} else {
|
||||
for (var i = 0, l = this.list.length; i < l; i ++) {
|
||||
delete this.list[i][key]
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.set = function (key, value, where) {
|
||||
var target
|
||||
|
||||
if (where) {
|
||||
target = this.sources[where]
|
||||
target = target && target.data
|
||||
if (!target) {
|
||||
return this.emit('error', new Error('not found '+where))
|
||||
}
|
||||
} else {
|
||||
target = this.list[0]
|
||||
if (!target) {
|
||||
return this.emit('error', new Error('cannot set, no confs!'))
|
||||
}
|
||||
}
|
||||
target[key] = value
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.get = function (key, where) {
|
||||
if (where) {
|
||||
where = this.sources[where]
|
||||
if (where) where = where.data
|
||||
if (where && Object.hasOwnProperty.call(where, key)) return where[key]
|
||||
return undefined
|
||||
}
|
||||
return this.list[0][key]
|
||||
}
|
||||
|
||||
ConfigChain.prototype.save = function (where, type, cb) {
|
||||
if (typeof type === 'function') cb = type, type = null
|
||||
var target = this.sources[where]
|
||||
if (!target || !(target.path || target.source) || !target.data) {
|
||||
// TODO: maybe save() to a url target could be a PUT or something?
|
||||
// would be easy to swap out with a reddis type thing, too
|
||||
return this.emit('error', new Error('bad save target: '+where))
|
||||
}
|
||||
|
||||
if (target.source) {
|
||||
var pref = target.prefix || ''
|
||||
Object.keys(target.data).forEach(function (k) {
|
||||
target.source[pref + k] = target.data[k]
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
var type = type || target.type
|
||||
var data = target.data
|
||||
if (target.type === 'json') {
|
||||
data = JSON.stringify(data)
|
||||
} else {
|
||||
data = ini.stringify(data)
|
||||
}
|
||||
|
||||
this._saving ++
|
||||
fs.writeFile(target.path, data, 'utf8', function (er) {
|
||||
this._saving --
|
||||
if (er) {
|
||||
if (cb) return cb(er)
|
||||
else return this.emit('error', er)
|
||||
}
|
||||
if (this._saving === 0) {
|
||||
if (cb) cb()
|
||||
this.emit('save')
|
||||
}
|
||||
}.bind(this))
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.addFile = function (file, type, name) {
|
||||
name = name || file
|
||||
var marker = {__source__:name}
|
||||
this.sources[name] = { path: file, type: type }
|
||||
this.push(marker)
|
||||
this._await()
|
||||
fs.readFile(file, 'utf8', function (er, data) {
|
||||
if (er) this.emit('error', er)
|
||||
this.addString(data, file, type, marker)
|
||||
}.bind(this))
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.addEnv = function (prefix, env, name) {
|
||||
name = name || 'env'
|
||||
var data = exports.env(prefix, env)
|
||||
this.sources[name] = { data: data, source: env, prefix: prefix }
|
||||
return this.add(data, name)
|
||||
}
|
||||
|
||||
ConfigChain.prototype.addUrl = function (req, type, name) {
|
||||
this._await()
|
||||
var href = url.format(req)
|
||||
name = name || href
|
||||
var marker = {__source__:name}
|
||||
this.sources[name] = { href: href, type: type }
|
||||
this.push(marker)
|
||||
http.request(req, function (res) {
|
||||
var c = []
|
||||
var ct = res.headers['content-type']
|
||||
if (!type) {
|
||||
type = ct.indexOf('json') !== -1 ? 'json'
|
||||
: ct.indexOf('ini') !== -1 ? 'ini'
|
||||
: href.match(/\.json$/) ? 'json'
|
||||
: href.match(/\.ini$/) ? 'ini'
|
||||
: null
|
||||
marker.type = type
|
||||
}
|
||||
|
||||
res.on('data', c.push.bind(c))
|
||||
.on('end', function () {
|
||||
this.addString(Buffer.concat(c), href, type, marker)
|
||||
}.bind(this))
|
||||
.on('error', this.emit.bind(this, 'error'))
|
||||
|
||||
}.bind(this))
|
||||
.on('error', this.emit.bind(this, 'error'))
|
||||
.end()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.addString = function (data, file, type, marker) {
|
||||
data = this.parse(data, file, type)
|
||||
this.add(data, marker)
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.add = function (data, marker) {
|
||||
if (marker && typeof marker === 'object') {
|
||||
var i = this.list.indexOf(marker)
|
||||
if (i === -1) {
|
||||
return this.emit('error', new Error('bad marker'))
|
||||
}
|
||||
this.splice(i, 1, data)
|
||||
marker = marker.__source__
|
||||
this.sources[marker] = this.sources[marker] || {}
|
||||
this.sources[marker].data = data
|
||||
// we were waiting for this. maybe emit 'load'
|
||||
this._resolve()
|
||||
} else {
|
||||
if (typeof marker === 'string') {
|
||||
this.sources[marker] = this.sources[marker] || {}
|
||||
this.sources[marker].data = data
|
||||
}
|
||||
// trigger the load event if nothing was already going to do so.
|
||||
this._await()
|
||||
this.push(data)
|
||||
process.nextTick(this._resolve.bind(this))
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
ConfigChain.prototype.parse = exports.parse
|
||||
|
||||
ConfigChain.prototype._await = function () {
|
||||
this._awaiting++
|
||||
}
|
||||
|
||||
ConfigChain.prototype._resolve = function () {
|
||||
this._awaiting--
|
||||
if (this._awaiting === 0) this.emit('load', this)
|
||||
}
|
||||
Reference in New Issue
Block a user