Socket
Socket
Sign inDemoInstall

@npmcli/arborist

Package Overview
Dependencies
Maintainers
7
Versions
192
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@npmcli/arborist - npm Package Compare versions

Comparing version 0.0.0-pre.10 to 0.0.0-pre.11

lib/update-dep-spec.js

101

lib/add-rm-pkg-deps.js

@@ -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]) {

77

lib/arborist/build-ideal-tree.js

@@ -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:

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc