@npmcli/arborist
Advanced tools
Comparing version 0.0.0-pre.10 to 0.0.0-pre.11
@@ -8,9 +8,23 @@ // add and remove dependency specs to/from pkg manifest | ||
'devDependencies', | ||
'peerDependenciesMeta', | ||
'peerDependencies', | ||
]) | ||
// these two ride along together | ||
if (type !== 'peerDependencies' && type !== 'peerDependenciesMeta') { | ||
others.delete(type) | ||
others.add('peerDependenciesMeta') | ||
others.add('peerDependencies') | ||
switch (type) { | ||
case 'prod': | ||
others.delete('dependencies') | ||
break | ||
case 'dev': | ||
others.delete('devDependencies') | ||
break | ||
case 'optional': | ||
others.delete('optionalDependencies') | ||
break | ||
case 'peer': | ||
case 'peerOptional': | ||
others.delete('peerDependencies') | ||
others.delete('peerDependenciesMeta') | ||
break | ||
} | ||
for (const other of others) { | ||
@@ -21,17 +35,5 @@ deleteSubKey(pkg, other, name) | ||
const add = (pkg, add) => { | ||
// if adding to one kind of dependency set, remove from others | ||
for (const [type, specs] of Object.entries(add)) { | ||
if (type === 'bundleDependencies') { | ||
pkg.bundleDependencies = pkg.bundleDependencies || [] | ||
pkg.bundleDependencies.push(...specs) | ||
} else { | ||
// keep the existing value if it's '' | ||
for (const [name, spec] of Object.entries(specs)) { | ||
removeFromOthers(name, type, pkg) | ||
pkg[type] = pkg[type] || {} | ||
if (spec !== '' || pkg[type][name] === undefined) | ||
pkg[type][name] = spec | ||
} | ||
} | ||
const add = ({pkg, add, saveBundle, saveType}) => { | ||
for (const spec of add) { | ||
addSingle({pkg, spec, saveBundle, saveType}) | ||
} | ||
@@ -41,2 +43,61 @@ return pkg | ||
const addSingle = ({pkg, spec, saveBundle, saveType}) => { | ||
if (!saveType) | ||
saveType = getSaveType(pkg, spec) | ||
const {name} = spec | ||
removeFromOthers(name, saveType, pkg) | ||
const type = saveType === 'prod' ? 'dependencies' | ||
: saveType === 'dev' ? 'devDependencies' | ||
: saveType === 'optional' ? 'optionalDependencies' | ||
: saveType === 'peer' || saveType === 'peerOptional' ? 'peerDependencies' | ||
: /* istanbul ignore next */ null | ||
pkg[type] = pkg[type] || {} | ||
if (spec.rawSpec !== '' || pkg[type][name] === undefined) | ||
pkg[type][name] = spec.rawSpec || '*' | ||
if (saveType === 'peer' || saveType === 'peerOptional') { | ||
const pdm = pkg.peerDependenciesMeta || {} | ||
if (saveType === 'peer' && pdm[name] && pdm[name].optional) | ||
pdm[name].optional = false | ||
else if (saveType === 'peerOptional') { | ||
pdm[name] = pdm[name] || {} | ||
pdm[name].optional = true | ||
pkg.peerDependenciesMeta = pdm | ||
} | ||
} | ||
if (saveBundle) { | ||
// keep it sorted, keep it unique | ||
const bd = new Set(pkg.bundleDependencies || []) | ||
bd.add(spec.name) | ||
pkg.bundleDependencies = [...bd].sort((a, b) => a.localeCompare(b)) | ||
} | ||
} | ||
const getSaveType = (pkg, spec) => { | ||
const {name} = spec | ||
const { | ||
// these names are so lonnnnngggg | ||
dependencies: deps, | ||
devDependencies: devDeps, | ||
optionalDependencies: optDeps, | ||
peerDependencies: peerDeps, | ||
peerDependenciesMeta: peerDepsMeta, | ||
} = pkg | ||
if (devDeps && devDeps[name] !== undefined) | ||
return 'dev' | ||
else if (optDeps && optDeps[name] !== undefined) | ||
return 'optional' | ||
else if (peerDeps && peerDeps[name] !== undefined) { | ||
if (peerDepsMeta && peerDepsMeta[name] && peerDepsMeta[name].optional) | ||
return 'peerOptional' | ||
else | ||
return 'peer' | ||
} else | ||
return 'prod' | ||
} | ||
const deleteSubKey = (obj, k, sk) => { | ||
@@ -43,0 +104,0 @@ if (obj[k]) { |
@@ -60,2 +60,3 @@ // mixin implementing the buildIdealTree method | ||
const _add = Symbol('add') | ||
const _resolvedAdd = Symbol.for('resolvedAdd') | ||
const _queueNamedUpdates = Symbol('queueNamedUpdates') | ||
@@ -75,3 +76,2 @@ const _shouldUpdateNode = Symbol('shouldUpdateNode') | ||
const _idealTreePrune = Symbol.for('idealTreePrune') | ||
const _resolvedAdd = Symbol.for('resolvedAdd') | ||
@@ -245,3 +245,3 @@ const Virtual = require('./load-virtual.js') | ||
return (options.add) | ||
? this[_add](options.add).then(after) | ||
? this[_add](options).then(after) | ||
: after() | ||
@@ -253,57 +253,28 @@ } | ||
// and need to call pacote.manifest to find the name. | ||
[_add] (add) { | ||
[_add] ({add, saveType = null, saveBundle = false}) { | ||
const promises = [] | ||
this[_resolvedAdd] = {} | ||
// not going to work for: | ||
// peerDepsMeta | ||
// bundledDeps | ||
for (const [type, specs] of Object.entries(add)) { | ||
// get the name for each of the specs in the list. | ||
// ie, doing `foo@bar` we just return foo | ||
// but if it's a url or git, we don't know the name until we | ||
// fetch it and look in its manifest. | ||
const p = Promise.all(specs.map(s => { | ||
const spec = npa(s, this.path) | ||
if (spec.name) { | ||
return spec | ||
} else { | ||
return pacote.manifest(spec).then(mani => { | ||
spec.name = mani.name | ||
return spec | ||
}) | ||
} | ||
})).then(specs => { | ||
for (const spec of specs) { | ||
if (type === 'bundleDependencies') { | ||
this[_resolvedAdd][type] = this[_resolvedAdd][type] || [] | ||
this[_resolvedAdd][type].push(spec.name) | ||
} else { | ||
// XXX this is a bit inefficient. we parse the spec, and then | ||
// immediately throw it away and keep just the rawSpec. Later, | ||
// when creating the Node, we parse them AGAIN for the Edge objs | ||
// and multiple other times when checking if a dep is valid. | ||
// It'd be eleganter to parse it once, and keep the spec around as | ||
// an object for all future uses, even though npa is pretty fast. | ||
this[_resolvedAdd][type] = this[_resolvedAdd][type] || {} | ||
this[_resolvedAdd][type][spec.name] = spec.rawSpec | ||
} | ||
} | ||
// get the name for each of the specs in the list. | ||
// ie, doing `foo@bar` we just return foo | ||
// but if it's a url or git, we don't know the name until we | ||
// fetch it and look in its manifest. | ||
return Promise.all(add.map(s => { | ||
const spec = npa(s, this.path) | ||
return spec.name ? spec : pacote.manifest(spec).then(mani => { | ||
spec.name = mani.name | ||
return spec | ||
}) | ||
promises.push(p) | ||
} | ||
return Promise.all(promises).then(() => { | ||
// get the list of deps that we're explicitly requesting, so that | ||
// 'npm install foo' will reinstall, even if we already have it. | ||
for (const [type, specs] of Object.entries(this[_resolvedAdd])) { | ||
if (type === 'dependencies' || type === 'devDependencies' || | ||
type === 'optionalDependencies' || type === 'peerDependencies') { | ||
for (const name of Object.keys(this[_resolvedAdd][type])) { | ||
this[_explicitRequests].add(name) | ||
} | ||
} | ||
})).then(add => { | ||
this[_resolvedAdd] = add | ||
// now add is a list of spec objects with names. | ||
// find a home for each of them! | ||
addRmPkgDeps.add({ | ||
pkg: this.idealTree.package, | ||
add, | ||
saveBundle, | ||
saveType, | ||
}) | ||
for (const spec of add) { | ||
this[_explicitRequests].add(spec.name) | ||
} | ||
addRmPkgDeps.add(this.idealTree.package, this[_resolvedAdd]) | ||
}) | ||
@@ -310,0 +281,0 @@ } |
@@ -15,2 +15,3 @@ // mixin implementing the reify method | ||
const {checkEngine, checkPlatform} = require('npm-install-checks') | ||
const updateDepSpec = require('../update-dep-spec.js') | ||
@@ -101,4 +102,8 @@ const boolEnv = b => b ? '1' : '' | ||
savePrefix = '^', | ||
binLinks = true, | ||
} = options | ||
if (!binLinks) | ||
this[_binLinks] = () => {} | ||
this[_ignoreScripts] = !!ignoreScripts | ||
@@ -361,3 +366,5 @@ this[_force] = !!force | ||
rpj(node.path + '/package.json').then(pkg => { | ||
node.package = pkg | ||
node.package.os = pkg.os | ||
node.package.cpu = pkg.cpu | ||
node.package.engines = pkg.engines | ||
return this[_checkEngineAndPlatform](node) | ||
@@ -483,9 +490,3 @@ }) | ||
for (const node of set) { | ||
promises.push(binLinks({ | ||
pkg: node.package, | ||
path: node.path, | ||
top: node.isTop || node.globalTop, | ||
force: this[_force], | ||
global: node.globalTop, | ||
})) | ||
promises.push(this[_binLinks](node)) | ||
} | ||
@@ -655,4 +656,4 @@ return promiseAllRejectLate(promises) | ||
return rpj(node.path + '/package.json').then(pkg => { | ||
node.package = pkg | ||
if (pkg.scripts) { | ||
node.package.scripts = pkg.scripts | ||
const val = [node, pkg] | ||
@@ -738,26 +739,22 @@ if (pkg.scripts.preinstall) | ||
if (this[_resolvedAdd]) { | ||
const pkg = this.idealTree.package | ||
// need to save these more nicely, now that we know what they are | ||
for (const [type, specs] of Object.entries(this[_resolvedAdd])) { | ||
if (!specs || typeof specs !== 'object' || Array.isArray(specs)) | ||
continue | ||
const root = this.idealTree | ||
const pkg = root.package | ||
for (const req of this[_resolvedAdd]) { | ||
const {name} = req | ||
const child = root.children.get(name) | ||
const res = npa(child.resolved) | ||
for (const [name, spec] of Object.entries(specs)) { | ||
const child = this.idealTree.children.get(name) | ||
const resolved = child.resolved | ||
const req = npa(spec) | ||
const res = npa(resolved) | ||
if (req.registry) { | ||
const version = child.package.version | ||
if (req.registry) { | ||
const range = this[_savePrefix] + version | ||
const pname = child.package.name | ||
const alias = name !== pname | ||
pkg[type][name] = (alias ? `npm:${pname}@` : '') + `${range}` | ||
} else if (req.hosted) { | ||
pkg[type][name] = req.hosted.shortcut({ noCommittish: false }) | ||
} else { | ||
pkg[type][name] = req.saveSpec | ||
} | ||
const range = this[_savePrefix] + version | ||
const pname = child.package.name | ||
const alias = name !== pname | ||
updateDepSpec(pkg, name, (alias ? `npm:${pname}@` : '') + range) | ||
} else if (req.hosted) { | ||
updateDepSpec(pkg, name, req.hosted.shortcut({ noCommittish: false })) | ||
} else { | ||
updateDepSpec(pkg, name, req.saveSpec) | ||
} | ||
} | ||
// refresh the edges so they have the correct specs | ||
@@ -764,0 +761,0 @@ this.idealTree.package = pkg |
{ | ||
"name": "@npmcli/arborist", | ||
"version": "0.0.0-pre.10", | ||
"version": "0.0.0-pre.11", | ||
"description": "Manage node_modules trees", | ||
@@ -13,3 +13,3 @@ "dependencies": { | ||
"npm-package-arg": "^8.0.0", | ||
"pacote": "^11.0.0", | ||
"pacote": "^11.1.0", | ||
"parse-conflict-json": "^1.0.0", | ||
@@ -16,0 +16,0 @@ "promise-all-reject-late": "^1.0.0", |
@@ -79,11 +79,17 @@ # @npmcli/arborist | ||
// rm: array of package names to remove at top level | ||
// add: object with the following potential properties: | ||
// - dependencies | ||
// - peerDependencies | ||
// - optionalDependencies | ||
// - devDependencies | ||
// - peerDependenciesMeta | ||
// Each is an array of package specifiers, which would be passed to | ||
// `npm install`. They're added to the root node's requirements, and | ||
// then the tree is built. | ||
// add: Array of package specifiers to add at the top level. Each of | ||
// these will be resolved with pacote.manifest if the name can't be | ||
// determined from the spec. (Eg, `github:foo/bar` vs `foo@somespec`.) | ||
// The dep will be saved in the location where it already exists, | ||
// (or pkg.dependencies) unless a different saveType is specified. | ||
// saveType: Save added packages in a specific dependency set. | ||
// - null (default) Wherever they exist already, or 'dependencies' | ||
// - prod: definitely in 'dependencies' | ||
// - optional: in 'optionalDependencies' | ||
// - dev: devDependencies | ||
// - peer: save in peerDependencies, and remove any optional flag from | ||
// peerDependenciesMeta if one exists | ||
// - peerOptional: save in peerDependencies, and add a | ||
// peerDepsMeta[name].optional flag | ||
// saveBundle: add newly added deps to the bundleDependencies list | ||
// update: Either `true` to just go ahead and update everything, or an | ||
@@ -90,0 +96,0 @@ // object with any or all of the following fields: |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
193839
4583
338
Updatedpacote@^11.1.0