diff --git a/lib/arborist/build-ideal-tree.js b/lib/arborist/build-ideal-tree.js index 4c2665021..a3036e61e 100644 --- a/lib/arborist/build-ideal-tree.js +++ b/lib/arborist/build-ideal-tree.js @@ -397,7 +397,7 @@ module.exports = cls => class IdealTreeBuilder extends cls { // that they're there, and not reinstall the world unnecessarily. if (this[_global] && (this[_updateAll] || this[_updateNames].length)) { const nm = resolve(this.path, 'node_modules') - for (const name of await readdir(nm)) { + for (const name of await readdir(nm).catch(() => [])) { tree.package.dependencies = tree.package.dependencies || {} if (this[_updateAll] || this[_updateNames].includes(name)) tree.package.dependencies[name] = '*' @@ -663,6 +663,11 @@ This is a one-time fix-up, please be patient... }) } await promiseCallLimit(queue) + + // have to re-calc dep flags, because the nodes don't have edges + // until their packages get assigned, so everything looks extraneous + calcDepFlags(this.idealTree) + // yes, yes, this isn't the "original" version, but now that it's been // upgraded, we need to make sure we don't do the work to upgrade it // again, since it's now as new as can be. diff --git a/lib/arborist/load-virtual.js b/lib/arborist/load-virtual.js index f03bd80c4..3a38905b7 100644 --- a/lib/arborist/load-virtual.js +++ b/lib/arborist/load-virtual.js @@ -24,6 +24,7 @@ const loadWorkspacesVirtual = Symbol.for('loadWorkspacesVirtual') const flagsSuspect = Symbol.for('flagsSuspect') const reCalcDepFlags = Symbol('reCalcDepFlags') const checkRootEdges = Symbol('checkRootEdges') +const rootOptionProvided = Symbol('rootOptionProvided') const depsToEdges = (type, deps) => Object.entries(deps).map(d => [type, ...d]) @@ -63,6 +64,8 @@ module.exports = cls => class VirtualLoader extends cls { root = await this[loadRoot](s), } = options + this[rootOptionProvided] = options.root + await this[loadFromShrinkwrap](s, root) return treeCheck(this.virtualTree) } @@ -74,13 +77,17 @@ module.exports = cls => class VirtualLoader extends cls { } async [loadFromShrinkwrap] (s, root) { - // root is never any of these things, but might be a brand new - // baby Node object that never had its dep flags calculated. - root.extraneous = false - root.dev = false - root.optional = false - root.devOptional = false - root.peer = false + if (!this[rootOptionProvided]) { + // root is never any of these things, but might be a brand new + // baby Node object that never had its dep flags calculated. + root.extraneous = false + root.dev = false + root.optional = false + root.devOptional = false + root.peer = false + } else + this[flagsSuspect] = true + this[checkRootEdges](s, root) root.meta = s this.virtualTree = root @@ -88,20 +95,23 @@ module.exports = cls => class VirtualLoader extends cls { await this[resolveLinks](links, nodes) this[assignBundles](nodes) if (this[flagsSuspect]) - this[reCalcDepFlags]() + this[reCalcDepFlags](nodes.values()) return root } - [reCalcDepFlags] () { + [reCalcDepFlags] (nodes) { // reset all dep flags - for (const node of this.virtualTree.inventory.values()) { + // can't use inventory here, because virtualTree might not be root + for (const node of nodes) { + if (node.isRoot || node === this[rootOptionProvided]) + continue node.extraneous = true node.dev = true node.optional = true node.devOptional = true node.peer = true } - calcDepFlags(this.virtualTree, true) + calcDepFlags(this.virtualTree, !this[rootOptionProvided]) } // check the lockfile deps, and see if they match. if they do not @@ -237,6 +247,12 @@ module.exports = cls => class VirtualLoader extends cls { // shrinkwrap doesn't include package name unless necessary if (!sw.name) sw.name = nameFromFolder(path) + + const dev = sw.dev + const optional = sw.optional + const devOptional = dev || optional || sw.devOptional + const peer = sw.peer + const node = new Node({ legacyPeerDeps: this.legacyPeerDeps, root: this.virtualTree, @@ -246,6 +262,10 @@ module.exports = cls => class VirtualLoader extends cls { resolved: consistentResolve(sw.resolved, this.path, path), pkg: sw, hasShrinkwrap: sw.hasShrinkwrap, + dev, + optional, + devOptional, + peer, }) // cast to boolean because they're undefined in the lock file when false node.extraneous = !!sw.extraneous diff --git a/lib/arborist/reify.js b/lib/arborist/reify.js index 1dd4b4b0f..b33823e46 100644 --- a/lib/arborist/reify.js +++ b/lib/arborist/reify.js @@ -442,7 +442,8 @@ module.exports = cls => class Reifier extends cls { if (this[_trashList].has(node.path)) return node - process.emit('time', `reifyNode:${node.location}`) + const timer = `reifyNode:${node.location}` + process.emit('time', timer) this.addTracker('reify', node.name, node.location) const p = Promise.resolve() @@ -454,7 +455,7 @@ module.exports = cls => class Reifier extends cls { return this[_handleOptionalFailure](node, p) .then(() => { this.finishTracker('reify', node.name, node.location) - process.emit('timeEnd', `reifyNode:${node.location}`) + process.emit('timeEnd', timer) return node }) } @@ -474,9 +475,14 @@ module.exports = cls => class Reifier extends cls { // no idea what this thing is. remove it from the tree. if (!res) { - node.parent = null + const warning = 'invalid or damaged lockfile detected\n' + + 'please re-try this operation once it completes\n' + + 'so that the damage can be corrected, or perform\n' + + 'a fresh install with no lockfile if the problem persists.' + this.log.warn('reify', warning) this.log.verbose('reify', 'unrecognized node in tree', node.path) node.parent = null + node.fsParent = null this[_addNodeToTrashList](node) return } diff --git a/tap-snapshots/test-arborist-build-ideal-tree.js-TAP.test.js b/tap-snapshots/test-arborist-build-ideal-tree.js-TAP.test.js index 8c46e23fb..aad06a40a 100644 --- a/tap-snapshots/test-arborist-build-ideal-tree.js-TAP.test.js +++ b/tap-snapshots/test-arborist-build-ideal-tree.js-TAP.test.js @@ -11530,6 +11530,7 @@ ArboristNode { "location": "node_modules/@isaacs/peer-dep-cycle-b", "name": "@isaacs/peer-dep-cycle-b", "path": "{CWD}/test/fixtures/peer-dep-cycle-with-sw/node_modules/@isaacs/peer-dep-cycle-b", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/peer-dep-cycle-b/-/peer-dep-cycle-b-1.0.0.tgz", "version": "1.0.0", }, @@ -11553,6 +11554,7 @@ ArboristNode { "location": "node_modules/@isaacs/peer-dep-cycle-c", "name": "@isaacs/peer-dep-cycle-c", "path": "{CWD}/test/fixtures/peer-dep-cycle-with-sw/node_modules/@isaacs/peer-dep-cycle-c", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/peer-dep-cycle-c/-/peer-dep-cycle-c-1.0.0.tgz", "version": "1.0.0", }, @@ -24971,6 +24973,7 @@ ArboristNode { }, "location": "node_modules/tap/node_modules/nyc/node_modules/align-text", "name": "align-text", + "optional": true, "path": "{CWD}/test/fixtures/sax/node_modules/tap/node_modules/nyc/node_modules/align-text", "version": "0.1.4", }, @@ -27847,6 +27850,7 @@ ArboristNode { }, "location": "node_modules/tap/node_modules/nyc/node_modules/longest", "name": "longest", + "optional": true, "path": "{CWD}/test/fixtures/sax/node_modules/tap/node_modules/nyc/node_modules/longest", "version": "1.0.1", }, @@ -69947,6 +69951,7 @@ ArboristNode { "location": "node_modules/@isaacs/peer-dep-cycle-b", "name": "@isaacs/peer-dep-cycle-b", "path": "{CWD}/test/fixtures/peer-dep-cycle-nested-with-sw/node_modules/@isaacs/peer-dep-cycle-b", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/peer-dep-cycle-b/-/peer-dep-cycle-b-1.0.0.tgz", "version": "1.0.0", }, @@ -69970,6 +69975,7 @@ ArboristNode { "location": "node_modules/@isaacs/peer-dep-cycle-c", "name": "@isaacs/peer-dep-cycle-c", "path": "{CWD}/test/fixtures/peer-dep-cycle-nested-with-sw/node_modules/@isaacs/peer-dep-cycle-c", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/peer-dep-cycle-c/-/peer-dep-cycle-c-1.0.0.tgz", "version": "1.0.0", }, @@ -127712,6 +127718,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-b", "name": "@isaacs/testing-peer-deps-b", "path": "{CWD}/test/fixtures/testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-b", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-b/-/testing-peer-deps-b-1.2.4.tgz", "version": "1.2.4", }, @@ -127727,6 +127734,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-c", "name": "@isaacs/testing-peer-deps-c", "path": "{CWD}/test/fixtures/testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-c", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-c/-/testing-peer-deps-c-1.2.3.tgz", "version": "1.2.3", }, @@ -127775,6 +127783,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-b", "name": "@isaacs/testing-peer-deps-b", "path": "{CWD}/test/fixtures/testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-b", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-b/-/testing-peer-deps-b-2.0.1.tgz", "version": "2.0.1", }, @@ -127790,6 +127799,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-c", "name": "@isaacs/testing-peer-deps-c", "path": "{CWD}/test/fixtures/testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-c", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-c/-/testing-peer-deps-c-2.0.0.tgz", "version": "2.0.0", }, @@ -128782,6 +128792,22 @@ ArboristNode { } ` +exports[`test/arborist/build-ideal-tree.js TAP update global when nothing in global > update with empty node_modules 1`] = ` +ArboristNode { + "location": "", + "name": "empty_nm", + "path": "{CWD}/test/arborist/build-ideal-tree-update-global-when-nothing-in-global/empty_nm", +} +` + +exports[`test/arborist/build-ideal-tree.js TAP update global when nothing in global > update without node_modules 1`] = ` +ArboristNode { + "location": "", + "name": "no_nm", + "path": "{CWD}/test/arborist/build-ideal-tree-update-global-when-nothing-in-global/no_nm", +} +` + exports[`test/arborist/build-ideal-tree.js TAP update mkdirp to non-minimist-using version > must match snapshot 1`] = ` ArboristNode { "children": Map { diff --git a/tap-snapshots/test-arborist-reify.js-TAP.test.js b/tap-snapshots/test-arborist-reify.js-TAP.test.js index 29c7dbbe1..8dbeb3864 100644 --- a/tap-snapshots/test-arborist-reify.js-TAP.test.js +++ b/tap-snapshots/test-arborist-reify.js-TAP.test.js @@ -29604,6 +29604,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-b", "name": "@isaacs/testing-peer-deps-b", "path": "{CWD}/test/arborist/reify-testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-b", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-b/-/testing-peer-deps-b-1.2.4.tgz", "version": "1.2.4", }, @@ -29619,6 +29620,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-c", "name": "@isaacs/testing-peer-deps-c", "path": "{CWD}/test/arborist/reify-testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-c", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-c/-/testing-peer-deps-c-1.2.3.tgz", "version": "1.2.3", }, @@ -29667,6 +29669,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-b", "name": "@isaacs/testing-peer-deps-b", "path": "{CWD}/test/arborist/reify-testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-b", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-b/-/testing-peer-deps-b-2.0.1.tgz", "version": "2.0.1", }, @@ -29682,6 +29685,7 @@ ArboristNode { "location": "node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-c", "name": "@isaacs/testing-peer-deps-c", "path": "{CWD}/test/arborist/reify-testing-peer-deps-nested/node_modules/@isaacs/testing-peer-deps-d/node_modules/@isaacs/testing-peer-deps-c", + "peer": true, "resolved": "https://registry.npmjs.org/@isaacs/testing-peer-deps-c/-/testing-peer-deps-c-2.0.0.tgz", "version": "2.0.0", }, @@ -42960,6 +42964,50 @@ exports[`test/arborist/reify.js TAP update a yarn.lock file > updated yarn lock ` +exports[`test/arborist/reify.js TAP warn and correct if damaged data in lockfile first pass logs > "fixed" lockfile 1`] = ` +{ + "name": "reify-warn-and-correct-if-damaged-data-in-lockfile", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "abbrev": "" + } + } + } +} + +` + +exports[`test/arborist/reify.js TAP warn and correct if damaged data in lockfile second pass just does the right thing > actually fixed lockfile 1`] = ` +{ + "name": "reify-warn-and-correct-if-damaged-data-in-lockfile", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "dependencies": { + "abbrev": "" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + } + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + } + } +} + +` + exports[`test/arborist/reify.js TAP weirdly broken lockfile without resolved value > expect resolving Promise 1`] = ` ArboristNode { "children": Map { diff --git a/test/arborist/build-ideal-tree.js b/test/arborist/build-ideal-tree.js index 1835f1902..e7cc5eaa1 100644 --- a/test/arborist/build-ideal-tree.js +++ b/test/arborist/build-ideal-tree.js @@ -2268,6 +2268,20 @@ t.test('update global', async t => { 'update all the deps') }) +t.test('update global when nothing in global', async t => { + const path = t.testdir({ + no_nm: {}, + empty_nm: { + node_modules: {}, + }, + }) + const opts = { global: true, update: true } + t.matchSnapshot(await printIdeal(path + '/no_nm', opts), + 'update without node_modules') + t.matchSnapshot(await printIdeal(path + '/empty_nm', opts), + 'update with empty node_modules') +}) + t.test('peer dep that needs to be replaced', async t => { // this verifies that the webpack 5 that gets placed by default for // the initial dep will be successfully replaced by webpack 4 that @@ -2392,3 +2406,51 @@ t.test('set the current on ERESOLVE triggered by devDeps', async t => { }, }) }) + +t.test('shrinkwrapped dev/optional deps should not clobber flags', t => { + t.test('optional', async t => { + const path = t.testdir({ + 'package.json': JSON.stringify({ + name: 'project', + version: '1.2.3', + optionalDependencies: { + '@isaacs/test-package-with-shrinkwrap': '^1.0.0', + }, + }), + }) + const tree = await buildIdeal(path, { complete: true }) + const swName = '@isaacs/test-package-with-shrinkwrap' + const swDep = tree.children.get(swName) + const metaDep = swDep.children.get('abbrev') + t.equal(swDep.optional, true, 'shrinkwrapped dep is optional') + t.equal(metaDep.optional, true, 'shrinkwrapped metadep optional') + + // make sure we're not just somehow leaving ALL flags true + t.equal(swDep.dev, false, 'sw dep is not dev') + t.equal(metaDep.dev, false, 'meta dep is not dev') + }) + + t.test('dev', async t => { + const path = t.testdir({ + 'package.json': JSON.stringify({ + name: 'project', + version: '1.2.3', + devDependencies: { + '@isaacs/test-package-with-shrinkwrap': '^1.0.0', + }, + }), + }) + const tree = await buildIdeal(path, { complete: true }) + const swName = '@isaacs/test-package-with-shrinkwrap' + const swDep = tree.children.get(swName) + const metaDep = swDep.children.get('abbrev') + t.equal(swDep.dev, true, 'shrinkwrapped dep is dev') + t.equal(metaDep.dev, true, 'shrinkwrapped metadep dev') + + // make sure we're not just somehow leaving ALL flags true + t.equal(swDep.optional, false, 'sw dep is not optional') + t.equal(metaDep.optional, false, 'meta dep is not optional') + }) + + t.end() +}) diff --git a/test/arborist/load-virtual.js b/test/arborist/load-virtual.js index cf13803b1..7b17c1840 100644 --- a/test/arborist/load-virtual.js +++ b/test/arborist/load-virtual.js @@ -24,7 +24,7 @@ const { const cwd = normalizePath(process.cwd()) t.cleanSnapshot = s => s.split(cwd).join('{CWD}') -const loadVirtual = (path, opts = {}) => new Arborist({path, ...opts}).loadVirtual() +const loadVirtual = (path, opts) => new Arborist({path, ...(opts || {})}).loadVirtual(opts) t.test('load from fixture', t => loadVirtual(fixture).then(virtualTree => { @@ -205,3 +205,20 @@ t.test('workspaces', t => { t.end() }) + +t.test('do not reset flags on supplied root option', async t => { + const path = resolve(__dirname, '../fixtures/test-package-with-shrinkwrap') + const root = new Node({ + path, + pkg: require(path + '/package.json'), + dev: true, + optional: false, + peer: false, + devOptional: true, + }) + const tree = await loadVirtual(path, { root }) + t.equal(tree.dev, true, 'tree is still dev') + t.equal(tree.devOptional, true, 'tree is still devOptional') + t.equal(tree.optional, false, 'tree is not optional') + t.equal(tree.peer, false, 'tree is not peer') +}) diff --git a/test/arborist/reify.js b/test/arborist/reify.js index e8608ddbf..64460fb49 100644 --- a/test/arborist/reify.js +++ b/test/arborist/reify.js @@ -1361,3 +1361,56 @@ t.test('rollback if process is terminated during reify process', async t => { }) } }) + +t.test('warn and correct if damaged data in lockfile', async t => { + const path = t.testdir({ + 'package.json': JSON.stringify({ + dependencies: { + abbrev: '', + }, + }), + 'package-lock.json': JSON.stringify({ + name: 'garbage-in-reify-tree', + lockfileVersion: 2, + requires: true, + packages: { + '': { + dependencies: { + abbrev: '', + }, + }, + 'node_modules/abbrev': { + integrity: 'sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==', + }, + }, + dependencies: { + abbrev: { + integrity: 'sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==', + }, + }, + }), + }) + + t.test('first pass logs', async t => { + const getLogs = warningTracker() + await reify(path) + t.strictSame(getLogs(), [ + [ + 'warn', + 'reify', + 'invalid or damaged lockfile detected\n' + + 'please re-try this operation once it completes\n' + + 'so that the damage can be corrected, or perform\n' + + 'a fresh install with no lockfile if the problem persists.', + ], + ], 'got warnings') + t.matchSnapshot(fs.readFileSync(path + '/package-lock.json', 'utf8'), '"fixed" lockfile') + }) + + t.test('second pass just does the right thing', async t => { + const getLogs = warningTracker() + await reify(path) + t.strictSame(getLogs(), [], 'no warnings this time') + t.matchSnapshot(fs.readFileSync(path + '/package-lock.json', 'utf8'), 'actually fixed lockfile') + }) +}) diff --git a/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap.json b/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap.json new file mode 100644 index 000000000..997c07812 --- /dev/null +++ b/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap.json @@ -0,0 +1,56 @@ +{ + "_id": "@isaacs/test-package-with-shrinkwrap", + "name": "@isaacs/test-package-with-shrinkwrap", + "dist-tags": { + "latest": "1.0.0" + }, + "versions": { + "1.0.0": { + "name": "@isaacs/test-package-with-shrinkwrap", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + }, + "_id": "@isaacs/test-package-with-shrinkwrap@1.0.0", + "_nodeVersion": "15.3.0", + "_npmVersion": "7.5.3", + "dist": { + "integrity": "sha512-GDiKNO3uSliDRlGtwzg+QR23XrnkmReMqlca0njWJ9t6Cd7+2MRJqaYYScnYbv1OFnUZgfVg7W/gBo5s6bzu0g==", + "shasum": "a89ed71ae688c901cd95cd529025b19c6bdafd2b", + "tarball": "https://registry.npmjs.org/@isaacs/test-package-with-shrinkwrap/-/test-package-with-shrinkwrap-1.0.0.tgz", + "fileCount": 2, + "unpackedSize": 935, + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgIzwfCRA9TVsSAnZWagAAghMP/2iAP7WrexlrjnL5h3M6\nNPqFyffEBoeEQOfkfVLjDd5x3xGQGN9fzKwDtW1uqkzWxLIXN5QojL70Jnjf\nS26UXExnKzCxKY1qtP9FEmjVsPt3FVXXV+QBx5gd2Owqy2wZRqHn94Cadwtw\nQLJdApX6SKun+JpYxeprSNa+ZJfUdQONhfXJ9X3o/gQc2Scj6Vs1OXDxtVzx\nink2qSFPW+GP+ilPp5Xp0r7Aiob2DhuDAQNP2Js4nDVSfRPqMRgaWzQJO1yv\nehurCNco8XsyZWVqCysek3wh6/0Wv3a5im9zIW3+bsyHL0KPBpszwAfjyFI2\ng/ExLwnwqLzjkIiAnRqmyfc/6hCISRTBbzRRnI6M3VS3J9UvIae0VKLvrSfc\nY9A8NZM4IhGJkyABvOHK0yCaG0kaWch3sJR8xnx7Vz1vWKJEooCdZ3jmUGf6\nUIZcqAikYih/DeM5r3ICKzEjPxsOP71obZaV2tY7NCO3Btlo17TwwT28B0Sq\nJDMXm0KgB1f5YtzUdv7/jenUWUvL7o2LpnPA7OQV49wF8tDdCt+Ee/LXIx2q\nuAO5LHk2+LWPf2GuJvprhSI8dCfXhuz2aAYscFLVtx0hq2JGOHlvJ4Ar6Srh\n3Z8QfViYEBv1j2r+pdfo/ZnvkLP5UKsjpechhrvvkoY8W0UZdqF4fH2asvSL\ne84H\r\n=K+m4\r\n-----END PGP SIGNATURE-----\r\n" + }, + "_npmUser": { + "name": "isaacs", + "email": "i@izs.me" + }, + "directories": {}, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "_npmOperationalInternal": { + "host": "s3://npm-registry-packages", + "tmp": "tmp/test-package-with-shrinkwrap_1.0.0_1612921885954_0.9308552673485551" + }, + "_hasShrinkwrap": true + } + }, + "time": { + "created": "2021-02-10T01:51:25.916Z", + "1.0.0": "2021-02-10T01:51:26.072Z", + "modified": "2021-02-10T01:51:30.822Z" + }, + "maintainers": [ + { + "name": "isaacs", + "email": "i@izs.me" + } + ], + "readme": "ERROR: No README data found!", + "readmeFilename": "" +} diff --git a/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap.min.json b/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap.min.json new file mode 100644 index 000000000..542275dba --- /dev/null +++ b/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap.min.json @@ -0,0 +1,25 @@ +{ + "name": "@isaacs/test-package-with-shrinkwrap", + "dist-tags": { + "latest": "1.0.0" + }, + "versions": { + "1.0.0": { + "name": "@isaacs/test-package-with-shrinkwrap", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + }, + "_hasShrinkwrap": true, + "dist": { + "integrity": "sha512-GDiKNO3uSliDRlGtwzg+QR23XrnkmReMqlca0njWJ9t6Cd7+2MRJqaYYScnYbv1OFnUZgfVg7W/gBo5s6bzu0g==", + "shasum": "a89ed71ae688c901cd95cd529025b19c6bdafd2b", + "tarball": "https://registry.npmjs.org/@isaacs/test-package-with-shrinkwrap/-/test-package-with-shrinkwrap-1.0.0.tgz", + "fileCount": 2, + "unpackedSize": 935, + "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgIzwfCRA9TVsSAnZWagAAghMP/2iAP7WrexlrjnL5h3M6\nNPqFyffEBoeEQOfkfVLjDd5x3xGQGN9fzKwDtW1uqkzWxLIXN5QojL70Jnjf\nS26UXExnKzCxKY1qtP9FEmjVsPt3FVXXV+QBx5gd2Owqy2wZRqHn94Cadwtw\nQLJdApX6SKun+JpYxeprSNa+ZJfUdQONhfXJ9X3o/gQc2Scj6Vs1OXDxtVzx\nink2qSFPW+GP+ilPp5Xp0r7Aiob2DhuDAQNP2Js4nDVSfRPqMRgaWzQJO1yv\nehurCNco8XsyZWVqCysek3wh6/0Wv3a5im9zIW3+bsyHL0KPBpszwAfjyFI2\ng/ExLwnwqLzjkIiAnRqmyfc/6hCISRTBbzRRnI6M3VS3J9UvIae0VKLvrSfc\nY9A8NZM4IhGJkyABvOHK0yCaG0kaWch3sJR8xnx7Vz1vWKJEooCdZ3jmUGf6\nUIZcqAikYih/DeM5r3ICKzEjPxsOP71obZaV2tY7NCO3Btlo17TwwT28B0Sq\nJDMXm0KgB1f5YtzUdv7/jenUWUvL7o2LpnPA7OQV49wF8tDdCt+Ee/LXIx2q\nuAO5LHk2+LWPf2GuJvprhSI8dCfXhuz2aAYscFLVtx0hq2JGOHlvJ4Ar6Srh\n3Z8QfViYEBv1j2r+pdfo/ZnvkLP5UKsjpechhrvvkoY8W0UZdqF4fH2asvSL\ne84H\r\n=K+m4\r\n-----END PGP SIGNATURE-----\r\n" + } + } + }, + "modified": "2021-02-10T01:51:30.822Z" +} diff --git a/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap/-/test-package-with-shrinkwrap-1.0.0.tgz b/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap/-/test-package-with-shrinkwrap-1.0.0.tgz new file mode 100644 index 000000000..c46e1e2e0 Binary files /dev/null and b/test/fixtures/registry-mocks/content/isaacs/test-package-with-shrinkwrap/-/test-package-with-shrinkwrap-1.0.0.tgz differ diff --git a/test/fixtures/test-package-with-shrinkwrap/npm-shrinkwrap.json b/test/fixtures/test-package-with-shrinkwrap/npm-shrinkwrap.json new file mode 100644 index 000000000..702dfafc6 --- /dev/null +++ b/test/fixtures/test-package-with-shrinkwrap/npm-shrinkwrap.json @@ -0,0 +1,27 @@ +{ + "name": "@isaacs/test-package-with-shrinkwrap", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@isaacs/test-package-with-shrinkwrap", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + } + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + } + } +} diff --git a/test/fixtures/test-package-with-shrinkwrap/package.json b/test/fixtures/test-package-with-shrinkwrap/package.json new file mode 100644 index 000000000..cf8cf019d --- /dev/null +++ b/test/fixtures/test-package-with-shrinkwrap/package.json @@ -0,0 +1,7 @@ +{ + "name": "@isaacs/test-package-with-shrinkwrap", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } +}