Skip to content

Commit

Permalink
Find dependents (not dependencies) + prevent recursion loop
Browse files Browse the repository at this point in the history
  • Loading branch information
webpro committed Oct 3, 2023
1 parent 1148cec commit 5ab5a87
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 30 deletions.
6 changes: 6 additions & 0 deletions fixtures/workspaces-circular/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@workspaces-circular/root",
"workspaces": [
"packages/*"
]
}
5 changes: 5 additions & 0 deletions fixtures/workspaces-circular/packages/lib-a/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import circularB from '@workspaces-circular/lib-b';
import circularC from '@workspaces-circular/lib-c';

circularB;
circularC;
8 changes: 8 additions & 0 deletions fixtures/workspaces-circular/packages/lib-a/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@workspaces-circular/lib-a",
"version": "1.0.0",
"dependencies": {
"@workspaces-circular/lib-b": "1.0.0",
"@workspaces-circular/lib-c": "1.0.0"
}
}
1 change: 1 addition & 0 deletions fixtures/workspaces-circular/packages/lib-b/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 1;
5 changes: 5 additions & 0 deletions fixtures/workspaces-circular/packages/lib-b/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@workspaces-circular/lib-b",
"version": "1.0.0",
"dependencies": {}
}
5 changes: 5 additions & 0 deletions fixtures/workspaces-circular/packages/lib-c/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import circularA from '@workspaces-circular/lib-a';

circularA;

export default 1;
7 changes: 7 additions & 0 deletions fixtures/workspaces-circular/packages/lib-c/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@workspaces-circular/lib-c",
"version": "1.0.0",
"dependencies": {
"@workspaces-circular/lib-a": "1.0.0"
}
}
63 changes: 33 additions & 30 deletions src/ConfigurationChief.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,40 +333,43 @@ export class ConfigurationChief {
};

const workspaceNames = workspaceArg
? [
...this.availableWorkspaceNames.reduce(getAncestors(workspaceArg), []),
...this.availableWorkspaceNames.filter(name => name === workspaceArg),
]
? [...this.availableWorkspaceNames.reduce(getAncestors(workspaceArg), []), workspaceArg]
: this.availableWorkspaceNames;

const graph = this.workspacesGraph;

function getDeps(dir: string): string[] {
const node = graph?.graph[dir];
return [dir, ...(node?.dependencies ?? []), ...(node?.dependencies.flatMap(getDeps) ?? [])];
const graph = this.workspacesGraph?.graph;
const ws = new Set<string>();

if (graph && workspaceArg) {
const seen = new Set<string>();
const workspaceDirsWithDependants = new Set(workspaceNames.map(name => join(this.cwd, name)));
const addDependents = (dir: string) => {
seen.add(dir);
const deps = graph[dir]?.dependencies ?? [];
if (deps.length > 0 && Array.from(workspaceDirsWithDependants).some(dir => deps.includes(dir))) {
workspaceDirsWithDependants.add(dir);
deps.filter(dir => !seen.has(dir)).forEach(addDependents);
}
};
this.availableWorkspaceNames.map(name => join(this.cwd, name)).forEach(addDependents);
workspaceDirsWithDependants.forEach(dir => ws.add(relative(this.cwd, dir) || ROOT_WORKSPACE_NAME));
} else {
workspaceNames.forEach(name => ws.add(name));
}

const workspaceNamesWithDependencies = workspaceArg
? compact(
workspaceNames
.map(name => join(this.cwd, name))
.flatMap(getDeps)
.map(dir => relative(this.cwd, dir))
)
: workspaceNames;

return workspaceNamesWithDependencies.sort(byPathDepth).map((name): Workspace => {
const dir = join(this.cwd, name);
return {
name,
pkgName: this.manifestWorkspaces.get(name) ?? this.manifest?.name ?? `NOT_FOUND_${name}`,
dir,
config: this.getConfigForWorkspace(name),
ancestors: this.availableWorkspaceNames.reduce(getAncestors(name), []),
manifestPath: join(dir, 'package.json'),
manifest: this.availableWorkspaceManifests?.find(item => item.dir === dir)?.manifest ?? {},
};
});
return Array.from(ws)
.sort(byPathDepth)
.map((name): Workspace => {
const dir = join(this.cwd, name);
return {
name,
pkgName: this.manifestWorkspaces.get(name) ?? this.manifest?.name ?? `NOT_FOUND_${name}`,
dir,
config: this.getConfigForWorkspace(name),
ancestors: this.availableWorkspaceNames.reduce(getAncestors(name), []),
manifestPath: join(dir, 'package.json'),
manifest: this.availableWorkspaceManifests?.find(item => item.dir === dir)?.manifest ?? {},
};
});
}

public getWorkspaces() {
Expand Down
21 changes: 21 additions & 0 deletions tests/workspaces-circular.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { main } from '../src/index.js';
import { resolve } from '../src/util/path.js';
import baseArguments from './helpers/baseArguments.js';
import baseCounters from './helpers/baseCounters.js';

const cwd = resolve('fixtures/workspaces-circular');

test('Find unused files, dependencies and exports in workspaces (circular)', async () => {
const { counters } = await main({
...baseArguments,
cwd,
});

assert.deepEqual(counters, {
...baseCounters,
processed: 3,
total: 3,
});
});

0 comments on commit 5ab5a87

Please sign in to comment.