cortex-shrinkwrap
Advanced tools
Comparing version 1.0.2 to 1.1.0
276
lib/index.js
var path = require('path'); | ||
var fs = require('fs'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var semver = require('semver'); | ||
var async = require('async'); | ||
var sortedObject = require('sorted-object'); | ||
var async = require('async'); | ||
var depTravel = require('cortex-deps-traveller'); | ||
var shrinktree = require('./shrinktree'); | ||
var Visitor = depTravel.Visitor; | ||
module.exports = function(pkg, cache_root, options, callback) { | ||
@@ -20,223 +23,104 @@ if (!pkg || !cache_root) { | ||
var readjson = require('read-cortex-json'); | ||
var rootName = pkg.name, | ||
rootVersion = pkg.version, | ||
enableDev = options.dev, | ||
var enableDev = options.dev, | ||
enableAsync = options.async, | ||
enablePrerelease = options.enablePrerelease === true; | ||
stableOnly = options.stableOnly !== false; | ||
var holder = new EventEmitter(); | ||
var depCache = {}, verCache = {}; | ||
if (options.hasOwnProperty('enablePrerelease')) | ||
stableOnly = !options.enablePrerelease; | ||
process.nextTick(function() { | ||
depCache[rootName + '@' + rootVersion] = mergeDependencies(pkg, true); | ||
shrinkPackage(rootName, rootVersion, function(name, range, callback) { | ||
if (name == rootName && range == rootVersion) { | ||
return process.nextTick(callback.bind(null, null, range, depCache[name + '@' + range])); | ||
var firstRoot = true; | ||
var traveller = shrinktree(pkg, cache_root, { | ||
stableOnly: stableOnly, | ||
pkgDeps: function(pkg) { | ||
var dependencies = {}; | ||
if (pkg.dependencies) { | ||
for (var d in pkg.dependencies) { | ||
dependencies[d] = pkg.dependencies[d]; | ||
} | ||
} | ||
readVersions(name, function(err, versions) { | ||
if (err) return callback(err); | ||
var ver = semver.maxSatisfying(versions, range); | ||
if (!ver) { | ||
// TODO: whether go to registry, issue #1 | ||
return callback({ | ||
message: "Can not resolve package " + name + " from range: " + range + " in available versions: " + versions | ||
}); | ||
if (firstRoot) { | ||
firstRoot = false; | ||
if (enableDev) { | ||
var devDependencies = pkg.devDependencies || {}; | ||
for (var d in devDependencies) { | ||
dependencies[d] = devDependencies[d]; | ||
} | ||
var pkgDir = path.join(cache_root, name, ver, 'package'); | ||
var swPath = path.join(pkgDir, 'cortex-shrinkwrap.json'); | ||
fs.exists(swPath, function(exists) { | ||
if (exists) { | ||
fs.readFile(swPath, 'utf8', function(err, content) { | ||
var s; | ||
try { | ||
s = JSON.parse(content); | ||
} catch (e) { | ||
e.message = "Error when read: " + swPath + " " + e.message; | ||
return callback(e); | ||
} | ||
callback(null, ver, s.dependencies, true); | ||
}); | ||
} else { | ||
readjson.read(pkgDir, function(err, pkg) { | ||
if (err) return callback(err); | ||
callback(null, ver, depCache[name + "@" + ver] = mergeDependencies(pkg)); | ||
}); | ||
} | ||
}); | ||
}); | ||
}, | ||
function(err, shrinked) { | ||
if (err) return callback(err); | ||
// resolve engines | ||
var engines; | ||
var taskEngs = {}; | ||
for (var name in (pkg.engines || {})) { | ||
(function(range) { | ||
taskEngs[name] = function(cb) { | ||
readVersions(name, function(err, versions) { | ||
if (err) return cb(err); | ||
var ver = semver.maxSatisfying(versions, range); | ||
if (!ver) { | ||
return cb({ | ||
message: "Can not resolve engine " + name + " from range: " + range + " in available versions: " + versions | ||
}); | ||
} | ||
cb(null, { | ||
from: [name, range].join('@'), | ||
version: ver | ||
}); | ||
}); | ||
}; | ||
})(pkg.engines[name]); | ||
} else if (!isEmptyObject(pkg.devDependencies)) { | ||
for (var d in pkg.devDependencies) { | ||
this.emit("ignoreDev", d); | ||
} | ||
} | ||
async.parallel(taskEngs, function(err, results) { | ||
if (err) return callback(err); | ||
var rs = {}; | ||
rs.name = rootName; | ||
rs.version = rootVersion; | ||
if (!isEmptyObject(results)) { | ||
rs.engines = results; | ||
} | ||
if (!isEmptyObject(shrinked.dependencies)) | ||
if (!isEmptyObject(shrinked.dependencies)) | ||
rs.dependencies = shrinked.dependencies; | ||
callback(err, rs); | ||
}); | ||
}); | ||
}); | ||
return holder; | ||
function readVersions(name, cb) { | ||
// no multi process | ||
if (verCache[name]) { | ||
cb(null, verCache[name]); | ||
} else { | ||
var pkg_root = path.join(cache_root, name); | ||
fs.exists(pkg_root, function(exists) { | ||
if (!exists) | ||
return cb({ | ||
message: "No pacakge '" + name + "' installed, please run 'cortex install' first" | ||
}); | ||
fs.readdir(pkg_root, function(err, files) { | ||
if (err) return cb(err); | ||
var vers = files.filter(semver.valid); | ||
if (!enablePrerelease) { | ||
vers = vers.filter(function(ver) { | ||
return ver.indexOf('-') == -1; | ||
}); | ||
} | ||
cb(null, verCache[name] = vers); | ||
}); | ||
}); | ||
} | ||
} | ||
function mergeDependencies(pkg, isRoot) { | ||
var dependencies = {}; | ||
if (pkg.dependencies) { | ||
for (var d in pkg.dependencies) { | ||
dependencies[d] = pkg.dependencies[d]; | ||
} | ||
} | ||
if (isRoot) { | ||
if (enableDev) { | ||
var devDependencies = pkg.devDependencies || {}; | ||
for (var d in devDependencies) { | ||
dependencies[d] = devDependencies[d]; | ||
if (enableAsync) { | ||
var asyncDependencies = pkg.asyncDependencies || {}; | ||
for (var ad in asyncDependencies) { | ||
dependencies[ad] = asyncDependencies[ad]; | ||
} | ||
} else if (!isEmptyObject(pkg.devDependencies)) { | ||
for (var d in pkg.devDependencies) { | ||
holder.emit("ignoreDev", d); | ||
} else if (pkg.asyncDependencies) { | ||
for (var ad in pkg.asyncDependencies) { | ||
this.emit("ignoreAsync", ad); | ||
} | ||
} | ||
} | ||
if (enableAsync) { | ||
var asyncDependencies = pkg.asyncDependencies || {}; | ||
for (var ad in asyncDependencies) { | ||
dependencies[ad] = asyncDependencies[ad]; | ||
} | ||
} else if (pkg.asyncDependencies) { | ||
for (var ad in pkg.asyncDependencies) { | ||
holder.emit("ignoreAsync", ad); | ||
} | ||
return sortedObject(dependencies); | ||
} | ||
}, function(err, json) { | ||
if (err) return callback(err); | ||
delete json.from; | ||
json.name = pkg.name; | ||
return sortedObject(dependencies); | ||
} | ||
}; | ||
// resolve engines | ||
var engines; | ||
var taskEngs = {}; | ||
for (var name in (pkg.engines || {})) { | ||
(function(range) { | ||
taskEngs[name] = function(cb) { | ||
traveller.readVersions(name, function(err, versions) { | ||
if (err) return cb(err); | ||
var ver = semver.maxSatisfying(versions, range); | ||
if (!ver) { | ||
return cb({ | ||
message: "Can not resolve engine " + name + " from range: " + range + " in available versions: " + versions | ||
}); | ||
} | ||
function shrinkPackage(pkgName, range, findDeps, callback) { | ||
var tasks = {}; | ||
findDeps(pkgName, range, function(err, version, dependencies, nested) { | ||
if (err) return callback(err); | ||
if (nested) { | ||
if (isEmptyObject(dependencies)) { | ||
return callback(null, { | ||
from: pkgName + '@' + range, | ||
version: version | ||
}); | ||
} else { | ||
return callback(null, { | ||
from: pkgName + '@' + range, | ||
version: version, | ||
dependencies: dependencies | ||
}); | ||
} | ||
} | ||
for (var name in dependencies) { | ||
(function(name, range) { | ||
tasks[name] = function(cb) { | ||
shrinkPackage(name, range, findDeps, function(err, shrink) { | ||
cb(err, shrink); | ||
cb(null, { | ||
from: [name, range].join('@'), | ||
version: ver | ||
}); | ||
}); | ||
}; | ||
})(name, dependencies[name]); | ||
})(pkg.engines[name]); | ||
} | ||
async.parallel(tasks, function(err, rs) { | ||
async.parallel(taskEngs, function(err, results) { | ||
if (err) return callback(err); | ||
if (isEmptyObject(rs)) { | ||
callback(null, { | ||
from: pkgName + '@' + range, | ||
version: version | ||
}); | ||
} else { | ||
callback(null, { | ||
from: pkgName + '@' + range, | ||
version: version, | ||
dependencies: rs | ||
}); | ||
var rs = {}; | ||
rs.name = json.name; | ||
rs.version = json.version; | ||
if (!isEmptyObject(results)) { | ||
rs.engines = results; | ||
} | ||
if (!isEmptyObject(json.dependencies)) | ||
rs.dependencies = json.dependencies; | ||
callback(err, rs); | ||
}); | ||
}); | ||
} | ||
return traveller; | ||
}; | ||
module.exports.shrinktree = require('./shrinktree'); | ||
function isEmptyObject(obj) { | ||
@@ -250,2 +134,2 @@ if (!obj) return true; | ||
return true; | ||
} | ||
} |
{ | ||
"name": "cortex-shrinkwrap", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"description": "Lock down the versions of a package's dependencies", | ||
@@ -27,5 +27,5 @@ "main": "./lib/index.js", | ||
"devDependencies": { | ||
"mocha": "^1.20.0", | ||
"jshint": "^2.5.1", | ||
"underscore": "^1.6.0" | ||
"mocha": "~1.20.0", | ||
"jshint": "~2.5.1", | ||
"underscore": "~1.6.0" | ||
}, | ||
@@ -36,4 +36,5 @@ "dependencies": { | ||
"semver": "~2.3.0", | ||
"sorted-object": "~1.0.0" | ||
"sorted-object": "~1.0.0", | ||
"cortex-deps-traveller": "~0.0.1" | ||
} | ||
} |
@@ -58,13 +58,71 @@ # Cortex Shrinkwrap | ||
### pkg | ||
### shrinkwrap(pkg, cache_root, [options], callback) | ||
#### pkg | ||
Pakcage information stored in cortex.json. | ||
### Options | ||
#### cache_root | ||
Path of cortex build cache. | ||
#### Options | ||
* dev: whehter include `devDependencies` | ||
* async: whether incldue `asyncDependencies` | ||
* enablePrerelease: whether include prerelease version in shrinkwrap, default value is =false= | ||
* stableOnly: only include stable version in shrinkwrap, default value is =true= | ||
* enablePrerelease(=Deprecated=): whether include prerelease version in shrinkwrap, default value is =false= | ||
#### callback(err, shrinkedJson) | ||
### shrinktree((name, range)|pkg, cache_root, [options], callback) | ||
Generate a simple deps tree with information of shrinkwrap.json | ||
```javascript | ||
var shrinktree = require('cortex-shrinkwrap').shrinktree | ||
shrinktree('deep-eql', "~0.1.0", cache_root, function(err, tree) { | ||
}); | ||
// or provide a package json if already have one | ||
shrinktree({ | ||
name: 'deep-eql', | ||
version: '0.1.0', | ||
dependencies: { | ||
'type-detect': "~1.0.0" | ||
} | ||
}, cache_root, { | ||
enableDev: true | ||
}, function(err, tree) { | ||
}); | ||
``` | ||
#### name | ||
Package name of the tree root | ||
#### range | ||
Range of the tree root | ||
#### pkg | ||
Package json as the root | ||
#### cache_root | ||
Path of cortex build cache | ||
#### Options | ||
The same as options in shrinkwrap | ||
## License | ||
@@ -71,0 +129,0 @@ |
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
10651
6
218
133
5
2
1
+ Addedcortex-deps-traveller@~0.0.1
+ Addedasync@1.5.2(transitive)
+ Addedcortex-deps-traveller@0.0.3(transitive)
+ Addedfs-expand@0.2.2(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedread-cortex-json@2.1.1(transitive)