mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-28 02:53:15 -04:00
6
.changeset/dirty-flies-do.md
Normal file
6
.changeset/dirty-flies-do.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"@pnpm/resolve-dependencies": patch
|
||||||
|
"pnpm": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Decrease memory consumption [#8084](https://github.com/pnpm/pnpm/pull/8084).
|
||||||
@@ -53,7 +53,6 @@
|
|||||||
"graph-cycles": "1.2.1",
|
"graph-cycles": "1.2.1",
|
||||||
"is-inner-link": "^4.0.0",
|
"is-inner-link": "^4.0.0",
|
||||||
"is-subdir": "^1.2.0",
|
"is-subdir": "^1.2.0",
|
||||||
"mem": "^8.1.1",
|
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"p-defer": "^3.0.0",
|
"p-defer": "^3.0.0",
|
||||||
"path-exists": "^4.0.0",
|
"path-exists": "^4.0.0",
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ export async function resolveDependencies (
|
|||||||
dependenciesTree,
|
dependenciesTree,
|
||||||
outdatedDependencies,
|
outdatedDependencies,
|
||||||
resolvedImporters,
|
resolvedImporters,
|
||||||
resolvedPackagesByDepPath,
|
resolvedPkgsById,
|
||||||
wantedToBeSkippedPackageIds,
|
wantedToBeSkippedPackageIds,
|
||||||
appliedPatches,
|
appliedPatches,
|
||||||
time,
|
time,
|
||||||
@@ -301,7 +301,7 @@ export async function resolveDependencies (
|
|||||||
|
|
||||||
// waiting till package requests are finished
|
// waiting till package requests are finished
|
||||||
async function waitTillAllFetchingsFinish (): Promise<void> {
|
async function waitTillAllFetchingsFinish (): Promise<void> {
|
||||||
await Promise.all(Object.values(resolvedPackagesByDepPath).map(async ({ fetching }) => {
|
await Promise.all(Object.values(resolvedPkgsById).map(async ({ fetching }) => {
|
||||||
try {
|
try {
|
||||||
await fetching?.()
|
await fetching?.()
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|||||||
5
pkg-manager/resolve-dependencies/src/nextNodeId.ts
Normal file
5
pkg-manager/resolve-dependencies/src/nextNodeId.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
let nodeIdCounter = 0
|
||||||
|
|
||||||
|
export function nextNodeId (): string {
|
||||||
|
return (++nodeIdCounter).toString()
|
||||||
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
export function nodeIdContains (nodeId: string, pkgId: string): boolean {
|
|
||||||
const pkgIds = splitNodeId(nodeId)
|
|
||||||
return pkgIds.includes(pkgId)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function nodeIdContainsSequence (nodeId: string, pkgId1: string, pkgId2: string): boolean {
|
|
||||||
const pkgIds = splitNodeId(nodeId)
|
|
||||||
pkgIds.pop()
|
|
||||||
const pkg1Index = pkgIds.indexOf(pkgId1)
|
|
||||||
if (pkg1Index === -1) return false
|
|
||||||
const pkg2Index = pkgIds.lastIndexOf(pkgId2)
|
|
||||||
return pkg1Index < pkg2Index
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createNodeId (parentNodeId: string, pkgId: string): string {
|
|
||||||
// using ">" as a separator because it will never be used inside a package ID
|
|
||||||
return `${parentNodeId}${pkgId}>`
|
|
||||||
}
|
|
||||||
|
|
||||||
export function splitNodeId (nodeId: string): string[] {
|
|
||||||
return nodeId.split('>').slice(1, -1)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export function parentIdsContainSequence (pkgIds: string[], pkgId1: string, pkgId2: string): boolean {
|
||||||
|
const pkg1Index = pkgIds.indexOf(pkgId1)
|
||||||
|
if (pkg1Index === -1 || pkg1Index === pkgIds.length - 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const pkg2Index = pkgIds.lastIndexOf(pkgId2)
|
||||||
|
return pkg1Index < pkg2Index && pkg2Index !== pkgIds.length - 1
|
||||||
|
}
|
||||||
@@ -50,12 +50,8 @@ import semver from 'semver'
|
|||||||
import { encodePkgId } from './encodePkgId'
|
import { encodePkgId } from './encodePkgId'
|
||||||
import { getNonDevWantedDependencies, type WantedDependency } from './getNonDevWantedDependencies'
|
import { getNonDevWantedDependencies, type WantedDependency } from './getNonDevWantedDependencies'
|
||||||
import { safeIntersect } from './mergePeers'
|
import { safeIntersect } from './mergePeers'
|
||||||
import {
|
import { nextNodeId } from './nextNodeId'
|
||||||
createNodeId,
|
import { parentIdsContainSequence } from './parentIdsContainSequence'
|
||||||
nodeIdContainsSequence,
|
|
||||||
nodeIdContains,
|
|
||||||
splitNodeId,
|
|
||||||
} from './nodeIdUtils'
|
|
||||||
import { hoistPeers, getHoistableOptionalPeers } from './hoistPeers'
|
import { hoistPeers, getHoistableOptionalPeers } from './hoistPeers'
|
||||||
import { wantedDepIsLocallyAvailable } from './wantedDepIsLocallyAvailable'
|
import { wantedDepIsLocallyAvailable } from './wantedDepIsLocallyAvailable'
|
||||||
import { replaceVersionInPref } from './replaceVersionInPref'
|
import { replaceVersionInPref } from './replaceVersionInPref'
|
||||||
@@ -64,13 +60,14 @@ const dependencyResolvedLogger = logger('_dependency_resolved')
|
|||||||
|
|
||||||
const omitDepsFields = omit(['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta'])
|
const omitDepsFields = omit(['dependencies', 'optionalDependencies', 'peerDependencies', 'peerDependenciesMeta'])
|
||||||
|
|
||||||
export function nodeIdToParents (
|
export function getPkgsInfoFromIds (
|
||||||
nodeId: string,
|
ids: string[],
|
||||||
resolvedPackagesByDepPath: ResolvedPackagesByDepPath
|
resolvedPkgsById: ResolvedPkgsById
|
||||||
): Array<{ id: string, name: string, version: string }> {
|
): Array<{ id: string, name: string, version: string }> {
|
||||||
return splitNodeId(nodeId).slice(1)
|
return ids
|
||||||
.map((depPath) => {
|
.slice(1)
|
||||||
const { id, name, version } = resolvedPackagesByDepPath[depPath]
|
.map((id) => {
|
||||||
|
const { name, version } = resolvedPkgsById[id]
|
||||||
return { id, name, version }
|
return { id, name, version }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -99,7 +96,7 @@ string,
|
|||||||
DependenciesTreeNode<T>
|
DependenciesTreeNode<T>
|
||||||
>
|
>
|
||||||
|
|
||||||
export type ResolvedPackagesByDepPath = Record<string, ResolvedPackage>
|
export type ResolvedPkgsById = Record<string, ResolvedPackage>
|
||||||
|
|
||||||
export interface LinkedDependency {
|
export interface LinkedDependency {
|
||||||
isLinkedDependency: true
|
isLinkedDependency: true
|
||||||
@@ -120,12 +117,13 @@ export interface PendingNode {
|
|||||||
resolvedPackage: ResolvedPackage
|
resolvedPackage: ResolvedPackage
|
||||||
depth: number
|
depth: number
|
||||||
installable: boolean
|
installable: boolean
|
||||||
|
parentIds: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChildrenByParentDepPath {
|
export interface ChildrenByParentId {
|
||||||
[depPath: string]: Array<{
|
[id: string]: Array<{
|
||||||
alias: string
|
alias: string
|
||||||
depPath: string
|
id: string
|
||||||
}>
|
}>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,9 +140,9 @@ export interface ResolutionContext {
|
|||||||
dryRun: boolean
|
dryRun: boolean
|
||||||
forceFullResolution: boolean
|
forceFullResolution: boolean
|
||||||
ignoreScripts?: boolean
|
ignoreScripts?: boolean
|
||||||
resolvedPackagesByDepPath: ResolvedPackagesByDepPath
|
resolvedPkgsById: ResolvedPkgsById
|
||||||
outdatedDependencies: { [pkgId: string]: string }
|
outdatedDependencies: { [pkgId: string]: string }
|
||||||
childrenByParentDepPath: ChildrenByParentDepPath
|
childrenByParentId: ChildrenByParentId
|
||||||
patchedDependencies?: Record<string, PatchFile>
|
patchedDependencies?: Record<string, PatchFile>
|
||||||
pendingNodes: PendingNode[]
|
pendingNodes: PendingNode[]
|
||||||
wantedLockfile: Lockfile
|
wantedLockfile: Lockfile
|
||||||
@@ -246,7 +244,7 @@ export interface ResolvedPackage {
|
|||||||
parentImporterIds: Set<string>
|
parentImporterIds: Set<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
type ParentPkg = Pick<PkgAddress, 'nodeId' | 'installable' | 'depPath' | 'rootDir' | 'optional'>
|
type ParentPkg = Pick<PkgAddress, 'nodeId' | 'installable' | 'rootDir' | 'optional' | 'pkgId'>
|
||||||
|
|
||||||
export type ParentPkgAliases = Record<string, PkgAddress | true>
|
export type ParentPkgAliases = Record<string, PkgAddress | true>
|
||||||
|
|
||||||
@@ -254,6 +252,7 @@ export type UpdateMatchingFunction = (pkgName: string) => boolean
|
|||||||
|
|
||||||
interface ResolvedDependenciesOptions {
|
interface ResolvedDependenciesOptions {
|
||||||
currentDepth: number
|
currentDepth: number
|
||||||
|
parentIds: string[]
|
||||||
parentPkg: ParentPkg
|
parentPkg: ParentPkg
|
||||||
parentPkgAliases: ParentPkgAliases
|
parentPkgAliases: ParentPkgAliases
|
||||||
// If the package has been updated, the dependencies
|
// If the package has been updated, the dependencies
|
||||||
@@ -377,12 +376,14 @@ interface PkgAddressesByImportersWithoutPeers extends PeersResolutionResult {
|
|||||||
pkgAddresses: Array<PkgAddress | LinkedDependency>
|
pkgAddresses: Array<PkgAddress | LinkedDependency>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ImporterToResolveOptions = Omit<ResolvedDependenciesOptions, 'parentPkgAliases' | 'publishedBy'>
|
||||||
|
|
||||||
export interface ImporterToResolve {
|
export interface ImporterToResolve {
|
||||||
updatePackageManifest: boolean
|
updatePackageManifest: boolean
|
||||||
preferredVersions: PreferredVersions
|
preferredVersions: PreferredVersions
|
||||||
parentPkgAliases: ParentPkgAliases
|
parentPkgAliases: ParentPkgAliases
|
||||||
wantedDependencies: Array<WantedDependency & { updateDepth?: number }>
|
wantedDependencies: Array<WantedDependency & { updateDepth?: number }>
|
||||||
options: Omit<ResolvedDependenciesOptions, 'parentPkgAliases' | 'publishedBy'>
|
options: ImporterToResolveOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResolveDependenciesOfImportersResult {
|
interface ResolveDependenciesOfImportersResult {
|
||||||
@@ -456,7 +457,7 @@ async function resolveDependenciesOfImporters (
|
|||||||
if (pkgAddress.updated) {
|
if (pkgAddress.updated) {
|
||||||
ctx.updatedSet.add(pkgAddress.alias)
|
ctx.updatedSet.add(pkgAddress.alias)
|
||||||
}
|
}
|
||||||
const resolvedPackage = ctx.resolvedPackagesByDepPath[pkgAddress.depPath]
|
const resolvedPackage = ctx.resolvedPkgsById[pkgAddress.pkgId]
|
||||||
if (!resolvedPackage) continue // This will happen only with linked dependencies
|
if (!resolvedPackage) continue // This will happen only with linked dependencies
|
||||||
if (!Object.prototype.hasOwnProperty.call(newPreferredVersions, resolvedPackage.name)) {
|
if (!Object.prototype.hasOwnProperty.call(newPreferredVersions, resolvedPackage.name)) {
|
||||||
newPreferredVersions[resolvedPackage.name] = { ...importer.preferredVersions[resolvedPackage.name] }
|
newPreferredVersions[resolvedPackage.name] = { ...importer.preferredVersions[resolvedPackage.name] }
|
||||||
@@ -586,7 +587,7 @@ export async function resolveDependencies (
|
|||||||
if (pkgAddress.updated) {
|
if (pkgAddress.updated) {
|
||||||
ctx.updatedSet.add(pkgAddress.alias)
|
ctx.updatedSet.add(pkgAddress.alias)
|
||||||
}
|
}
|
||||||
const resolvedPackage = ctx.resolvedPackagesByDepPath[pkgAddress.depPath]
|
const resolvedPackage = ctx.resolvedPkgsById[pkgAddress.pkgId]
|
||||||
if (!resolvedPackage) continue // This will happen only with linked dependencies
|
if (!resolvedPackage) continue // This will happen only with linked dependencies
|
||||||
if (!Object.prototype.hasOwnProperty.call(newPreferredVersions, resolvedPackage.name)) {
|
if (!Object.prototype.hasOwnProperty.call(newPreferredVersions, resolvedPackage.name)) {
|
||||||
newPreferredVersions[resolvedPackage.name] = { ...preferredVersions[resolvedPackage.name] }
|
newPreferredVersions[resolvedPackage.name] = { ...preferredVersions[resolvedPackage.name] }
|
||||||
@@ -741,6 +742,7 @@ async function resolveDependenciesOfDependency (
|
|||||||
updateMatching: options.updateMatching,
|
updateMatching: options.updateMatching,
|
||||||
supportedArchitectures: options.supportedArchitectures,
|
supportedArchitectures: options.supportedArchitectures,
|
||||||
updateToLatest: options.updateToLatest,
|
updateToLatest: options.updateToLatest,
|
||||||
|
parentIds: options.parentIds,
|
||||||
}
|
}
|
||||||
const resolveDependencyResult = await resolveDependency(extendedWantedDep.wantedDependency, ctx, resolveDependencyOpts)
|
const resolveDependencyResult = await resolveDependency(extendedWantedDep.wantedDependency, ctx, resolveDependencyOpts)
|
||||||
|
|
||||||
@@ -773,6 +775,7 @@ async function resolveDependenciesOfDependency (
|
|||||||
parentPkg: resolveDependencyResult,
|
parentPkg: resolveDependencyResult,
|
||||||
dependencyLockfile: extendedWantedDep.infoFromLockfile?.dependencyLockfile,
|
dependencyLockfile: extendedWantedDep.infoFromLockfile?.dependencyLockfile,
|
||||||
parentDepth: options.currentDepth,
|
parentDepth: options.currentDepth,
|
||||||
|
parentIds: [...options.parentIds, resolveDependencyResult.pkgId],
|
||||||
updateDepth,
|
updateDepth,
|
||||||
prefix: options.prefix,
|
prefix: options.prefix,
|
||||||
updateMatching: options.updateMatching,
|
updateMatching: options.updateMatching,
|
||||||
@@ -820,6 +823,7 @@ async function resolveChildren (
|
|||||||
ctx: ResolutionContext,
|
ctx: ResolutionContext,
|
||||||
{
|
{
|
||||||
parentPkg,
|
parentPkg,
|
||||||
|
parentIds,
|
||||||
dependencyLockfile,
|
dependencyLockfile,
|
||||||
parentDepth,
|
parentDepth,
|
||||||
updateDepth,
|
updateDepth,
|
||||||
@@ -828,6 +832,7 @@ async function resolveChildren (
|
|||||||
supportedArchitectures,
|
supportedArchitectures,
|
||||||
}: {
|
}: {
|
||||||
parentPkg: PkgAddress
|
parentPkg: PkgAddress
|
||||||
|
parentIds: string[]
|
||||||
dependencyLockfile: PackageSnapshot | undefined
|
dependencyLockfile: PackageSnapshot | undefined
|
||||||
parentDepth: number
|
parentDepth: number
|
||||||
updateDepth: number
|
updateDepth: number
|
||||||
@@ -881,11 +886,12 @@ async function resolveChildren (
|
|||||||
updateDepth,
|
updateDepth,
|
||||||
updateMatching,
|
updateMatching,
|
||||||
supportedArchitectures,
|
supportedArchitectures,
|
||||||
|
parentIds,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ctx.childrenByParentDepPath[parentPkg.depPath] = pkgAddresses.map((child) => ({
|
ctx.childrenByParentId[parentPkg.pkgId] = pkgAddresses.map((child) => ({
|
||||||
alias: child.alias,
|
alias: child.alias,
|
||||||
depPath: child.depPath,
|
id: child.pkgId,
|
||||||
}))
|
}))
|
||||||
ctx.dependenciesTree.set(parentPkg.nodeId, {
|
ctx.dependenciesTree.set(parentPkg.nodeId, {
|
||||||
children: pkgAddresses.reduce((chn, child) => {
|
children: pkgAddresses.reduce((chn, child) => {
|
||||||
@@ -894,7 +900,7 @@ async function resolveChildren (
|
|||||||
}, {} as Record<string, string>),
|
}, {} as Record<string, string>),
|
||||||
depth: parentDepth,
|
depth: parentDepth,
|
||||||
installable: parentPkg.installable,
|
installable: parentPkg.installable,
|
||||||
resolvedPackage: ctx.resolvedPackagesByDepPath[parentPkg.depPath],
|
resolvedPackage: ctx.resolvedPkgsById[parentPkg.pkgId],
|
||||||
})
|
})
|
||||||
return resolvingPeers
|
return resolvingPeers
|
||||||
}
|
}
|
||||||
@@ -1078,6 +1084,7 @@ interface ResolveDependencyOptions {
|
|||||||
dependencyLockfile?: PackageSnapshot
|
dependencyLockfile?: PackageSnapshot
|
||||||
}
|
}
|
||||||
parentPkg: ParentPkg
|
parentPkg: ParentPkg
|
||||||
|
parentIds: string[]
|
||||||
parentPkgAliases: ParentPkgAliases
|
parentPkgAliases: ParentPkgAliases
|
||||||
preferredVersions: PreferredVersions
|
preferredVersions: PreferredVersions
|
||||||
prefix: string
|
prefix: string
|
||||||
@@ -1166,7 +1173,7 @@ async function resolveDependency (
|
|||||||
supportedArchitectures: options.supportedArchitectures,
|
supportedArchitectures: options.supportedArchitectures,
|
||||||
onFetchError: (err: any) => { // eslint-disable-line
|
onFetchError: (err: any) => { // eslint-disable-line
|
||||||
err.prefix = options.prefix
|
err.prefix = options.prefix
|
||||||
err.pkgsStack = nodeIdToParents(options.parentPkg.nodeId, ctx.resolvedPackagesByDepPath)
|
err.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
updateToLatest: options.updateToLatest,
|
updateToLatest: options.updateToLatest,
|
||||||
@@ -1180,21 +1187,21 @@ async function resolveDependency (
|
|||||||
pref: wantedDependency.pref,
|
pref: wantedDependency.pref,
|
||||||
version: wantedDependency.alias ? wantedDependency.pref : undefined,
|
version: wantedDependency.alias ? wantedDependency.pref : undefined,
|
||||||
},
|
},
|
||||||
parents: nodeIdToParents(options.parentPkg.nodeId, ctx.resolvedPackagesByDepPath),
|
parents: getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById),
|
||||||
prefix: options.prefix,
|
prefix: options.prefix,
|
||||||
reason: 'resolution_failure',
|
reason: 'resolution_failure',
|
||||||
})
|
})
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
err.prefix = options.prefix
|
err.prefix = options.prefix
|
||||||
err.pkgsStack = nodeIdToParents(options.parentPkg.nodeId, ctx.resolvedPackagesByDepPath)
|
err.pkgsStack = getPkgsInfoFromIds(options.parentIds, ctx.resolvedPkgsById)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyResolvedLogger.debug({
|
dependencyResolvedLogger.debug({
|
||||||
resolution: pkgResponse.body.id,
|
resolution: pkgResponse.body.id,
|
||||||
wanted: {
|
wanted: {
|
||||||
dependentId: options.parentPkg.depPath,
|
dependentId: options.parentPkg.pkgId,
|
||||||
name: wantedDependency.alias,
|
name: wantedDependency.alias,
|
||||||
rawSpec: wantedDependency.pref,
|
rawSpec: wantedDependency.pref,
|
||||||
},
|
},
|
||||||
@@ -1289,11 +1296,11 @@ async function resolveDependency (
|
|||||||
// because zoo is a new parent package:
|
// because zoo is a new parent package:
|
||||||
// foo > bar > qar > zoo > qar
|
// foo > bar > qar > zoo > qar
|
||||||
if (
|
if (
|
||||||
nodeIdContainsSequence(
|
parentIdsContainSequence(
|
||||||
options.parentPkg.nodeId,
|
options.parentIds,
|
||||||
options.parentPkg.depPath,
|
options.parentPkg.pkgId,
|
||||||
depPath
|
pkgResponse.body.id
|
||||||
) || depPath === options.parentPkg.depPath
|
) || pkgResponse.body.id === options.parentPkg.pkgId
|
||||||
) {
|
) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -1342,14 +1349,12 @@ async function resolveDependency (
|
|||||||
}
|
}
|
||||||
// In case of leaf dependencies (dependencies that have no prod deps or peer deps),
|
// In case of leaf dependencies (dependencies that have no prod deps or peer deps),
|
||||||
// we only ever need to analyze one leaf dep in a graph, so the nodeId can be short and stateless.
|
// we only ever need to analyze one leaf dep in a graph, so the nodeId can be short and stateless.
|
||||||
const nodeId = pkgIsLeaf(pkg)
|
const nodeId = pkgIsLeaf(pkg) ? pkgResponse.body.id : nextNodeId()
|
||||||
? `>${depPath}>`
|
|
||||||
: createNodeId(options.parentPkg.nodeId, depPath)
|
|
||||||
|
|
||||||
const parentIsInstallable = options.parentPkg.installable === undefined || options.parentPkg.installable
|
const parentIsInstallable = options.parentPkg.installable === undefined || options.parentPkg.installable
|
||||||
const installable = parentIsInstallable && pkgResponse.body.isInstallable !== false
|
const installable = parentIsInstallable && pkgResponse.body.isInstallable !== false
|
||||||
const isNew = !ctx.resolvedPackagesByDepPath[depPath]
|
const isNew = !ctx.resolvedPkgsById[pkgResponse.body.id]
|
||||||
const parentImporterId = options.parentPkg.nodeId.substring(0, options.parentPkg.nodeId.indexOf('>', 1) + 1)
|
const parentImporterId = options.parentIds[0]
|
||||||
let resolveChildren = false
|
let resolveChildren = false
|
||||||
const currentIsOptional = wantedDependency.optional || options.parentPkg.optional
|
const currentIsOptional = wantedDependency.optional || options.parentPkg.optional
|
||||||
|
|
||||||
@@ -1379,7 +1384,7 @@ async function resolveDependency (
|
|||||||
|
|
||||||
// WARN: It is very important to keep this sync
|
// WARN: It is very important to keep this sync
|
||||||
// Otherwise, deprecation messages for the same package might get written several times
|
// Otherwise, deprecation messages for the same package might get written several times
|
||||||
ctx.resolvedPackagesByDepPath[depPath] = getResolvedPackage({
|
ctx.resolvedPkgsById[pkgResponse.body.id] = getResolvedPackage({
|
||||||
allowBuild: ctx.allowBuild,
|
allowBuild: ctx.allowBuild,
|
||||||
dependencyLockfile: currentPkg.dependencyLockfile,
|
dependencyLockfile: currentPkg.dependencyLockfile,
|
||||||
depPath,
|
depPath,
|
||||||
@@ -1394,17 +1399,17 @@ async function resolveDependency (
|
|||||||
optional: currentIsOptional,
|
optional: currentIsOptional,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
ctx.resolvedPackagesByDepPath[depPath].prod = ctx.resolvedPackagesByDepPath[depPath].prod || !wantedDependency.dev && !wantedDependency.optional
|
ctx.resolvedPkgsById[pkgResponse.body.id].prod = ctx.resolvedPkgsById[pkgResponse.body.id].prod || !wantedDependency.dev && !wantedDependency.optional
|
||||||
ctx.resolvedPackagesByDepPath[depPath].dev = ctx.resolvedPackagesByDepPath[depPath].dev || wantedDependency.dev
|
ctx.resolvedPkgsById[pkgResponse.body.id].dev = ctx.resolvedPkgsById[pkgResponse.body.id].dev || wantedDependency.dev
|
||||||
ctx.resolvedPackagesByDepPath[depPath].optional = ctx.resolvedPackagesByDepPath[depPath].optional && currentIsOptional
|
ctx.resolvedPkgsById[pkgResponse.body.id].optional = ctx.resolvedPkgsById[pkgResponse.body.id].optional && currentIsOptional
|
||||||
if (ctx.hoistPeers) {
|
if (ctx.hoistPeers) {
|
||||||
resolveChildren = !ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id].missingPeersOfChildren.resolved &&
|
resolveChildren = !ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id].missingPeersOfChildren.resolved &&
|
||||||
!ctx.resolvedPackagesByDepPath[depPath].parentImporterIds.has(parentImporterId)
|
!ctx.resolvedPkgsById[pkgResponse.body.id].parentImporterIds.has(parentImporterId)
|
||||||
ctx.resolvedPackagesByDepPath[depPath].parentImporterIds.add(parentImporterId)
|
ctx.resolvedPkgsById[pkgResponse.body.id].parentImporterIds.add(parentImporterId)
|
||||||
}
|
}
|
||||||
if (ctx.resolvedPackagesByDepPath[depPath].fetching == null && pkgResponse.fetching != null) {
|
if (ctx.resolvedPkgsById[pkgResponse.body.id].fetching == null && pkgResponse.fetching != null) {
|
||||||
ctx.resolvedPackagesByDepPath[depPath].fetching = pkgResponse.fetching
|
ctx.resolvedPkgsById[pkgResponse.body.id].fetching = pkgResponse.fetching
|
||||||
ctx.resolvedPackagesByDepPath[depPath].filesIndexFile = pkgResponse.filesIndexFile!
|
ctx.resolvedPkgsById[pkgResponse.body.id].filesIndexFile = pkgResponse.filesIndexFile!
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.dependenciesTree.has(nodeId)) {
|
if (ctx.dependenciesTree.has(nodeId)) {
|
||||||
@@ -1413,9 +1418,10 @@ async function resolveDependency (
|
|||||||
ctx.pendingNodes.push({
|
ctx.pendingNodes.push({
|
||||||
alias: wantedDependency.alias || pkg.name,
|
alias: wantedDependency.alias || pkg.name,
|
||||||
depth: options.currentDepth,
|
depth: options.currentDepth,
|
||||||
|
parentIds: options.parentIds,
|
||||||
installable,
|
installable,
|
||||||
nodeId,
|
nodeId,
|
||||||
resolvedPackage: ctx.resolvedPackagesByDepPath[depPath],
|
resolvedPackage: ctx.resolvedPkgsById[pkgResponse.body.id],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1424,9 +1430,9 @@ async function resolveDependency (
|
|||||||
? path.resolve(ctx.lockfileDir, (pkgResponse.body.resolution as DirectoryResolution).directory)
|
? path.resolve(ctx.lockfileDir, (pkgResponse.body.resolution as DirectoryResolution).directory)
|
||||||
: options.prefix
|
: options.prefix
|
||||||
let missingPeersOfChildren!: MissingPeersOfChildren | undefined
|
let missingPeersOfChildren!: MissingPeersOfChildren | undefined
|
||||||
if (ctx.hoistPeers && !nodeIdContains(options.parentPkg.nodeId, depPath)) {
|
if (ctx.hoistPeers && !options.parentIds.includes(pkgResponse.body.id)) {
|
||||||
if (ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id]) {
|
if (ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id]) {
|
||||||
if (!options.parentPkg.nodeId.startsWith(ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id].parentImporterId)) {
|
if (options.parentIds[0] !== ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id].parentImporterId) {
|
||||||
missingPeersOfChildren = ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id].missingPeersOfChildren
|
missingPeersOfChildren = ctx.missingPeersOfChildrenByPkgId[pkgResponse.body.id].missingPeersOfChildren
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1453,7 +1459,7 @@ async function resolveDependency (
|
|||||||
pkgId: pkgResponse.body.id,
|
pkgId: pkgResponse.body.id,
|
||||||
rootDir,
|
rootDir,
|
||||||
missingPeers: getMissingPeers(pkg),
|
missingPeers: getMissingPeers(pkg),
|
||||||
optional: ctx.resolvedPackagesByDepPath[depPath].optional,
|
optional: ctx.resolvedPkgsById[pkgResponse.body.id].optional,
|
||||||
|
|
||||||
// Next fields are actually only needed when isNew = true
|
// Next fields are actually only needed when isNew = true
|
||||||
installable,
|
installable,
|
||||||
|
|||||||
@@ -11,25 +11,23 @@ import {
|
|||||||
import partition from 'ramda/src/partition'
|
import partition from 'ramda/src/partition'
|
||||||
import zipObj from 'ramda/src/zipObj'
|
import zipObj from 'ramda/src/zipObj'
|
||||||
import { type WantedDependency } from './getNonDevWantedDependencies'
|
import { type WantedDependency } from './getNonDevWantedDependencies'
|
||||||
|
import { nextNodeId } from './nextNodeId'
|
||||||
|
import { parentIdsContainSequence } from './parentIdsContainSequence'
|
||||||
import {
|
import {
|
||||||
createNodeId,
|
type ChildrenByParentId,
|
||||||
nodeIdContainsSequence,
|
|
||||||
} from './nodeIdUtils'
|
|
||||||
import {
|
|
||||||
type ChildrenByParentDepPath,
|
|
||||||
type DependenciesTree,
|
type DependenciesTree,
|
||||||
type LinkedDependency,
|
type LinkedDependency,
|
||||||
type ImporterToResolve,
|
type ImporterToResolve,
|
||||||
|
type ImporterToResolveOptions,
|
||||||
type ParentPkgAliases,
|
type ParentPkgAliases,
|
||||||
type PendingNode,
|
type PendingNode,
|
||||||
type PkgAddress,
|
type PkgAddress,
|
||||||
resolveRootDependencies,
|
resolveRootDependencies,
|
||||||
type ResolvedPackage,
|
type ResolvedPackage,
|
||||||
type ResolvedPackagesByDepPath,
|
type ResolvedPkgsById,
|
||||||
type ResolutionContext,
|
type ResolutionContext,
|
||||||
} from './resolveDependencies'
|
} from './resolveDependencies'
|
||||||
|
|
||||||
export * from './nodeIdUtils'
|
|
||||||
export type { LinkedDependency, ResolvedPackage, DependenciesTree, DependenciesTreeNode } from './resolveDependencies'
|
export type { LinkedDependency, ResolvedPackage, DependenciesTree, DependenciesTreeNode } from './resolveDependencies'
|
||||||
|
|
||||||
export interface ResolvedImporters {
|
export interface ResolvedImporters {
|
||||||
@@ -113,7 +111,7 @@ export interface ResolveDependencyTreeResult {
|
|||||||
[pkgId: string]: string
|
[pkgId: string]: string
|
||||||
}
|
}
|
||||||
resolvedImporters: ResolvedImporters
|
resolvedImporters: ResolvedImporters
|
||||||
resolvedPackagesByDepPath: ResolvedPackagesByDepPath
|
resolvedPkgsById: ResolvedPkgsById
|
||||||
wantedToBeSkippedPackageIds: Set<string>
|
wantedToBeSkippedPackageIds: Set<string>
|
||||||
appliedPatches: Set<string>
|
appliedPatches: Set<string>
|
||||||
time?: Record<string, string>
|
time?: Record<string, string>
|
||||||
@@ -130,7 +128,7 @@ export async function resolveDependencyTree<T> (
|
|||||||
autoInstallPeersFromHighestMatch: opts.autoInstallPeersFromHighestMatch === true,
|
autoInstallPeersFromHighestMatch: opts.autoInstallPeersFromHighestMatch === true,
|
||||||
allowBuild: opts.allowBuild,
|
allowBuild: opts.allowBuild,
|
||||||
allowedDeprecatedVersions: opts.allowedDeprecatedVersions,
|
allowedDeprecatedVersions: opts.allowedDeprecatedVersions,
|
||||||
childrenByParentDepPath: {} as ChildrenByParentDepPath,
|
childrenByParentId: {} as ChildrenByParentId,
|
||||||
currentLockfile: opts.currentLockfile,
|
currentLockfile: opts.currentLockfile,
|
||||||
defaultTag: opts.tag,
|
defaultTag: opts.tag,
|
||||||
dependenciesTree: new Map() as DependenciesTree<ResolvedPackage>,
|
dependenciesTree: new Map() as DependenciesTree<ResolvedPackage>,
|
||||||
@@ -149,7 +147,7 @@ export async function resolveDependencyTree<T> (
|
|||||||
preferWorkspacePackages: opts.preferWorkspacePackages,
|
preferWorkspacePackages: opts.preferWorkspacePackages,
|
||||||
readPackageHook: opts.hooks.readPackage,
|
readPackageHook: opts.hooks.readPackage,
|
||||||
registries: opts.registries,
|
registries: opts.registries,
|
||||||
resolvedPackagesByDepPath: {} as ResolvedPackagesByDepPath,
|
resolvedPkgsById: {} as ResolvedPkgsById,
|
||||||
resolutionMode: opts.resolutionMode,
|
resolutionMode: opts.resolutionMode,
|
||||||
skipped: wantedToBeSkippedPackageIds,
|
skipped: wantedToBeSkippedPackageIds,
|
||||||
storeController: opts.storeController,
|
storeController: opts.storeController,
|
||||||
@@ -170,15 +168,16 @@ export async function resolveDependencyTree<T> (
|
|||||||
// We only need to proceed resolving every dependency
|
// We only need to proceed resolving every dependency
|
||||||
// if the newly added dependency has peer dependencies.
|
// if the newly added dependency has peer dependencies.
|
||||||
const proceed = importer.id === '.' || importer.hasRemovedDependencies === true || importer.wantedDependencies.some((wantedDep: any) => wantedDep.isNew) // eslint-disable-line @typescript-eslint/no-explicit-any
|
const proceed = importer.id === '.' || importer.hasRemovedDependencies === true || importer.wantedDependencies.some((wantedDep: any) => wantedDep.isNew) // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
const resolveOpts = {
|
const resolveOpts: ImporterToResolveOptions = {
|
||||||
currentDepth: 0,
|
currentDepth: 0,
|
||||||
parentPkg: {
|
parentPkg: {
|
||||||
installable: true,
|
installable: true,
|
||||||
nodeId: `>${importer.id}>`,
|
nodeId: `>${importer.id}>`,
|
||||||
optional: false,
|
optional: false,
|
||||||
depPath: importer.id,
|
pkgId: importer.id,
|
||||||
rootDir: importer.rootDir,
|
rootDir: importer.rootDir,
|
||||||
},
|
},
|
||||||
|
parentIds: [importer.id],
|
||||||
proceed,
|
proceed,
|
||||||
resolvedDependencies: {
|
resolvedDependencies: {
|
||||||
...projectSnapshot.dependencies,
|
...projectSnapshot.dependencies,
|
||||||
@@ -206,8 +205,9 @@ export async function resolveDependencyTree<T> (
|
|||||||
|
|
||||||
ctx.pendingNodes.forEach((pendingNode) => {
|
ctx.pendingNodes.forEach((pendingNode) => {
|
||||||
ctx.dependenciesTree.set(pendingNode.nodeId, {
|
ctx.dependenciesTree.set(pendingNode.nodeId, {
|
||||||
children: () => buildTree(ctx, pendingNode.nodeId, pendingNode.resolvedPackage.id,
|
children: () => buildTree(ctx, pendingNode.resolvedPackage.id,
|
||||||
ctx.childrenByParentDepPath[pendingNode.resolvedPackage.depPath], pendingNode.depth + 1, pendingNode.installable),
|
pendingNode.parentIds,
|
||||||
|
ctx.childrenByParentId[pendingNode.resolvedPackage.id], pendingNode.depth + 1, pendingNode.installable),
|
||||||
depth: pendingNode.depth,
|
depth: pendingNode.depth,
|
||||||
installable: pendingNode.installable,
|
installable: pendingNode.installable,
|
||||||
resolvedPackage: pendingNode.resolvedPackage,
|
resolvedPackage: pendingNode.resolvedPackage,
|
||||||
@@ -250,7 +250,7 @@ export async function resolveDependencyTree<T> (
|
|||||||
dependenciesTree: ctx.dependenciesTree,
|
dependenciesTree: ctx.dependenciesTree,
|
||||||
outdatedDependencies: ctx.outdatedDependencies,
|
outdatedDependencies: ctx.outdatedDependencies,
|
||||||
resolvedImporters,
|
resolvedImporters,
|
||||||
resolvedPackagesByDepPath: ctx.resolvedPackagesByDepPath,
|
resolvedPkgsById: ctx.resolvedPkgsById,
|
||||||
wantedToBeSkippedPackageIds,
|
wantedToBeSkippedPackageIds,
|
||||||
appliedPatches: ctx.appliedPatches,
|
appliedPatches: ctx.appliedPatches,
|
||||||
time,
|
time,
|
||||||
@@ -260,40 +260,40 @@ export async function resolveDependencyTree<T> (
|
|||||||
|
|
||||||
function buildTree (
|
function buildTree (
|
||||||
ctx: {
|
ctx: {
|
||||||
childrenByParentDepPath: ChildrenByParentDepPath
|
childrenByParentId: ChildrenByParentId
|
||||||
dependenciesTree: DependenciesTree<ResolvedPackage>
|
dependenciesTree: DependenciesTree<ResolvedPackage>
|
||||||
resolvedPackagesByDepPath: ResolvedPackagesByDepPath
|
resolvedPkgsById: ResolvedPkgsById
|
||||||
skipped: Set<string>
|
skipped: Set<string>
|
||||||
},
|
},
|
||||||
parentNodeId: string,
|
|
||||||
parentId: string,
|
parentId: string,
|
||||||
children: Array<{ alias: string, depPath: string }>,
|
parentIds: string[],
|
||||||
|
children: Array<{ alias: string, id: string }>,
|
||||||
depth: number,
|
depth: number,
|
||||||
installable: boolean
|
installable: boolean
|
||||||
): Record<string, string> {
|
): Record<string, string> {
|
||||||
const childrenNodeIds: Record<string, string> = {}
|
const childrenNodeIds: Record<string, string> = {}
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
if (child.depPath.startsWith('link:')) {
|
if (child.id.startsWith('link:')) {
|
||||||
childrenNodeIds[child.alias] = child.depPath
|
childrenNodeIds[child.alias] = child.id
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (nodeIdContainsSequence(parentNodeId, parentId, child.depPath) || parentId === child.depPath) {
|
if (parentIdsContainSequence(parentIds, parentId, child.id) || parentId === child.id) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const childNodeId = createNodeId(parentNodeId, child.depPath)
|
const childNodeId = nextNodeId()
|
||||||
childrenNodeIds[child.alias] = childNodeId
|
childrenNodeIds[child.alias] = childNodeId
|
||||||
installable = installable || !ctx.skipped.has(child.depPath)
|
installable = installable || !ctx.skipped.has(child.id)
|
||||||
ctx.dependenciesTree.set(childNodeId, {
|
ctx.dependenciesTree.set(childNodeId, {
|
||||||
children: () => buildTree(ctx,
|
children: () => buildTree(ctx,
|
||||||
childNodeId,
|
child.id,
|
||||||
child.depPath,
|
[...parentIds, child.id],
|
||||||
ctx.childrenByParentDepPath[child.depPath],
|
ctx.childrenByParentId[child.id],
|
||||||
depth + 1,
|
depth + 1,
|
||||||
installable
|
installable
|
||||||
),
|
),
|
||||||
depth,
|
depth,
|
||||||
installable,
|
installable,
|
||||||
resolvedPackage: ctx.resolvedPackagesByDepPath[child.depPath],
|
resolvedPackage: ctx.resolvedPkgsById[child.id],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return childrenNodeIds
|
return childrenNodeIds
|
||||||
|
|||||||
@@ -10,11 +10,9 @@ import type {
|
|||||||
PeerDependencyIssuesByProjects,
|
PeerDependencyIssuesByProjects,
|
||||||
} from '@pnpm/types'
|
} from '@pnpm/types'
|
||||||
import { depPathToFilename, createPeersDirSuffix, type PeerId } from '@pnpm/dependency-path'
|
import { depPathToFilename, createPeersDirSuffix, type PeerId } from '@pnpm/dependency-path'
|
||||||
import memoize from 'mem'
|
|
||||||
import mapValues from 'ramda/src/map'
|
import mapValues from 'ramda/src/map'
|
||||||
import partition from 'ramda/src/partition'
|
import partition from 'ramda/src/partition'
|
||||||
import pick from 'ramda/src/pick'
|
import pick from 'ramda/src/pick'
|
||||||
import scan from 'ramda/src/scan'
|
|
||||||
import {
|
import {
|
||||||
type ChildrenMap,
|
type ChildrenMap,
|
||||||
type PeerDependencies,
|
type PeerDependencies,
|
||||||
@@ -24,7 +22,6 @@ import {
|
|||||||
} from './resolveDependencies'
|
} from './resolveDependencies'
|
||||||
import { type ResolvedImporters } from './resolveDependencyTree'
|
import { type ResolvedImporters } from './resolveDependencyTree'
|
||||||
import { mergePeers } from './mergePeers'
|
import { mergePeers } from './mergePeers'
|
||||||
import { createNodeId, splitNodeId } from './nodeIdUtils'
|
|
||||||
import { dedupeInjectedDeps } from './dedupeInjectedDeps'
|
import { dedupeInjectedDeps } from './dedupeInjectedDeps'
|
||||||
|
|
||||||
export interface GenericDependenciesGraphNode {
|
export interface GenericDependenciesGraphNode {
|
||||||
@@ -107,10 +104,12 @@ export async function resolvePeers<T extends PartialResolvedPackage> (
|
|||||||
// eslint-disable-next-line no-await-in-loop
|
// eslint-disable-next-line no-await-in-loop
|
||||||
const { finishing } = await resolvePeersOfChildren(directNodeIdsByAlias, pkgsByName, {
|
const { finishing } = await resolvePeersOfChildren(directNodeIdsByAlias, pkgsByName, {
|
||||||
allPeerDepNames: opts.allPeerDepNames,
|
allPeerDepNames: opts.allPeerDepNames,
|
||||||
getParentPkgs: {},
|
parentPkgsOfNode: new Map(),
|
||||||
dependenciesTree: opts.dependenciesTree,
|
dependenciesTree: opts.dependenciesTree,
|
||||||
depGraph,
|
depGraph,
|
||||||
lockfileDir: opts.lockfileDir,
|
lockfileDir: opts.lockfileDir,
|
||||||
|
parentNodeIds: [],
|
||||||
|
parentDepPathsChain: [],
|
||||||
pathsByNodeId,
|
pathsByNodeId,
|
||||||
pathsByNodeIdPromises,
|
pathsByNodeIdPromises,
|
||||||
depPathsByPkgId,
|
depPathsByPkgId,
|
||||||
@@ -271,6 +270,7 @@ function createPkgsByName<T extends PartialResolvedPackage> (
|
|||||||
alias,
|
alias,
|
||||||
node: dependenciesTree.get(directNodeIdsByAlias[alias])!,
|
node: dependenciesTree.get(directNodeIdsByAlias[alias])!,
|
||||||
nodeId: directNodeIdsByAlias[alias],
|
nodeId: directNodeIdsByAlias[alias],
|
||||||
|
parentNodeIds: [],
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
const _updateParentRefs = updateParentRefs.bind(null, parentRefs)
|
const _updateParentRefs = updateParentRefs.bind(null, parentRefs)
|
||||||
@@ -281,6 +281,7 @@ function createPkgsByName<T extends PartialResolvedPackage> (
|
|||||||
depth: 0,
|
depth: 0,
|
||||||
version,
|
version,
|
||||||
nodeId: linkedDir,
|
nodeId: linkedDir,
|
||||||
|
parentNodeIds: [],
|
||||||
}
|
}
|
||||||
_updateParentRefs(name, pkg)
|
_updateParentRefs(name, pkg)
|
||||||
if (alias && alias !== name) {
|
if (alias && alias !== name) {
|
||||||
@@ -318,14 +319,17 @@ interface ParentPkgInfo {
|
|||||||
depth?: number
|
depth?: number
|
||||||
occurrence?: number
|
occurrence?: number
|
||||||
}
|
}
|
||||||
type GetParentPkgs = () => Record<string, ParentPkgInfo>
|
|
||||||
|
type ParentPkgsOfNode = Map<string, Record<string, ParentPkgInfo>>
|
||||||
|
|
||||||
async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
||||||
nodeId: string,
|
nodeId: string,
|
||||||
parentParentPkgs: ParentRefs,
|
parentParentPkgs: ParentRefs,
|
||||||
ctx: ResolvePeersContext & {
|
ctx: ResolvePeersContext & {
|
||||||
allPeerDepNames: Set<string>
|
allPeerDepNames: Set<string>
|
||||||
getParentPkgs: Record<string, GetParentPkgs>
|
parentPkgsOfNode: ParentPkgsOfNode
|
||||||
|
parentNodeIds: string[]
|
||||||
|
parentDepPathsChain: string[]
|
||||||
dependenciesTree: DependenciesTree<T>
|
dependenciesTree: DependenciesTree<T>
|
||||||
depGraph: GenericDependenciesGraph<T>
|
depGraph: GenericDependenciesGraph<T>
|
||||||
virtualStoreDir: string
|
virtualStoreDir: string
|
||||||
@@ -352,6 +356,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
if (typeof node.children === 'function') {
|
if (typeof node.children === 'function') {
|
||||||
node.children = node.children()
|
node.children = node.children()
|
||||||
}
|
}
|
||||||
|
const parentNodeIds = [...ctx.parentNodeIds, nodeId]
|
||||||
const children = node.children
|
const children = node.children
|
||||||
let parentPkgs: ParentRefs
|
let parentPkgs: ParentRefs
|
||||||
if (Object.keys(children).length === 0) {
|
if (Object.keys(children).length === 0) {
|
||||||
@@ -365,6 +370,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
alias,
|
alias,
|
||||||
node: ctx.dependenciesTree.get(nodeId)!,
|
node: ctx.dependenciesTree.get(nodeId)!,
|
||||||
nodeId,
|
nodeId,
|
||||||
|
parentNodeIds,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -398,7 +404,11 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
resolvedPeers: unknownResolvedPeersOfChildren,
|
resolvedPeers: unknownResolvedPeersOfChildren,
|
||||||
missingPeers: missingPeersOfChildren,
|
missingPeers: missingPeersOfChildren,
|
||||||
finishing,
|
finishing,
|
||||||
} = await resolvePeersOfChildren(children, parentPkgs, ctx)
|
} = await resolvePeersOfChildren(children, parentPkgs, {
|
||||||
|
...ctx,
|
||||||
|
parentNodeIds,
|
||||||
|
parentDepPathsChain: ctx.parentDepPathsChain.includes(resolvedPackage.depPath) ? ctx.parentDepPathsChain : [...ctx.parentDepPathsChain, resolvedPackage.depPath],
|
||||||
|
})
|
||||||
|
|
||||||
const { resolvedPeers, missingPeers } = Object.keys(resolvedPackage.peerDependencies).length === 0
|
const { resolvedPeers, missingPeers } = Object.keys(resolvedPackage.peerDependencies).length === 0
|
||||||
? { resolvedPeers: new Map<string, string>(), missingPeers: new Set<string>() }
|
? { resolvedPeers: new Map<string, string>(), missingPeers: new Set<string>() }
|
||||||
@@ -411,6 +421,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
peerDependencyIssues: ctx.peerDependencyIssues,
|
peerDependencyIssues: ctx.peerDependencyIssues,
|
||||||
resolvedPackage,
|
resolvedPackage,
|
||||||
rootDir: ctx.rootDir,
|
rootDir: ctx.rootDir,
|
||||||
|
parentNodeIds,
|
||||||
})
|
})
|
||||||
|
|
||||||
const allResolvedPeers = unknownResolvedPeersOfChildren
|
const allResolvedPeers = unknownResolvedPeersOfChildren
|
||||||
@@ -539,7 +550,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
ctx.depGraph[depPath] = {
|
ctx.depGraph[depPath] = {
|
||||||
...(node.resolvedPackage as T),
|
...(node.resolvedPackage as T),
|
||||||
children: Object.assign(
|
children: Object.assign(
|
||||||
getPreviouslyResolvedChildren(nodeId, ctx.dependenciesTree),
|
getPreviouslyResolvedChildren(ctx, (node.resolvedPackage as T).depPath),
|
||||||
children,
|
children,
|
||||||
Object.fromEntries(resolvedPeers.entries())
|
Object.fromEntries(resolvedPeers.entries())
|
||||||
),
|
),
|
||||||
@@ -558,7 +569,7 @@ async function resolvePeersOfNode<T extends PartialResolvedPackage> (
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findHit<T extends PartialResolvedPackage> (ctx: {
|
function findHit<T extends PartialResolvedPackage> (ctx: {
|
||||||
getParentPkgs: Record<string, GetParentPkgs>
|
parentPkgsOfNode: ParentPkgsOfNode
|
||||||
peersCache: PeersCache
|
peersCache: PeersCache
|
||||||
purePkgs: Set<string>
|
purePkgs: Set<string>
|
||||||
pathsByNodeId: Map<string, string>
|
pathsByNodeId: Map<string, string>
|
||||||
@@ -599,12 +610,12 @@ function findHit<T extends PartialResolvedPackage> (ctx: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parentPackagesMatch (ctx: {
|
function parentPackagesMatch (ctx: {
|
||||||
getParentPkgs: Record<string, GetParentPkgs>
|
parentPkgsOfNode: ParentPkgsOfNode
|
||||||
purePkgs: Set<string>
|
purePkgs: Set<string>
|
||||||
}, cachedNodeId: string, checkedNodeId: string): boolean {
|
}, cachedNodeId: string, checkedNodeId: string): boolean {
|
||||||
const cachedParentPkgs = ctx.getParentPkgs[cachedNodeId]?.()
|
const cachedParentPkgs = ctx.parentPkgsOfNode.get(cachedNodeId)
|
||||||
if (!cachedParentPkgs) return false
|
if (!cachedParentPkgs) return false
|
||||||
const checkedParentPkgs = ctx.getParentPkgs[checkedNodeId]?.()
|
const checkedParentPkgs = ctx.parentPkgsOfNode.get(checkedNodeId)
|
||||||
if (!checkedParentPkgs) return false
|
if (!checkedParentPkgs) return false
|
||||||
if (Object.keys(cachedParentPkgs).length !== Object.keys(checkedParentPkgs).length) return false
|
if (Object.keys(cachedParentPkgs).length !== Object.keys(checkedParentPkgs).length) return false
|
||||||
const maxDepth = Object.values(checkedParentPkgs)
|
const maxDepth = Object.values(checkedParentPkgs)
|
||||||
@@ -640,27 +651,34 @@ function parentPkgsHaveSingleOccurrence (parentPkgs: Record<string, ParentPkgInf
|
|||||||
// from the dependencies of the parent package.
|
// from the dependencies of the parent package.
|
||||||
// So we need to merge all the children of all the parent packages with same ID as the resolved package.
|
// So we need to merge all the children of all the parent packages with same ID as the resolved package.
|
||||||
// This way we get all the children that were removed, when ending cycles.
|
// This way we get all the children that were removed, when ending cycles.
|
||||||
function getPreviouslyResolvedChildren<T extends PartialResolvedPackage> (nodeId: string, dependenciesTree: DependenciesTree<T>): ChildrenMap {
|
function getPreviouslyResolvedChildren<T extends PartialResolvedPackage> (
|
||||||
const parentIds = splitNodeId(nodeId)
|
{
|
||||||
const ownId = parentIds.pop()
|
parentNodeIds,
|
||||||
|
parentDepPathsChain,
|
||||||
|
dependenciesTree,
|
||||||
|
}: {
|
||||||
|
parentNodeIds: string[]
|
||||||
|
parentDepPathsChain: string[]
|
||||||
|
dependenciesTree: DependenciesTree<T>
|
||||||
|
},
|
||||||
|
currentDepPath: string
|
||||||
|
): ChildrenMap {
|
||||||
const allChildren: ChildrenMap = {}
|
const allChildren: ChildrenMap = {}
|
||||||
|
|
||||||
if (!ownId || !parentIds.includes(ownId)) return allChildren
|
if (!currentDepPath || !parentDepPathsChain.includes(currentDepPath)) return allChildren
|
||||||
|
|
||||||
const nodeIdChunks = parentIds.join('>').split(`>${ownId}>`)
|
for (let i = parentNodeIds.length - 1; i >= 0; i--) {
|
||||||
nodeIdChunks.pop()
|
const parentNode = dependenciesTree.get(parentNodeIds[i])!
|
||||||
nodeIdChunks.reduce((accNodeId, part) => {
|
if ((parentNode.resolvedPackage as T).depPath === currentDepPath) {
|
||||||
accNodeId += `>${part}>${ownId}`
|
if (typeof parentNode.children === 'function') {
|
||||||
const parentNode = dependenciesTree.get(`${accNodeId}>`)!
|
parentNode.children = parentNode.children()
|
||||||
if (typeof parentNode.children === 'function') {
|
}
|
||||||
parentNode.children = parentNode.children()
|
Object.assign(
|
||||||
|
allChildren,
|
||||||
|
parentNode.children
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Object.assign(
|
}
|
||||||
allChildren,
|
|
||||||
parentNode.children
|
|
||||||
)
|
|
||||||
return accNodeId
|
|
||||||
}, '')
|
|
||||||
return allChildren
|
return allChildren
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,7 +689,9 @@ async function resolvePeersOfChildren<T extends PartialResolvedPackage> (
|
|||||||
parentPkgs: ParentRefs,
|
parentPkgs: ParentRefs,
|
||||||
ctx: ResolvePeersContext & {
|
ctx: ResolvePeersContext & {
|
||||||
allPeerDepNames: Set<string>
|
allPeerDepNames: Set<string>
|
||||||
getParentPkgs: Record<string, GetParentPkgs>
|
parentPkgsOfNode: ParentPkgsOfNode
|
||||||
|
parentNodeIds: string[]
|
||||||
|
parentDepPathsChain: string[]
|
||||||
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
peerDependencyIssues: Pick<PeerDependencyIssues, 'bad' | 'missing'>
|
||||||
peersCache: PeersCache
|
peersCache: PeersCache
|
||||||
virtualStoreDir: string
|
virtualStoreDir: string
|
||||||
@@ -701,24 +721,21 @@ async function resolvePeersOfChildren<T extends PartialResolvedPackage> (
|
|||||||
const calculateDepPaths: CalculateDepPath[] = []
|
const calculateDepPaths: CalculateDepPath[] = []
|
||||||
const graph = []
|
const graph = []
|
||||||
const finishingList: FinishingResolutionPromise[] = []
|
const finishingList: FinishingResolutionPromise[] = []
|
||||||
const cachedGetParentPkgs = memoize(() => {
|
const parentDepPaths: Record<string, ParentPkgInfo> = {}
|
||||||
const parentDepPaths: Record<string, ParentPkgInfo> = {}
|
for (const [name, parentPkg] of Object.entries(parentPkgs)) {
|
||||||
for (const [name, parentPkg] of Object.entries(parentPkgs)) {
|
if (!ctx.allPeerDepNames.has(name)) continue
|
||||||
if (!ctx.allPeerDepNames.has(name)) continue
|
if (parentPkg.nodeId && !parentPkg.nodeId.startsWith('link:')) {
|
||||||
if (parentPkg.nodeId && !parentPkg.nodeId.startsWith('link:')) {
|
parentDepPaths[name] = {
|
||||||
parentDepPaths[name] = {
|
depPath: (ctx.dependenciesTree.get(parentPkg.nodeId)!.resolvedPackage as T).depPath,
|
||||||
depPath: (ctx.dependenciesTree.get(parentPkg.nodeId)!.resolvedPackage as T).depPath,
|
depth: parentPkg.depth,
|
||||||
depth: parentPkg.depth,
|
occurrence: parentPkg.occurrence,
|
||||||
occurrence: parentPkg.occurrence,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
parentDepPaths[name] = { version: parentPkg.version }
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
parentDepPaths[name] = { version: parentPkg.version }
|
||||||
}
|
}
|
||||||
return parentDepPaths
|
}
|
||||||
})
|
|
||||||
for (const childNodeId of nodeIds) {
|
for (const childNodeId of nodeIds) {
|
||||||
ctx.getParentPkgs[childNodeId] = cachedGetParentPkgs
|
ctx.parentPkgsOfNode.set(childNodeId, parentDepPaths)
|
||||||
}
|
}
|
||||||
for (const childNodeId of nodeIds) {
|
for (const childNodeId of nodeIds) {
|
||||||
const {
|
const {
|
||||||
@@ -765,6 +782,7 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
|||||||
lockfileDir: string
|
lockfileDir: string
|
||||||
nodeId: string
|
nodeId: string
|
||||||
parentPkgs: ParentRefs
|
parentPkgs: ParentRefs
|
||||||
|
parentNodeIds: string[]
|
||||||
resolvedPackage: T
|
resolvedPackage: T
|
||||||
dependenciesTree: DependenciesTree<T>
|
dependenciesTree: DependenciesTree<T>
|
||||||
rootDir: string
|
rootDir: string
|
||||||
@@ -781,11 +799,7 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
|||||||
|
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
missingPeers.add(peerName)
|
missingPeers.add(peerName)
|
||||||
const location = getLocationFromNodeIdAndPkg({
|
const location = getLocationFromParentNodeIds(ctx)
|
||||||
dependenciesTree: ctx.dependenciesTree,
|
|
||||||
nodeId: ctx.nodeId,
|
|
||||||
pkg: ctx.resolvedPackage,
|
|
||||||
})
|
|
||||||
if (!ctx.peerDependencyIssues.missing[peerName]) {
|
if (!ctx.peerDependencyIssues.missing[peerName]) {
|
||||||
ctx.peerDependencyIssues.missing[peerName] = []
|
ctx.peerDependencyIssues.missing[peerName] = []
|
||||||
}
|
}
|
||||||
@@ -798,19 +812,15 @@ function _resolvePeers<T extends PartialResolvedPackage> (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!semverUtils.satisfiesWithPrereleases(resolved.version, peerVersionRange, true)) {
|
if (!semverUtils.satisfiesWithPrereleases(resolved.version, peerVersionRange, true)) {
|
||||||
const location = getLocationFromNodeIdAndPkg({
|
const location = getLocationFromParentNodeIds(ctx)
|
||||||
dependenciesTree: ctx.dependenciesTree,
|
|
||||||
nodeId: ctx.nodeId,
|
|
||||||
pkg: ctx.resolvedPackage,
|
|
||||||
})
|
|
||||||
if (!ctx.peerDependencyIssues.bad[peerName]) {
|
if (!ctx.peerDependencyIssues.bad[peerName]) {
|
||||||
ctx.peerDependencyIssues.bad[peerName] = []
|
ctx.peerDependencyIssues.bad[peerName] = []
|
||||||
}
|
}
|
||||||
const peerLocation = resolved.nodeId == null
|
const peerLocation = resolved.nodeId == null
|
||||||
? []
|
? []
|
||||||
: getLocationFromNodeId({
|
: getLocationFromParentNodeIds({
|
||||||
dependenciesTree: ctx.dependenciesTree,
|
dependenciesTree: ctx.dependenciesTree,
|
||||||
nodeId: resolved.nodeId,
|
parentNodeIds: resolved.parentNodeIds,
|
||||||
}).parents
|
}).parents
|
||||||
ctx.peerDependencyIssues.bad[peerName].push({
|
ctx.peerDependencyIssues.bad[peerName].push({
|
||||||
foundVersion: resolved.version,
|
foundVersion: resolved.version,
|
||||||
@@ -831,41 +841,19 @@ interface Location {
|
|||||||
parents: ParentPackages
|
parents: ParentPackages
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLocationFromNodeIdAndPkg<T> (
|
function getLocationFromParentNodeIds<T> (
|
||||||
{
|
{
|
||||||
dependenciesTree,
|
dependenciesTree,
|
||||||
nodeId,
|
parentNodeIds,
|
||||||
pkg,
|
|
||||||
}: {
|
}: {
|
||||||
dependenciesTree: DependenciesTree<T>
|
dependenciesTree: DependenciesTree<T>
|
||||||
nodeId: string
|
parentNodeIds: string[]
|
||||||
pkg: { name: string, version: string }
|
|
||||||
}
|
}
|
||||||
): Location {
|
): Location {
|
||||||
const { projectId, parents } = getLocationFromNodeId({ dependenciesTree, nodeId })
|
const parents = parentNodeIds
|
||||||
parents.push({ name: pkg.name, version: pkg.version })
|
|
||||||
return {
|
|
||||||
projectId,
|
|
||||||
parents,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLocationFromNodeId<T> (
|
|
||||||
{
|
|
||||||
dependenciesTree,
|
|
||||||
nodeId,
|
|
||||||
}: {
|
|
||||||
dependenciesTree: DependenciesTree<T>
|
|
||||||
nodeId: string
|
|
||||||
}
|
|
||||||
): Location {
|
|
||||||
const parts = splitNodeId(nodeId).slice(0, -1)
|
|
||||||
const parents = scan((prevNodeId, pkgId) => createNodeId(prevNodeId, pkgId), '>', parts)
|
|
||||||
.slice(2)
|
|
||||||
|
|
||||||
.map((nid) => pick(['name', 'version'], dependenciesTree.get(nid)!.resolvedPackage as ResolvedPackage))
|
.map((nid) => pick(['name', 'version'], dependenciesTree.get(nid)!.resolvedPackage as ResolvedPackage))
|
||||||
return {
|
return {
|
||||||
projectId: parts[0],
|
projectId: '.',
|
||||||
parents,
|
parents,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -881,24 +869,27 @@ interface ParentRef {
|
|||||||
nodeId?: string
|
nodeId?: string
|
||||||
alias?: string
|
alias?: string
|
||||||
occurrence: number
|
occurrence: number
|
||||||
|
parentNodeIds: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ParentPkgNode<T> {
|
interface ParentPkgNode<T> {
|
||||||
alias: string
|
alias: string
|
||||||
nodeId: string
|
nodeId: string
|
||||||
node: DependenciesTreeNode<T>
|
node: DependenciesTreeNode<T>
|
||||||
|
parentNodeIds: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
function toPkgByName<T extends PartialResolvedPackage> (nodes: Array<ParentPkgNode<T>>): ParentRefs {
|
function toPkgByName<T extends PartialResolvedPackage> (nodes: Array<ParentPkgNode<T>>): ParentRefs {
|
||||||
const pkgsByName: ParentRefs = {}
|
const pkgsByName: ParentRefs = {}
|
||||||
const _updateParentRefs = updateParentRefs.bind(null, pkgsByName)
|
const _updateParentRefs = updateParentRefs.bind(null, pkgsByName)
|
||||||
for (const { alias, node, nodeId } of nodes) {
|
for (const { alias, node, nodeId, parentNodeIds } of nodes) {
|
||||||
const pkg = {
|
const pkg = {
|
||||||
alias,
|
alias,
|
||||||
depth: node.depth,
|
depth: node.depth,
|
||||||
nodeId,
|
nodeId,
|
||||||
version: node.resolvedPackage.version,
|
version: node.resolvedPackage.version,
|
||||||
occurrence: 0,
|
occurrence: 0,
|
||||||
|
parentNodeIds,
|
||||||
}
|
}
|
||||||
_updateParentRefs(alias, pkg)
|
_updateParentRefs(alias, pkg)
|
||||||
if (alias !== node.resolvedPackage.name) {
|
if (alias !== node.resolvedPackage.name) {
|
||||||
|
|||||||
@@ -61,8 +61,7 @@ function toLockfileDependency (
|
|||||||
}
|
}
|
||||||
): PackageSnapshot {
|
): PackageSnapshot {
|
||||||
const lockfileResolution = toLockfileResolution(
|
const lockfileResolution = toLockfileResolution(
|
||||||
{ id: pkg.id, name: pkg.name, version: pkg.version },
|
{ name: pkg.name, version: pkg.version },
|
||||||
opts.depPath,
|
|
||||||
pkg.resolution,
|
pkg.resolution,
|
||||||
opts.registry,
|
opts.registry,
|
||||||
opts.lockfileIncludeTarballUrl
|
opts.lockfileIncludeTarballUrl
|
||||||
@@ -175,11 +174,9 @@ function updateResolvedDeps (
|
|||||||
|
|
||||||
function toLockfileResolution (
|
function toLockfileResolution (
|
||||||
pkg: {
|
pkg: {
|
||||||
id: string
|
|
||||||
name: string
|
name: string
|
||||||
version: string
|
version: string
|
||||||
},
|
},
|
||||||
depPath: string,
|
|
||||||
resolution: Resolution,
|
resolution: Resolution,
|
||||||
registry: string,
|
registry: string,
|
||||||
lockfileIncludeTarballUrl?: boolean
|
lockfileIncludeTarballUrl?: boolean
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
import { nodeIdContainsSequence } from '../lib/nodeIdUtils'
|
|
||||||
|
|
||||||
test('nodeIdContainsSequence()', () => {
|
|
||||||
expect(nodeIdContainsSequence('>.>b>a>c>b>a>', 'a', 'b')).toBeTruthy()
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { parentIdsContainSequence } from '../lib/parentIdsContainSequence'
|
||||||
|
|
||||||
|
test('parentIdsContainSequence()', () => {
|
||||||
|
expect(parentIdsContainSequence(['.', 'b', 'a', 'c', 'b', 'a'], 'a', 'b')).toBeTruthy()
|
||||||
|
})
|
||||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -4307,9 +4307,6 @@ importers:
|
|||||||
is-subdir:
|
is-subdir:
|
||||||
specifier: ^1.2.0
|
specifier: ^1.2.0
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
mem:
|
|
||||||
specifier: ^8.1.1
|
|
||||||
version: 8.1.1
|
|
||||||
normalize-path:
|
normalize-path:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user