Skip to content

Commit dde4309

Browse files
authored
fix: always use package key-value refs when reading from dependency list instead of required package name (#9583)
1 parent 3a3f439 commit dde4309

7 files changed

Lines changed: 7580 additions & 109 deletions

File tree

.changeset/thick-cases-refuse.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"app-builder-lib": patch
3+
---
4+
5+
fix: use package key when reading from dependency list instead of package `from` to not mislabel package-version strings

packages/app-builder-lib/src/node-module-collector/nodeModulesCollector.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,10 @@ export abstract class NodeModulesCollector<ProdDepType extends Dependency<ProdDe
186186
return `${pkg.name}::${pkg.version}::${rel ?? "."}`
187187
}
188188

189-
protected packageVersionString(pkg: Pick<ProdDepType, "name" | "version">): string {
190-
return `${pkg.name}@${pkg.version}`
189+
// We use the key (alias name) instead of value.name for npm aliased packages
190+
// e.g., { "foo": { name: "@scope/bar", ... } } should be stored as "foo@version"
191+
protected normalizePackageVersion(key: string, pkg: ProdDepType) {
192+
return { id: `${key}@${pkg.version}`, pkgOverride: { ...pkg, name: key } }
191193
}
192194

193195
/**

packages/app-builder-lib/src/node-module-collector/npmNodeModulesCollector.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,22 @@ export class NpmNodeModulesCollector extends NodeModulesCollector<NpmDependency,
1414

1515
protected async collectAllDependencies(tree: NpmDependency) {
1616
for (const [key, value] of Object.entries(tree.dependencies || {})) {
17+
const { id: childDependencyId, pkgOverride } = this.normalizePackageVersion(key, value)
18+
19+
// Only skip if this exact version is already collected AND it's a duplicate reference
20+
// We need to collect nested versions even if a different version exists at top level
1721
if (this.isDuplicatedNpmDependency(value)) {
22+
// This is a reference to a package already defined elsewhere in the tree
23+
// Still add it to allDependencies if we haven't seen this exact version yet
24+
if (!this.allDependencies.has(childDependencyId)) {
25+
this.allDependencies.set(childDependencyId, pkgOverride)
26+
}
1827
continue
1928
}
20-
// Use the key (alias name) instead of value.name for npm aliased packages
21-
// e.g., { "foo": { name: "@scope/bar", ... } } should be stored as "foo@version"
22-
// This ensures aliased packages are copied to the correct location in node_modules
23-
const normalizedDep: NpmDependency = key !== value.name ? { ...value, name: key } : value
24-
this.allDependencies.set(this.packageVersionString(normalizedDep), normalizedDep)
25-
await this.collectAllDependencies(value)
29+
30+
// Always store this dependency and recurse into its children
31+
this.allDependencies.set(childDependencyId, pkgOverride)
32+
await this.collectAllDependencies(pkgOverride)
2633
}
2734
}
2835

@@ -51,8 +58,8 @@ export class NpmNodeModulesCollector extends NodeModulesCollector<NpmDependency,
5158
if (Object.keys(dependency).length === 0) {
5259
continue
5360
}
54-
const childDependencyId = this.packageVersionString({ name: packageName, version: dependency.version })
55-
await this.extractProductionDependencyGraph(dependency, childDependencyId)
61+
const { id: childDependencyId, pkgOverride } = this.normalizePackageVersion(packageName, dependency)
62+
await this.extractProductionDependencyGraph(pkgOverride, childDependencyId)
5663
collectedDependencies.push(childDependencyId)
5764
}
5865
}

packages/app-builder-lib/src/node-module-collector/pnpmNodeModulesCollector.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export class PnpmNodeModulesCollector extends NodeModulesCollector<PnpmDependenc
4141
return undefined
4242
}
4343
}
44-
const childDependencyId = this.packageVersionString(dependency)
45-
await this.extractProductionDependencyGraph(dependency, childDependencyId)
44+
const { id: childDependencyId, pkgOverride } = this.normalizePackageVersion(packageName, dependency)
45+
await this.extractProductionDependencyGraph(pkgOverride, childDependencyId)
4646
return childDependencyId
4747
})
4848

@@ -72,11 +72,6 @@ export class PnpmNodeModulesCollector extends NodeModulesCollector<PnpmDependenc
7272
}
7373
}
7474

75-
protected packageVersionString(pkg: PnpmDependency): string {
76-
// we use 'from' field because 'name' may be different in case of aliases
77-
return `${pkg.from}@${pkg.version}`
78-
}
79-
8075
protected parseDependenciesTree(jsonBlob: string): PnpmDependency {
8176
// pnpm returns an array of dependency trees
8277
const dependencyTree: PnpmDependency[] = this.extractJsonFromPollutedOutput<PnpmDependency[]>(jsonBlob)

packages/app-builder-lib/src/node-module-collector/traversalNodeModulesCollector.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ export class TraversalNodeModulesCollector extends NodeModulesCollector<Traverse
2121
}
2222

2323
protected async collectAllDependencies(tree: TraversedDependency, appPackageName: string) {
24-
for (const [, value] of Object.entries({ ...tree.dependencies, ...tree.optionalDependencies })) {
25-
this.allDependencies.set(this.packageVersionString(value), value)
24+
for (const [packageKey, value] of Object.entries({ ...tree.dependencies, ...tree.optionalDependencies })) {
25+
const normalizedDep = this.normalizePackageVersion(packageKey, value)
26+
this.allDependencies.set(normalizedDep.id, normalizedDep.pkgOverride)
2627
await this.collectAllDependencies(value, appPackageName)
2728
}
2829
}
@@ -39,8 +40,8 @@ export class TraversalNodeModulesCollector extends NodeModulesCollector<Traverse
3940
const collectedDependencies: string[] = []
4041
for (const packageName in prodDependencies) {
4142
const dependency = prodDependencies[packageName]
42-
const childDependencyId = this.packageVersionString(dependency)
43-
await this.extractProductionDependencyGraph(dependency, childDependencyId)
43+
const { id: childDependencyId, pkgOverride } = this.normalizePackageVersion(packageName, dependency)
44+
await this.extractProductionDependencyGraph(pkgOverride, childDependencyId)
4445
collectedDependencies.push(childDependencyId)
4546
}
4647
this.productionGraph[dependencyId] = { dependencies: collectedDependencies }

0 commit comments

Comments
 (0)