Skip to content

Commit d84f9b5

Browse files
committed
install: add support for package aliases
1 parent 3ce1563 commit d84f9b5

14 files changed

+382
-63
lines changed

lib/install.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ Installer.prototype.normalizeCurrentTree = function (cb) {
401401
if (this.currentTree.error) {
402402
for (let child of this.currentTree.children) {
403403
if (!child.fakeChild && isExtraneous(child)) {
404-
this.currentTree.package.dependencies[child.package.name] = computeVersionSpec(this.currentTree, child)
404+
this.currentTree.package.dependencies[moduleName(child)] = computeVersionSpec(this.currentTree, child)
405405
}
406406
}
407407
}
@@ -825,7 +825,11 @@ Installer.prototype.printInstalledForHuman = function (diffs, auditResult) {
825825
var report = ''
826826
if (this.args.length && (added || updated)) {
827827
report += this.args.map((p) => {
828-
return `+ ${p.name}@${p.version}`
828+
return `+ ${p.name}@${p.version}${
829+
!p._requested.name || p._requested.name === p.name
830+
? ''
831+
: ` (as ${p._requested.name})`
832+
}`
829833
}).join('\n') + '\n'
830834
}
831835
var actions = []
@@ -922,10 +926,14 @@ Installer.prototype.printInstalledForJSON = function (diffs, auditResult) {
922926
function recordAction (action) {
923927
var mutation = action[0]
924928
var child = action[1]
929+
const isAlias = child.package && child.package._requested && child.package._requested.type === 'alias'
930+
const name = isAlias
931+
? child.package._requested.name
932+
: child.package && child.package.name
925933
var result = {
926934
action: mutation,
927-
name: moduleName(child),
928-
version: child.package && child.package.version,
935+
name,
936+
version: child.package && `${isAlias ? `npm:${child.package.name}@` : ''}${child.package.version}`,
929937
path: child.path
930938
}
931939
if (mutation === 'move') {
@@ -947,10 +955,16 @@ Installer.prototype.printInstalledForParseable = function (diffs) {
947955
} else if (mutation === 'update') {
948956
var previousVersion = child.oldPkg.package && child.oldPkg.package.version
949957
}
958+
const isAlias = child.package._requested && child.package._requested.type === 'alias'
959+
const version = child.package && isAlias
960+
? `npm:${child.package.name}@${child.package.version}`
961+
: child.package
962+
? child.package.version
963+
: ''
950964
output(
951965
mutation + '\t' +
952966
moduleName(child) + '\t' +
953-
(child.package ? child.package.version : '') + '\t' +
967+
version + '\t' +
954968
(child.path ? path.relative(self.where, child.path) : '') + '\t' +
955969
(previousVersion || '') + '\t' +
956970
(previousPath || ''))

lib/install/action/extract.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const figgyPudding = require('figgy-pudding')
66
const stat = BB.promisify(require('graceful-fs').stat)
77
const gentlyRm = BB.promisify(require('../../utils/gently-rm.js'))
88
const mkdirp = BB.promisify(require('mkdirp'))
9+
const moduleName = require('../../utils/module-name.js')
910
const moduleStagingPath = require('../module-staging-path.js')
1011
const move = require('../../utils/move.js')
1112
const npa = require('npm-package-arg')
@@ -113,7 +114,7 @@ function readBundled (pkg, staging, extractTo) {
113114
}
114115

115116
function stageBundledModule (bundler, child, staging, parentPath) {
116-
const stageFrom = path.join(parentPath, 'node_modules', child.package.name)
117+
const stageFrom = path.join(parentPath, 'node_modules', moduleName(child))
117118
const stageTo = moduleStagingPath(staging, child)
118119

119120
return BB.map(child.children, (child) => {

lib/install/action/global-install.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ var path = require('path')
33
var npm = require('../../npm.js')
44
var Installer = require('../../install.js').Installer
55
var packageId = require('../../utils/package-id.js')
6+
var moduleName = require('../../utils/module-name.js')
67

78
module.exports = function (staging, pkg, log, next) {
89
log.silly('global-install', packageId(pkg))
910
var globalRoot = path.resolve(npm.globalDir, '..')
1011
npm.config.set('global', true)
11-
var install = new Installer(globalRoot, false, [pkg.package.name + '@' + pkg.package._requested.fetchSpec])
12+
var install = new Installer(globalRoot, false, [moduleName(pkg) + '@' + pkg.package._requested.rawSpec])
1213
install.link = false
1314
install.run(function () {
1415
npm.config.set('global', false)

lib/install/action/global-link.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
'use strict'
2+
var moduleName = require('../../utils/module-name.js')
23
var npm = require('../../npm.js')
34
var packageId = require('../../utils/package-id.js')
45

56
module.exports = function (staging, pkg, log, next) {
67
log.silly('global-link', packageId(pkg))
7-
npm.link(pkg.package.name, next)
8+
npm.link(moduleName(pkg), next)
89
}

lib/install/and-add-parent-to-errors.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
'use strict'
2+
var moduleName = require('../utils/module-name.js')
23
var validate = require('aproba')
34

45
module.exports = function (parent, cb) {
56
validate('F', [cb])
67
return function (er) {
78
if (!er) return cb.apply(null, arguments)
89
if (er instanceof Error && parent && parent.package && parent.package.name) {
9-
er.parent = parent.package.name
10+
er.parent = moduleName(parent)
1011
}
1112
cb(er)
1213
}

lib/install/deps.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ function doesChildVersionMatch (child, requested, requestor) {
5757
if (fromSw.toString() === requested.toString()) return true
5858
}
5959

60+
if (requested.type === 'alias') {
61+
return doesChildVersionMatch(child, requested.subSpec, requestor)
62+
}
63+
6064
if (!registryTypes[requested.type]) {
6165
var childReq = child.package._requested
6266
if (childReq) {
@@ -72,7 +76,7 @@ function doesChildVersionMatch (child, requested, requestor) {
7276
// You'll see this scenario happen with at least tags and git dependencies.
7377
// Some buggy clients will write spaces into the module name part of a _from.
7478
if (child.package._from) {
75-
var fromReq = npa.resolve(moduleName(child), child.package._from.replace(new RegExp('^\\s*' + moduleName(child) + '\\s*@'), ''))
79+
var fromReq = npa(child.package._from)
7680
if (fromReq.rawSpec === requested.rawSpec) return true
7781
if (fromReq.type === requested.type && fromReq.saveSpec && fromReq.saveSpec === requested.saveSpec) return true
7882
}
@@ -289,11 +293,13 @@ function computeVersionSpec (tree, child) {
289293
var requested
290294
var childReq = child.package._requested
291295
if (child.isLink) {
292-
requested = npa.resolve(child.package.name, 'file:' + child.realpath, getTop(tree).path)
296+
requested = npa.resolve(moduleName(child), 'file:' + child.realpath, getTop(tree).path)
293297
} else if (childReq && (isNotEmpty(childReq.saveSpec) || (isNotEmpty(childReq.rawSpec) && isNotEmpty(childReq.fetchSpec)))) {
294298
requested = child.package._requested
295299
} else if (child.package._from) {
296300
requested = npa(child.package._from, tree.path)
301+
} else if (child.name && child.name !== child.package.name) {
302+
requested = npa.resolve(child.name, `npm:${child.package.name}@${child.package.version})`)
297303
} else {
298304
requested = npa.resolve(child.package.name, child.package.version)
299305
}
@@ -305,6 +311,9 @@ function computeVersionSpec (tree, child) {
305311
!npm.config.get('save-exact')) {
306312
rangeDescriptor = npm.config.get('save-prefix')
307313
}
314+
if (requested.type === 'alias') {
315+
rangeDescriptor = `npm:${requested.subSpec.name}@${rangeDescriptor}`
316+
}
308317
return rangeDescriptor + version
309318
} else if (requested.type === 'directory' || requested.type === 'file') {
310319
return 'file:' + unixFormatPath(path.relative(getTop(tree).path, requested.fetchSpec))
@@ -324,7 +333,7 @@ exports.removeDeps = function (args, tree, saveToDependencies, next) {
324333
for (let pkg of args) {
325334
var pkgName = moduleName(pkg)
326335
var toRemove = tree.children.filter(moduleNameMatches(pkgName))
327-
var pkgToRemove = toRemove[0] || createChild({package: {name: pkgName}})
336+
var pkgToRemove = toRemove[0] || createChild({name: pkgName})
328337
var saveType = getSaveType(tree, pkg) || 'dependencies'
329338
if (tree.isTop && saveToDependencies) {
330339
pkgToRemove.save = saveType
@@ -652,11 +661,13 @@ function resolveWithNewModule (pkg, tree, log, next) {
652661
addBundled(pkg, (bundleErr) => {
653662
var parent = earliestInstallable(tree, tree, pkg, log) || tree
654663
var isLink = pkg._requested.type === 'directory'
664+
var name = pkg._requested.name || pkg.name
655665
var child = createChild({
666+
name,
656667
package: pkg,
657668
parent: parent,
658-
path: path.join(parent.isLink ? parent.realpath : parent.path, 'node_modules', pkg.name),
659-
realpath: isLink ? pkg._requested.fetchSpec : path.join(parent.realpath, 'node_modules', pkg.name),
669+
path: path.join(parent.isLink ? parent.realpath : parent.path, 'node_modules', name),
670+
realpath: isLink ? pkg._requested.fetchSpec : path.join(parent.realpath, 'node_modules', name),
660671
children: pkg._bundled || [],
661672
isLink: isLink,
662673
isInLink: parent.isLink,
@@ -759,7 +770,7 @@ var earliestInstallable = exports.earliestInstallable = function (requiredBy, tr
759770
validate('OOOO', arguments)
760771

761772
function undeletedModuleMatches (child) {
762-
return !child.removed && moduleName(child) === pkg.name
773+
return !child.removed && moduleName(child) === ((pkg._requested && pkg._requested.name) || pkg.name)
763774
}
764775
const undeletedMatches = tree.children.filter(undeletedModuleMatches)
765776
if (undeletedMatches.length) {

lib/install/is-only-optional.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
module.exports = isOptional
33

44
const isOptDep = require('./is-opt-dep.js')
5+
const moduleName = require('../utils/module-name.js')
56

67
function isOptional (node, seen) {
78
if (!seen) seen = new Set()
@@ -15,6 +16,6 @@ function isOptional (node, seen) {
1516
const swOptional = node.fromShrinkwrap && node.package._optional
1617
return node.requiredBy.every(function (req) {
1718
if (req.fakeChild && swOptional) return true
18-
return isOptDep(req, node.package.name) || isOptional(req, seen)
19+
return isOptDep(req, moduleName(node)) || isOptional(req, seen)
1920
})
2021
}

lib/ls.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var readPackageTree = require('read-package-tree')
1212
var archy = require('archy')
1313
var semver = require('semver')
1414
var color = require('ansicolors')
15+
var moduleName = require('./utils/module-name.js')
1516
var npa = require('npm-package-arg')
1617
var sortedObject = require('sorted-object')
1718
var npm = require('./npm.js')
@@ -59,7 +60,9 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
5960
args = []
6061
} else {
6162
args = args.map(function (a) {
62-
if (typeof a === 'object') {
63+
if (typeof a === 'object' && a.package._requested.type === 'alias') {
64+
return [moduleName(a), `npm:${a.package.name}@${a.package.version}`, a]
65+
} else if (typeof a === 'object') {
6366
return [a.package.name, a.package.version, a]
6467
} else {
6568
var p = npa(a)
@@ -392,8 +395,11 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
392395
}
393396

394397
var out = {}
395-
// the top level is a bit special.
396-
out.label = data._id || ''
398+
if (data._requested && data._requested.type === 'alias') {
399+
out.label = `${d}@npm:${data._id}`
400+
} else {
401+
out.label = data._id || ''
402+
}
397403
if (data._found === 'explicit' && data._id) {
398404
if (npm.color) {
399405
out.label = color.bgBlack(color.yellow(out.label.trim())) + ' '

lib/outdated.js

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,30 @@ outdated.usage = 'npm outdated [[<@scope>/]<pkg> ...]'
2020

2121
outdated.completion = require('./utils/completion/installed-deep.js')
2222

23-
var os = require('os')
24-
var url = require('url')
25-
var path = require('path')
26-
var readPackageTree = require('read-package-tree')
27-
var asyncMap = require('slide').asyncMap
28-
var color = require('ansicolors')
29-
var styles = require('ansistyles')
30-
var table = require('text-table')
31-
var semver = require('semver')
32-
var npa = require('libnpm/parse-arg')
33-
var pickManifest = require('npm-pick-manifest')
34-
var fetchPackageMetadata = require('./fetch-package-metadata.js')
35-
var mutateIntoLogicalTree = require('./install/mutate-into-logical-tree.js')
36-
var npm = require('./npm.js')
23+
const os = require('os')
24+
const url = require('url')
25+
const path = require('path')
26+
const readPackageTree = require('read-package-tree')
27+
const asyncMap = require('slide').asyncMap
28+
const color = require('ansicolors')
29+
const styles = require('ansistyles')
30+
const table = require('text-table')
31+
const semver = require('semver')
32+
const npa = require('libnpm/parse-arg')
33+
const pickManifest = require('npm-pick-manifest')
34+
const fetchPackageMetadata = require('./fetch-package-metadata.js')
35+
const mutateIntoLogicalTree = require('./install/mutate-into-logical-tree.js')
36+
const npm = require('./npm.js')
3737
const npmConfig = require('./config/figgy-config.js')
3838
const figgyPudding = require('figgy-pudding')
3939
const packument = require('libnpm/packument')
40-
var long = npm.config.get('long')
41-
var isExtraneous = require('./install/is-extraneous.js')
42-
var computeMetadata = require('./install/deps.js').computeMetadata
43-
var computeVersionSpec = require('./install/deps.js').computeVersionSpec
44-
var moduleName = require('./utils/module-name.js')
45-
var output = require('./utils/output.js')
46-
var ansiTrim = require('./utils/ansi-trim')
40+
const long = npm.config.get('long')
41+
const isExtraneous = require('./install/is-extraneous.js')
42+
const computeMetadata = require('./install/deps.js').computeMetadata
43+
const computeVersionSpec = require('./install/deps.js').computeVersionSpec
44+
const moduleName = require('./utils/module-name.js')
45+
const output = require('./utils/output.js')
46+
const ansiTrim = require('./utils/ansi-trim')
4747

4848
const OutdatedConfig = figgyPudding({
4949
also: {},
@@ -215,8 +215,8 @@ function makeJSON (list, opts) {
215215

216216
function outdated_ (args, path, tree, parentHas, depth, opts, cb) {
217217
if (!tree.package) tree.package = {}
218-
if (path && tree.package.name) path += ' > ' + tree.package.name
219-
if (!path && tree.package.name) path = tree.package.name
218+
if (path && moduleName(tree)) path += ' > ' + tree.package.name
219+
if (!path && moduleName(tree)) path = tree.package.name
220220
if (depth > opts.depth) {
221221
return cb(null, [])
222222
}
@@ -298,10 +298,10 @@ function outdated_ (args, path, tree, parentHas, depth, opts, cb) {
298298

299299
var has = Object.create(parentHas)
300300
tree.children.forEach(function (child) {
301-
if (child.package.name && child.package.private) {
301+
if (moduleName(child) && child.package.private) {
302302
deps = deps.filter(function (dep) { return dep !== child })
303303
}
304-
has[child.package.name] = {
304+
has[moduleName(child)] = {
305305
version: child.isLink ? 'linked' : child.package.version,
306306
from: child.isLink ? 'file:' + child.path : child.package._from
307307
}
@@ -349,13 +349,6 @@ function shouldUpdate (args, tree, dep, has, req, depth, pkgpath, opts, cb, type
349349
cb)
350350
}
351351

352-
function doIt (wanted, latest) {
353-
if (!long) {
354-
return cb(null, [[tree, dep, curr && curr.version, wanted, latest, req, null, pkgpath]])
355-
}
356-
cb(null, [[tree, dep, curr && curr.version, wanted, latest, req, type, pkgpath]])
357-
}
358-
359352
if (args.length && args.indexOf(dep) === -1) return skip()
360353

361354
if (tree.isLink && req == null) return skip()
@@ -374,11 +367,22 @@ function shouldUpdate (args, tree, dep, has, req, depth, pkgpath, opts, cb, type
374367
} else if (parsed.type === 'file') {
375368
return updateLocalDeps()
376369
} else {
377-
return packument(dep, opts.concat({
370+
return packument(parsed, opts.concat({
378371
'prefer-online': true
379372
})).nodeify(updateDeps)
380373
}
381374

375+
function doIt (wanted, latest) {
376+
let c = curr && curr.version
377+
if (parsed.type === 'alias') {
378+
c = `npm:${parsed.subSpec.name}@${c}`
379+
}
380+
if (!long) {
381+
return cb(null, [[tree, dep, c, wanted, latest, req, null, pkgpath]])
382+
}
383+
cb(null, [[tree, dep, c, wanted, latest, req, type, pkgpath]])
384+
}
385+
382386
function updateLocalDeps (latestRegistryVersion) {
383387
fetchPackageMetadata('file:' + parsed.fetchSpec, '.', (er, localDependency) => {
384388
if (er) return cb()
@@ -405,6 +409,9 @@ function shouldUpdate (args, tree, dep, has, req, depth, pkgpath, opts, cb, type
405409
function updateDeps (er, d) {
406410
if (er) return cb(er)
407411

412+
if (parsed.type === 'alias') {
413+
req = parsed.subSpec.rawSpec
414+
}
408415
try {
409416
var l = pickManifest(d, 'latest')
410417
var m = pickManifest(d, req)
@@ -421,11 +428,20 @@ function shouldUpdate (args, tree, dep, has, req, depth, pkgpath, opts, cb, type
421428
var dFromUrl = m._from && url.parse(m._from).protocol
422429
var cFromUrl = curr && curr.from && url.parse(curr.from).protocol
423430

424-
if (!curr ||
425-
(dFromUrl && cFromUrl && m._from !== curr.from) ||
426-
m.version !== curr.version ||
427-
m.version !== l.version) {
428-
doIt(m.version, l.version)
431+
if (
432+
!curr ||
433+
(dFromUrl && cFromUrl && m._from !== curr.from) ||
434+
m.version !== curr.version ||
435+
m.version !== l.version
436+
) {
437+
if (parsed.type === 'alias') {
438+
doIt(
439+
`npm:${parsed.subSpec.name}@${m.version}`,
440+
`npm:${parsed.subSpec.name}@${l.version}`
441+
)
442+
} else {
443+
doIt(m.version, l.version)
444+
}
429445
} else {
430446
skip()
431447
}

0 commit comments

Comments
 (0)