From ac9f4d83fe3cebc58a7f847a9c62292664a756c5 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Fri, 21 Feb 2020 22:58:21 -0500 Subject: [PATCH] feat: npm workspaces Introduces support to workspaces; adding ability to build an ideal tree that links defined workspaces, storing and reading lockfiles that contains workspaces info and also reifying installation trees properly symlinking nested workspaces into place. Handling of the config definitions is done via @npmcli/map-workspaces module added. refs: - https://github.com/npm/rfcs/blob/ea2d3024e6e149cd8c6366ed18373c9a566b1124/accepted/0026-workspaces.md - https://www.npmjs.com/package/@npmcli/map-workspaces - https://github.com/npm/rfcs/pull/103 --- lib/arborist/build-ideal-tree.js | 13 + lib/arborist/load-virtual.js | 17 +- lib/edge.js | 6 + lib/node.js | 29 + lib/shrinkwrap.js | 1 + notes/workspace.md | 205 +++- package-lock.json | 11 + package.json | 1 + ...t-arborist-build-ideal-tree.js-TAP.test.js | 958 ++++++++++++++++++ .../test-arborist-load-virtual.js-TAP.test.js | 538 ++++++++++ .../test-arborist-reify.js-TAP.test.js | 198 ++++ tap-snapshots/test-node.js-TAP.test.js | 29 + test/arborist/build-ideal-tree.js | 61 ++ test/arborist/load-virtual.js | 53 + test/arborist/reify.js | 35 + test/edge.js | 6 + .../reify-cases/workspaces-link-bin.js | 38 + .../fixtures/reify-cases/workspaces-simple.js | 25 + .../package-lock.json | 91 ++ .../package.json | 10 + .../package.json | 11 + .../packages/a/package.json | 7 + .../packages/b/package.json | 7 + .../workspaces-duplicate/package.json | 6 + .../packages/a/package.json | 4 + .../packages/b/package.json | 4 + .../package-lock.json | 28 + .../workspaces-ignore-nm-virtual/package.json | 6 + .../workspaces-ignore-nm/package.json | 7 + .../packages/a/node_modules/c/package.json | 4 + .../nested-workspace/d/package.json | 7 + .../nested-workspace/package.json | 7 + .../packages/a/package.json | 5 + test/fixtures/workspaces-link-bin/foo.js | 0 .../fixtures/workspaces-link-bin/package.json | 10 + .../workspaces-link-bin/packages/a/file.js | 0 .../packages/a/package.json | 6 + .../workspaces-link-bin/packages/b/file.js | 0 .../packages/b/package.json | 6 + .../package-lock.json | 42 + .../package.json | 7 + .../workspaces-prefer-linking/package.json | 7 + .../packages/a/package.json | 7 + .../packages/abbrev/package.json | 6 + .../workspaces-scoped-pkg/package.json | 6 + .../packages/a/package.json | 7 + .../packages/b/package.json | 4 + .../package-lock.json | 86 ++ .../package.json | 7 + .../workspaces-shared-deps/package.json | 7 + .../packages/a/package.json | 7 + .../packages/b/package.json | 7 + .../packages/c/package.json | 7 + .../workspaces-simple-virtual/a/package.json | 7 + .../workspaces-simple-virtual/b/package.json | 4 + .../package-lock.json | 43 + .../workspaces-simple-virtual/package.json | 7 + .../fixtures/workspaces-simple/a/package.json | 7 + .../fixtures/workspaces-simple/b/package.json | 4 + test/fixtures/workspaces-simple/package.json | 7 + .../package-lock.json | 33 + .../package.json | 10 + .../workspaces-top-level-link/package.json | 11 + .../packages/a/package.json | 5 + .../package-lock.json | 63 ++ .../package.json | 7 + .../workspaces-transitive-deps/package.json | 7 + .../packages/a/package.json | 7 + .../package-lock.json | 59 ++ .../package.json | 7 + .../package.json | 8 + .../packages/a/package.json | 7 + .../packages/abbrev/package.json | 6 + .../workspaces-with-files-spec/d/package.json | 7 + .../workspaces-with-files-spec/package.json | 11 + .../packages/a/package.json | 7 + .../packages/b/package.json | 4 + .../packages/c/package.json | 4 + test/node.js | 73 ++ 79 files changed, 3029 insertions(+), 43 deletions(-) create mode 100644 test/fixtures/reify-cases/workspaces-link-bin.js create mode 100644 test/fixtures/reify-cases/workspaces-simple.js create mode 100644 test/fixtures/workspaces-conflicting-versions-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-conflicting-versions-virtual/package.json create mode 100644 test/fixtures/workspaces-conflicting-versions/package.json create mode 100644 test/fixtures/workspaces-conflicting-versions/packages/a/package.json create mode 100644 test/fixtures/workspaces-conflicting-versions/packages/b/package.json create mode 100644 test/fixtures/workspaces-duplicate/package.json create mode 100644 test/fixtures/workspaces-duplicate/packages/a/package.json create mode 100644 test/fixtures/workspaces-duplicate/packages/b/package.json create mode 100644 test/fixtures/workspaces-ignore-nm-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-ignore-nm-virtual/package.json create mode 100644 test/fixtures/workspaces-ignore-nm/package.json create mode 100644 test/fixtures/workspaces-ignore-nm/packages/a/node_modules/c/package.json create mode 100644 test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/d/package.json create mode 100644 test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/package.json create mode 100644 test/fixtures/workspaces-ignore-nm/packages/a/package.json create mode 100644 test/fixtures/workspaces-link-bin/foo.js create mode 100644 test/fixtures/workspaces-link-bin/package.json create mode 100644 test/fixtures/workspaces-link-bin/packages/a/file.js create mode 100644 test/fixtures/workspaces-link-bin/packages/a/package.json create mode 100644 test/fixtures/workspaces-link-bin/packages/b/file.js create mode 100644 test/fixtures/workspaces-link-bin/packages/b/package.json create mode 100644 test/fixtures/workspaces-prefer-linking-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-prefer-linking-virtual/package.json create mode 100644 test/fixtures/workspaces-prefer-linking/package.json create mode 100644 test/fixtures/workspaces-prefer-linking/packages/a/package.json create mode 100644 test/fixtures/workspaces-prefer-linking/packages/abbrev/package.json create mode 100644 test/fixtures/workspaces-scoped-pkg/package.json create mode 100644 test/fixtures/workspaces-scoped-pkg/packages/a/package.json create mode 100644 test/fixtures/workspaces-scoped-pkg/packages/b/package.json create mode 100644 test/fixtures/workspaces-shared-deps-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-shared-deps-virtual/package.json create mode 100644 test/fixtures/workspaces-shared-deps/package.json create mode 100644 test/fixtures/workspaces-shared-deps/packages/a/package.json create mode 100644 test/fixtures/workspaces-shared-deps/packages/b/package.json create mode 100644 test/fixtures/workspaces-shared-deps/packages/c/package.json create mode 100644 test/fixtures/workspaces-simple-virtual/a/package.json create mode 100644 test/fixtures/workspaces-simple-virtual/b/package.json create mode 100644 test/fixtures/workspaces-simple-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-simple-virtual/package.json create mode 100644 test/fixtures/workspaces-simple/a/package.json create mode 100644 test/fixtures/workspaces-simple/b/package.json create mode 100644 test/fixtures/workspaces-simple/package.json create mode 100644 test/fixtures/workspaces-top-level-link-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-top-level-link-virtual/package.json create mode 100644 test/fixtures/workspaces-top-level-link/package.json create mode 100644 test/fixtures/workspaces-top-level-link/packages/a/package.json create mode 100644 test/fixtures/workspaces-transitive-deps-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-transitive-deps-virtual/package.json create mode 100644 test/fixtures/workspaces-transitive-deps/package.json create mode 100644 test/fixtures/workspaces-transitive-deps/packages/a/package.json create mode 100644 test/fixtures/workspaces-version-unsatisfied-virtual/package-lock.json create mode 100644 test/fixtures/workspaces-version-unsatisfied-virtual/package.json create mode 100644 test/fixtures/workspaces-version-unsatisfied/package.json create mode 100644 test/fixtures/workspaces-version-unsatisfied/packages/a/package.json create mode 100644 test/fixtures/workspaces-version-unsatisfied/packages/abbrev/package.json create mode 100644 test/fixtures/workspaces-with-files-spec/d/package.json create mode 100644 test/fixtures/workspaces-with-files-spec/package.json create mode 100644 test/fixtures/workspaces-with-files-spec/packages/a/package.json create mode 100644 test/fixtures/workspaces-with-files-spec/packages/b/package.json create mode 100644 test/fixtures/workspaces-with-files-spec/packages/c/package.json diff --git a/lib/arborist/build-ideal-tree.js b/lib/arborist/build-ideal-tree.js index bf78d57d3..ba8101348 100644 --- a/lib/arborist/build-ideal-tree.js +++ b/lib/arborist/build-ideal-tree.js @@ -5,6 +5,7 @@ const npa = require('npm-package-arg') const pacote = require('pacote') const semver = require('semver') const pickManifest = require('npm-pick-manifest') +const mapWorkspaces = require('@npmcli/map-workspaces') const calcDepFlags = require('../calc-dep-flags.js') const Shrinkwrap = require('../shrinkwrap.js') @@ -46,6 +47,7 @@ const _nodeFromSpec = Symbol('nodeFromSpec') const _fetchManifest = Symbol('fetchManifest') const _problemEdges = Symbol('problemEdges') const _manifests = Symbol('manifests') +const _mapWorkspaces = Symbol('mapWorkspaces') const _linkFromSpec = Symbol('linkFromSpec') const _loadPeerSet = Symbol('loadPeerSet') // shared symbols so we can hit them with unit tests @@ -203,6 +205,7 @@ module.exports = cls => class IdealTreeBuilder extends Tracker(Virtual(Actual(cl .then(meta => Object.assign(root, {meta})) : this.loadVirtual({ root })) + .then(tree => this[_mapWorkspaces](tree)) .then(tree => { // null the virtual tree, because we're about to hack away at it // if you want another one, load another copy. @@ -234,9 +237,19 @@ module.exports = cls => class IdealTreeBuilder extends Tracker(Virtual(Actual(cl optional: false, global: this[_global], legacyPeerDeps: this.legacyPeerDeps, + hasWorkspaces: !!pkg.workspaces, }) } + [_mapWorkspaces] (node) { + return mapWorkspaces({ cwd: node.path, pkg: node.package }) + .then(workspaces => { + if (workspaces.size) + node.workspaces = workspaces + return node + }) + } + // process the add/rm requests by modifying the root node, and the // update.names request by queueing nodes dependent on those named. [_applyUserRequests] (options) { diff --git a/lib/arborist/load-virtual.js b/lib/arborist/load-virtual.js index 946e88d8c..0b1d0f91a 100644 --- a/lib/arborist/load-virtual.js +++ b/lib/arborist/load-virtual.js @@ -1,6 +1,7 @@ // mixin providing the loadVirtual method const {resolve} = require('path') +const mapWorkspaces = require('@npmcli/map-workspaces') const consistentResolve = require('../consistent-resolve.js') const Shrinkwrap = require('../shrinkwrap.js') @@ -15,6 +16,7 @@ const resolveLinks = Symbol('resolveLinks') const assignParentage = Symbol('assignParentage') const loadNode = Symbol('loadVirtualNode') const loadLink = Symbol('loadVirtualLink') +const loadWorkspaces = Symbol('loadWorkspaces') module.exports = cls => class VirtualLoader extends cls { constructor (options) { @@ -39,7 +41,10 @@ module.exports = cls => class VirtualLoader extends cls { // when building the ideal tree, we pass in a root node to this function // otherwise, load it from the root package in the lockfile const { - root = this[loadNode]('', s.data.packages[''] || {}) + root = this[loadWorkspaces]( + this[loadNode]('', s.data.packages[''] || {}), + s + ) } = options return this[loadFromShrinkwrap](s, root) @@ -160,6 +165,16 @@ module.exports = cls => class VirtualLoader extends cls { return node } + [loadWorkspaces] (node, s) { + const workspaces = mapWorkspaces.virtual({ + cwd: node.path, + lockfile: s.data + }) + if (workspaces.size) + node.workspaces = workspaces + return node + } + [loadLink] (location, targetLoc, target, meta) { const path = resolve(this.path, location) const link = new Link({ diff --git a/lib/edge.js b/lib/edge.js index 29003b64a..a0bb7a432 100644 --- a/lib/edge.js +++ b/lib/edge.js @@ -1,6 +1,7 @@ // An edge in the dependency graph // Represents a dependency relationship of some kind +const npa = require('npm-package-arg') const depValid = require('./dep-valid.js') const _from = Symbol('_from') const _to = Symbol('_to') @@ -18,6 +19,7 @@ const types = new Set([ 'optional', 'peer', 'peerOptional', + 'workspace' ]) class Edge { @@ -26,6 +28,10 @@ class Edge { if (typeof spec !== 'string') throw new TypeError('must provide string spec') + + if (type === 'workspace' && npa(spec).type !== 'directory') + throw new TypeError('workspace edges must be a symlink') + this[_spec] = spec if (accept !== undefined) { diff --git a/lib/node.js b/lib/node.js index b065beae2..f17e61dc5 100644 --- a/lib/node.js +++ b/lib/node.js @@ -46,6 +46,7 @@ const _fsParent = Symbol('_fsParent') const _reloadEdges = Symbol('_reloadEdges') const _loadType = Symbol('_loadType') const _loadDepType = Symbol('_loadDepType') +const _loadWorkspaces = Symbol('_loadWorkspaces') const _reloadNamedEdges = Symbol('_reloadNamedEdges') // overridden by Link class const _loadDeps = Symbol.for('Arborist.Node._loadDeps') @@ -55,6 +56,7 @@ const _refreshTopMeta = Symbol('_refreshTopMeta') const _refreshPath = Symbol('_refreshPath') const _delistFromMeta = Symbol('_delistFromMeta') const _global = Symbol.for('global') +const _workspaces = Symbol('_workspaces') const relpath = require('./relpath.js') const consistentResolve = require('./consistent-resolve.js') @@ -93,6 +95,8 @@ class Node { // true if part of a global install this[_global] = global + this[_workspaces] = null + this.errors = error ? [error] : [] const pkg = normalize(options.pkg || {}) @@ -209,6 +213,22 @@ class Node { return this.global && this.parent.isRoot } + get workspaces() { + return this[_workspaces] + } + + set workspaces(workspaces) { + // deletes edges if they already exists + if (this[_workspaces]) + for (const [name, path] of this[_workspaces].entries()) { + if (!workspaces.has(name)) this.edgesOut.get(name).detach() + } + + this[_workspaces] = workspaces + this[_loadWorkspaces]() + this[_loadDeps]() + } + get binPaths () { if (!this.parent) return [] @@ -242,6 +262,7 @@ class Node { } this[_package] = pkg + this[_loadWorkspaces]() this[_loadDeps]() // do a hard reload, since the dependents may now be valid or invalid // as a result of the package change. @@ -334,6 +355,14 @@ class Node { return this[_root] || this } + [_loadWorkspaces] () { + if (!this[_workspaces]) return + + for (const [name, path] of this[_workspaces].entries()) { + new Edge({ from: this, name, spec: `file:${path}`, type: 'workspace' }) + } + } + [_loadDeps] () { // Caveat! Order is relevant! // packages in optionalDependencies and prod/peer/dev are diff --git a/lib/shrinkwrap.js b/lib/shrinkwrap.js index 29d761d05..aa094c8e6 100644 --- a/lib/shrinkwrap.js +++ b/lib/shrinkwrap.js @@ -104,6 +104,7 @@ const pkgMetaKeys = [ 'hasInstallScript', 'bin', 'deprecated', + 'workspaces', ] const nodeMetaKeys = [ diff --git a/notes/workspace.md b/notes/workspace.md index 289705a77..d8c09e937 100644 --- a/notes/workspace.md +++ b/notes/workspace.md @@ -1,60 +1,181 @@ # workspaces -A few ways to do this: - -## Option A: link packages to root `node_modules`, install others - -This is how yarn does it. Probably better. +Conceptual install example: ``` root -+-- app (uses a, b, c, i) -| +-- node_modules -| +-- i +-- node_modules -| +-- app => root/app -| +-- a => root/pkgs/a -| +-- b => root/pkgs/b -| +-- c => root/pkgs/c +| +-- app => app +| +-- a => pkgs/a +| +-- b => pkgs/b +| +-- c => pkgs/c +| +-- x +| +-- y +| +-- z +| +-- i +| +-- n ? +| +-- j +| +-- k ++-- app +-- pkgs - +-- a (b, c, x) + +-- a (b, c, x, m@file:./m) + | +-- m (n) + | | +-- node_modules + | | +-- n ? | +-- node_modules + | +-- n ? + | +-- m => pkgs/a/m | +-- x + | +-- b => pkgs/b + | +-- c => pkgs/c +-- b (a, c, y) - | +-- node_modules - | +-- y +-- c (a, b, z) - +-- node_modules - +-- z + +-- w (nested workspace) + +-- pkgs + +-- j + +-- k ``` -## Option B: Link packages into one another +- `root/package.json`: -Kind of a mess. Not as good, but should still be supported, because that's -what pre-arborist `npm link ../foo` would generate. +```json +{ + "workspaces": [ + "pkgs/*", + "app" + ] +} +``` + +root `Node` + +- be aware it's a **Top-level workspace** +- 4 Edges in edgesOut with type=workspace, referencing workspace children + - that means we create a link node in root.children.get('app') + targetting `./app` Node, etc. +- during buildIdeal: + - need to know that app is in root's workspace + - app.wsParent = root + - root.wsChildren.add(app) + - if any dep CAN be satisfied by a named dep in the workspace, then + create a Link targetting that workspace child node + - resolving: _first_ check this.wsParent.get('dep-name'), and if + that's ok, then resolve with a link to that target. + - no hoisting by default: when doing `_canPlaceDep`, if target is + node.wsParent, AND we're not hoisting, THEN: return CONFLICT +- When setting Node.parent or Node.fsParent, set wsParent = parent.wsParent + +## Questions / Thoughts +- What a Workspace node class does? + - Add metadata to lock files + - Glob only relevant for loadActual +- maybe wsParent wsChildren +- when creating +- start with loadActual + - loadActual.loadFSNode + - on check for path is real add another check to make load from/as a workspace +- General impl ideas + - Do we support an opt-out flag? + - Do we want to add extra top-level commands to the cli? + - `npm workspaces info`: Retrieves workspaces locations (might be useful for tooling) + - What do we do with binaries? Do we only link bins for workspaces that are defined as a top-level dep? + - In order to support subsets of packages the way Wes been advocating for, instead of supporting adjacent folders with package.json defining different workspaces, what if we were to support a different workspaces config definition within the top-level package.json - maybe something that allows for definition of subsets? something in the likes of: + ``` + "workspaces": [ + "packages": { + "set-a": [ + "packages/*" + ], + "set-b": [ + "express/express-namespace", + "express/express" + ] + } + ] + ``` + - But then we'd need a way for commands to be aware of these subsets... + +## Registry vs workspace relationship: ``` -root -+-- pkgs - +-- app - | +-- node_modules - | +-- a => pkgs/a - | +-- b => pkgs/b - | +-- c => pkgs/c - | +-- i - +-- a (b, c, x) - | +-- node_modules - | +-- x - | +-- b => pkgs/b - | +-- c => pkgs/c - +-- b (a, c, y) - | +-- node_modules - | +-- y - | +-- a => pkgs/a - | +-- c => pkgs/c - +-- c (a, b, z) +given that registry has latest: a@1.1.0 + +workspace-root ++-- packages + +-- a (a@1.0.1) + +-- b (a@^1.0.0) + +npm install + +workspace-root ++-- packages + +-- a (a@1.0.1) + +-- b (a@^1.0.0) + +-- node_modules + +-- a -> ../../a + +workspaces always prefer to install a nested package if semver is satisfied +``` + +``` +given that registry has latest: a@2.0.0 + +workspace-root ++-- packages + +-- a@1.0.1 + +-- b (a@^2.0.0) + +npm install + +workspace-root ++-- packages + +-- a@1.0.1 + +-- b (a@^2.0.0) +-- node_modules - +-- z - +-- a => pkgs/a - +-- b => pkgs/b + +-- a@2.0.0 + +workspaces will try to install deps from registry if no satisfying semver version was found within its nested packages ``` + +## Implementation + +### Build Ideal Tree + +1. Read list of "workpaces" from `package.json` +2. Turn globs into actual locations, retrieve the final list of workspaces paths +3. Arborist needs to be made aware of the list of worskpaces paths + 1. Workspace info parsed (steps 1 and 2) needs to be attached before build ideal tree + 2. On building ideal tree, checks against existing workspaces to append them as child nodes + 3. Edge needs to support a `workspace` type + 4. Edge `satisfiedBy` and/or the `dep-valid` module needs to check against the available workspaces + 5. `edgesOut` with `type: workspace` +4. Represent a workspace node within a tree - is it just `node.workspace` ? + +NOTE: +- Now the build ideal tree is reading fs other than `package.json` and `package-lock` + +### Load Virtual + +1. How to figure out all the structure of workspaces form a pakcage-lock + 1. How it gets saved? + 2. How to build the virtual tree out of reading package-lock +2. maybe support a subset of glob? we need to optimize mapWorkspace regardless +3. lib/shrinkwrap.js has to be aware of workspaces and the structure + 1. Reading from lockfile might render nodes extraneous? + 2. include workspaces map into package-lock files + 3. loadVirtual reads from the lock file and put nodes in the right place + + +### Reify + +1. Correctly symlink workspaces to its dependants `node_modules` + +## Open Ended Questions + +- Maybe do not hoist workspace dependencies by default? + +## Missing: +- Nested workspaces + - Add support to `mapWorkspaces` in buildIdealTree `_linkFromSpec` + - Tests +- Test case with a mixed relationship between `file:` deps and workspaces diff --git a/package-lock.json b/package-lock.json index d309cbb41..50e8223ca 100644 --- a/package-lock.json +++ b/package-lock.json @@ -180,6 +180,17 @@ "readdir-scoped-modules": "^1.1.0" } }, + "@npmcli/map-workspaces": { + "version": "0.0.0-pre.1", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-0.0.0-pre.1.tgz", + "integrity": "sha512-IovEVdr17hW/Stt0kpPjz1r0ZxRX3RGah7ww3tQpi5NtyOapJwbUffWuWETyQkOjud5soC45mnjOOBtfTggtng==", + "requires": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^7.1.6", + "minimatch": "^3.0.4", + "read-package-json-fast": "^1.1.3" + } + }, "@npmcli/name-from-folder": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", diff --git a/package.json b/package.json index e73c6f571..f9cc794b4 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/map-workspaces": "0.0.0-pre.1", "@npmcli/run-script": "^1.3.1", "bin-links": "^2.1.2", "json-stringify-nice": "^1.1.1", 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 5cf4e43be..4ee8d799f 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 @@ -50318,3 +50318,961 @@ Node { "resolved": null, } ` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should ignore nested node_modules folders > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-ignore-nm/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-ignore-nm/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "location": "packages/a", + "name": "a", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-ignore-nm", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should install a simple example > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-simple/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-simple/b", + "type": "workspace", + }, + Edge { + "from": "a", + "name": "b", + "spec": "^1.0.0", + "type": "prod", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../b", + "target": Object { + "name": "b", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-simple/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-simple/b", + "to": "node_modules/b", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "b" => Edge { + "name": "b", + "spec": "^1.0.0", + "to": "node_modules/b", + "type": "prod", + }, + }, + "location": "a", + "name": "a", + "resolved": null, + }, + Node { + "location": "b", + "name": "b", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-simple", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should install a simple scoped pkg example > expect resolving Promise 1`] = ` +Node { + "children": Map { + "@ruyadorno/scoped-a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "@ruyadorno/scoped-a", + "spec": "file:{CWD}/test/fixtures/workspaces-scoped-pkg/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/@ruyadorno/scoped-a", + "name": "@ruyadorno/scoped-a", + "resolved": "file:../../packages/a", + "target": Object { + "name": "@ruyadorno/scoped-a", + "parent": null, + }, + }, + "@ruyadorno/scoped-b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "@ruyadorno/scoped-b", + "spec": "file:{CWD}/test/fixtures/workspaces-scoped-pkg/packages/b", + "type": "workspace", + }, + Edge { + "from": "packages/a", + "name": "@ruyadorno/scoped-b", + "spec": "^1.0.0", + "type": "prod", + }, + }, + "location": "node_modules/@ruyadorno/scoped-b", + "name": "@ruyadorno/scoped-b", + "resolved": "file:../../packages/b", + "target": Object { + "name": "@ruyadorno/scoped-b", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "@ruyadorno/scoped-a" => Edge { + "name": "@ruyadorno/scoped-a", + "spec": "file:{CWD}/test/fixtures/workspaces-scoped-pkg/packages/a", + "to": "node_modules/@ruyadorno/scoped-a", + "type": "workspace", + }, + "@ruyadorno/scoped-b" => Edge { + "name": "@ruyadorno/scoped-b", + "spec": "file:{CWD}/test/fixtures/workspaces-scoped-pkg/packages/b", + "to": "node_modules/@ruyadorno/scoped-b", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "@ruyadorno/scoped-b" => Edge { + "name": "@ruyadorno/scoped-b", + "spec": "^1.0.0", + "to": "node_modules/@ruyadorno/scoped-b", + "type": "prod", + }, + }, + "location": "packages/a", + "name": "@ruyadorno/scoped-a", + "resolved": null, + }, + Node { + "location": "packages/b", + "name": "@ruyadorno/scoped-b", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-scoped-pkg", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should install conflicting dep versions > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions/packages/b", + "type": "workspace", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../packages/b", + "target": Object { + "name": "b", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "abbrev" => Edge { + "name": "abbrev", + "spec": "^1.1.1", + "to": "node_modules/abbrev", + "type": "prod", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions/packages/b", + "to": "node_modules/b", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "children": Map { + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "packages/a", + "name": "abbrev", + "spec": "=1.0.4", + "type": "prod", + }, + }, + "location": "packages/a/node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz", + }, + }, + "edgesOut": Map { + "abbrev" => Edge { + "name": "abbrev", + "spec": "=1.0.4", + "to": "packages/a/node_modules/abbrev", + "type": "prod", + }, + }, + "location": "packages/a", + "name": "a", + "resolved": null, + }, + Node { + "children": Map { + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "packages/b", + "name": "abbrev", + "spec": "=1.1.0", + "type": "prod", + }, + }, + "location": "packages/b/node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + }, + }, + "edgesOut": Map { + "abbrev" => Edge { + "name": "abbrev", + "spec": "=1.1.0", + "to": "packages/b/node_modules/abbrev", + "type": "prod", + }, + }, + "location": "packages/b", + "name": "b", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-conflicting-versions", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should install from registry on version not satisfied > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "abbrev" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied/packages/abbrev", + "type": "workspace", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "file:../packages/abbrev", + "target": Object { + "name": "abbrev", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "abbrev" => Edge { + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied/packages/abbrev", + "to": "node_modules/abbrev", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "children": Map { + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "packages/a", + "name": "abbrev", + "spec": "=1.1.1", + "type": "prod", + }, + }, + "location": "packages/a/node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + }, + }, + "edgesOut": Map { + "abbrev" => Edge { + "name": "abbrev", + "spec": "=1.1.1", + "to": "packages/a/node_modules/abbrev", + "type": "prod", + }, + }, + "location": "packages/a", + "name": "a", + "resolved": null, + }, + Node { + "location": "packages/abbrev", + "name": "abbrev", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-version-unsatisfied", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should install shared dependencies into root folder > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "packages/a", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + Edge { + "from": "packages/b", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps/packages/b", + "type": "workspace", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../packages/b", + "target": Object { + "name": "b", + "parent": null, + }, + }, + "c" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "c", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps/packages/c", + "type": "workspace", + }, + }, + "location": "node_modules/c", + "name": "c", + "resolved": "file:../packages/c", + "target": Object { + "name": "c", + "parent": null, + }, + }, + "uuid" => Node { + "edgesIn": Set { + Edge { + "from": "packages/c", + "name": "uuid", + "spec": "=3.3.3", + "type": "prod", + }, + }, + "location": "node_modules/uuid", + "name": "uuid", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps/packages/b", + "to": "node_modules/b", + "type": "workspace", + }, + "c" => Edge { + "name": "c", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps/packages/c", + "to": "node_modules/c", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "abbrev" => Edge { + "name": "abbrev", + "spec": "^1.1.1", + "to": "node_modules/abbrev", + "type": "prod", + }, + }, + "location": "packages/a", + "name": "a", + "resolved": null, + }, + Node { + "edgesOut": Map { + "abbrev" => Edge { + "name": "abbrev", + "spec": "^1.1.1", + "to": "node_modules/abbrev", + "type": "prod", + }, + }, + "location": "packages/b", + "name": "b", + "resolved": null, + }, + Node { + "edgesOut": Map { + "uuid" => Edge { + "name": "uuid", + "spec": "=3.3.3", + "to": "node_modules/uuid", + "type": "prod", + }, + }, + "location": "packages/c", + "name": "c", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-shared-deps", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should install workspace transitive dependencies > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-transitive-deps/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "once" => Node { + "dev": true, + "edgesIn": Set { + Edge { + "from": "packages/a", + "name": "once", + "spec": "^1.4.0", + "type": "dev", + }, + }, + "edgesOut": Map { + "wrappy" => Edge { + "name": "wrappy", + "spec": "1", + "to": "node_modules/wrappy", + "type": "prod", + }, + }, + "location": "node_modules/once", + "name": "once", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + }, + "wrappy" => Node { + "dev": true, + "edgesIn": Set { + Edge { + "from": "node_modules/once", + "name": "wrappy", + "spec": "1", + "type": "prod", + }, + }, + "location": "node_modules/wrappy", + "name": "wrappy", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-transitive-deps/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "once" => Edge { + "name": "once", + "spec": "^1.4.0", + "to": "node_modules/once", + "type": "dev", + }, + }, + "location": "packages/a", + "name": "a", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-transitive-deps", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should link top level nested workspaces > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-top-level-link/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-top-level-link/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "location": "packages/a", + "name": "a", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-top-level-link", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should prefer linking nested workspaces > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "abbrev" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking/packages/abbrev", + "type": "workspace", + }, + Edge { + "from": "packages/a", + "name": "abbrev", + "spec": "*", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "file:../packages/abbrev", + "target": Object { + "name": "abbrev", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "abbrev" => Edge { + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking/packages/abbrev", + "to": "node_modules/abbrev", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "abbrev" => Edge { + "name": "abbrev", + "spec": "*", + "to": "node_modules/abbrev", + "type": "prod", + }, + }, + "location": "packages/a", + "name": "a", + "resolved": null, + }, + Node { + "location": "packages/abbrev", + "name": "abbrev", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-prefer-linking", + "resolved": null, +} +` + +exports[`test/arborist/build-ideal-tree.js TAP workspaces should work with files spec > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-with-files-spec/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-with-files-spec/packages/b", + "type": "workspace", + }, + Edge { + "from": "d", + "name": "b", + "spec": "^1.0.0", + "type": "prod", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../packages/b", + "target": Object { + "name": "b", + "parent": null, + }, + }, + "c" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "c", + "spec": "file:packages/c", + "type": "prod", + }, + }, + "location": "node_modules/c", + "name": "c", + "resolved": "file:../packages/c", + "target": Object { + "name": "c", + "parent": null, + }, + }, + "d" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "d", + "spec": "file:d", + "type": "prod", + }, + Edge { + "from": "packages/a", + "name": "d", + "spec": "^1.0.0", + "type": "prod", + }, + }, + "location": "node_modules/d", + "name": "d", + "resolved": "file:../d", + "target": Object { + "name": "d", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-with-files-spec/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-with-files-spec/packages/b", + "to": "node_modules/b", + "type": "workspace", + }, + "c" => Edge { + "name": "c", + "spec": "file:packages/c", + "to": "node_modules/c", + "type": "prod", + }, + "d" => Edge { + "name": "d", + "spec": "file:d", + "to": "node_modules/d", + "type": "prod", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "b" => Edge { + "name": "b", + "spec": "^1.0.0", + "to": "node_modules/b", + "type": "prod", + }, + }, + "location": "d", + "name": "d", + "resolved": null, + }, + Node { + "edgesOut": Map { + "d" => Edge { + "name": "d", + "spec": "^1.0.0", + "to": "node_modules/d", + "type": "prod", + }, + }, + "location": "packages/a", + "name": "a", + "resolved": null, + }, + Node { + "location": "packages/b", + "name": "b", + "resolved": null, + }, + Node { + "location": "packages/c", + "name": "c", + "resolved": null, + }, + }, + "location": "", + "name": "workspaces-with-files-spec", + "resolved": null, +} +` diff --git a/tap-snapshots/test-arborist-load-virtual.js-TAP.test.js b/tap-snapshots/test-arborist-load-virtual.js-TAP.test.js index c480aaa21..5b9f13887 100644 --- a/tap-snapshots/test-arborist-load-virtual.js-TAP.test.js +++ b/tap-snapshots/test-arborist-load-virtual.js-TAP.test.js @@ -13552,3 +13552,541 @@ Node { "resolved": null, } ` + +exports[`test/arborist/load-virtual.js TAP workspaces load a simple example > virtual tree with multiple bundles 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-simple-virtual/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-simple-virtual/b", + "type": "workspace", + }, + Edge { + "from": "a", + "name": "b", + "spec": "^1.0.0", + "type": "prod", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../b", + "target": Object { + "name": "b", + "parent": undefined, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-simple-virtual/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-simple-virtual/b", + "to": "node_modules/b", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-simple-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load conflicting dep versions example > virtual tree with resolved conflicting dependencies 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + Edge { + "error": "INVALID", + "from": "packages/a", + "name": "abbrev", + "spec": "=1.0.4", + "type": "prod", + }, + Edge { + "error": "INVALID", + "from": "packages/b", + "name": "abbrev", + "spec": "=1.1.0", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions-virtual/packages/b", + "type": "workspace", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../packages/b", + "target": Object { + "name": "b", + "parent": undefined, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "abbrev" => Edge { + "name": "abbrev", + "spec": "^1.1.1", + "to": "node_modules/abbrev", + "type": "prod", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-conflicting-versions-virtual/packages/b", + "to": "node_modules/b", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-conflicting-versions-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load installed from registry on version not satisfied > virtual tree with deduped dep 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + "abbrev" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied-virtual/packages/abbrev", + "type": "workspace", + }, + Edge { + "error": "INVALID", + "from": "packages/a", + "name": "abbrev", + "spec": "=1.1.1", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "file:../packages/abbrev", + "target": Object { + "name": "abbrev", + "parent": undefined, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "abbrev" => Edge { + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-version-unsatisfied-virtual/packages/abbrev", + "to": "node_modules/abbrev", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-version-unsatisfied-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load installed tree with ignored nested node_modules folders > virtual tree ignoring nested node_modules 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-ignore-nm-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-ignore-nm-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-ignore-nm-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load installed workspace with transitive dependencies > virtual tree with transitive deps 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-transitive-deps-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + "once" => Node { + "dev": true, + "edgesIn": Set { + Edge { + "from": "packages/a", + "name": "once", + "spec": "^1.4.0", + "type": "dev", + }, + }, + "edgesOut": Map { + "wrappy" => Edge { + "name": "wrappy", + "spec": "1", + "to": "node_modules/wrappy", + "type": "prod", + }, + }, + "location": "node_modules/once", + "name": "once", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + }, + "wrappy" => Node { + "dev": true, + "edgesIn": Set { + Edge { + "from": "node_modules/once", + "name": "wrappy", + "spec": "1", + "type": "prod", + }, + }, + "location": "node_modules/wrappy", + "name": "wrappy", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-transitive-deps-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-transitive-deps-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load linked top level nested workspaces > virtual tree top level dep 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-top-level-link-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-top-level-link-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-top-level-link-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load prefer linking nested workspaces > virtual tree linking to local workspaces 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + "abbrev" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking-virtual/packages/abbrev", + "type": "workspace", + }, + Edge { + "from": "packages/a", + "name": "abbrev", + "spec": "*", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "file:../packages/abbrev", + "target": Object { + "name": "abbrev", + "parent": undefined, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "abbrev" => Edge { + "name": "abbrev", + "spec": "file:{CWD}/test/fixtures/workspaces-prefer-linking-virtual/packages/abbrev", + "to": "node_modules/abbrev", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-prefer-linking-virtual", + "resolved": null, +} +` + +exports[`test/arborist/load-virtual.js TAP workspaces load shared dependencies example > virtual tree with shared dependencies 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps-virtual/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": undefined, + }, + }, + "abbrev" => Node { + "edgesIn": Set { + Edge { + "from": "packages/a", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + Edge { + "from": "packages/b", + "name": "abbrev", + "spec": "^1.1.1", + "type": "prod", + }, + }, + "location": "node_modules/abbrev", + "name": "abbrev", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps-virtual/packages/b", + "type": "workspace", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../packages/b", + "target": Object { + "name": "b", + "parent": undefined, + }, + }, + "c" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "c", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps-virtual/packages/c", + "type": "workspace", + }, + }, + "location": "node_modules/c", + "name": "c", + "resolved": "file:../packages/c", + "target": Object { + "name": "c", + "parent": undefined, + }, + }, + "uuid" => Node { + "edgesIn": Set { + Edge { + "from": "packages/c", + "name": "uuid", + "spec": "=3.3.3", + "type": "prod", + }, + }, + "location": "node_modules/uuid", + "name": "uuid", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps-virtual/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps-virtual/packages/b", + "to": "node_modules/b", + "type": "workspace", + }, + "c" => Edge { + "name": "c", + "spec": "file:{CWD}/test/fixtures/workspaces-shared-deps-virtual/packages/c", + "to": "node_modules/c", + "type": "workspace", + }, + }, + "location": "", + "name": "workspaces-shared-deps-virtual", + "resolved": null, +} +` diff --git a/tap-snapshots/test-arborist-reify.js-TAP.test.js b/tap-snapshots/test-arborist-reify.js-TAP.test.js index c564bb5b5..2fe428037 100644 --- a/tap-snapshots/test-arborist-reify.js-TAP.test.js +++ b/tap-snapshots/test-arborist-reify.js-TAP.test.js @@ -33323,3 +33323,201 @@ Node { "resolved": null, } ` + +exports[`test/arborist/reify.js TAP workspaces reify simple-workspaces > should reify simple workspaces 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-simple-workspaces/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-simple-workspaces/b", + "type": "workspace", + }, + Edge { + "from": "a", + "name": "b", + "spec": "^1.0.0", + "type": "prod", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../b", + "target": Object { + "name": "b", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-simple-workspaces/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-simple-workspaces/b", + "to": "node_modules/b", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "edgesOut": Map { + "b" => Edge { + "name": "b", + "spec": "^1.0.0", + "to": "node_modules/b", + "type": "prod", + }, + }, + "location": "a", + "name": "a", + "resolved": null, + }, + Node { + "location": "b", + "name": "b", + "resolved": null, + }, + }, + "location": "", + "name": "reify-workspaces-reify-simple-workspaces", + "resolved": null, +} +` + +exports[`test/arborist/reify.js TAP workspaces reify workspaces bin files > expect resolving Promise 1`] = ` +Node { + "children": Map { + "a" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "a", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-workspaces-bin-files/packages/a", + "type": "workspace", + }, + }, + "location": "node_modules/a", + "name": "a", + "resolved": "file:../packages/a", + "target": Object { + "name": "a", + "parent": null, + }, + }, + "b" => Link { + "edgesIn": Set { + Edge { + "from": "", + "name": "b", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-workspaces-bin-files/packages/b", + "type": "workspace", + }, + }, + "location": "node_modules/b", + "name": "b", + "resolved": "file:../packages/b", + "target": Object { + "name": "b", + "parent": null, + }, + }, + }, + "edgesOut": Map { + "a" => Edge { + "name": "a", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-workspaces-bin-files/packages/a", + "to": "node_modules/a", + "type": "workspace", + }, + "b" => Edge { + "name": "b", + "spec": "file:{CWD}/test/arborist/reify-workspaces-reify-workspaces-bin-files/packages/b", + "to": "node_modules/b", + "type": "workspace", + }, + }, + "fsChildren": Set { + Node { + "location": "packages/a", + "name": "a", + "resolved": null, + }, + Node { + "location": "packages/b", + "name": "b", + "resolved": null, + }, + }, + "location": "", + "name": "reify-workspaces-reify-workspaces-bin-files", + "resolved": null, +} +` + +exports[`test/arborist/reify.js TAP workspaces reify workspaces lockfile > should lock workspaces config 1`] = ` +Object { + "dependencies": Object { + "a": Object { + "version": "file:a", + }, + "b": Object { + "version": "file:b", + }, + }, + "lockfileVersion": 2, + "name": "workspace-simple", + "packages": Object { + "": Object { + "name": "workspace-simple", + "workspaces": Array [ + "a", + "b", + ], + }, + "a": Object { + "dependencies": Object { + "b": "^1.0.0", + }, + "name": "a", + "version": "1.0.0", + }, + "b": Object { + "name": "b", + "version": "1.0.0", + }, + "node_modules/a": Object { + "link": true, + "resolved": "a", + }, + "node_modules/b": Object { + "link": true, + "resolved": "b", + }, + }, + "requires": true, +} +` diff --git a/tap-snapshots/test-node.js-TAP.test.js b/tap-snapshots/test-node.js-TAP.test.js index 810e2e99a..7de4940de 100644 --- a/tap-snapshots/test-node.js-TAP.test.js +++ b/tap-snapshots/test-node.js-TAP.test.js @@ -31,6 +31,35 @@ Node { } ` +exports[`test/node.js TAP set workspaces > should setup edges out for each workspace 1`] = ` +Node { + "children": Map {}, + "dev": true, + "devOptional": true, + "edgesIn": Set {}, + "edgesOut": Map { + "foo" => Edge {}, + "bar" => Edge {}, + }, + "errors": Array [], + "extraneous": true, + "fsChildren": Set {}, + "hasShrinkwrap": false, + "integrity": null, + "inventory": Inventory {}, + "legacyPeerDeps": false, + "linksIn": Set {}, + "location": "", + "meta": undefined, + "name": "workspaces_root", + "optional": true, + "path": "/home/user/projects/workspaces_root", + "peer": true, + "realpath": "/home/user/projects/workspaces_root", + "resolved": null, +} +` + exports[`test/node.js TAP testing with dep tree with meta > add new meta under prod 1`] = ` Node { "children": Map { diff --git a/test/arborist/build-ideal-tree.js b/test/arborist/build-ideal-tree.js index 743e8b093..14a550752 100644 --- a/test/arborist/build-ideal-tree.js +++ b/test/arborist/build-ideal-tree.js @@ -1015,3 +1015,64 @@ t.test('no fix available, linked top package', async t => { "'cd ./mkdirp-unfixable' and run 'npm audit' for details." ]]) }) + +t.test('workspaces', t => { + t.test('should install a simple example', t => { + const path = resolve(__dirname, '../fixtures/workspaces-simple') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should install a simple scoped pkg example', t => { + const path = resolve(__dirname, '../fixtures/workspaces-scoped-pkg') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should not work with duplicate names', t => { + const path = resolve(__dirname, '../fixtures/workspaces-duplicate') + return t.rejects(printIdeal(path), { code: 'EDUPLICATEWORKSPACE' }, 'throws EDUPLICATEWORKSPACE error') + }) + + t.test('should install shared dependencies into root folder', t => { + const path = resolve(__dirname, '../fixtures/workspaces-shared-deps') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should install conflicting dep versions', t => { + const path = resolve(__dirname, '../fixtures/workspaces-conflicting-versions') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should prefer linking nested workspaces', t => { + const path = resolve(__dirname, '../fixtures/workspaces-prefer-linking') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should install from registry on version not satisfied', t => { + const path = resolve(__dirname, '../fixtures/workspaces-version-unsatisfied') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should link top level nested workspaces', t => { + const path = resolve(__dirname, '../fixtures/workspaces-top-level-link') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should install workspace transitive dependencies', t => { + const path = resolve(__dirname, '../fixtures/workspaces-transitive-deps') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should ignore nested node_modules folders', t => { + // packages/a/node_modules/nested-workspaces should not be installed + const path = resolve(__dirname, '../fixtures/workspaces-ignore-nm') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.test('should work with files spec', t => { + const path = resolve(__dirname, '../fixtures/workspaces-with-files-spec') + return t.resolveMatchSnapshot(printIdeal(path)) + }) + + t.end() +}) + diff --git a/test/arborist/load-virtual.js b/test/arborist/load-virtual.js index d870090d2..4abff3b82 100644 --- a/test/arborist/load-virtual.js +++ b/test/arborist/load-virtual.js @@ -146,3 +146,56 @@ t.test('load a tree with a bunch of bundles', t => t.test('load a tree with an empty dep set and a lockfile', t => loadVirtual(emptyFixture).then(tree => t.matchSnapshot(printTree(tree), 'virtual tree with no deps'))) + +t.test('workspaces', t => { + t.test('load a simple example', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-simple-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree with multiple bundles'))) + + t.test('load shared dependencies example', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-shared-deps-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree with shared dependencies'))) + + t.test('load conflicting dep versions example', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-conflicting-versions-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree with resolved conflicting dependencies'))) + + t.test('load prefer linking nested workspaces', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-prefer-linking-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree linking to local workspaces'))) + + t.test('load installed from registry on version not satisfied', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-version-unsatisfied-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree with deduped dep'))) + + + t.test('load linked top level nested workspaces', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-top-level-link-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree top level dep'))) + + t.test('load installed workspace with transitive dependencies', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-transitive-deps-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree with transitive deps'))) + + t.test('load installed tree with ignored nested node_modules folders', t => + loadVirtual( + resolve(__dirname, '../fixtures/workspaces-ignore-nm-virtual') + ).then(tree => + t.matchSnapshot(printTree(tree), 'virtual tree ignoring nested node_modules'))) + + t.end() +}) diff --git a/test/arborist/reify.js b/test/arborist/reify.js index 3494c8218..3b92cd8e9 100644 --- a/test/arborist/reify.js +++ b/test/arborist/reify.js @@ -886,3 +886,38 @@ t.test('global', t => { t.end() }) + +t.test('workspaces', t => { + t.test('reify simple-workspaces', t => + t.resolveMatchSnapshot(printReified(fixture(t, 'workspaces-simple')), 'should reify simple workspaces')) + + t.test('reify workspaces lockfile', t => { + const path = fixture(t, 'workspaces-simple') + reify(path).then(() => { + t.matchSnapshot(require(path + '/package-lock.json'), 'should lock workspaces config') + t.end() + }) + }) + + t.test('reify workspaces bin files', t => { + const path = fixture(t, 'workspaces-link-bin') + + const bins = [ + resolve(path, 'node_modules/.bin/a'), + resolve(path, 'node_modules/.bin/b'), + ] + + const checkBin = () => { + for (const bin of bins) + if (process.platform === 'win32') + t.ok(fs.statSync(bin + '.cmd').isFile(), 'created shim') + else + t.ok(fs.lstatSync(bin).isSymbolicLink(), 'created symlink') + } + + return t.resolveMatchSnapshot(printReified(path, {})) + .then(checkBin) + }) + + t.end() +}) diff --git a/test/edge.js b/test/edge.js index 3a23c6216..10fdfb925 100644 --- a/test/edge.js +++ b/test/edge.js @@ -278,3 +278,9 @@ t.throws(() => new Edge({ name: 'foo', spec: '', }), new TypeError('must provide "from" node')) + +t.throws(() => new Edge({ + type: 'workspace', + name: 'foo', + spec: '*', +}), new TypeError('workspace edges must be a symlink')) diff --git a/test/fixtures/reify-cases/workspaces-link-bin.js b/test/fixtures/reify-cases/workspaces-link-bin.js new file mode 100644 index 000000000..52a8158e8 --- /dev/null +++ b/test/fixtures/reify-cases/workspaces-link-bin.js @@ -0,0 +1,38 @@ +// generated from test/fixtures/workspaces-link-bin +module.exports = t => ({ + "foo.js": "", + "package.json": JSON.stringify({ + "name": "workspace-duplicate", + "bin": "foo.js", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "a": "*" + } + }), + "packages": { + "a": { + "file.js": "", + "package.json": JSON.stringify({ + "name": "a", + "version": "1.0.0", + "files": [ + "file.js" + ], + "bin": "file.js" + }) + }, + "b": { + "file.js": "", + "package.json": JSON.stringify({ + "name": "b", + "version": "1.0.0", + "files": [ + "file.js" + ], + "bin": "file.js" + }) + } + } +}) diff --git a/test/fixtures/reify-cases/workspaces-simple.js b/test/fixtures/reify-cases/workspaces-simple.js new file mode 100644 index 000000000..bc0f0e256 --- /dev/null +++ b/test/fixtures/reify-cases/workspaces-simple.js @@ -0,0 +1,25 @@ +// generated from test/fixtures/workspaces-simple +module.exports = t => ({ + "a": { + "package.json": JSON.stringify({ + "name": "a", + "version": "1.0.0", + "dependencies": { + "b": "^1.0.0" + } + }) + }, + "b": { + "package.json": JSON.stringify({ + "name": "b", + "version": "1.0.0" + }) + }, + "package.json": JSON.stringify({ + "name": "workspace-simple", + "workspaces": [ + "a", + "b" + ] + }) +}) diff --git a/test/fixtures/workspaces-conflicting-versions-virtual/package-lock.json b/test/fixtures/workspaces-conflicting-versions-virtual/package-lock.json new file mode 100644 index 000000000..03986615a --- /dev/null +++ b/test/fixtures/workspaces-conflicting-versions-virtual/package-lock.json @@ -0,0 +1,91 @@ +{ + "name": "workspaces-conflicting-deps", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspaces-conflicting-deps", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + }, + "workspaces": { + "packages": [ + "packages/*" + ] + } + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "node_modules/abbrev": { + "name": "abbrev", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/b": { + "resolved": "packages/b", + "link": true + }, + "packages/a": { + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "=1.0.4" + } + }, + "packages/a/node_modules/abbrev": { + "name": "abbrev", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz", + "integrity": "sha1-vVWuXkE7oXIu5Mq6H26hBBSlns0=" + }, + "packages/b": { + "name": "b", + "version": "1.0.0", + "dependencies": { + "abbrev": "=1.1.0" + } + }, + "packages/b/node_modules/abbrev": { + "name": "abbrev", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "b": { + "version": "file:packages/b" + }, + "packages/a": { + "dependencies": { + "abbrev": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.4.tgz", + "integrity": "sha1-vVWuXkE7oXIu5Mq6H26hBBSlns0=" + } + } + }, + "packages/b": { + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" + } + } + } + } +} diff --git a/test/fixtures/workspaces-conflicting-versions-virtual/package.json b/test/fixtures/workspaces-conflicting-versions-virtual/package.json new file mode 100644 index 000000000..651d43b5b --- /dev/null +++ b/test/fixtures/workspaces-conflicting-versions-virtual/package.json @@ -0,0 +1,10 @@ +{ + "name": "workspaces-conflicting-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "abbrev": "^1.1.1" + } +} diff --git a/test/fixtures/workspaces-conflicting-versions/package.json b/test/fixtures/workspaces-conflicting-versions/package.json new file mode 100644 index 000000000..447380094 --- /dev/null +++ b/test/fixtures/workspaces-conflicting-versions/package.json @@ -0,0 +1,11 @@ +{ + "name": "workspaces-conflicting-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "abbrev": "^1.1.1" + } +} + diff --git a/test/fixtures/workspaces-conflicting-versions/packages/a/package.json b/test/fixtures/workspaces-conflicting-versions/packages/a/package.json new file mode 100644 index 000000000..f9904d309 --- /dev/null +++ b/test/fixtures/workspaces-conflicting-versions/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "=1.0.4" + } +} diff --git a/test/fixtures/workspaces-conflicting-versions/packages/b/package.json b/test/fixtures/workspaces-conflicting-versions/packages/b/package.json new file mode 100644 index 000000000..a3440f267 --- /dev/null +++ b/test/fixtures/workspaces-conflicting-versions/packages/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "1.0.0", + "dependencies": { + "abbrev": "=1.1.0" + } +} diff --git a/test/fixtures/workspaces-duplicate/package.json b/test/fixtures/workspaces-duplicate/package.json new file mode 100644 index 000000000..985971c00 --- /dev/null +++ b/test/fixtures/workspaces-duplicate/package.json @@ -0,0 +1,6 @@ +{ + "name": "workspace-duplicate", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-duplicate/packages/a/package.json b/test/fixtures/workspaces-duplicate/packages/a/package.json new file mode 100644 index 000000000..9113c2528 --- /dev/null +++ b/test/fixtures/workspaces-duplicate/packages/a/package.json @@ -0,0 +1,4 @@ +{ + "name": "a", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-duplicate/packages/b/package.json b/test/fixtures/workspaces-duplicate/packages/b/package.json new file mode 100644 index 000000000..9113c2528 --- /dev/null +++ b/test/fixtures/workspaces-duplicate/packages/b/package.json @@ -0,0 +1,4 @@ +{ + "name": "a", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-ignore-nm-virtual/package-lock.json b/test/fixtures/workspaces-ignore-nm-virtual/package-lock.json new file mode 100644 index 000000000..c56b75472 --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm-virtual/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "workspace-ignore-nm", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspace-ignore-nm", + "workspaces": { + "packages": [ + "packages/**" + ] + } + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "packages/a": { + "name": "a", + "version": "1.0.0" + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + } + } +} diff --git a/test/fixtures/workspaces-ignore-nm-virtual/package.json b/test/fixtures/workspaces-ignore-nm-virtual/package.json new file mode 100644 index 000000000..5d63a1514 --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm-virtual/package.json @@ -0,0 +1,6 @@ +{ + "name": "workspace-ignore-nm", + "workspaces": [ + "packages/**" + ] +} diff --git a/test/fixtures/workspaces-ignore-nm/package.json b/test/fixtures/workspaces-ignore-nm/package.json new file mode 100644 index 000000000..be7d871a6 --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspace-ignore-nm", + "workspaces": [ + "packages/**" + ] +} + diff --git a/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/c/package.json b/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/c/package.json new file mode 100644 index 000000000..abd338493 --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/c/package.json @@ -0,0 +1,4 @@ +{ + "name": "c", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/d/package.json b/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/d/package.json new file mode 100644 index 000000000..ebbfbae0d --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/d/package.json @@ -0,0 +1,7 @@ +{ + "name": "d", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } +} diff --git a/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/package.json b/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/package.json new file mode 100644 index 000000000..b156dca8f --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm/packages/a/node_modules/nested-workspace/package.json @@ -0,0 +1,7 @@ +{ + "name": "nested-workspace", + "version": "1.0.0", + "workspaces": [ + "./d" + ] +} diff --git a/test/fixtures/workspaces-ignore-nm/packages/a/package.json b/test/fixtures/workspaces-ignore-nm/packages/a/package.json new file mode 100644 index 000000000..8fe98232f --- /dev/null +++ b/test/fixtures/workspaces-ignore-nm/packages/a/package.json @@ -0,0 +1,5 @@ +{ + "name": "a", + "version": "1.0.0" +} + diff --git a/test/fixtures/workspaces-link-bin/foo.js b/test/fixtures/workspaces-link-bin/foo.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/workspaces-link-bin/package.json b/test/fixtures/workspaces-link-bin/package.json new file mode 100644 index 000000000..d3560fc73 --- /dev/null +++ b/test/fixtures/workspaces-link-bin/package.json @@ -0,0 +1,10 @@ +{ + "name": "workspace-duplicate", + "bin": "foo.js", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "a": "*" + } +} diff --git a/test/fixtures/workspaces-link-bin/packages/a/file.js b/test/fixtures/workspaces-link-bin/packages/a/file.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/workspaces-link-bin/packages/a/package.json b/test/fixtures/workspaces-link-bin/packages/a/package.json new file mode 100644 index 000000000..c8fa2d1d7 --- /dev/null +++ b/test/fixtures/workspaces-link-bin/packages/a/package.json @@ -0,0 +1,6 @@ +{ + "name": "a", + "version": "1.0.0", + "files": ["file.js"], + "bin": "file.js" +} diff --git a/test/fixtures/workspaces-link-bin/packages/b/file.js b/test/fixtures/workspaces-link-bin/packages/b/file.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/workspaces-link-bin/packages/b/package.json b/test/fixtures/workspaces-link-bin/packages/b/package.json new file mode 100644 index 000000000..52a65b6fa --- /dev/null +++ b/test/fixtures/workspaces-link-bin/packages/b/package.json @@ -0,0 +1,6 @@ +{ + "name": "b", + "version": "1.0.0", + "files": ["file.js"], + "bin": "file.js" +} diff --git a/test/fixtures/workspaces-prefer-linking-virtual/package-lock.json b/test/fixtures/workspaces-prefer-linking-virtual/package-lock.json new file mode 100644 index 000000000..53b4e2d51 --- /dev/null +++ b/test/fixtures/workspaces-prefer-linking-virtual/package-lock.json @@ -0,0 +1,42 @@ +{ + "name": "workspaces-prefer-linking", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspaces-prefer-linking", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "node_modules/abbrev": { + "resolved": "packages/abbrev", + "link": true + }, + "packages/a": { + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "*" + } + }, + "packages/abbrev": { + "name": "abbrev", + "version": "2.0.0" + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + }, + "abbrev": { + "version": "file:packages/abbrev" + } + } +} diff --git a/test/fixtures/workspaces-prefer-linking-virtual/package.json b/test/fixtures/workspaces-prefer-linking-virtual/package.json new file mode 100644 index 000000000..6a15efe53 --- /dev/null +++ b/test/fixtures/workspaces-prefer-linking-virtual/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-prefer-linking", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-prefer-linking/package.json b/test/fixtures/workspaces-prefer-linking/package.json new file mode 100644 index 000000000..6a15efe53 --- /dev/null +++ b/test/fixtures/workspaces-prefer-linking/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-prefer-linking", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-prefer-linking/packages/a/package.json b/test/fixtures/workspaces-prefer-linking/packages/a/package.json new file mode 100644 index 000000000..7d15acabe --- /dev/null +++ b/test/fixtures/workspaces-prefer-linking/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "*" + } +} diff --git a/test/fixtures/workspaces-prefer-linking/packages/abbrev/package.json b/test/fixtures/workspaces-prefer-linking/packages/abbrev/package.json new file mode 100644 index 000000000..36b0d44ae --- /dev/null +++ b/test/fixtures/workspaces-prefer-linking/packages/abbrev/package.json @@ -0,0 +1,6 @@ +{ + "name": "abbrev", + "version": "2.0.0", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter " +} diff --git a/test/fixtures/workspaces-scoped-pkg/package.json b/test/fixtures/workspaces-scoped-pkg/package.json new file mode 100644 index 000000000..695f4a49e --- /dev/null +++ b/test/fixtures/workspaces-scoped-pkg/package.json @@ -0,0 +1,6 @@ +{ + "name": "workspace-simple", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-scoped-pkg/packages/a/package.json b/test/fixtures/workspaces-scoped-pkg/packages/a/package.json new file mode 100644 index 000000000..cc566d017 --- /dev/null +++ b/test/fixtures/workspaces-scoped-pkg/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "@ruyadorno/scoped-a", + "version": "1.0.0", + "dependencies": { + "@ruyadorno/scoped-b": "^1.0.0" + } +} diff --git a/test/fixtures/workspaces-scoped-pkg/packages/b/package.json b/test/fixtures/workspaces-scoped-pkg/packages/b/package.json new file mode 100644 index 000000000..3b48f952e --- /dev/null +++ b/test/fixtures/workspaces-scoped-pkg/packages/b/package.json @@ -0,0 +1,4 @@ +{ + "name": "@ruyadorno/scoped-b", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-shared-deps-virtual/package-lock.json b/test/fixtures/workspaces-shared-deps-virtual/package-lock.json new file mode 100644 index 000000000..3d77c2f42 --- /dev/null +++ b/test/fixtures/workspaces-shared-deps-virtual/package-lock.json @@ -0,0 +1,86 @@ +{ + "name": "workspaces-shared-deps", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspaces-shared-deps", + "version": "1.0.0", + "workspaces": { + "packages": [ + "packages/*" + ] + } + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "node_modules/abbrev": { + "name": "abbrev", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/b": { + "resolved": "packages/b", + "link": true + }, + "node_modules/c": { + "resolved": "packages/c", + "link": true + }, + "node_modules/uuid": { + "name": "uuid", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "bin": { + "uuid": "bin/uuid" + } + }, + "packages/a": { + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } + }, + "packages/b": { + "name": "b", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } + }, + "packages/c": { + "name": "c", + "version": "1.0.0", + "dependencies": { + "uuid": "=3.3.3" + } + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "b": { + "version": "file:packages/b" + }, + "c": { + "version": "file:packages/c" + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + } + } +} diff --git a/test/fixtures/workspaces-shared-deps-virtual/package.json b/test/fixtures/workspaces-shared-deps-virtual/package.json new file mode 100644 index 000000000..4c634a1e0 --- /dev/null +++ b/test/fixtures/workspaces-shared-deps-virtual/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-shared-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-shared-deps/package.json b/test/fixtures/workspaces-shared-deps/package.json new file mode 100644 index 000000000..4c634a1e0 --- /dev/null +++ b/test/fixtures/workspaces-shared-deps/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-shared-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-shared-deps/packages/a/package.json b/test/fixtures/workspaces-shared-deps/packages/a/package.json new file mode 100644 index 000000000..7a2d0d4df --- /dev/null +++ b/test/fixtures/workspaces-shared-deps/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } +} diff --git a/test/fixtures/workspaces-shared-deps/packages/b/package.json b/test/fixtures/workspaces-shared-deps/packages/b/package.json new file mode 100644 index 000000000..4c9154387 --- /dev/null +++ b/test/fixtures/workspaces-shared-deps/packages/b/package.json @@ -0,0 +1,7 @@ +{ + "name": "b", + "version": "1.0.0", + "dependencies": { + "abbrev": "^1.1.1" + } +} diff --git a/test/fixtures/workspaces-shared-deps/packages/c/package.json b/test/fixtures/workspaces-shared-deps/packages/c/package.json new file mode 100644 index 000000000..7f017b6a5 --- /dev/null +++ b/test/fixtures/workspaces-shared-deps/packages/c/package.json @@ -0,0 +1,7 @@ +{ + "name": "c", + "version": "1.0.0", + "dependencies": { + "uuid": "=3.3.3" + } +} diff --git a/test/fixtures/workspaces-simple-virtual/a/package.json b/test/fixtures/workspaces-simple-virtual/a/package.json new file mode 100644 index 000000000..0dd22e08b --- /dev/null +++ b/test/fixtures/workspaces-simple-virtual/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "b": "^1.0.0" + } +} diff --git a/test/fixtures/workspaces-simple-virtual/b/package.json b/test/fixtures/workspaces-simple-virtual/b/package.json new file mode 100644 index 000000000..c2d84cc12 --- /dev/null +++ b/test/fixtures/workspaces-simple-virtual/b/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-simple-virtual/package-lock.json b/test/fixtures/workspaces-simple-virtual/package-lock.json new file mode 100644 index 000000000..dc8021e80 --- /dev/null +++ b/test/fixtures/workspaces-simple-virtual/package-lock.json @@ -0,0 +1,43 @@ +{ + "name": "workspace-simple", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspace-simple", + "workspaces": { + "packages": [ + "a", + "b" + ] + } + }, + "a": { + "name": "a", + "version": "1.0.0", + "dependencies": { + "b": "^1.0.0" + } + }, + "b": { + "name": "b", + "version": "1.0.0" + }, + "node_modules/a": { + "resolved": "a", + "link": true + }, + "node_modules/b": { + "resolved": "b", + "link": true + } + }, + "dependencies": { + "a": { + "version": "file:a" + }, + "b": { + "version": "file:b" + } + } +} diff --git a/test/fixtures/workspaces-simple-virtual/package.json b/test/fixtures/workspaces-simple-virtual/package.json new file mode 100644 index 000000000..6fb34c3f2 --- /dev/null +++ b/test/fixtures/workspaces-simple-virtual/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspace-simple", + "workspaces": [ + "a", + "b" + ] +} diff --git a/test/fixtures/workspaces-simple/a/package.json b/test/fixtures/workspaces-simple/a/package.json new file mode 100644 index 000000000..0dd22e08b --- /dev/null +++ b/test/fixtures/workspaces-simple/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "b": "^1.0.0" + } +} diff --git a/test/fixtures/workspaces-simple/b/package.json b/test/fixtures/workspaces-simple/b/package.json new file mode 100644 index 000000000..c2d84cc12 --- /dev/null +++ b/test/fixtures/workspaces-simple/b/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-simple/package.json b/test/fixtures/workspaces-simple/package.json new file mode 100644 index 000000000..6fb34c3f2 --- /dev/null +++ b/test/fixtures/workspaces-simple/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspace-simple", + "workspaces": [ + "a", + "b" + ] +} diff --git a/test/fixtures/workspaces-top-level-link-virtual/package-lock.json b/test/fixtures/workspaces-top-level-link-virtual/package-lock.json new file mode 100644 index 000000000..1114c807c --- /dev/null +++ b/test/fixtures/workspaces-top-level-link-virtual/package-lock.json @@ -0,0 +1,33 @@ +{ + "name": "workspaces-top-level-link", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspaces-top-level-link", + "version": "1.0.0", + "dependencies": { + "a": "^1.0.0" + }, + "workspaces": { + "packages": [ + "packages/*" + ] + } + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "packages/a": { + "name": "a", + "version": "1.0.0" + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + } + } +} diff --git a/test/fixtures/workspaces-top-level-link-virtual/package.json b/test/fixtures/workspaces-top-level-link-virtual/package.json new file mode 100644 index 000000000..2d2564945 --- /dev/null +++ b/test/fixtures/workspaces-top-level-link-virtual/package.json @@ -0,0 +1,10 @@ +{ + "name": "workspaces-top-level-link", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "a": "^1.0.0" + } +} diff --git a/test/fixtures/workspaces-top-level-link/package.json b/test/fixtures/workspaces-top-level-link/package.json new file mode 100644 index 000000000..aaa2088e4 --- /dev/null +++ b/test/fixtures/workspaces-top-level-link/package.json @@ -0,0 +1,11 @@ +{ + "name": "workspaces-top-level-link", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "a": "^1.0.0" + } +} + diff --git a/test/fixtures/workspaces-top-level-link/packages/a/package.json b/test/fixtures/workspaces-top-level-link/packages/a/package.json new file mode 100644 index 000000000..8fe98232f --- /dev/null +++ b/test/fixtures/workspaces-top-level-link/packages/a/package.json @@ -0,0 +1,5 @@ +{ + "name": "a", + "version": "1.0.0" +} + diff --git a/test/fixtures/workspaces-transitive-deps-virtual/package-lock.json b/test/fixtures/workspaces-transitive-deps-virtual/package-lock.json new file mode 100644 index 000000000..8e939d83e --- /dev/null +++ b/test/fixtures/workspaces-transitive-deps-virtual/package-lock.json @@ -0,0 +1,63 @@ +{ + "name": "workspaces-transitive-deps", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspaces-transitive-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "node_modules/once": { + "name": "once", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/wrappy": { + "name": "wrappy", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "packages/a": { + "name": "a", + "version": "1.0.0", + "devDependencies": { + "once": "^1.4.0" + } + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/test/fixtures/workspaces-transitive-deps-virtual/package.json b/test/fixtures/workspaces-transitive-deps-virtual/package.json new file mode 100644 index 000000000..91c627055 --- /dev/null +++ b/test/fixtures/workspaces-transitive-deps-virtual/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-transitive-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-transitive-deps/package.json b/test/fixtures/workspaces-transitive-deps/package.json new file mode 100644 index 000000000..91c627055 --- /dev/null +++ b/test/fixtures/workspaces-transitive-deps/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-transitive-deps", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-transitive-deps/packages/a/package.json b/test/fixtures/workspaces-transitive-deps/packages/a/package.json new file mode 100644 index 000000000..b1d8baa8c --- /dev/null +++ b/test/fixtures/workspaces-transitive-deps/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "devDependencies": { + "once": "^1.4.0" + } +} diff --git a/test/fixtures/workspaces-version-unsatisfied-virtual/package-lock.json b/test/fixtures/workspaces-version-unsatisfied-virtual/package-lock.json new file mode 100644 index 000000000..eeca401bd --- /dev/null +++ b/test/fixtures/workspaces-version-unsatisfied-virtual/package-lock.json @@ -0,0 +1,59 @@ +{ + "name": "workspaces-version-unsatisfied", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "workspaces-version-unsatisfied", + "version": "1.0.0", + "workspaces": { + "packages": [ + "packages/*" + ] + } + }, + "node_modules/a": { + "resolved": "packages/a", + "link": true + }, + "node_modules/abbrev": { + "resolved": "packages/abbrev", + "link": true + }, + "packages/a": { + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "=1.1.1" + } + }, + "packages/a/node_modules/abbrev": { + "name": "abbrev", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "packages/abbrev": { + "name": "abbrev", + "version": "2.0.0" + } + }, + "dependencies": { + "a": { + "version": "file:packages/a" + }, + "abbrev": { + "version": "file:packages/abbrev" + }, + "packages/a": { + "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/workspaces-version-unsatisfied-virtual/package.json b/test/fixtures/workspaces-version-unsatisfied-virtual/package.json new file mode 100644 index 000000000..6622e0690 --- /dev/null +++ b/test/fixtures/workspaces-version-unsatisfied-virtual/package.json @@ -0,0 +1,7 @@ +{ + "name": "workspaces-version-unsatisfied", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} diff --git a/test/fixtures/workspaces-version-unsatisfied/package.json b/test/fixtures/workspaces-version-unsatisfied/package.json new file mode 100644 index 000000000..48a2cffa1 --- /dev/null +++ b/test/fixtures/workspaces-version-unsatisfied/package.json @@ -0,0 +1,8 @@ +{ + "name": "workspaces-version-unsatisfied", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ] +} + diff --git a/test/fixtures/workspaces-version-unsatisfied/packages/a/package.json b/test/fixtures/workspaces-version-unsatisfied/packages/a/package.json new file mode 100644 index 000000000..925ed61e5 --- /dev/null +++ b/test/fixtures/workspaces-version-unsatisfied/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "abbrev": "=1.1.1" + } +} diff --git a/test/fixtures/workspaces-version-unsatisfied/packages/abbrev/package.json b/test/fixtures/workspaces-version-unsatisfied/packages/abbrev/package.json new file mode 100644 index 000000000..36b0d44ae --- /dev/null +++ b/test/fixtures/workspaces-version-unsatisfied/packages/abbrev/package.json @@ -0,0 +1,6 @@ +{ + "name": "abbrev", + "version": "2.0.0", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter " +} diff --git a/test/fixtures/workspaces-with-files-spec/d/package.json b/test/fixtures/workspaces-with-files-spec/d/package.json new file mode 100644 index 000000000..391cb7e1e --- /dev/null +++ b/test/fixtures/workspaces-with-files-spec/d/package.json @@ -0,0 +1,7 @@ +{ + "name": "d", + "version": "1.0.0", + "dependencies": { + "b": "^1.0.0" + } +} diff --git a/test/fixtures/workspaces-with-files-spec/package.json b/test/fixtures/workspaces-with-files-spec/package.json new file mode 100644 index 000000000..55838a6c9 --- /dev/null +++ b/test/fixtures/workspaces-with-files-spec/package.json @@ -0,0 +1,11 @@ +{ + "name": "workspaces-with-files-spec", + "workspaces": [ + "packages/*", + "!packages/c" + ], + "dependencies": { + "c": "file:packages/c", + "d": "file:d" + } +} diff --git a/test/fixtures/workspaces-with-files-spec/packages/a/package.json b/test/fixtures/workspaces-with-files-spec/packages/a/package.json new file mode 100644 index 000000000..e3dcbda8f --- /dev/null +++ b/test/fixtures/workspaces-with-files-spec/packages/a/package.json @@ -0,0 +1,7 @@ +{ + "name": "a", + "version": "1.0.0", + "dependencies": { + "d": "^1.0.0" + } +} diff --git a/test/fixtures/workspaces-with-files-spec/packages/b/package.json b/test/fixtures/workspaces-with-files-spec/packages/b/package.json new file mode 100644 index 000000000..c2d84cc12 --- /dev/null +++ b/test/fixtures/workspaces-with-files-spec/packages/b/package.json @@ -0,0 +1,4 @@ +{ + "name": "b", + "version": "1.0.0" +} diff --git a/test/fixtures/workspaces-with-files-spec/packages/c/package.json b/test/fixtures/workspaces-with-files-spec/packages/c/package.json new file mode 100644 index 000000000..abd338493 --- /dev/null +++ b/test/fixtures/workspaces-with-files-spec/packages/c/package.json @@ -0,0 +1,4 @@ +{ + "name": "c", + "version": "1.0.0" +} diff --git a/test/node.js b/test/node.js index 389e6e3c4..d824c5f67 100644 --- a/test/node.js +++ b/test/node.js @@ -1134,6 +1134,7 @@ t.test('has install script', t => { t.end() }) + t.test('legacy peer dependencies', t => { const root = new Node({ pkg: { @@ -1162,3 +1163,75 @@ t.test('legacy peer dependencies', t => { t.equal(root.edgesOut.size, 0, 'should have no edges out') t.end() }) + +t.test('set workspaces', t => { + const root = new Node({ + pkg: { name: 'workspaces_root' }, + path: '/home/user/projects/workspaces_root', + realpath: '/home/user/projects/workspaces_root', + }) + + root.workspaces = new Map([ + ['foo', '/home/user/projects/workspaces_root/foo'], + ['bar', '/home/user/projects/workspaces_root/bar'], + ]) + + t.matchSnapshot(root, 'should setup edges out for each workspace') + t.end() +}) + +t.test('get workspaces', t => { + const root = new Node({ + pkg: { name: 'workspaces_root' }, + path: '/home/user/projects/workspaces_root', + realpath: '/home/user/projects/workspaces_root', + }) + + t.equal(root.workspaces, null, 'should default to null when no workspaces defined') + + const ws = new Map() + root.workspaces = ws + + t.equal(root.workspaces, ws, 'should match set value') + t.end() +}) + +t.test('replace workspaces', t => { + const root = new Node({ + pkg: { name: 'workspaces_root' }, + path: '/home/user/projects/workspaces_root', + realpath: '/home/user/projects/workspaces_root', + }) + + root.workspaces = new Map([ + ['foo', '/home/user/projects/workspaces_root/foo'], + ['bar', '/home/user/projects/workspaces_root/bar'], + ]) + + const ws = new Map() + root.workspaces = ws + + t.equal(root.workspaces, ws, 'should remove previously set workspaces') + t.end() +}) + +t.test('replace workspaces keeping existing edges out', t => { + const root = new Node({ + pkg: { name: 'workspaces_root' }, + path: '/home/user/projects/workspaces_root', + realpath: '/home/user/projects/workspaces_root', + }) + + root.workspaces = new Map([ + ['foo', '/home/user/projects/workspaces_root/foo'], + ]) + + const ws = new Map([ + ['foo', '/home/user/projects/workspaces_root/foo'], + ['bar', '/home/user/projects/workspaces_root/bar'], + ]) + root.workspaces = ws + + t.equal(root.workspaces, ws, 'should keep existing edges out') + t.end() +})