Permalink
Browse files

Merge branch 'newconf'

  • Loading branch information...
2 parents 7b26c04 + e716167 commit feea6d1f2edc1f2e4d3f83b98d38026af2f7e2eb @isaacs isaacs committed Aug 15, 2012
Showing with 1,900 additions and 574 deletions.
  1. +2 −2 bin/npm-cli.js
  2. +5 −6 lib/adduser.js
  3. +5 −3 lib/build.js
  4. +3 −1 lib/completion.js
  5. +82 −101 lib/config.js
  6. +28 −29 lib/npm.js
  7. +2 −3 lib/utils/error-handler.js
  8. +0 −352 lib/utils/ini.js
  9. +2 −3 lib/utils/lifecycle.js
  10. +0 −1 lib/view.js
  11. +25 −7 node_modules/ini/ini.js
  12. +10 −6 node_modules/ini/package.json
  13. +23 −0 node_modules/ini/test/bar.js
  14. +29 −0 node_modules/ini/test/fixtures/foo.ini
  15. +59 −0 node_modules/ini/test/foo.js
  16. +1 −0 node_modules/npmconf/.npmignore
  17. +33 −0 node_modules/npmconf/README.md
  18. +11 −3 {lib/utils → node_modules/npmconf}/config-defs.js
  19. +3 −0 node_modules/npmconf/node_modules/config-chain/.npmignore
  20. +22 −0 node_modules/npmconf/node_modules/config-chain/LICENCE
  21. +282 −0 node_modules/npmconf/node_modules/config-chain/index.js
  22. 0 node_modules/{ → npmconf/node_modules/config-chain/node_modules}/proto-list/LICENSE
  23. 0 node_modules/{ → npmconf/node_modules/config-chain/node_modules}/proto-list/README.md
  24. +28 −0 node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json
  25. +30 −43 node_modules/{ → npmconf/node_modules/config-chain/node_modules}/proto-list/proto-list.js
  26. +61 −0 node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/test/basic.js
  27. +28 −0 node_modules/npmconf/node_modules/config-chain/package.json
  28. +228 −0 node_modules/npmconf/node_modules/config-chain/readme.markdown
  29. +10 −0 node_modules/npmconf/node_modules/config-chain/test/broken.js
  30. +21 −0 node_modules/npmconf/node_modules/config-chain/test/broken.json
  31. +100 −0 node_modules/npmconf/node_modules/config-chain/test/chain-class.js
  32. +10 −0 node_modules/npmconf/node_modules/config-chain/test/env.js
  33. +13 −0 node_modules/npmconf/node_modules/config-chain/test/find-file.js
  34. +5 −0 node_modules/npmconf/node_modules/config-chain/test/ignore-unfound-file.js
  35. +18 −0 node_modules/npmconf/node_modules/config-chain/test/ini.js
  36. +59 −0 node_modules/npmconf/node_modules/config-chain/test/save.js
  37. +324 −0 node_modules/npmconf/npmconf.js
  38. +42 −0 node_modules/npmconf/package.json
  39. +27 −0 node_modules/npmconf/test/00-setup.js
  40. +72 −0 node_modules/npmconf/test/basic.js
  41. +72 −0 node_modules/npmconf/test/builtin.js
  42. +1 −0 node_modules/npmconf/test/fixtures/builtin
  43. +1 −0 node_modules/npmconf/test/fixtures/globalconfig
  44. +22 −0 node_modules/npmconf/test/fixtures/userconfig
  45. +21 −0 node_modules/npmconf/test/fixtures/userconfig-with-gc
  46. +74 −0 node_modules/npmconf/test/save.js
  47. +0 −9 node_modules/proto-list/package.json
  48. +6 −5 package.json
View
4 bin/npm-cli.js
@@ -22,10 +22,10 @@ log.info("it worked if it ends with", "ok")
var fs = require("graceful-fs")
, path = require("path")
, npm = require("../lib/npm.js")
- , ini = require("../lib/utils/ini.js")
+ , npmconf = require("npmconf")
, errorHandler = require("../lib/utils/error-handler.js")
- , configDefs = require("../lib/utils/config-defs.js")
+ , configDefs = npmconf.defs
, shorthands = configDefs.shorthands
, types = configDefs.types
, nopt = require("nopt")
View
11 lib/adduser.js
@@ -1,8 +1,7 @@
module.exports = adduser
-var ini = require("./utils/ini.js")
- , log = require("npmlog")
+var log = require("npmlog")
, npm = require("./npm.js")
, registry = npm.registry
, read = require("read")
@@ -130,10 +129,10 @@ function save (c, u, cb) {
registry.username = u.u
registry.password = u.p
registry.email = u.e
- ini.set("username", u.u, "user")
- ini.set("_password", u.p, "user")
- ini.set("email", u.e, "user")
+ npm.config.set("username", u.u, "user")
+ npm.config.set("_password", u.p, "user")
+ npm.config.set("email", u.e, "user")
log.info("adduser", "Authorized user %s", u.u)
- ini.save("user", cb)
+ npm.config.save("user", cb)
})
}
View
8 lib/build.js
@@ -1,4 +1,3 @@
-
// npm build command
// everything about the installation after the creation of
@@ -62,8 +61,11 @@ function build_ (global, didPre, didRB) { return function (folder, cb) {
function writeBuiltinConf (folder, cb) {
// the builtin config is "sticky". Any time npm installs itself,
// it puts its builtin config file there, as well.
- var ini = require("./utils/ini.js")
- ini.saveConfig("builtin", path.resolve(folder, "npmrc"), cb)
+ if (!npm.config.usingBuiltin
+ || folder !== path.dirname(__dirname)) {
+ return cb()
+ }
+ npm.config.save("builtin", cb)
}
function linkStuff (pkg, folder, global, didRB, cb) {
View
4 lib/completion.js
@@ -5,7 +5,9 @@ completion.usage = "npm completion >> ~/.bashrc\n"
+ "npm completion >> ~/.zshrc\n"
+ "source <(npm completion)"
-var configDefs = require("./utils/config-defs.js")
+var npm = require("./npm.js")
+ , npmconf = require("npmconf")
+ , configDefs = npmconf.defs
, configTypes = configDefs.types
, shorthands = configDefs.shorthands
, nopt = require("nopt")
View
183 lib/config.js
@@ -9,13 +9,13 @@ config.usage = "npm config set <key> <value>"
+ "\nnpm set <key> <value>"
+ "\nnpm get [<key>]"
-var ini = require("./utils/ini.js")
- , log = require("npmlog")
+var log = require("npmlog")
, npm = require("./npm.js")
, exec = require("./utils/exec.js")
, fs = require("graceful-fs")
- , dc
- , types = require("./utils/config-defs.js").types
+ , npmconf = require("npmconf")
+ , types = npmconf.defs.types
+ , ini = require("ini")
config.completion = function (opts, cb) {
var argv = opts.conf.argv.remain
@@ -59,18 +59,17 @@ function config (args, cb) {
}
function edit (cb) {
- var e = ini.get("editor")
- , which = ini.get("global") ? "global" : "user"
- , f = ini.get(which + "config")
+ var e = npm.config.get("editor")
+ , which = npm.config.get("global") ? "global" : "user"
+ , f = npm.config.get(which + "config")
, eol = process.platform === "win32" ? "\r\n" : "\n"
if (!e) return cb(new Error("No EDITOR config or environ set."))
- ini.save(which, function (er) {
+ npm.config.save(which, function (er) {
if (er) return cb(er)
fs.readFile(f, "utf8", function (er, data) {
if (er) data = ""
- dc = dc || require("./utils/config-defs.js").defaults
data = [ ";;;;"
- , "; npm "+(ini.get("global") ?
+ , "; npm "+(npm.config.get("global") ?
"globalconfig" : "userconfig")+" file"
, "; this is a simple ini-formatted file"
, "; lines that start with semi-colons are comments."
@@ -83,8 +82,8 @@ function edit (cb) {
, ";;;;"
]
)
- .concat(Object.keys(dc).map(function (k) {
- return "; " + k + " = " + ini.unParseField(dc[k],k)
+ .concat(Object.keys(npmconf.defaults).map(function (k) {
+ return "; " + k + " = " + npmconf.defaults[k]
}))
.concat([""])
.join(eol)
@@ -94,13 +93,7 @@ function edit (cb) {
, "utf8"
, function (er) {
if (er) return cb(er)
- exec(e, [f], function (er) {
- if (er) return cb(er)
- ini.resolveConfigs(function (er) {
- if (er) return cb(er)
- ini.save(which, cb)
- })
- })
+ exec(e, [f], cb)
}
)
})
@@ -109,8 +102,9 @@ function edit (cb) {
function del (key, cb) {
if (!key) return cb(new Error("no key provided"))
- ini.del(key)
- ini.save(ini.get("global") ? "global" : "user", cb)
+ var where = npm.config.get("global") ? "global" : "user"
+ npm.config.del(key, where)
+ npm.config.save(where, cb)
}
function set (key, val, cb) {
@@ -129,9 +123,9 @@ function set (key, val, cb) {
key = key.trim()
val = val.trim()
log.info("config", "set %j %j", key, val)
- var where = ini.get("global") ? "global" : "user"
- ini.set(key, val, where)
- ini.save(where, cb)
+ var where = npm.config.get("global") ? "global" : "user"
+ npm.config.set(key, val, where)
+ npm.config.save(where, cb)
}
function get (key, cb) {
@@ -151,140 +145,127 @@ function reverse (a, b) {
return a > b ? -1 : 1
}
+function public (k) {
+ return !(k.charAt(0) === "_" || types[k] !== types[k])
+}
+
+function getKeys (data) {
+ return Object.keys(data).filter(public).sort(sort)
+}
+
function list (cb) {
var msg = ""
, long = npm.config.get("long")
- // cli configs.
- // show any that aren't secret
- var cli = ini.configList.list[ini.TRANS.cli]
- , eol = process.platform === "win32" ? "\r\n" : "\n"
- , cliKeys = Object.keys(cli).filter(function (k) {
- return !(k.charAt(0) === "_" || types[k] !== types[k])
- }).sort(function (a, b) {
- return a > b ? 1 : -1
- })
+ var cli = npm.config.sources.cli.data
+ , cliKeys = getKeys(cli)
if (cliKeys.length) {
- msg += "; cli configs" + eol
+ msg += "; cli configs\n"
cliKeys.forEach(function (k) {
if (cli[k] && typeof cli[k] === "object") return
if (k === "argv") return
- msg += k + " = " + JSON.stringify(cli[k]) + eol
+ msg += k + " = " + JSON.stringify(cli[k]) + "\n"
})
- msg += eol
+ msg += "\n"
}
// env configs
- var env = ini.configList.list[ini.TRANS.env]
- , envKeys = Object.keys(env).filter(function (k) {
- return !(k.charAt(0) === "_" || types[k] !== types[k])
- }).sort(function (a, b) {
- return a > b ? 1 : -1
- })
+ var env = npm.config.sources.env.data
+ , envKeys = getKeys(env)
if (envKeys.length) {
- msg += "; environment configs" + eol
+ msg += "; environment configs\n"
envKeys.forEach(function (k) {
- if (env[k] !== ini.get(k)) {
+ if (env[k] !== npm.config.get(k)) {
if (!long) return
msg += "; " + k + " = " + JSON.stringify(env[k])
- + " (overridden)" + eol
- } else msg += k + " = " + JSON.stringify(env[k]) + eol
+ + " (overridden)\n"
+ } else msg += k + " = " + JSON.stringify(env[k]) + "\n"
})
- msg += eol
+ msg += "\n"
}
// user config file
- var uconf = ini.configList.list[ini.TRANS.user]
- , uconfKeys = Object.keys(uconf).filter(function (k) {
- return types[k] === types[k]
- }).sort(function (a, b) {
- return a > b ? 1 : -1
- })
+ var uconf = npm.config.sources.user.data
+ , uconfKeys = getKeys(uconf)
if (uconfKeys.length) {
- msg += "; userconfig " + ini.get("userconfig") + eol
+ msg += "; userconfig " + npm.config.get("userconfig") + "\n"
uconfKeys.forEach(function (k) {
var val = (k.charAt(0) === "_")
? "---sekretz---"
: JSON.stringify(uconf[k])
- if (uconf[k] !== ini.get(k)) {
+ if (uconf[k] !== npm.config.get(k)) {
if (!long) return
msg += "; " + k + " = " + val
- + " (overridden)" + eol
- } else msg += k + " = " + val + eol
+ + " (overridden)\n"
+ } else msg += k + " = " + val + "\n"
})
- msg += eol
+ msg += "\n"
}
// global config file
- var gconf = ini.configList.list[ini.TRANS.global]
- , gconfKeys = Object.keys(gconf).filter(function (k) {
- return types[k] === types[k]
- }).sort(function (a, b) {
- return a > b ? 1 : -1
- })
+ var gconf = npm.config.sources.global.data
+ , gconfKeys = getKeys(gconf)
if (gconfKeys.length) {
- msg += "; globalconfig " + ini.get("globalconfig") + eol
+ msg += "; globalconfig " + npm.config.get("globalconfig") + "\n"
gconfKeys.forEach(function (k) {
var val = (k.charAt(0) === "_")
? "---sekretz---"
: JSON.stringify(gconf[k])
- if (gconf[k] !== ini.get(k)) {
+ if (gconf[k] !== npm.config.get(k)) {
if (!long) return
msg += "; " + k + " = " + val
- + " (overridden)" + eol
- } else msg += k + " = " + val + eol
+ + " (overridden)\n"
+ } else msg += k + " = " + val + "\n"
})
- msg += eol
+ msg += "\n"
}
// builtin config file
- var bconf = ini.configList.list[ini.TRANS.builtin]
- , bconfKeys = Object.keys(bconf).filter(function (k) {
- return types[k] === types[k]
- }).sort(function (a, b) {
- return a > b ? 1 : -1
+ var builtin = npm.config.sources.builtin || {}
+ if (builtin && builtin.data) {
+ var bconf = builtin.data
+ , bpath = builtin.path
+ , bconfKeys = getKeys(bconf)
+ if (bconfKeys.length) {
+ var path = require("path")
+ msg += "; builtin config " + bpath + "\n"
+ bconfKeys.forEach(function (k) {
+ var val = (k.charAt(0) === "_")
+ ? "---sekretz---"
+ : JSON.stringify(bconf[k])
+ if (bconf[k] !== npm.config.get(k)) {
+ if (!long) return
+ msg += "; " + k + " = " + val
+ + " (overridden)\n"
+ } else msg += k + " = " + val + "\n"
})
- if (bconfKeys.length) {
- var path = require("path")
- msg += "; builtin config " + path.resolve(__dirname, "../npmrc") + eol
- bconfKeys.forEach(function (k) {
- var val = (k.charAt(0) === "_")
- ? "---sekretz---"
- : JSON.stringify(bconf[k])
- if (bconf[k] !== ini.get(k)) {
- if (!long) return
- msg += "; " + k + " = " + val
- + " (overridden)" + eol
- } else msg += k + " = " + val + eol
- })
- msg += eol
+ msg += "\n"
+ }
}
// only show defaults if --long
if (!long) {
- msg += "; node install prefix = " + process.installPrefix + eol
- + "; node bin location = " + process.execPath + eol
- + "; cwd = " + process.cwd() + eol
- + "; HOME = " + process.env.HOME + eol
- + "; 'npm config ls -l' to show all defaults." + eol
+ msg += "; node bin location = " + process.execPath + "\n"
+ + "; cwd = " + process.cwd() + "\n"
+ + "; HOME = " + process.env.HOME + "\n"
+ + "; 'npm config ls -l' to show all defaults.\n"
console.log(msg)
return cb()
}
- var defaults = ini.defaultConfig
- , defKeys = Object.keys(defaults)
- msg += "; default values" + eol
+ var defaults = npmconf.defaults
+ , defKeys = getKeys(defaults)
+ msg += "; default values\n"
defKeys.forEach(function (k) {
if (defaults[k] && typeof defaults[k] === "object") return
var val = JSON.stringify(defaults[k])
- if (defaults[k] !== ini.get(k)) {
- if (!long) return
+ if (defaults[k] !== npm.config.get(k)) {
msg += "; " + k + " = " + val
- + " (overridden)" + eol
- } else msg += k + " = " + val + eol
+ + " (overridden)\n"
+ } else msg += k + " = " + val + "\n"
})
- msg += eol
+ msg += "\n"
console.log(msg)
return cb()
View
57 lib/npm.js
@@ -17,7 +17,7 @@ require("path").SPLIT_CHAR = process.platform === "win32" ? "\\" : "/"
var EventEmitter = require("events").EventEmitter
, npm = module.exports = new EventEmitter
, config = require("./config.js")
- , ini = require("./utils/ini.js")
+ , npmconf = require("npmconf")
, log = require("npmlog")
, fs = require("graceful-fs")
, path = require("path")
@@ -31,6 +31,8 @@ var EventEmitter = require("events").EventEmitter
, chain = slide.chain
, RegClient = require("npm-registry-client")
+npm.config = {loaded: false}
+
// /usr/local is often a read-only fs, which is not
// well handled by node or mkdirp. Just double-check
// in the case of errors when making the prefix dirs.
@@ -223,11 +225,10 @@ function loadCb (er) {
loadListeners.length = 0
}
-
-npm.load = function (conf, cb_) {
- if (!cb_ && typeof conf === "function") cb_ = conf , conf = {}
+npm.load = function (cli, cb_) {
+ if (!cb_ && typeof cli === "function") cb_ = cli , cli = {}
if (!cb_) cb_ = function () {}
- if (!conf) conf = {}
+ if (!cli) cli = {}
loadListeners.push(cb_)
if (loaded || loadErr) return cb(loadErr)
if (loading) return
@@ -236,6 +237,7 @@ npm.load = function (conf, cb_) {
function cb (er) {
if (loadErr) return
+ npm.config.loaded = true
loaded = true
loadCb(loadErr = er)
if (onload = onload && npm.config.get("onload-script")) {
@@ -246,11 +248,10 @@ npm.load = function (conf, cb_) {
log.pause()
- load(npm, conf, cb)
+ load(npm, cli, cb)
}
-
-function load (npm, conf, cb) {
+function load (npm, cli, cb) {
which(process.argv[0], function (er, node) {
if (!er && node.toUpperCase() !== process.execPath.toUpperCase()) {
log.verbose("node symlink", node)
@@ -261,12 +262,16 @@ function load (npm, conf, cb) {
// look up configs
//console.error("about to look up configs")
- ini.resolveConfigs(conf, function (er) {
- var color = npm.config.get("color")
+ npmconf.load(cli, function (er, conf) {
+ if (er === conf) er = null
+
+ npm.config = conf
- log.level = npm.config.get("loglevel")
+ var color = conf.get("color")
+
+ log.level = conf.get("loglevel")
log.heading = "npm"
- log.stream = npm.config.get("logstream")
+ log.stream = conf.get("logstream")
switch (color) {
case "always": log.enableColor(); break
case false: log.disableColor(); break
@@ -294,12 +299,12 @@ function load (npm, conf, cb) {
// at this point the configs are all set.
// go ahead and spin up the registry client.
- var token = npm.config.get("_token")
+ var token = conf.get("_token")
if (typeof token === "string") {
try {
token = JSON.parse(token)
- npm.config.set("_token", token, "user")
- ini.save("user", function () {})
+ conf.set("_token", token, "user")
+ conf.save("user")
} catch (e) { token = null }
}
@@ -329,20 +334,20 @@ function load (npm, conf, cb) {
// save the token cookie in the config file
if (npm.registry.couchLogin) {
npm.registry.couchLogin.tokenSet = function (tok) {
- ini.set("_token", tok, "user")
+ npm.config.set("_token", tok, "user")
// ignore save error. best effort.
- ini.save("user", function () {})
+ npm.config.save("user")
}
}
- var umask = parseInt(conf.umask, 8)
+ var umask = parseInt(cli.umask, 8)
npm.modes = { exec: 0777 & (~umask)
, file: 0666 & (~umask)
, umask: umask }
- chain([ [ loadPrefix, npm, conf ]
- , [ setUser, ini.configList, ini.defaultConfig ]
- , [ loadUid, npm, conf ]
+ chain([ [ loadPrefix, npm, cli ]
+ , [ setUser, conf, conf.root ]
+ , [ loadUid, npm ]
], cb)
})
})
@@ -393,7 +398,7 @@ function loadPrefix (npm, conf, cb) {
}
-function loadUid (npm, conf, cb) {
+function loadUid (npm, cb) {
// if we're not in unsafe-perm mode, then figure out who
// to run stuff as. Do this first, to support `npm update npm -g`
if (!npm.config.get("unsafe-perm")) {
@@ -427,12 +432,6 @@ function setUser (cl, dc, cb) {
}
-npm.config =
- { get : function (key) { return ini.get(key) }
- , set : function (key, val, which) { return ini.set(key, val, which) }
- , del : function (key, val, which) { return ini.del(key, val, which) }
- }
-
Object.defineProperty(npm, "prefix",
{ get : function () {
return npm.config.get("global") ? npm.globalPrefix : npm.localPrefix
@@ -497,7 +496,7 @@ Object.defineProperty(npm, "tmp",
// the better to repl you with
Object.getOwnPropertyNames(npm.commands).forEach(function (n) {
- if (npm.hasOwnProperty(n)) return
+ if (npm.hasOwnProperty(n) || n === "config") return
Object.defineProperty(npm, n, { get: function () {
return function () {
View
5 lib/utils/error-handler.js
@@ -7,14 +7,13 @@ var cbCalled = false
, rm = require("rimraf")
, itWorked = false
, path = require("path")
- , ini = require("./ini.js")
, wroteLogFile = false
, exitCode = 0
process.on("exit", function (code) {
// console.error("exit", code)
- if (!ini.resolved) return
+ if (!npm.config.loaded) return
if (code) itWorked = false
if (itWorked) log.info("ok")
else {
@@ -71,7 +70,7 @@ function exit (code, noLog) {
function errorHandler (er) {
var printStack = false
// console.error("errorHandler", er)
- if (!ini.resolved) {
+ if (!npm.config.loaded) {
// logging won't work unless we pretend that it's ready
er = er || new Error("Exit prior to config file resolving.")
console.error(er.stack || er.message)
View
352 lib/utils/ini.js
@@ -1,352 +0,0 @@
-// Create a chain of config objects, in this priority order:
-//
-// CLI - the --foo things in the command line.
-// ENV - all the things starting with npm_config_ in the environment
-// USER - $HOME/.npmrc
-// GLOBAL - $PREFIX/etc/npmrc
-//
-// If the CLI or ENV specify a userconfig, then that file is used
-// as the USER config.
-//
-// If the CLI or ENV specify a globalconfig, then that file is used
-// as the GLOBAL config.
-//
-// export npm_config_userconfig=/some/other/file
-// export npm_config_globalconfig=global
-//
-// For implementation reasons, "_" in env vars is turned into "-". So,
-// export npm_config_node_version
-
-exports.resolveConfigs = resolveConfigs
-exports.save = save
-exports.saveConfig = saveConfig
-exports.del = del
-exports.get = get
-exports.set = set
-exports.unParseField = unParseField
-exports.defaultConfig = null
-
-Object.defineProperty(exports, "keys",
- { get : function () { return configList.keys }})
-
-var fs = require("graceful-fs")
- , fstream = require("fstream")
- , rimraf = require("rimraf")
- , path = require("path")
- , nopt = require("nopt")
- , ini = require("ini")
- , ProtoList = require("proto-list")
- , mkdir = require("mkdirp")
- , npm = require("../npm.js")
-
- , log = require("npmlog")
- , configDefs = require("./config-defs.js")
-
- , myUid = process.env.SUDO_UID !== undefined
- ? process.env.SUDO_UID : (process.getuid && process.getuid())
- , myGid = process.env.SUDO_GID !== undefined
- ? process.env.SUDO_GID : (process.getgid && process.getgid())
-
- , eol = process.platform === "win32" ? "\r\n" : "\n"
- , privateKey = null
- , defaultConfig
- , configList = new ProtoList()
- , types = configDefs.types
-
- , TRANS = exports.TRANS =
- { "default" : 5
- , "builtin": 4
- , "global" : 3
- , "user" : 2
- , "env" : 1
- , "cli" : 0
- }
-
-exports.configList = configList
-
-// just put this here for a moment, so that the logs
-// in the config-loading phase don't cause it to blow up.
-
-function resolveConfigs (cli, cb_) {
- defaultConfig = defaultConfig || configDefs.defaults
- exports.defaultConfig = defaultConfig
- configList.pop()
- configList.push(defaultConfig)
- var cl = configList
- , dc = cl.pop()
- if (!cb_) cb_ = cli, cli = {}
-
- function cb (er) {
- //console.error("resolving configs")
- exports.resolved = true
- cb_(er)
- }
-
- cl.list.length = 0
- Object.keys(cli).forEach(function (k) {
- cli[k] = parseField(cli[k], k)
- })
- cl.push(cli)
- cl.push(parseEnv(process.env))
-
- parseFile(cl.get("userconfig") || dc.userconfig, function (er, conf) {
- if (er) return cb(er)
- cl.push(conf)
-
- // globalconfig and globalignorefile defaults
- // need to respond to the "prefix" setting up to this point.
- // Eg, `npm config get globalconfig --prefix ~/local` should
- // return `~/local/etc/npmrc`
- if (cl.get("prefix")) {
- dc.globalconfig = path.resolve(cl.get("prefix"), "etc", "npmrc")
- dc.globalignorefile = path.resolve(cl.get("prefix"), "etc", "npmignore")
- }
-
- parseFile( cl.get("globalconfig") || dc.globalconfig
- , function (er, conf) {
- if (er) return cb(er)
-
- if (conf.hasOwnProperty("prefix")) {
- log.warn( "globalconfig"
- , "Cannot set prefix in globalconfig file"
- , cl.get("globalconfig"))
- delete conf.prefix
- }
-
- cl.push(conf)
- // the builtin config file, for distros to use.
-
- parseFile(path.resolve(__dirname, "../../npmrc"), function (er, conf) {
- if (er) conf = {}
- cl.push(conf)
- cl.push(dc)
- validate(cl)
- cb()
- })
- })
- })
-}
-
-function validate (cl) {
- // warn about invalid configs at every level.
- cl.list.forEach(function (conf, level) {
- // clean(data, types, typeDefs)
- nopt.clean(conf, configDefs.types)
- })
-}
-
-
-function parseEnv (env) {
- var conf = {}
- Object.keys(env)
- .filter(function (k) { return k.match(/^npm_config_[^_]/i) })
- .forEach(function (k) {
- if (!env[k]) return
-
- conf[k.replace(/^npm_config_/i, "")
- .toLowerCase()
- .replace(/_/g, "-")] = parseField(env[k], k)
- })
- return conf
-}
-
-function unParseField (f, k) {
- // type can be an array or single thing.
- var isPath = -1 !== [].concat(types[k]).indexOf(path)
- if (isPath) {
- if (typeof process.env.HOME !== 'undefined') {
- if (process.env.HOME.substr(-1) === "/") {
- process.env.HOME = process.env.HOME.slice(0, process.env.HOME.length-1)
- }
- if (f.indexOf(process.env.HOME) === 0) {
- f = "~"+f.substr(process.env.HOME.length)
- }
- }
- }
- return (!f || typeof f !== "object") ? ini.safe(f) : f
- return ini.safe(f)
-}
-
-function parseField (f, k, emptyIsFalse) {
- if (typeof f !== "string" && !(f instanceof String)) return f
- // type can be an array or single thing.
- var isPath = -1 !== [].concat(types[k]).indexOf(path)
- , isBool = -1 !== [].concat(types[k]).indexOf(Boolean)
- , isString = -1 !== [].concat(types[k]).indexOf(String)
- f = ini.unsafe((""+f).trim())
- if (isBool && !isString && f === "") return f = true
- switch (f) {
- case "true": return true
- case "false": return false
- case "null": return null
- case "undefined": return undefined
- }
-
- f = envReplace(f)
-
- if (isPath) {
- var homePattern = process.platform === "win32" ? /^~(\/|\\)/ : /^~\//
- if (f.match(homePattern) && process.env.HOME) {
- f = path.resolve(process.env.HOME, f.substr(2))
- }
- f = path.resolve(f)
- }
-
- return f
-}
-
-function parseFile (file, cb) {
- if (!file) return cb(null, {})
- log.verbose("config file", file)
- fs.readFile(file, function (er, data) {
- // treat all errors as just an empty file
- if (er) return cb(null, {})
- var d = ini.parse(""+data)
- , f = {}
- Object.keys(d).forEach(function (k) {
- f[k] = parseField(d[k], k)
- })
- cb(null, parseAuth(f))
- })
-}
-
-function encryptAuth (config, cb) {
- if (config.username && config._password) {
- var b = new Buffer(config.username+":"+config._password)
- config._auth = b.toString("base64")
- }
- delete config.username
- delete config._password
- return cb(null, config)
-}
-
-function parseAuth (config) {
- if (!config._auth) return config
- var b = new Buffer(config._auth, "base64")
- , unpw = b.toString().split(":")
- , un = unpw.shift()
- , pw = unpw.join(":")
- config.username = un = (config.username || un)
- config._password = pw = (config._password || pw)
- b = new Buffer(un + ":" + pw)
- config._auth = b.toString("base64")
- return config
-}
-
-function save (which, cb) {
- if (typeof which === "function") cb = which, which = null
- if (!which) which = ["global", "user", "builtin"]
- if (!Array.isArray(which)) which = [which]
- var errState = null
- , done = which.length
- , failed = []
- which.forEach(function (c) {
- saveConfig(c, function (er) {
- if (errState) return
- if (er) return cb(errState = er)
- if (-- done === 0) return cb()
- })
- })
-}
-
-function saveConfig (which, file, cb) {
- if (typeof file === "function") cb = file, file = null
- if (!file) {
- switch (which) {
- case "builtin":
- file = path.resolve(__dirname, "../../npmrc")
- break
- case "global":
- file = configList.get("globalconfig")
- break
- default:
- file = configList.get("userconfig")
- which = "user"
- }
- }
-
- saveConfigfile
- ( file
- , configList.list[TRANS[which]]
- , which
- , cb )
-}
-
-function saveConfigfile (file, config, which, cb) {
- encryptAuth(config, function () { // ignore errors
- var data = {}
- Object.keys(config).forEach(function (k) {
- data[k] = unParseField(config[k], k)
- })
- data = ini.stringify(data)
- return (data.trim())
- ? writeConfigfile(file, data, which, cb)
- : rimraf(file, cb)
- })
-}
-
-function writeConfigfile (configfile, data, which, cb) {
- data = data.split(/\r*\n/).join(eol)
- var props = { type: "File", path: configfile }
- if (which === "user") {
- props.mode = 0600
- if (typeof myUid === "number") {
- props.uid = +myUid
- props.gid = +myGid
- }
- } else {
- props.mode = 0644
- }
- fstream.Writer(props)
- .on("close", cb)
- .on("error", cb)
- .end(data)
-}
-
-function snapshot (which) {
- var x = (!which) ? configList.snapshot
- : configList.list[TRANS[which]] ? configList.list[TRANS[which]]
- : undefined
- if (!x) return
- Object.keys(x).forEach(function (k) { if (k.match(/^_/)) delete x[k] })
- return x
-}
-function get (key, which) {
- return (!key) ? snapshot(which)
- : (!which) ? configList.get(key) // resolved
- : configList.list[TRANS[which]]
- ? envReplace(configList.list[TRANS[which]][key])
- : undefined
-}
-
-function envReplace (f) {
- if (typeof f !== "string" || !f) return f
-
- // replace any ${ENV} values with the appropriate environ.
- var envExpr = /(\\*)\$\{([^}]+)\}/g
- return f.replace(envExpr, function (orig, esc, name, i, s) {
- esc = esc.length && esc.length % 2
- if (esc) return orig
- if (undefined === process.env[name]) {
- throw new Error("Failed to replace env in config: "+orig)
- }
- return process.env[name]
- })
-}
-
-function del (key, which) {
- if (!which) configList.list.forEach(function (l) {
- delete l[key]
- })
- else if (configList.list[TRANS[which]]) {
- delete configList.list[TRANS[which]]
- }
-}
-function set (key, value, which) {
- which = which || "cli"
- if (configList.length === 1) {
- return new Error("trying to set before loading")
- }
- configList.list[TRANS[which]][key] = value
- return value
-}
View
5 lib/utils/lifecycle.js
@@ -242,8 +242,7 @@ function makeEnv (data, prefix, env) {
prefix = "npm_config_"
var pkgConfig = {}
- , ini = require("./ini.js")
- , keys = ini.keys
+ , keys = npm.config.keys
, pkgVerConfig = {}
, namePref = data.name + ":"
, verPref = data.name + "@" + data.version + ":"
@@ -252,7 +251,7 @@ function makeEnv (data, prefix, env) {
if (i.charAt(0) === "_" && i.indexOf("_"+namePref) !== 0) {
return
}
- var value = ini.get(i)
+ var value = npm.config.get(i)
if (value instanceof Stream) return
if (!value) value = ""
else if (typeof value !== "string") value = JSON.stringify(value)
View
1 lib/view.js
@@ -41,7 +41,6 @@ view.completion = function (opts, cb) {
var npm = require("./npm.js")
, registry = npm.registry
- , ini = require("ini")
, log = require("npmlog")
, util = require("util")
, semver = require("semver")
View
32 node_modules/ini/ini.js
@@ -5,6 +5,8 @@ exports.stringify = exports.encode = encode
exports.safe = safe
exports.unsafe = unsafe
+var eol = process.platform === "win32" ? "\r\n" : "\n"
+
function encode (obj, section) {
var children = []
, out = ""
@@ -14,25 +16,35 @@ function encode (obj, section) {
if (val && typeof val === "object") {
children.push(k)
} else {
- out += safe(k) + " = " + safe(val) + "\n"
+ out += safe(k) + " = " + safe(val) + eol
}
})
if (section && out.length) {
- out = "[" + safe(section) + "]" + "\n" + out
+ out = "[" + safe(section) + "]" + eol + out
}
children.forEach(function (k, _, __) {
- var child = encode(obj[k], (section ? section + "." : "") + k)
+ var nk = dotSplit(k).join('\\.')
+ var child = encode(obj[k], (section ? section + "." : "") + nk)
if (out.length && child.length) {
- out += "\n"
+ out += eol
}
out += child
})
return out
}
+function dotSplit (str) {
+ return str.replace(/\1/g, '\2LITERAL\\1LITERAL\2')
+ .replace(/\\\./g, '\1')
+ .split(/\./).map(function (part) {
+ return part.replace(/\1/g, '\\.')
+ .replace(/\2LITERAL\\1LITERAL\2/g, '\1')
+ })
+}
+
function decode (str) {
var out = {}
, p = out
@@ -57,6 +69,11 @@ function decode (str) {
}
var key = unsafe(match[2])
, value = match[3] ? unsafe((match[4] || "")) : true
+ switch (value) {
+ case 'true':
+ case 'false':
+ case 'null': value = JSON.parse(value)
+ }
p[key] = value
})
@@ -66,15 +83,16 @@ function decode (str) {
if (!out[k] || typeof out[k] !== "object") return false
// see if the parent section is also an object.
// if so, add it to that, and mark this one for deletion
- var parts = k.split(".")
+ var parts = dotSplit(k)
, p = out
, l = parts.pop()
+ , nl = l.replace(/\\\./g, '.')
parts.forEach(function (part, _, __) {
if (!p[part] || typeof p[part] !== "object") p[part] = {}
p = p[part]
})
- if (p === out) return false
- p[l] = out[k]
+ if (p === out && nl === l) return false
+ p[nl] = out[k]
return true
}).forEach(function (del, _, __) {
delete out[del]
View
16 node_modules/ini/package.json
@@ -1,15 +1,19 @@
{
- "author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "url": "http://blog.izs.me/"
+ },
"name": "ini",
"description": "An ini encoder/decoder for node",
- "version": "1.0.2",
+ "version": "1.0.4",
"repository": {
"type": "git",
"url": "git://github.com/isaacs/ini.git"
},
"main": "ini.js",
"scripts": {
- "test": "node ini.js"
+ "test": "tap test/*.js"
},
"engines": {
"node": "*"
@@ -18,7 +22,7 @@
"devDependencies": {
"tap": "~0.0.9"
},
- "scripts": {
- "test": "tap test/*.js"
- }
+ "readme": "An ini format parser and serializer for node.\n\nSections are treated as nested objects. Items before the first heading\nare saved on the object directly.\n\n## Usage\n\nConsider an ini-file `config.ini` that looks like this:\n\n ; this comment is being ignored\n scope = global\n\n [database]\n user = dbuser\n password = dbpassword\n database = use_this_database\n\n [paths.default]\n datadir = /var/lib/data\n\nYou can read, manipulate and write the ini-file like so:\n\n var fs = require('fs')\n , ini = require('ini')\n\n var config = ini.parse(fs.readFileSync('./config.ini', 'utf-8'))\n\n config.scope = 'local'\n config.database.database = 'use_another_database'\n config.paths.default.tmpdir = '/tmp'\n delete config.paths.default.datadir\n\n fs.writeFileSync('./config_modified.ini', ini.stringify(config, 'section'))\n\nThis will result in a file called `config_modified.ini` being written to the filesystem with the following content:\n\n [section]\n scope = local\n [section.database]\n user = dbuser\n password = dbpassword\n database = use_another_database\n [section.paths.default]\n tmpdir = /tmp\n\n## API\n\n### decode(inistring)\nDecode the ini-style formatted `inistring` into a nested object.\n\n### parse(inistring)\nAlias for `decode(inistring)`\n\n### encode(object, [section])\nEncode the object `object` into an ini-style formatted string. If the optional parameter `section` is given, then all top-level properties of the object are put into this section and the `section`-string is prepended to all sub-sections, see the usage example above.\n\n### stringify(object, [section])\nAlias for `encode(object, [section])`\n\n### safe(val)\nEscapes the string `val` such that it is safe to be used as a key or value in an ini-file. Basically escapes quotes. For example\n\n ini.safe('\"unsafe string\"')\n\nwould result in\n\n \"\\\"unsafe string\\\"\"\n\n### unsafe(val)\nUnescapes the string `val`\n\n",
+ "_id": "ini@1.0.4",
+ "_from": "ini@latest"
}
View
23 node_modules/ini/test/bar.js
@@ -0,0 +1,23 @@
+//test that parse(stringify(obj) deepEqu
+
+var ini = require('../')
+var test = require('tap').test
+
+var data = {
+ 'number': {count: 10},
+ 'string': {drink: 'white russian'},
+ 'boolean': {isTrue: true},
+ 'nested boolean': {theDude: {abides: true, rugCount: 1}}
+}
+
+
+test('parse(stringify(x)) deepEqual x', function (t) {
+
+ for (var k in data) {
+ var s = ini.stringify(data[k])
+ console.log(s, data[k])
+ t.deepEqual(ini.parse(s), data[k])
+ }
+
+ t.end()
+})
View
29 node_modules/ini/test/fixtures/foo.ini
@@ -0,0 +1,29 @@
+o = p
+
+ a with spaces = b c
+
+; wrap in quotes to JSON-decode and preserve spaces
+" xa n p " = "\"\r\nyoyoyo\r\r\n"
+
+; wrap in quotes to get a key with a bracket, not a section.
+"[disturbing]" = hey you never know
+
+; a section
+[a]
+av = a val
+e = { o: p, a: { av: a val, b: { c: { e: "this [value]" } } } }
+j = "{ o: "p", a: { av: "a val", b: { c: { e: "this [value]" } } } }"
+"[]" = a square?
+
+; nested child without middle parent
+; should create otherwise-empty a.b
+[a.b.c]
+e = 1
+j = 2
+
+; dots in the section name should be literally interpreted
+[x\.y\.z]
+x.y.z = xyz
+
+[x\.y\.z.a\.b\.c]
+a.b.c = abc
View
59 node_modules/ini/test/foo.js
@@ -0,0 +1,59 @@
+var i = require("../")
+ , tap = require("tap")
+ , test = tap.test
+ , fs = require("fs")
+ , path = require("path")
+ , fixture = path.resolve(__dirname, "./fixtures/foo.ini")
+ , data = fs.readFileSync(fixture, "utf8")
+ , d
+ , expectE = 'o = p\n'
+ + 'a with spaces = b c\n'
+ + '" xa n p " = "\\"\\r\\nyoyoyo\\r\\r\\n"\n'
+ + '"[disturbing]" = hey you never know\n'
+ + '\n'
+ + '[a]\n'
+ + 'av = a val\n'
+ + 'e = { o: p, a: '
+ + '{ av: a val, b: { c: { e: "this [value]" '
+ + '} } } }\nj = "\\"{ o: \\"p\\", a: { av:'
+ + ' \\"a val\\", b: { c: { e: \\"this [value]'
+ + '\\" } } } }\\""\n"[]" = a square?\n\n[a.b.c]\ne = 1\n'
+ + 'j = 2\n\n[x\\.y\\.z]\nx.y.z = xyz\n\n'
+ + '[x\\.y\\.z.a\\.b\\.c]\n'
+ + 'a.b.c = abc\n'
+ , expectD =
+ { o: 'p',
+ 'a with spaces': 'b c',
+ " xa n p ":'"\r\nyoyoyo\r\r\n',
+ '[disturbing]': 'hey you never know',
+ a:
+ { av: 'a val',
+ e: '{ o: p, a: { av: a val, b: { c: { e: "this [value]" } } } }',
+ j: '"{ o: "p", a: { av: "a val", b: { c: { e: "this [value]" } } } }"',
+ "[]": "a square?",
+ b: { c: { e: '1', j: '2' } } },
+ 'x.y.z': {
+ 'x.y.z': 'xyz',
+ 'a.b.c': {
+ 'a.b.c': 'abc'
+ }
+ }
+ }
+
+test("decode from file", function (t) {
+ var d = i.decode(data)
+ t.deepEqual(d, expectD)
+ t.end()
+})
+
+test("encode from data", function (t) {
+ var e = i.encode(expectD)
+ t.deepEqual(e, expectE)
+
+ var obj = {log: { type:'file', level: {label:'debug', value:10} } }
+ e = i.encode(obj)
+ t.notEqual(e.slice(0, 1), '\n', 'Never a blank first line')
+ t.notEqual(e.slice(-2), '\n\n', 'Never a blank final line')
+
+ t.end()
+})
View
1 node_modules/npmconf/.npmignore
@@ -0,0 +1 @@
+/test/fixtures/userconfig-with-gc
View
33 node_modules/npmconf/README.md
@@ -0,0 +1,33 @@
+# npmconf
+
+The config thing npm uses
+
+If you are interested in interacting with the config settings that npm
+uses, then use this module.
+
+However, if you are writing a new Node.js program, and want
+configuration functionality similar to what npm has, but for your
+own thing, then I'd recommend using [rc](https://github.com/dominictarr/rc),
+which is probably what you want.
+
+If I were to do it all over again, that's what I'd do for npm. But,
+alas, there are many systems depending on many of the particulars of
+npm's configuration setup, so it's not worth the cost of changing.
+
+## USAGE
+
+```javascript
+var npmconf = require('npmconf')
+
+// pass in the cli options that you read from the cli
+// or whatever top-level configs you want npm to use for now.
+npmconf.load({some:'configs'}, function (er, conf) {
+ // do stuff with conf
+ conf.get('some', 'cli') // 'configs'
+ conf.get('username') // 'joebobwhatevers'
+ conf.set('foo', 'bar', 'user')
+ conf.save('user', function (er) {
+ // foo = bar is now saved to ~/.npmrc or wherever
+ })
+})
+```
View
14 lib/utils/config-defs.js → node_modules/npmconf/config-defs.js
@@ -7,10 +7,18 @@ var path = require("path")
, semver = require("semver")
, stableFamily = semver.parse(process.version)
, nopt = require("nopt")
- , log = require("npmlog")
- , npm = require("../npm.js")
, osenv = require("osenv")
+try {
+ var log = require("npmlog")
+} catch (er) {
+ var util = require('util')
+ var log = { warn: function (m) {
+ console.warn(m + util.format.apply(util, [].slice.call(arguments, 1)))
+ } }
+}
+
+exports.Octal = Octal
function Octal () {}
function validateOctal (data, k, val) {
// must be either an integer or an octal string.
@@ -176,7 +184,7 @@ Object.defineProperty(exports, "defaults", {get: function () {
, proxy : process.env.HTTP_PROXY || process.env.http_proxy || null
, "https-proxy" : process.env.HTTPS_PROXY || process.env.https_proxy ||
process.env.HTTP_PROXY || process.env.http_proxy || null
- , "user-agent" : "npm/" + npm.version + " node/" + process.version
+ , "user-agent" : "node/" + process.version
, "rebuild-bundle" : true
, registry : "https://registry.npmjs.org/"
, rollback : true
View
3 node_modules/npmconf/node_modules/config-chain/.npmignore
@@ -0,0 +1,3 @@
+node_modules
+node_modules/*
+npm_debug.log
View
22 node_modules/npmconf/node_modules/config-chain/LICENCE
@@ -0,0 +1,22 @@
+Copyright (c) 2011 Dominic Tarr
+
+Permission is hereby granted, free of charge,
+to any person obtaining a copy of this software and
+associated documentation files (the "Software"), to
+deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
282 node_modules/npmconf/node_modules/config-chain/index.js
@@ -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(start != '/')
+ 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) }
+ } 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 file = path.join.apply(null, [].slice.call(arguments))
+ 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((i =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 && where.hasOwnProperty(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)
+}
View
0 node_modules/proto-list/LICENSE → ...fig-chain/node_modules/proto-list/LICENSE
File renamed without changes.
View
0 node_modules/proto-list/README.md → ...g-chain/node_modules/proto-list/README.md
File renamed without changes.
View
28 node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "proto-list",
+ "version": "1.2.2",
+ "description": "A utility for managing a prototype chain",
+ "main": "./proto-list.js",
+ "author": {
+ "name": "Isaac Z. Schlueter",
+ "email": "i@izs.me",
+ "url": "http://blog.izs.me/"
+ },
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/isaacs/proto-list"
+ },
+ "license": {
+ "type": "MIT",
+ "url": "https://github.com/isaacs/proto-list/blob/master/LICENSE"
+ },
+ "devDependencies": {
+ "tap": "0"
+ },
+ "readme": "A list of objects, bound by their prototype chain.\n\nUsed in npm's config stuff.\n",
+ "_id": "proto-list@1.2.2",
+ "_from": "proto-list@~1.2.1"
+}
View
73 node_modules/proto-list/proto-list.js → ...ain/node_modules/proto-list/proto-list.js
@@ -1,7 +1,22 @@
module.exports = ProtoList
-function ProtoList () { this.list = [] }
+function ProtoList () {
+ this.list = []
+ var root = null
+ Object.defineProperty(this, 'root', {
+ get: function () { return root },
+ set: function (r) {
+ root = r
+ if (this.list.length) {
+ this.list[this.list.length - 1].__proto__ = r
+ }
+ },
+ enumerable: true,
+ configurable: true
+ })
+}
+
ProtoList.prototype =
{ get length () { return this.list.length }
, get keys () {
@@ -14,27 +29,30 @@ ProtoList.prototype =
this.keys.forEach(function (k) { o[k] = this.get(k) }, this)
return o
}
+ , get store () {
+ return this.list[0]
+ }
, push : function (obj) {
if (typeof obj !== "object") obj = {valueOf:obj}
if (this.list.length >= 1) {
this.list[this.list.length - 1].__proto__ = obj
}
- obj.__proto__ = Object.prototype
+ obj.__proto__ = this.root
return this.list.push(obj)
}
, pop : function () {
if (this.list.length >= 2) {
- this.list[this.list.length - 2].__proto__ = Object.prototype
+ this.list[this.list.length - 2].__proto__ = this.root
}
return this.list.pop()
}
, unshift : function (obj) {
- obj.__proto__ = this.list[0] || Object.prototype
+ obj.__proto__ = this.list[0] || this.root
return this.list.unshift(obj)
}
, shift : function () {
- if (this.list.length >= 1) {
- this.list[0].__proto__ = Object.prototype
+ if (this.list.length === 1) {
+ this.list[0].__proto__ = this.root
}
return this.list.shift()
}
@@ -53,42 +71,11 @@ ProtoList.prototype =
return this.list.slice.apply(this.list, arguments)
}
, splice : function () {
- return this.list.splice.apply(this.list, arguments)
+ // handle injections
+ var ret = this.list.splice.apply(this.list, arguments)
+ for (var i = 0, l = this.list.length; i < l; i++) {
+ this.list[i].__proto__ = this.list[i + 1] || this.root
+ }
+ return ret
}
}
-
-if (module === require.main) {
-
-var tap = require("tap")
- , test = tap.test
-
-tap.plan(1)
-
-tap.test("protoList tests", function (t) {
- var p = new ProtoList
- p.push({foo:"bar"})
- p.push({})
- p.set("foo", "baz")
- t.equal(p.get("foo"), "baz")
-
- var p = new ProtoList
- p.push({foo:"bar"})
- p.set("foo", "baz")
- t.equal(p.get("foo"), "baz")
- t.equal(p.length, 1)
- p.pop()
- t.equal(p.length, 0)
- p.set("foo", "asdf")
- t.equal(p.length, 1)
- t.equal(p.get("foo"), "asdf")
- p.push({bar:"baz"})
- t.equal(p.length, 2)
- t.equal(p.get("foo"), "asdf")
- p.shift()
- t.equal(p.length, 1)
- t.equal(p.get("foo"), undefined)
- t.end()
-})
-
-
-}
View
61 node_modules/npmconf/node_modules/config-chain/node_modules/proto-list/test/basic.js
@@ -0,0 +1,61 @@
+var tap = require("tap")
+ , test = tap.test
+ , ProtoList = require("../proto-list.js")
+
+tap.plan(1)
+
+tap.test("protoList tests", function (t) {
+ var p = new ProtoList
+ p.push({foo:"bar"})
+ p.push({})
+ p.set("foo", "baz")
+ t.equal(p.get("foo"), "baz")
+
+ var p = new ProtoList
+ p.push({foo:"bar"})
+ p.set("foo", "baz")
+ t.equal(p.get("foo"), "baz")
+ t.equal(p.length, 1)
+ p.pop()
+ t.equal(p.length, 0)
+ p.set("foo", "asdf")
+ t.equal(p.length, 1)
+ t.equal(p.get("foo"), "asdf")
+ p.push({bar:"baz"})
+ t.equal(p.length, 2)
+ t.equal(p.get("foo"), "asdf")
+ p.shift()
+ t.equal(p.length, 1)
+ t.equal(p.get("foo"), undefined)
+
+
+ p.unshift({foo:"blo", bar:"rab"})
+ p.unshift({foo:"boo"})
+ t.equal(p.length, 3)
+ t.equal(p.get("foo"), "boo")
+ t.equal(p.get("bar"), "rab")
+
+ var ret = p.splice(1, 1, {bar:"bar"})
+ t.same(ret, [{foo:"blo", bar:"rab"}])
+ t.equal(p.get("bar"), "bar")
+
+ // should not inherit default object properties
+ t.equal(p.get('hasOwnProperty'), undefined)
+
+ // unless we give it those.
+ p.root = {}
+ t.equal(p.get('hasOwnProperty'), {}.hasOwnProperty)
+
+ p.root = {default:'monkey'}
+ t.equal(p.get('default'), 'monkey')
+
+ p.push({red:'blue'})
+ p.push({red:'blue'})
+ p.push({red:'blue'})
+ while (p.length) {
+ t.equal(p.get('default'), 'monkey')
+ p.shift()
+ }
+
+ t.end()
+})
View
28 node_modules/npmconf/node_modules/config-chain/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "config-chain",
+ "version": "1.1.1",
+ "description": "HANDLE CONFIGURATION ONCE AND FOR ALL",
+ "homepage": "http://github.com/dominictarr/config-chain",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/dominictarr/config-chain.git"
+ },
+ "dependencies": {
+ "proto-list": "~1.2.1",
+ "ini": "~1.0.2"
+ },
+ "devDependencies": {
+ "tap": "0.3.0"
+ },
+ "author": {
+ "name": "Dominic Tarr",
+ "email": "dominic.tarr@gmail.com",
+ "url": "http://dominictarr.com"
+ },
+ "scripts": {
+ "test": "tap test/"
+ },
+ "readme": "#config-chain\n\nUSE THIS MODULE TO LOAD ALL YOUR CONFIGURATIONS\n\n``` js\n\n //npm install config-chain\n\n var cc = require('config-chain')\n , opts = require('optimist').argv //ALWAYS USE OPTIMIST FOR COMMAND LINE OPTIONS.\n , env = opts.env || process.env.YOUR_APP_ENV || 'dev' //SET YOUR ENV LIKE THIS.\n\n // EACH ARG TO CONFIGURATOR IS LOADED INTO CONFIGURATION CHAIN\n // EARLIER ITEMS OVERIDE LATER ITEMS\n // PUTS COMMAND LINE OPTS FIRST, AND DEFAULTS LAST!\n\n //strings are interpereted as filenames.\n //will be loaded synchronously\n\n var conf =\n cc(\n //OVERRIDE SETTINGS WITH COMMAND LINE OPTS\n opts,\n\n //ENV VARS IF PREFIXED WITH 'myApp_'\n\n cc.env('myApp_'), //myApp_foo = 'like this'\n\n //FILE NAMED BY ENV\n path.join(__dirname, 'config.' + env + '.json'),\n\n //IF `env` is PRODUCTION\n env === 'prod'\n ? path.join(__dirname, 'special.json') //load a special file\n : null //NULL IS IGNORED!\n\n //SUBDIR FOR ENV CONFIG\n path.join(__dirname, 'config', env, 'config.json'),\n\n //SEARCH PARENT DIRECTORIES FROM CURRENT DIR FOR FILE\n cc.find('config.json'),\n\n //PUT DEFAULTS LAST\n {\n host: 'localhost'\n port: 8000\n })\n\n var host = conf.get('host')\n\n // or\n\n var host = conf.store.host\n\n```\n\nFINALLY, EASY FLEXIBLE CONFIGURATIONS!\n\n##see also: [proto-list](https://github.com/isaacs/proto-list/)\n\nWHATS THAT YOU SAY?\n\nYOU WANT A \"CLASS\" SO THAT YOU CAN DO CRAYCRAY JQUERY CRAPS?\n\nEXTEND WITH YOUR OWN FUNCTIONALTY!?\n\n## CONFIGCHAIN LIVES TO SERVE ONLY YOU!\n\n```javascript\nvar cc = require('config-chain')\n\n// all the stuff you did before\nvar config = cc({\n some: 'object'\n },\n cc.find('config.json'),\n cc.env('myApp_')\n )\n // CONFIGS AS A SERVICE, aka \"CaaS\", aka EVERY DEVOPS DREAM OMG!\n .addUrl('http://configurator:1234/my-configs')\n // ASYNC FTW!\n .addFile('/path/to/file.json')\n\n // OBJECTS ARE OK TOO, they're SYNC but they still ORDER RIGHT\n // BECAUSE PROMISES ARE USED BUT NO, NOT *THOSE* PROMISES, JUST\n // ACTUAL PROMISES LIKE YOU MAKE TO YOUR MOM, KEPT OUT OF LOVE\n .add({ another: 'object' })\n\n // DIE A THOUSAND DEATHS IF THIS EVER HAPPENS!!\n .on('error', function (er) {\n // IF ONLY THERE WAS SOMETHIGN HARDER THAN THROW\n // MY SORROW COULD BE ADEQUATELY EXPRESSED. /o\\\n throw er\n })\n\n // THROW A PARTY IN YOUR FACE WHEN ITS ALL LOADED!!\n .on('load', function (config) {\n console.awesome('HOLY SHIT!')\n })\n```\n\n# BORING API DOCS\n\n## cc(...args)\n\nMAKE A CHAIN AND ADD ALL THE ARGS.\n\nIf the arg is a STRING, then it shall be a JSON FILENAME.\n\nSYNC I/O!\n\nRETURN THE CHAIN!\n\n## cc.json(...args)\n\nJoin the args INTO A JSON FILENAME!\n\nSYNC I/O!\n\n## cc.find(relativePath)\n\nSEEK the RELATIVE PATH by climbing the TREE OF DIRECTORIES.\n\nRETURN THE FOUND PATH!\n\nSYNC I/O!\n\n## cc.parse(content, file, type)\n\nParse the content string, and guess the type from either the\nspecified type or the filename.\n\nRETURN THE RESULTING OBJECT!\n\nNO I/O!\n\n## cc.env(prefix, env=process.env)\n\nGet all the keys on the provided env object (or process.env) which are\nprefixed by the specified prefix, and put the values on a new object.\n\nRETURN THE RESULTING OBJECT!\n\nNO I/O!\n\n## cc.ConfigChain()\n\nThe ConfigChain class for CRAY CRAY JQUERY STYLE METHOD CHAINING!\n\nOne of these is returned by the main exported function, as well.\n\nIt inherits (prototypically) from\n[ProtoList](https://github.com/isaacs/proto-list/), and also inherits\n(parasitically) from\n[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)\n\nIt has all the methods from both, and except where noted, they are\nunchanged.\n\n### LET IT BE KNOWN THAT chain IS AN INSTANCE OF ConfigChain.\n\n## chain.sources\n\nA list of all the places where it got stuff. The keys are the names\npassed to addFile or addUrl etc, and the value is an object with some\ninfo about the data source.\n\n## chain.addFile(filename, type, [name=filename])\n\nFilename is the name of the file. Name is an arbitrary string to be\nused later if you desire. Type is either 'ini' or 'json', and will\ntry to guess intelligently if omitted.\n\nLoaded files can be saved later.\n\n## chain.addUrl(url, type, [name=url])\n\nSame as the filename thing, but with a url.\n\nCan't be saved later.\n\n## chain.addEnv(prefix, env, [name='env'])\n\nAdd all the keys from the env object that start with the prefix.\n\n## chain.addString(data, file, type, [name])\n\nParse the string and add it to the set. (Mainly used internally.)\n\n## chain.add(object, [name])\n\nAdd the object to the set.\n\n## chain.root {Object}\n\nThe root from which all the other config objects in the set descend\nprototypically.\n\nPut your defaults here.\n\n## chain.set(key, value, name)\n\nSet the key to the value on the named config object. If name is\nunset, then set it on the first config object in the set. (That is,\nthe one with the highest priority, which was added first.)\n\n## chain.get(key, [name])\n\nGet the key from the named config object explicitly, or from the\nresolved configs if not specified.\n\n## chain.save(name, type)\n\nWrite the named config object back to its origin.\n\nCurrently only supported for env and file config types.\n\nFor files, encode the data according to the type.\n\n## chain.on('save', function () {})\n\nWhen one or more files are saved, emits `save` event when they're all\nsaved.\n\n## chain.on('load', function (chain) {})\n\nWhen the config chain has loaded all the specified files and urls and\nsuch, the 'load' event fires.\n",
+ "_id": "config-chain@1.1.1",
+ "_from": "config-chain@~1.1.1"
+}
View
228 node_modules/npmconf/node_modules/config-chain/readme.markdown
@@ -0,0 +1,228 @@
+#config-chain
+
+USE THIS MODULE TO LOAD ALL YOUR CONFIGURATIONS
+
+``` js
+
+ //npm install config-chain
+
+ var cc = require('config-chain')
+ , opts = require('optimist').argv //ALWAYS USE OPTIMIST FOR COMMAND LINE OPTIONS.
+ , env = opts.env || process.env.YOUR_APP_ENV || 'dev' //SET YOUR ENV LIKE THIS.
+
+ // EACH ARG TO CONFIGURATOR IS LOADED INTO CONFIGURATION CHAIN
+ // EARLIER ITEMS OVERIDE LATER ITEMS
+ // PUTS COMMAND LINE OPTS FIRST, AND DEFAULTS LAST!
+
+ //strings are interpereted as filenames.
+ //will be loaded synchronously
+
+ var conf =
+ cc(
+ //OVERRIDE SETTINGS WITH COMMAND LINE OPTS
+ opts,
+
+ //ENV VARS IF PREFIXED WITH 'myApp_'
+
+ cc.env('myApp_'), //myApp_foo = 'like this'
+
+ //FILE NAMED BY ENV
+ path.join(__dirname, 'config.' + env + '.json'),
+
+ //IF `env` is PRODUCTION
+ env === 'prod'
+ ? path.join(__dirname, 'special.json') //load a special file
+ : null //NULL IS IGNORED!
+
+ //SUBDIR FOR ENV CONFIG
+ path.join(__dirname, 'config', env, 'config.json'),
+
+ //SEARCH PARENT DIRECTORIES FROM CURRENT DIR FOR FILE
+ cc.find('config.json'),
+
+ //PUT DEFAULTS LAST
+ {
+ host: 'localhost'
+ port: 8000
+ })
+
+ var host = conf.get('host')
+
+ // or
+
+ var host = conf.store.host
+
+```
+
+FINALLY, EASY FLEXIBLE CONFIGURATIONS!
+
+##see also: [proto-list](https://github.com/isaacs/proto-list/)
+
+WHATS THAT YOU SAY?
+
+YOU WANT A "CLASS" SO THAT YOU CAN DO CRAYCRAY JQUERY CRAPS?
+
+EXTEND WITH YOUR OWN FUNCTIONALTY!?
+
+## CONFIGCHAIN LIVES TO SERVE ONLY YOU!
+
+```javascript
+var cc = require('config-chain')
+
+// all the stuff you did before
+var config = cc({
+ some: 'object'
+ },
+ cc.find('config.json'),
+ cc.env('myApp_')
+ )
+ // CONFIGS AS A SERVICE, aka "CaaS", aka EVERY DEVOPS DREAM OMG!
+ .addUrl('http://configurator:1234/my-configs')
+ // ASYNC FTW!
+ .addFile('/path/to/file.json')
+
+ // OBJECTS ARE OK TOO, they're SYNC but they still ORDER RIGHT
+ // BECAUSE PROMISES ARE USED BUT NO, NOT *THOSE* PROMISES, JUST
+ // ACTUAL PROMISES LIKE YOU MAKE TO YOUR MOM, KEPT OUT OF LOVE
+ .add({ another: 'object' })
+
+ // DIE A THOUSAND DEATHS IF THIS EVER HAPPENS!!
+ .on('error', function (er) {
+ // IF ONLY THERE WAS SOMETHIGN HARDER THAN THROW
+ // MY SORROW COULD BE ADEQUATELY EXPRESSED. /o\
+ throw er
+ })
+
+ // THROW A PARTY IN YOUR FACE WHEN ITS ALL LOADED!!
+ .on('load', function (config) {
+ console.awesome('HOLY SHIT!')
+ })
+```
+
+# BORING API DOCS
+
+## cc(...args)
+
+MAKE A CHAIN AND ADD ALL THE ARGS.
+
+If the arg is a STRING, then it shall be a JSON FILENAME.
+
+SYNC I/O!
+
+RETURN THE CHAIN!