Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

peerDependencies #2769

Closed
wants to merge 6 commits into from

2 participants

@carlos8f

This addresses 1. and 2. of #1400. I might need help with 3 (never include in the package when publishing)

@isaacs
Owner

It looks like this is installing peer dependencies inside the package that depends on them, though. That's not quite the right semantic in this case. (Plus, that's what dependencies and devDependencies are for.)

The intention of peerDeps is to install them at the same level as the thing depending on them.

@carlos8f carlos8f closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
41 lib/install.js
@@ -189,6 +189,18 @@ function readDependencies (context, where, opts, cb) {
})
}
+ // If the package is the top target, and not global, then install
+ // peer deps as normal deps for testing/development purposes.
+ if ((!context || !context.parent.name) &&
+ !npm.config.get("global") &&
+ !npm.config.get("skip-peer") &&
+ data.peerDependencies) {
+ data.dependencies || (data.dependencies = {})
+ Object.keys(data.peerDependencies).forEach(function (d) {
+ data.dependencies[d] = data.peerDependencies[d]
+ })
+ }
+
if (wrap) {
log.verbose("readDependencies: using existing wrap", [where, wrap])
var rv = {}
@@ -241,7 +253,8 @@ function readDependencies (context, where, opts, cb) {
function save (where, installed, tree, pretty, cb) {
if (!npm.config.get("save") &&
!npm.config.get("save-dev") &&
- !npm.config.get("save-optional") ||
+ !npm.config.get("save-optional") &&
+ !npm.config.get("save-peer") ||
npm.config.get("global")) {
return cb(null, installed, tree, pretty)
}
@@ -283,6 +296,7 @@ function save (where, installed, tree, pretty, cb) {
var deps = npm.config.get("save-optional") ? "optionalDependencies"
: npm.config.get("save-dev") ? "devDependencies"
+ : npm.config.get("save-peer") ? "peerDependencies"
: "dependencies"
if (saveBundle) {
@@ -700,6 +714,7 @@ function installOne_ (target, where, context, cb) {
, [checkPlatform, target]
, [checkCycle, target, context.ancestors]
, [checkGit, targetFolder]
+ , [checkPeerDeps, target, context]
, [write, target, targetFolder, context] ]
, function (er, d) {
if (er) return cb(er)
@@ -849,6 +864,30 @@ function checkGit_ (folder, cb) {
})
}
+function checkPeerDeps (target, context, cb) {
+ if (!target.peerDependencies ||
+ npm.config.get("force") ||
+ npm.config.get("skip-peer") ||
+ target._from === ".") return cb()
+
+ var unsatisfied = false
+ Object.keys(target.peerDependencies).forEach(function (d) {
+ if (!semver.satisfies(context.family[d], target.peerDependencies[d])) {
+ log.error(target.name, "requires", d, target.peerDependencies[d],
+ "but package is", context.family[d] || "missing");
+ unsatisfied = true
+ }
+ })
+ if (unsatisfied) {
+ var e = new Error("Peer dependencies not satisfied.")
+ e.deps = unsatisfied
+ e.pkgid = target._id
+ e.code = "EPEER"
+ return cb(e)
+ }
+ cb()
+}
+
function write (target, targetFolder, context, cb_) {
var up = npm.config.get("unsafe-perm")
, user = up ? null : npm.config.get("user")
View
1  test/packages/npm-test-peer-deps-dev/README
@@ -0,0 +1 @@
+just an npm test
View
5 test/packages/npm-test-peer-deps-dev/package.json
@@ -0,0 +1,5 @@
+{ "name": "npm-test-peer-deps-dev"
+, "version": "1.2.0"
+, "scripts": { "test": "node test.js" }
+, "peerDependencies": { "lump": "*" }
+}
View
1  test/packages/npm-test-peer-deps-dev/test.js
@@ -0,0 +1 @@
+require('lump')
View
1  test/packages/npm-test-peer-deps-fail/README
@@ -0,0 +1 @@
+just an npm test
View
8 test/packages/npm-test-peer-deps-fail/package.json
@@ -0,0 +1,8 @@
+{ "name": "npm-test-peer-deps-fail"
+, "private": true
+, "version": "1.2.5"
+, "scripts": { "test": "node test.js" }
+, "dependencies":
+ { "npm-test-peer-deps-dep": "https://raw.github.com/gist/3562345/1b8c1652d04aa899298de9c1c56982a2581eb65c/index.js"
+ , "dnode": "*" }
+}
View
1  test/packages/npm-test-peer-deps-fail/test.js
@@ -0,0 +1 @@
+require('npm-test-peer-deps-dep')
View
66 test/run.js
@@ -63,11 +63,13 @@ function prefix (content, pref) {
}
var execCount = 0
-function exec (cmd, shouldFail, cb) {
- if (typeof shouldFail === "function") {
- cb = shouldFail, shouldFail = false
+function exec (cmd, opts, cb) {
+ if (typeof opts === "function") {
+ cb = opts, opts = {}
}
- console.error("\n+"+cmd + (shouldFail ? " (expect failure)" : ""))
+ if (typeof opts === 'boolean') opts = {shouldFail: true}
+ opts.env || (opts.env = env)
+ console.error("\n+"+cmd + (opts.shouldFail ? " (expect failure)" : ""))
// special: replace 'node' with the current execPath,
// and 'npm' with the thing we installed.
@@ -75,7 +77,7 @@ function exec (cmd, shouldFail, cb) {
cmd = cmd.replace(/^npm /, path.resolve(npmPath, "npm") + " ")
cmd = cmd.replace(/^node /, process.execPath + " ")
- child_process.exec(cmd, {env: env}, function (er, stdout, stderr) {
+ child_process.exec(cmd, opts, function (er, stdout, stderr) {
if (stdout) {
console.error(prefix(stdout, " 1> "))
}
@@ -84,7 +86,7 @@ function exec (cmd, shouldFail, cb) {
}
execCount ++
- if (!shouldFail && !er || shouldFail && er) {
+ if (!opts.shouldFail && !er || opts.shouldFail && er) {
// stdout = (""+stdout).trim()
console.log("ok " + execCount + " " + cmdShow)
return cb()
@@ -96,10 +98,13 @@ function exec (cmd, shouldFail, cb) {
}
function execChain (cmds, cb) {
+ if (typeof opts === "function") {
+ cb = opts, opts = {}
+ }
chain(cmds.reduce(function (l, r) {
return l.concat(r)
}, []).map(function (cmd) {
- return [exec, cmd]
+ return Array.isArray(cmd) ? [exec, cmd[0], cmd[1]] : [exec, cmd]
}), cb)
}
@@ -132,7 +137,7 @@ function main (cb) {
// get the list of packages
var packages = fs.readdirSync(path.resolve(testdir, "packages"))
packages = packages.filter(function (p) {
- return p && !p.match(/^\./)
+ return p && !p.match(/^\.|\-(fail|dev)$/)
})
installAllThenTestAll()
@@ -150,7 +155,7 @@ function main (cb) {
, [ execChain, packages.concat("npm").map(function (p) {
return "npm rm " + p
}) ]
- , installAndTestEach
+ , installAndTestEach, installAndTestEachDev, publishTest, peerDepsTest
]
, cb
)
@@ -165,7 +170,32 @@ function main (cb) {
, "npm rm "+p ]
}) ]
, [exec, "npm rm npm"]
- , publishTest
+ ], cb )
+ }
+
+ function installAndTestEachDev (cb) {
+ var packages = fs.readdirSync(path.resolve(testdir, "packages"))
+ packages = packages.filter(function (p) {
+ return p && p.match(/\-dev$/)
+ })
+ if (!packages.length) return cb()
+
+ var devEnv = {}
+ Object.keys(env).forEach(function (k) {
+ devEnv[k] = env[k]
+ })
+ devEnv.npm_config_global = ""
+
+ chain
+ ( [ setup
+ , [ execChain, packages.map(function (p) {
+ var opts = { cwd: path.resolve(testdir, "packages/"+p)
+ , env: devEnv }
+ return [ [ "npm install", opts ]
+ , [ "npm test", opts ]
+ , "npm rm "+p ]
+ }) ]
+ , [exec, "npm rm npm"]
], cb )
}
@@ -179,7 +209,7 @@ function main (cb) {
chain
( [ setup
, [ execChain, packages.filter(function (p) {
- return !p.match(/private/)
+ return !p.match(/private|fail/)
}).map(function (p) {
return [ "npm publish packages/"+p
, "npm install "+p
@@ -202,6 +232,20 @@ function main (cb) {
cleanup(cb)
})
}
+
+ function peerDepsTest (cb) {
+ chain
+ ( [ setup
+ , [ exec, "npm install packages/npm-test-peer-deps-fail", true ]
+ , [ execChain
+ , [ "npm install packages/npm-test-peer-deps-fail --force"
+ , "npm test npm-test-peer-deps-fail"
+ , "npm rm npm-test-peer-deps-fail"
+ ]
+ ]
+ , cleanup
+ ], cb )
+ }
}
main(function (er) {
Something went wrong with that request. Please try again.