refactor: improve resolver types (#9544)

This commit is contained in:
Khải
2025-05-16 18:14:06 +07:00
committed by GitHub
parent a90dffc19d
commit 272129193c
7 changed files with 90 additions and 42 deletions

View File

@@ -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.

View File

@@ -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<DefaultResolveResult>
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 {

View File

@@ -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<ResolveResult | null>
}) => Promise<GitResolveResult | null>
export function createGitResolver (
opts: AgentOptions
): GitResolver {
return async function resolveGit (wantedDependency): Promise<ResolveResult | null> {
return async function resolveGit (wantedDependency): Promise<GitResolveResult | null> {
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) {

View File

@@ -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<ResolveFromLocalResult | null> {
): Promise<LocalResolveResult | null> {
const spec = parseBareSpecifier(wantedDependency, opts.projectDir, opts.lockfileDir ?? opts.projectDir)
if (spec == null) return null
if (spec.type === 'file') {

View File

@@ -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<ResolveResult | null>
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<NpmResolveResult | JsrResolveResult | WorkspaceResolveResult | null>
export function createNpmResolver (
fetchFromRegistry: FetchFromRegistry,
@@ -152,7 +176,7 @@ async function resolveNpm (
ctx: ResolveFromNpmContext,
wantedDependency: WantedDependency,
opts: ResolveFromNpmOptions
): Promise<ResolveResult | null> {
): Promise<NpmResolveResult | WorkspaceResolveResult | null> {
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<ResolveFromNpmOptions, 'registry'>
): Promise<ResolveResult | null> {
): Promise<JsrResolveResult | null> {
if (!wantedDependency.bareSpecifier) return null
const defaultTag = opts.defaultTag ?? 'latest'

View File

@@ -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

View File

@@ -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<ResolveResult | null> {
): Promise<TarballResolveResult | null> {
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' })