diff --git a/src/build-dag.js b/src/build-dag.js index f8d8c2fc..ac8819a4 100644 --- a/src/build-dag.js +++ b/src/build-dag.js @@ -3,8 +3,14 @@ const dependencyTypes = require('./dependency-types'); const { collectPackages } = require('./build-dep-graph'); -function doesDependOnPackage(_package, packageName) { +function doesDependOnPackage(_package, packageName, { + shouldIncludeDevDependencies, +}) { for (let dependencyType of dependencyTypes) { + if (!shouldIncludeDevDependencies && dependencyType === 'devDependencies') { + return; + } + if (Object.keys(_package[dependencyType]).includes(packageName)) { return { dependencyType, @@ -19,6 +25,7 @@ function thirdPass({ group, branch, visitedNodes, + shouldIncludeDevDependencies, }) { let currentPackageName = group.node.packageName; @@ -32,7 +39,9 @@ function thirdPass({ let { dependencyType, dependencyRange, - } = doesDependOnPackage(_package, currentPackageName) || {}; + } = doesDependOnPackage(_package, currentPackageName, { + shouldIncludeDevDependencies, + }) || {}; if (dependencyType) { let parent = group; @@ -73,6 +82,7 @@ function thirdPass({ group: newGroup, branch: newBranch, visitedNodes, + shouldIncludeDevDependencies, }); } } @@ -113,7 +123,9 @@ function createPackageNode({ }; } -function buildDAG(workspaceMeta, packageName) { +function buildDAG(workspaceMeta, packageName, { + shouldIncludeDevDependencies = true, +} = {}) { let { newGroup, newBranch, @@ -130,6 +142,7 @@ function buildDAG(workspaceMeta, packageName) { group: newGroup, branch: newBranch, visitedNodes, + shouldIncludeDevDependencies, }); return newGroup; diff --git a/test/build-dag-test.js b/test/build-dag-test.js index a3c642bf..5e94bf4c 100644 --- a/test/build-dag-test.js +++ b/test/build-dag-test.js @@ -294,4 +294,82 @@ describe(buildDAG, function() { }, })); }); + + describe('devDependencies', function() { + beforeEach(function() { + fixturify.writeSync(tmpPath, { + 'packages': { + 'package-a': { + 'package.json': stringifyJson({ + 'name': '@scope/package-a', + 'version': '1.0.0', + 'devDependencies': { + '@scope/package-b': '1.0.0', + }, + }), + }, + 'package-b': { + 'package.json': stringifyJson({ + 'name': '@scope/package-b', + 'version': '1.0.0', + 'dependencies': { + '@scope/package-a': '1.0.0', + }, + }), + }, + }, + 'package.json': stringifyJson({ + 'private': true, + 'workspaces': [ + 'packages/*', + ], + }), + }); + }); + + it('can stop traversing devDependencies if enabled', async function() { + let dag = buildDAG(await buildDepGraph({ workspaceCwd: tmpPath }), '@scope/package-a', { shouldIncludeDevDependencies: false }); + + expect(dag).to.match(this.match({ + node: { + packageName: '@scope/package-a', + dependents: [ + this.match({ + dependencyType: 'dependencies', + node: { + packageName: '@scope/package-b', + dependents: [], + }, + }), + ], + }, + })); + }); + + it('doesn\'t stop traversing devDependencies by default', async function() { + let dag = buildDAG(await buildDepGraph({ workspaceCwd: tmpPath }), '@scope/package-a'); + + expect(dag).to.match(this.match({ + node: { + packageName: '@scope/package-a', + dependents: [ + this.match({ + dependencyType: 'dependencies', + node: { + packageName: '@scope/package-b', + dependents: [ + this.match({ + dependencyType: 'devDependencies', + node: { + packageName: '@scope/package-a', + }, + }), + ], + }, + }), + ], + }, + })); + }); + }); });