From 7db6b33cdf8e0b4da134008e098bccc9abadc823 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 26 Aug 2022 04:07:51 +0300 Subject: [PATCH 1/5] refactor: resolve dependencies --- .../src/resolveDependencies.ts | 161 ++++++++++++++---- .../src/resolveDependencyTree.ts | 21 ++- 2 files changed, 138 insertions(+), 44 deletions(-) diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index 22f0ae25904..247ec0a3b6a 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -41,6 +41,7 @@ import { import * as dp from 'dependency-path' import exists from 'path-exists' import isEmpty from 'ramda/src/isEmpty' +import zipWith from 'ramda/src/zipWith' import semver from 'semver' import encodePkgId from './encodePkgId' import getNonDevWantedDependencies, { WantedDependency } from './getNonDevWantedDependencies' @@ -240,43 +241,59 @@ type PostponedResolutionFunction = (preferredVersions: PreferredVersions, parent }> export async function resolveRootDependencies ( - ctx: ResolutionContext, - preferredVersions: PreferredVersions, - wantedDependencies: Array, - options: ResolvedDependenciesOptions -): Promise> { - const pkgAddresses: Array = [] - const parentPkgAliases: ParentPkgAliases = {} - for (const wantedDep of wantedDependencies) { - if (wantedDep.alias) { - parentPkgAliases[wantedDep.alias] = true + importers: Record + options: Omit + }> +): Promise>> { + const importersToResolve: ImporterToResolve[] = [] + for (const { ctx, options, wantedDependencies, preferredVersions } of Object.values(importers)) { + const parentPkgAliases: ParentPkgAliases = {} + for (const wantedDep of wantedDependencies) { + if (wantedDep.alias) { + parentPkgAliases[wantedDep.alias] = true + } } + importersToResolve.push({ ctx, options, parentPkgAliases, preferredVersions, wantedDependencies }) } - while (true) { - const result = await resolveDependencies(ctx, preferredVersions, wantedDependencies, { - ...options, - parentPkgAliases, - }) - pkgAddresses.push(...result.pkgAddresses) - if (!ctx.autoInstallPeers) break - for (const pkgAddress of result.pkgAddresses) { - parentPkgAliases[pkgAddress.alias] = true - } - for (const missingPeerName of Object.keys(result.missingPeers ?? {})) { - parentPkgAliases[missingPeerName] = true - } - // All the missing peers should get installed in the root. - // Otherwise, pending nodes will not work. - // even those peers should be hoisted that are not autoinstalled - for (const [resolvedPeerName, resolvedPeerAddress] of Object.entries(result.resolvedPeers ?? {})) { - if (!parentPkgAliases[resolvedPeerName]) { - pkgAddresses.push(resolvedPeerAddress) + const result = await resolveDependenciesOfImporters(importersToResolve) + const results = await Promise.all(result.map(async (importerResolutionResult, index) => { + const pkgAddresses: Array = importerResolutionResult.pkgAddresses + const parentPkgAliases = importersToResolve[index].parentPkgAliases + while (true) { + if (!importersToResolve[index].ctx.autoInstallPeers) break + for (const pkgAddress of importerResolutionResult.pkgAddresses) { + parentPkgAliases[pkgAddress.alias] = true + } + for (const missingPeerName of Object.keys(importerResolutionResult.missingPeers ?? {})) { + parentPkgAliases[missingPeerName] = true } + // All the missing peers should get installed in the root. + // Otherwise, pending nodes will not work. + // even those peers should be hoisted that are not autoinstalled + for (const [resolvedPeerName, resolvedPeerAddress] of Object.entries(importerResolutionResult.resolvedPeers ?? {})) { + if (!parentPkgAliases[resolvedPeerName]) { + pkgAddresses.push(resolvedPeerAddress) + } + } + if (!Object.keys(importerResolutionResult.missingPeers).length) break + const wantedDependencies = getNonDevWantedDependencies({ dependencies: importerResolutionResult.missingPeers }) + + importerResolutionResult = await resolveDependencies(importersToResolve[index].ctx, importersToResolve[index].preferredVersions, wantedDependencies, { + ...importersToResolve[index].options, + parentPkgAliases, + }) + pkgAddresses.push(...importerResolutionResult.pkgAddresses) } - if (!Object.keys(result.missingPeers).length) break - wantedDependencies = getNonDevWantedDependencies({ dependencies: result.missingPeers }) - } - return pkgAddresses + return pkgAddresses + })) + const pkgAddressesByImporterId = {} + Object.keys(importers).forEach((importerId, index) => { + pkgAddressesByImporterId[importerId] = results[index] + }) + return pkgAddressesByImporterId } interface ResolvedDependenciesResult { @@ -285,6 +302,84 @@ interface ResolvedDependenciesResult { resolvedPeers: ResolvedPeers } +interface ImporterToResolve { + ctx: ResolutionContext + preferredVersions: PreferredVersions + parentPkgAliases: ParentPkgAliases + wantedDependencies: Array + options: Omit +} + +export async function resolveDependenciesOfImporters ( + importers: ImporterToResolve[] +): Promise { + const extendedWantedDepsByImporters = importers.map(({ ctx, wantedDependencies, options }) => getDepsToResolve(wantedDependencies, ctx.wantedLockfile, { + preferredDependencies: options.preferredDependencies, + prefix: ctx.prefix, + proceed: options.proceed || ctx.forceFullResolution, + registries: ctx.registries, + resolvedDependencies: options.resolvedDependencies, + })) + const resolveResults = await Promise.all( + extendedWantedDepsByImporters.map(async (extendedWantedDeps, index) => { + const postponedResolutionsQueue: PostponedResolutionFunction[] = [] + const pkgAddresses = ( + await Promise.all( + extendedWantedDeps.map(async (extendedWantedDep) => resolveDependenciesOfDependency( + postponedResolutionsQueue, + importers[index].ctx, + importers[index].preferredVersions, + { ...importers[index].options, parentPkgAliases: importers[index].parentPkgAliases }, + extendedWantedDep + )) + ) + ).filter(Boolean) as PkgAddress[] + return { pkgAddresses, postponedResolutionsQueue } + }) + ) + return Promise.all(zipWith(async (importer, { pkgAddresses, postponedResolutionsQueue }) => { + const newPreferredVersions = { ...importer.preferredVersions } + const newParentPkgAliases = { ...importer.parentPkgAliases } + for (const pkgAddress of pkgAddresses) { + if (newParentPkgAliases[pkgAddress.alias] !== true) { + newParentPkgAliases[pkgAddress.alias] = pkgAddress + } + if (pkgAddress.updated) { + importer.ctx.updatedSet.add(pkgAddress.alias) + } + const resolvedPackage = importer.ctx.resolvedPackagesByDepPath[pkgAddress.depPath] + if (!resolvedPackage) continue // This will happen only with linked dependencies + if (!newPreferredVersions[resolvedPackage.name]) { + newPreferredVersions[resolvedPackage.name] = {} + } + newPreferredVersions[resolvedPackage.name][resolvedPackage.version] = 'version' + } + const childrenResults = await Promise.all( + postponedResolutionsQueue.map( + async (postponedResolution) => postponedResolution(newPreferredVersions, newParentPkgAliases) + ) + ) + if (!importer.ctx.autoInstallPeers) { + return { + missingPeers: {}, + pkgAddresses, + resolvedPeers: {}, + } + } + const allMissingPeers = mergePkgsDeps( + [ + ...pkgAddresses, + ...childrenResults, + ].map(({ missingPeers }) => missingPeers).filter(Boolean) + ) + return { + missingPeers: allMissingPeers, + pkgAddresses, + resolvedPeers: [...pkgAddresses, ...childrenResults].reduce((acc, { resolvedPeers }) => Object.assign(acc, resolvedPeers), {}), + } + }, importers, resolveResults)) +} + export async function resolveDependencies ( ctx: ResolutionContext, preferredVersions: PreferredVersions, diff --git a/packages/resolve-dependencies/src/resolveDependencyTree.ts b/packages/resolve-dependencies/src/resolveDependencyTree.ts index de583f201f1..b056af5839f 100644 --- a/packages/resolve-dependencies/src/resolveDependencyTree.ts +++ b/packages/resolve-dependencies/src/resolveDependencyTree.ts @@ -85,8 +85,6 @@ export default async function ( importers: Array>, opts: ResolveDependenciesOptions ) { - const directDepsByImporterId = {} as {[id: string]: Array} - const wantedToBeSkippedPackageIds = new Set() const ctx = { autoInstallPeers: opts.autoInstallPeers === true, @@ -119,7 +117,8 @@ export default async function ( appliedPatches: new Set(), } - await Promise.all(importers.map(async (importer) => { + const resolveArgs = {} + importers.map(async (importer) => { const projectSnapshot = opts.wantedLockfile.importers[importer.id] // This array will only contain the dependencies that should be linked in. // The already linked-in dependencies will not be added. @@ -144,7 +143,6 @@ export default async function ( depPath: importer.id, rootDir: importer.rootDir, }, - parentPkgAliases: {}, proceed, resolvedDependencies: { ...projectSnapshot.dependencies, @@ -154,13 +152,14 @@ export default async function ( updateDepth: -1, workspacePackages: opts.workspacePackages, } - directDepsByImporterId[importer.id] = await resolveRootDependencies( - resolveCtx, - importer.preferredVersions ?? {}, - importer.wantedDependencies, - resolveOpts - ) - })) + resolveArgs[importer.id] = { + ctx: resolveCtx, + preferredVersions: importer.preferredVersions ?? {}, + wantedDependencies: importer.wantedDependencies, + options: resolveOpts, + } + }) + const directDepsByImporterId: {[id: string]: Array} = await resolveRootDependencies(resolveArgs) ctx.pendingNodes.forEach((pendingNode) => { ctx.dependenciesTree[pendingNode.nodeId] = { From 1efb987bb239d1a6bce94e4704ae5909855a42a5 Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 26 Aug 2022 14:44:34 +0300 Subject: [PATCH 2/5] refactor: resolve dependencies --- .../src/resolveDependencies.ts | 114 ++++++++++-------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index 247ec0a3b6a..6c82fc0ccfd 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -259,11 +259,11 @@ export async function resolveRootDependencies ( importersToResolve.push({ ctx, options, parentPkgAliases, preferredVersions, wantedDependencies }) } const result = await resolveDependenciesOfImporters(importersToResolve) - const results = await Promise.all(result.map(async (importerResolutionResult, index) => { + const results = await Promise.all(zipWith(async (importerResolutionResult, importerToResolve) => { const pkgAddresses: Array = importerResolutionResult.pkgAddresses - const parentPkgAliases = importersToResolve[index].parentPkgAliases + const parentPkgAliases = importerToResolve.parentPkgAliases while (true) { - if (!importersToResolve[index].ctx.autoInstallPeers) break + if (!importerToResolve.ctx.autoInstallPeers) break for (const pkgAddress of importerResolutionResult.pkgAddresses) { parentPkgAliases[pkgAddress.alias] = true } @@ -281,14 +281,14 @@ export async function resolveRootDependencies ( if (!Object.keys(importerResolutionResult.missingPeers).length) break const wantedDependencies = getNonDevWantedDependencies({ dependencies: importerResolutionResult.missingPeers }) - importerResolutionResult = await resolveDependencies(importersToResolve[index].ctx, importersToResolve[index].preferredVersions, wantedDependencies, { - ...importersToResolve[index].options, + importerResolutionResult = await resolveDependencies(importerToResolve.ctx, importerToResolve.preferredVersions, wantedDependencies, { + ...importerToResolve.options, parentPkgAliases, }) pkgAddresses.push(...importerResolutionResult.pkgAddresses) } return pkgAddresses - })) + }, result, importersToResolve)) const pkgAddressesByImporterId = {} Object.keys(importers).forEach((importerId, index) => { pkgAddressesByImporterId[importerId] = results[index] @@ -323,17 +323,22 @@ export async function resolveDependenciesOfImporters ( const resolveResults = await Promise.all( extendedWantedDepsByImporters.map(async (extendedWantedDeps, index) => { const postponedResolutionsQueue: PostponedResolutionFunction[] = [] - const pkgAddresses = ( - await Promise.all( - extendedWantedDeps.map(async (extendedWantedDep) => resolveDependenciesOfDependency( - postponedResolutionsQueue, - importers[index].ctx, - importers[index].preferredVersions, - { ...importers[index].options, parentPkgAliases: importers[index].parentPkgAliases }, - extendedWantedDep - )) - ) - ).filter(Boolean) as PkgAddress[] + const pkgAddresses: PkgAddress[] = [] + ;(await Promise.all( + extendedWantedDeps.map((extendedWantedDep) => resolveDependenciesOfDependency( + importers[index].ctx, + importers[index].preferredVersions, + { ...importers[index].options, parentPkgAliases: importers[index].parentPkgAliases }, + extendedWantedDep + )) + )).forEach(({ resolveDependencyResult, postponedResolution }) => { + if (resolveDependencyResult) { + pkgAddresses.push(resolveDependencyResult as PkgAddress) + } + if (postponedResolution) { + postponedResolutionsQueue.push(postponedResolution) + } + }) return { pkgAddresses, postponedResolutionsQueue } }) ) @@ -386,7 +391,6 @@ export async function resolveDependencies ( wantedDependencies: Array, options: ResolvedDependenciesOptions ): Promise { - const postponedResolutionsQueue: PostponedResolutionFunction[] = [] const extendedWantedDeps = getDepsToResolve(wantedDependencies, ctx.wantedLockfile, { preferredDependencies: options.preferredDependencies, prefix: ctx.prefix, @@ -394,17 +398,23 @@ export async function resolveDependencies ( registries: ctx.registries, resolvedDependencies: options.resolvedDependencies, }) - const pkgAddresses = ( - await Promise.all( - extendedWantedDeps.map(async (extendedWantedDep) => resolveDependenciesOfDependency( - postponedResolutionsQueue, - ctx, - preferredVersions, - options, - extendedWantedDep - )) - ) - ).filter(Boolean) as PkgAddress[] + const postponedResolutionsQueue: PostponedResolutionFunction[] = [] + const pkgAddresses: PkgAddress[] = [] + ;(await Promise.all( + extendedWantedDeps.map((extendedWantedDep) => resolveDependenciesOfDependency( + ctx, + preferredVersions, + options, + extendedWantedDep + )) + )).forEach(({ resolveDependencyResult, postponedResolution }) => { + if (resolveDependencyResult) { + pkgAddresses.push(resolveDependencyResult as PkgAddress) + } + if (postponedResolution) { + postponedResolutionsQueue.push(postponedResolution) + } + }) const newPreferredVersions = { ...preferredVersions } const newParentPkgAliases = { ...options.parentPkgAliases } for (const pkgAddress of pkgAddresses) { @@ -468,13 +478,17 @@ interface ExtendedWantedDependency { wantedDependency: WantedDependency & { updateDepth?: number } } +interface ResolveDependenciesOfDependency { + postponedResolution?: PostponedResolutionFunction + resolveDependencyResult: ResolveDependencyResult +} + async function resolveDependenciesOfDependency ( - postponedResolutionsQueue: PostponedResolutionFunction[], ctx: ResolutionContext, preferredVersions: PreferredVersions, options: ResolvedDependenciesOptions, extendedWantedDep: ExtendedWantedDependency -) { +): Promise { const updateDepth = typeof extendedWantedDep.wantedDependency.updateDepth === 'number' ? extendedWantedDep.wantedDependency.updateDepth : options.updateDepth @@ -508,7 +522,7 @@ async function resolveDependenciesOfDependency ( } const resolveDependencyResult = await resolveDependency(extendedWantedDep.wantedDependency, ctx, resolveDependencyOpts) - if (resolveDependencyResult == null) return null + if (resolveDependencyResult == null) return { resolveDependencyResult: null } if (resolveDependencyResult.isLinkedDependency) { ctx.dependenciesTree[resolveDependencyResult.pkgId] = { children: {}, @@ -519,24 +533,24 @@ async function resolveDependenciesOfDependency ( version: resolveDependencyResult.version, }, } - return resolveDependencyResult + return { resolveDependencyResult } } - if (!resolveDependencyResult.isNew) return resolveDependencyResult - - postponedResolutionsQueue.push(async (preferredVersions, parentPkgAliases) => - resolveChildren( - ctx, - resolveDependencyResult, - parentPkgAliases, - extendedWantedDep.infoFromLockfile?.dependencyLockfile, - options.workspacePackages, - options.currentDepth, - updateDepth, - preferredVersions - ) - ) + if (!resolveDependencyResult.isNew) return { resolveDependencyResult } - return resolveDependencyResult + return { + resolveDependencyResult, + postponedResolution: async (preferredVersions, parentPkgAliases) => + resolveChildren( + ctx, + resolveDependencyResult, + parentPkgAliases, + extendedWantedDep.infoFromLockfile?.dependencyLockfile, + options.workspacePackages, + options.currentDepth, + updateDepth, + preferredVersions + ), + } } async function resolveChildren ( @@ -784,11 +798,13 @@ interface ResolveDependencyOptions { workspacePackages?: WorkspacePackages } +type ResolveDependencyResult = PkgAddress | LinkedDependency | null + async function resolveDependency ( wantedDependency: WantedDependency, ctx: ResolutionContext, options: ResolveDependencyOptions -): Promise { +): Promise { const currentPkg = options.currentPkg ?? {} const currentLockfileContainsTheDep = currentPkg.depPath From f65792a3ab6c1a85fecedd50d63606a1f379886a Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 26 Aug 2022 15:22:14 +0300 Subject: [PATCH 3/5] refactor: resolve dependencies --- .../src/resolveDependencies.ts | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index 6c82fc0ccfd..ce5d3cec23e 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -40,7 +40,9 @@ import { } from '@pnpm/types' import * as dp from 'dependency-path' import exists from 'path-exists' +import fromPairs from 'ramda/src/fromPairs' import isEmpty from 'ramda/src/isEmpty' +import zipObj from 'ramda/src/zipObj' import zipWith from 'ramda/src/zipWith' import semver from 'semver' import encodePkgId from './encodePkgId' @@ -248,22 +250,17 @@ export async function resolveRootDependencies ( options: Omit }> ): Promise>> { - const importersToResolve: ImporterToResolve[] = [] - for (const { ctx, options, wantedDependencies, preferredVersions } of Object.values(importers)) { - const parentPkgAliases: ParentPkgAliases = {} - for (const wantedDep of wantedDependencies) { - if (wantedDep.alias) { - parentPkgAliases[wantedDep.alias] = true - } - } - importersToResolve.push({ ctx, options, parentPkgAliases, preferredVersions, wantedDependencies }) - } - const result = await resolveDependenciesOfImporters(importersToResolve) - const results = await Promise.all(zipWith(async (importerResolutionResult, importerToResolve) => { - const pkgAddresses: Array = importerResolutionResult.pkgAddresses - const parentPkgAliases = importerToResolve.parentPkgAliases + const importersToResolve = Object.values(importers).map((importer) => ({ + parentPkgAliases: fromPairs( + importer.wantedDependencies.filter(({ alias }) => alias).map(({ alias }) => [alias, true]) + ) as ParentPkgAliases, + ...importer, + })) + const pkgAddressesByImportersWithoutPeers = await resolveDependenciesOfImporters(importersToResolve) + const pkgAddressesByImporters = await Promise.all(zipWith(async (importerResolutionResult, { ctx, parentPkgAliases, preferredVersions, options }) => { + const pkgAddresses = importerResolutionResult.pkgAddresses + if (!ctx.autoInstallPeers) return pkgAddresses while (true) { - if (!importerToResolve.ctx.autoInstallPeers) break for (const pkgAddress of importerResolutionResult.pkgAddresses) { parentPkgAliases[pkgAddress.alias] = true } @@ -281,19 +278,15 @@ export async function resolveRootDependencies ( if (!Object.keys(importerResolutionResult.missingPeers).length) break const wantedDependencies = getNonDevWantedDependencies({ dependencies: importerResolutionResult.missingPeers }) - importerResolutionResult = await resolveDependencies(importerToResolve.ctx, importerToResolve.preferredVersions, wantedDependencies, { - ...importerToResolve.options, + importerResolutionResult = await resolveDependencies(ctx, preferredVersions, wantedDependencies, { + ...options, parentPkgAliases, }) pkgAddresses.push(...importerResolutionResult.pkgAddresses) } return pkgAddresses - }, result, importersToResolve)) - const pkgAddressesByImporterId = {} - Object.keys(importers).forEach((importerId, index) => { - pkgAddressesByImporterId[importerId] = results[index] - }) - return pkgAddressesByImporterId + }, pkgAddressesByImportersWithoutPeers, importersToResolve)) + return zipObj(Object.keys(importers), pkgAddressesByImporters) } interface ResolvedDependenciesResult { From 85fc7f890293c65a80fbb032eb551014accc961e Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 26 Aug 2022 15:54:23 +0300 Subject: [PATCH 4/5] refactor: resolve dependencies --- .../resolve-dependencies/src/resolveDependencies.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index ce5d3cec23e..535860ca0a2 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -314,14 +314,14 @@ export async function resolveDependenciesOfImporters ( resolvedDependencies: options.resolvedDependencies, })) const resolveResults = await Promise.all( - extendedWantedDepsByImporters.map(async (extendedWantedDeps, index) => { + zipWith(async (extendedWantedDeps, importer) => { const postponedResolutionsQueue: PostponedResolutionFunction[] = [] const pkgAddresses: PkgAddress[] = [] ;(await Promise.all( extendedWantedDeps.map((extendedWantedDep) => resolveDependenciesOfDependency( - importers[index].ctx, - importers[index].preferredVersions, - { ...importers[index].options, parentPkgAliases: importers[index].parentPkgAliases }, + importer.ctx, + importer.preferredVersions, + { ...importer.options, parentPkgAliases: importer.parentPkgAliases }, extendedWantedDep )) )).forEach(({ resolveDependencyResult, postponedResolution }) => { @@ -333,7 +333,7 @@ export async function resolveDependenciesOfImporters ( } }) return { pkgAddresses, postponedResolutionsQueue } - }) + }, extendedWantedDepsByImporters, importers) ) return Promise.all(zipWith(async (importer, { pkgAddresses, postponedResolutionsQueue }) => { const newPreferredVersions = { ...importer.preferredVersions } From d1453fbe625f44e37cde753692ce2af7efde3bed Mon Sep 17 00:00:00 2001 From: Zoltan Kochan Date: Fri, 26 Aug 2022 17:40:45 +0300 Subject: [PATCH 5/5] refactor: resolve dependencies --- .../src/resolveDependencies.ts | 28 ++++--------------- .../src/resolveDependencyTree.ts | 15 +++++++--- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index 535860ca0a2..caa5cbb59cf 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -40,9 +40,7 @@ import { } from '@pnpm/types' import * as dp from 'dependency-path' import exists from 'path-exists' -import fromPairs from 'ramda/src/fromPairs' import isEmpty from 'ramda/src/isEmpty' -import zipObj from 'ramda/src/zipObj' import zipWith from 'ramda/src/zipWith' import semver from 'semver' import encodePkgId from './encodePkgId' @@ -221,7 +219,7 @@ export interface ResolvedPackage { type ParentPkg = Pick -type ParentPkgAliases = Record +export type ParentPkgAliases = Record interface ResolvedDependenciesOptions { currentDepth: number @@ -242,22 +240,9 @@ type PostponedResolutionFunction = (preferredVersions: PreferredVersions, parent resolvedPeers: ResolvedPeers }> -export async function resolveRootDependencies ( - importers: Record - options: Omit - }> -): Promise>> { - const importersToResolve = Object.values(importers).map((importer) => ({ - parentPkgAliases: fromPairs( - importer.wantedDependencies.filter(({ alias }) => alias).map(({ alias }) => [alias, true]) - ) as ParentPkgAliases, - ...importer, - })) - const pkgAddressesByImportersWithoutPeers = await resolveDependenciesOfImporters(importersToResolve) - const pkgAddressesByImporters = await Promise.all(zipWith(async (importerResolutionResult, { ctx, parentPkgAliases, preferredVersions, options }) => { +export async function resolveRootDependencies (importers: ImporterToResolve[]): Promise>> { + const pkgAddressesByImportersWithoutPeers = await resolveDependenciesOfImporters(importers) + return Promise.all(zipWith(async (importerResolutionResult, { ctx, parentPkgAliases, preferredVersions, options }) => { const pkgAddresses = importerResolutionResult.pkgAddresses if (!ctx.autoInstallPeers) return pkgAddresses while (true) { @@ -285,8 +270,7 @@ export async function resolveRootDependencies ( pkgAddresses.push(...importerResolutionResult.pkgAddresses) } return pkgAddresses - }, pkgAddressesByImportersWithoutPeers, importersToResolve)) - return zipObj(Object.keys(importers), pkgAddressesByImporters) + }, pkgAddressesByImportersWithoutPeers, importers)) } interface ResolvedDependenciesResult { @@ -295,7 +279,7 @@ interface ResolvedDependenciesResult { resolvedPeers: ResolvedPeers } -interface ImporterToResolve { +export interface ImporterToResolve { ctx: ResolutionContext preferredVersions: PreferredVersions parentPkgAliases: ParentPkgAliases diff --git a/packages/resolve-dependencies/src/resolveDependencyTree.ts b/packages/resolve-dependencies/src/resolveDependencyTree.ts index b056af5839f..758ffc54594 100644 --- a/packages/resolve-dependencies/src/resolveDependencyTree.ts +++ b/packages/resolve-dependencies/src/resolveDependencyTree.ts @@ -7,7 +7,9 @@ import { ReadPackageHook, Registries, } from '@pnpm/types' +import fromPairs from 'ramda/src/fromPairs' import partition from 'ramda/src/partition' +import zipObj from 'ramda/src/zipObj' import { WantedDependency } from './getNonDevWantedDependencies' import { createNodeId, @@ -17,6 +19,8 @@ import { ChildrenByParentDepPath, DependenciesTree, LinkedDependency, + ImporterToResolve, + ParentPkgAliases, PendingNode, PkgAddress, resolveRootDependencies, @@ -117,8 +121,7 @@ export default async function ( appliedPatches: new Set(), } - const resolveArgs = {} - importers.map(async (importer) => { + const resolveArgs: ImporterToResolve[] = importers.map((importer) => { const projectSnapshot = opts.wantedLockfile.importers[importer.id] // This array will only contain the dependencies that should be linked in. // The already linked-in dependencies will not be added. @@ -152,14 +155,18 @@ export default async function ( updateDepth: -1, workspacePackages: opts.workspacePackages, } - resolveArgs[importer.id] = { + return { ctx: resolveCtx, + parentPkgAliases: fromPairs( + importer.wantedDependencies.filter(({ alias }) => alias).map(({ alias }) => [alias, true]) + ) as ParentPkgAliases, preferredVersions: importer.preferredVersions ?? {}, wantedDependencies: importer.wantedDependencies, options: resolveOpts, } }) - const directDepsByImporterId: {[id: string]: Array} = await resolveRootDependencies(resolveArgs) + const pkgAddressesByImporters = await resolveRootDependencies(resolveArgs) + const directDepsByImporterId = zipObj(importers.map(({ id }) => id), pkgAddressesByImporters) ctx.pendingNodes.forEach((pendingNode) => { ctx.dependenciesTree[pendingNode.nodeId] = {