From 272129193c1e6a5ed46f5c8facb42e87b419e666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kh=E1=BA=A3i?= Date: Fri, 16 May 2025 18:14:06 +0700 Subject: [PATCH] refactor: improve resolver types (#9544) --- .changeset/dull-carrots-matter.md | 10 ++++++++ resolving/default-resolver/src/index.ts | 27 ++++++++++++++++---- resolving/git-resolver/src/index.ts | 18 ++++++++----- resolving/local-resolver/src/index.ts | 17 +++++-------- resolving/npm-resolver/src/index.ts | 34 +++++++++++++++++++++---- resolving/resolver-base/src/index.ts | 14 +--------- resolving/tarball-resolver/src/index.ts | 12 ++++++--- 7 files changed, 90 insertions(+), 42 deletions(-) create mode 100644 .changeset/dull-carrots-matter.md diff --git a/.changeset/dull-carrots-matter.md b/.changeset/dull-carrots-matter.md new file mode 100644 index 0000000000..21bd879108 --- /dev/null +++ b/.changeset/dull-carrots-matter.md @@ -0,0 +1,10 @@ +--- +"@pnpm/default-resolver": minor +"@pnpm/tarball-resolver": minor +"@pnpm/local-resolver": major +"@pnpm/resolver-base": major +"@pnpm/git-resolver": minor +"@pnpm/npm-resolver": minor +--- + +Create different resolver result types which provide more information. diff --git a/resolving/default-resolver/src/index.ts b/resolving/default-resolver/src/index.ts index 779d053203..e369b320c9 100644 --- a/resolving/default-resolver/src/index.ts +++ b/resolving/default-resolver/src/index.ts @@ -1,16 +1,23 @@ import { PnpmError } from '@pnpm/error' import { type FetchFromRegistry, type GetAuthHeader } from '@pnpm/fetching-types' -import { createGitResolver } from '@pnpm/git-resolver' -import { resolveFromLocal } from '@pnpm/local-resolver' +import { type GitResolveResult, createGitResolver } from '@pnpm/git-resolver' +import { type LocalResolveResult, resolveFromLocal } from '@pnpm/local-resolver' import { createNpmResolver, + type JsrResolveResult, + type NpmResolveResult, + type WorkspaceResolveResult, type PackageMeta, type PackageMetaCache, type ResolveFromNpmOptions, type ResolverFactoryOptions, } from '@pnpm/npm-resolver' -import { type ResolveFunction } from '@pnpm/resolver-base' -import { resolveFromTarball } from '@pnpm/tarball-resolver' +import { + type ResolveFunction, + type ResolveOptions, + type WantedDependency, +} from '@pnpm/resolver-base' +import { type TarballResolveResult, resolveFromTarball } from '@pnpm/tarball-resolver' export type { PackageMeta, @@ -19,11 +26,21 @@ export type { ResolverFactoryOptions, } +export type DefaultResolveResult = + | NpmResolveResult + | JsrResolveResult + | GitResolveResult + | LocalResolveResult + | TarballResolveResult + | WorkspaceResolveResult + +export type DefaultResolver = (wantedDependency: WantedDependency, opts: ResolveOptions) => Promise + export function createResolver ( fetchFromRegistry: FetchFromRegistry, getAuthHeader: GetAuthHeader, pnpmOpts: ResolverFactoryOptions -): { resolve: ResolveFunction, clearCache: () => void } { +): { resolve: DefaultResolver, clearCache: () => void } { const { resolveFromNpm, resolveFromJsr, clearCache } = createNpmResolver(fetchFromRegistry, getAuthHeader, pnpmOpts) const resolveFromGit = createGitResolver(pnpmOpts) return { diff --git a/resolving/git-resolver/src/index.ts b/resolving/git-resolver/src/index.ts index 1502e38a7a..2afdea13c3 100644 --- a/resolving/git-resolver/src/index.ts +++ b/resolving/git-resolver/src/index.ts @@ -1,4 +1,4 @@ -import { type TarballResolution, type GitResolution, type ResolveResult, type PkgResolutionId } from '@pnpm/resolver-base' +import { type TarballResolution, type GitResolution, type PkgResolutionId, type ResolveResult } from '@pnpm/resolver-base' import git from 'graceful-git' import semver from 'semver' import { parseBareSpecifier, type HostedPackageSpec } from './parseBareSpecifier' @@ -9,14 +9,20 @@ export { createGitHostedPkgId } export type { HostedPackageSpec } +export interface GitResolveResult extends ResolveResult { + normalizedBareSpecifier: string + resolution: GitResolution | TarballResolution + resolvedVia: 'git-repository' +} + export type GitResolver = (wantedDependency: { bareSpecifier: string -}) => Promise +}) => Promise export function createGitResolver ( opts: AgentOptions ): GitResolver { - return async function resolveGit (wantedDependency): Promise { + return async function resolveGit (wantedDependency): Promise { const parsedSpec = await parseBareSpecifier(wantedDependency.bareSpecifier, opts) if (parsedSpec == null) return null @@ -25,7 +31,7 @@ export function createGitResolver ( ? 'HEAD' : parsedSpec.gitCommittish const commit = await resolveRef(parsedSpec.fetchSpec, bareSpecifier, parsedSpec.gitRange) - let resolution + let resolution: GitResolution | TarballResolution | undefined if ((parsedSpec.hosted != null) && !isSsh(parsedSpec.fetchSpec)) { // don't use tarball for ssh url, they are likely private repo @@ -35,7 +41,7 @@ export function createGitResolver ( const tarball = hosted.tarball?.() if (tarball) { - resolution = { tarball } as TarballResolution + resolution = { tarball } } } @@ -44,7 +50,7 @@ export function createGitResolver ( commit, repo: parsedSpec.fetchSpec, type: 'git', - } as GitResolution + } } if (parsedSpec.path) { diff --git a/resolving/local-resolver/src/index.ts b/resolving/local-resolver/src/index.ts index a07bc064e9..952b5c8a1c 100644 --- a/resolving/local-resolver/src/index.ts +++ b/resolving/local-resolver/src/index.ts @@ -3,21 +3,18 @@ import path from 'path' import { getTarballIntegrity } from '@pnpm/crypto.hash' import { PnpmError } from '@pnpm/error' import { readProjectManifestOnly } from '@pnpm/read-project-manifest' -import { - type DirectoryResolution, - type ResolveResult, - type TarballResolution, -} from '@pnpm/resolver-base' +import { type DirectoryResolution, type ResolveResult, type TarballResolution } from '@pnpm/resolver-base' import { type DependencyManifest } from '@pnpm/types' import { logger } from '@pnpm/logger' import { parseBareSpecifier, type WantedLocalDependency } from './parseBareSpecifier' -export type { WantedLocalDependency } +export { type WantedLocalDependency } -export interface ResolveFromLocalResult extends ResolveResult { - normalizedBareSpecifier: string - resolution: TarballResolution | DirectoryResolution +export interface LocalResolveResult extends ResolveResult { manifest?: DependencyManifest + normalizedBareSpecifier: string + resolution: DirectoryResolution | TarballResolution + resolvedVia: 'local-filesystem' } /** @@ -29,7 +26,7 @@ export async function resolveFromLocal ( lockfileDir?: string projectDir: string } -): Promise { +): Promise { const spec = parseBareSpecifier(wantedDependency, opts.projectDir, opts.lockfileDir ?? opts.projectDir) if (spec == null) return null if (spec.type === 'file') { diff --git a/resolving/npm-resolver/src/index.ts b/resolving/npm-resolver/src/index.ts index 6bda398aea..b16c94481f 100644 --- a/resolving/npm-resolver/src/index.ts +++ b/resolving/npm-resolver/src/index.ts @@ -9,16 +9,17 @@ import { import { pickRegistryForPackage } from '@pnpm/pick-registry-for-package' import { resolveWorkspaceRange } from '@pnpm/resolve-workspace-range' import { + type DirectoryResolution, type PkgResolutionId, type PreferredVersions, type ResolveResult, + type TarballResolution, type WantedDependency, type WorkspacePackage, type WorkspacePackages, type WorkspacePackagesByVersion, - type WorkspaceResolveResult, } from '@pnpm/resolver-base' -import { type Registries, type PinnedVersion } from '@pnpm/types' +import { type DependencyManifest, type Registries, type PinnedVersion } from '@pnpm/types' import { LRUCache } from 'lru-cache' import normalize from 'normalize-path' import pMemoize from 'p-memoize' @@ -75,7 +76,30 @@ export interface ResolverFactoryOptions { saveWorkspaceProtocol?: boolean | 'rolling' } -export type NpmResolver = (wantedDependency: WantedDependency, opts: ResolveFromNpmOptions) => Promise +export interface NpmResolveResult extends ResolveResult { + latest: string + manifest: DependencyManifest + resolution: TarballResolution + resolvedVia: 'npm-registry' +} + +export interface JsrResolveResult extends ResolveResult { + alias: string + manifest: DependencyManifest + resolution: TarballResolution + resolvedVia: 'jsr-registry' +} + +export interface WorkspaceResolveResult extends ResolveResult { + manifest: DependencyManifest + resolution: DirectoryResolution + resolvedVia: 'workspace' +} + +export type NpmResolver = ( + wantedDependency: WantedDependency, + opts: ResolveFromNpmOptions +) => Promise export function createNpmResolver ( fetchFromRegistry: FetchFromRegistry, @@ -152,7 +176,7 @@ async function resolveNpm ( ctx: ResolveFromNpmContext, wantedDependency: WantedDependency, opts: ResolveFromNpmOptions -): Promise { +): Promise { const defaultTag = opts.defaultTag ?? 'latest' const registry = wantedDependency.alias ? pickRegistryForPackage(ctx.registries, wantedDependency.alias, wantedDependency.bareSpecifier) @@ -297,7 +321,7 @@ async function resolveJsr ( ctx: ResolveFromNpmContext, wantedDependency: WantedDependency, opts: Omit -): Promise { +): Promise { if (!wantedDependency.bareSpecifier) return null const defaultTag = opts.defaultTag ?? 'latest' diff --git a/resolving/resolver-base/src/index.ts b/resolving/resolver-base/src/index.ts index baab14f4b4..b08b996474 100644 --- a/resolving/resolver-base/src/index.ts +++ b/resolving/resolver-base/src/index.ts @@ -44,23 +44,11 @@ export interface ResolveResult { publishedAt?: string manifest?: DependencyManifest resolution: Resolution - resolvedVia: 'npm-registry' | 'git-repository' | 'local-filesystem' | 'workspace' | 'url' | string + resolvedVia: string normalizedBareSpecifier?: string alias?: string } -/** - * A dependency on a workspace package. - */ -export interface WorkspaceResolveResult extends ResolveResult { - /** - * 'workspace' will be returned for workspace: protocol dependencies or a - * package in the workspace that matches the wanted dependency's name and - * version range. - */ - resolvedVia: 'workspace' -} - export interface WorkspacePackage { rootDir: ProjectRootDir manifest: DependencyManifest diff --git a/resolving/tarball-resolver/src/index.ts b/resolving/tarball-resolver/src/index.ts index 069324be67..66fe66b54a 100644 --- a/resolving/tarball-resolver/src/index.ts +++ b/resolving/tarball-resolver/src/index.ts @@ -1,17 +1,23 @@ -import { type PkgResolutionId, type ResolveResult } from '@pnpm/resolver-base' +import { type PkgResolutionId, type ResolveResult, type TarballResolution } from '@pnpm/resolver-base' import { type FetchFromRegistry } from '@pnpm/fetching-types' +export interface TarballResolveResult extends ResolveResult { + normalizedBareSpecifier: string + resolution: TarballResolution + resolvedVia: 'url' +} + export async function resolveFromTarball ( fetchFromRegistry: FetchFromRegistry, wantedDependency: { bareSpecifier: string } -): Promise { +): Promise { if (!wantedDependency.bareSpecifier.startsWith('http:') && !wantedDependency.bareSpecifier.startsWith('https:')) { return null } if (isRepository(wantedDependency.bareSpecifier)) return null - let resolvedUrl + let resolvedUrl: string // If there are redirects and the response is immutable, we want to get the final URL address const response = await fetchFromRegistry(wantedDependency.bareSpecifier, { method: 'HEAD' })