Skip to content

Commit ec57f5f

Browse files
committed
chore: fix dependencies script for circular workspace deps
1 parent ccd8420 commit ec57f5f

File tree

3 files changed

+41
-14
lines changed

3 files changed

+41
-14
lines changed

DEPENDENCIES.json

+4-6
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,10 @@
22
[
33
"npm"
44
],
5-
[
6-
"@npmcli/smoke-tests",
7-
"libnpmaccess",
8-
"libnpmexec",
9-
"libnpmpublish"
10-
],
115
[
126
"@npmcli/mock-registry",
137
"libnpmdiff",
8+
"libnpmexec",
149
"libnpmfund",
1510
"libnpmpack"
1611
],
@@ -28,7 +23,9 @@
2823
[
2924
"@npmcli/map-workspaces",
3025
"@npmcli/run-script",
26+
"libnpmaccess",
3127
"libnpmorg",
28+
"libnpmpublish",
3229
"libnpmsearch",
3330
"libnpmteam",
3431
"init-package-json",
@@ -50,6 +47,7 @@
5047
],
5148
[
5249
"@npmcli/docs",
50+
"@npmcli/smoke-tests",
5351
"@npmcli/fs",
5452
"npm-bundled",
5553
"npm-install-checks",

DEPENDENCIES.md

+5-4
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ graph LR;
166166
npmcli-arborist-->npmcli-installed-package-contents["@npmcli/installed-package-contents"];
167167
npmcli-arborist-->npmcli-map-workspaces["@npmcli/map-workspaces"];
168168
npmcli-arborist-->npmcli-metavuln-calculator["@npmcli/metavuln-calculator"];
169+
npmcli-arborist-->npmcli-mock-registry["@npmcli/mock-registry"];
169170
npmcli-arborist-->npmcli-name-from-folder["@npmcli/name-from-folder"];
170171
npmcli-arborist-->npmcli-node-gyp["@npmcli/node-gyp"];
171172
npmcli-arborist-->npmcli-package-json["@npmcli/package-json"];
@@ -578,6 +579,7 @@ graph LR;
578579
npmcli-arborist-->npmcli-installed-package-contents["@npmcli/installed-package-contents"];
579580
npmcli-arborist-->npmcli-map-workspaces["@npmcli/map-workspaces"];
580581
npmcli-arborist-->npmcli-metavuln-calculator["@npmcli/metavuln-calculator"];
582+
npmcli-arborist-->npmcli-mock-registry["@npmcli/mock-registry"];
581583
npmcli-arborist-->npmcli-name-from-folder["@npmcli/name-from-folder"];
582584
npmcli-arborist-->npmcli-node-gyp["@npmcli/node-gyp"];
583585
npmcli-arborist-->npmcli-package-json["@npmcli/package-json"];
@@ -777,14 +779,13 @@ Each group depends on packages lower down the chain, nothing depends on
777779
packages higher up the chain.
778780

779781
- npm
780-
- @npmcli/smoke-tests, libnpmaccess, libnpmexec, libnpmpublish
781-
- @npmcli/mock-registry, libnpmdiff, libnpmfund, libnpmpack
782+
- @npmcli/mock-registry, libnpmdiff, libnpmexec, libnpmfund, libnpmpack
782783
- @npmcli/arborist
783784
- @npmcli/metavuln-calculator
784785
- pacote, @npmcli/config, libnpmversion
785-
- @npmcli/map-workspaces, @npmcli/run-script, libnpmorg, libnpmsearch, libnpmteam, init-package-json, npm-profile
786+
- @npmcli/map-workspaces, @npmcli/run-script, libnpmaccess, libnpmorg, libnpmpublish, libnpmsearch, libnpmteam, init-package-json, npm-profile
786787
- @npmcli/package-json, npm-registry-fetch
787788
- @npmcli/git, make-fetch-happen
788789
- @npmcli/installed-package-contents, npm-pick-manifest, cacache, promzard
789-
- @npmcli/docs, @npmcli/fs, npm-bundled, npm-install-checks, npm-package-arg, normalize-package-data, unique-filename, npm-packlist, bin-links, nopt, parse-conflict-json, read-package-json-fast, @npmcli/mock-globals, read
790+
- @npmcli/docs, @npmcli/smoke-tests, @npmcli/fs, npm-bundled, npm-install-checks, npm-package-arg, normalize-package-data, unique-filename, npm-packlist, bin-links, nopt, parse-conflict-json, read-package-json-fast, @npmcli/mock-globals, read
790791
- @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, @npmcli/promise-spawn, ini, hosted-git-info, proc-log, validate-npm-package-name, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/node-gyp, @npmcli/redact, @npmcli/agent, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, proggy, minify-registry-metadata, mute-stream, npm-audit-report, npm-user-validate

scripts/dependency-graph.js

+32-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,31 @@ const { run, CWD, pkg, fs, EOL } = require('./util.js')
1111
// npx -p @npmcli/stafftools gh repos --json | json -a name | sort > scripts/npm-cli-repos.txt
1212
const repos = readFileSync(join(CWD, 'scripts', 'npm-cli-repos.txt'), 'utf-8').trim().split(os.EOL)
1313

14+
// Packages with known circular dependencies. This is typically something with arborist as a dependency which is also in arborist's dev dependencies. Not a problem if they're workspaces so we ignore repeats
15+
const circular = new Set(['@npmcli/mock-registry'])
16+
17+
// TODO Set.intersection/difference was added in node 22.11.0, once we're above that line we can use the builtin
18+
// https://node.green/#ES2025-features-Set-methods-Set-prototype-intersection--
19+
function intersection (set1, set2) {
20+
const result = new Set()
21+
for (const item of set1) {
22+
if (set2.has(item)) {
23+
result.add(item)
24+
}
25+
}
26+
return result
27+
}
28+
29+
function difference (set1, set2) {
30+
const result = new Set()
31+
for (const item of set1) {
32+
if (!set2.has(item)) {
33+
result.add(item)
34+
}
35+
}
36+
return result
37+
}
38+
1439
// these have a different package name than the repo name, and are ours.
1540
const aliases = {
1641
semver: 'node-semver',
@@ -29,6 +54,7 @@ const namespaced = [
2954
'git',
3055
'installed-package-contents',
3156
'lint',
57+
'mock-registry',
3258
'map-workspaces',
3359
'metavuln-calculator',
3460
'move-file',
@@ -140,7 +166,11 @@ const walk = function (tree, onlyOurs) {
140166
log.silly(dep, '::', [...dependedBy[dep]].join(', '))
141167
log.silly('-'.repeat(80))
142168

143-
if (!dependedBy[dep].size) {
169+
// things that depend on us that are at the same level
170+
const both = intersection(allDeps, dependedBy[dep])
171+
// ... minus the known circular dependencies
172+
const neither = difference(both, circular)
173+
if (!dependedBy[dep].size || !neither.size) {
144174
level.push(dep)
145175
foundDeps.add(dep)
146176
}
@@ -177,9 +207,7 @@ const iterate = function (node, dependedBy, annotations, onlyOurs) {
177207
dependedBy[node.packageName] = new Set()
178208
}
179209
for (const [name, edge] of node.edgesOut) {
180-
if (
181-
(!onlyOurs || isOurs(name)) && !node.dev
182-
) {
210+
if ((!onlyOurs || isOurs(name)) && !node.dev) {
183211
if (!dependedBy[node.packageName].has(edge.name)) {
184212
dependedBy[node.packageName].add(edge.name)
185213
annotations.push(` ${stripName(node.packageName)}-->${escapeName(edge.name)};`)

0 commit comments

Comments
 (0)