mirror of
https://github.com/pnpm/pnpm.git
synced 2026-05-12 18:49:41 -04:00
This is consistent with #9358, but implements support for the GitHub Packages npm registry and, more broadly, for vlt-style https://docs.vlt.sh/cli/registries for any registry. This PR adds a built-in gh: specifier that resolves against the GitHub Packages npm registry, plus a namedRegistries config key so a project can map its own aliases to arbitrary registries. A project can mix public npm packages and private GitHub Packages (or self-hosted) ones without applying a scope-wide registry override to every @scope/* package. - pnpm add gh:@acme/private writes "@acme/private": "gh:^1.0.0" and resolves from https://npm.pkg.github.com/. - pnpm add gh:@acme/private@^1.0.0 (with or without an alias) is also supported. Aliased form writes "my-alias": "gh:@acme/private@^1.0.0". - Auth comes from the existing per-URL .npmrc mechanism, e.g. //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}. No new auth surface. - @github is intentionally not defaulted to https://npm.pkg.github.com/ - hardcoding that would hijack installs of the public @github/* packages on npmjs.org (e.g. @github/relative-time-element) for users without a scope-wide override. Use gh: to install from GitHub Packages, or configure @github:registry=... yourself if that's really what you want. - Additional named registries (a self-hosted proxy, GitHub Enterprise Server, etc.) can be configured in pnpm-workspace.yaml: ```yml namedRegistries: gh: https://npm.pkg.github.example.com/ # optional: overrides the built-in `gh` alias for GHES work: https://npm.work.example.com/ ``` - Then work:@corp/lib@^2.0.0 resolves against https://npm.work.example.com/, and the built-in gh alias can be redirected to a GHES host. - Env-var substitution (${VAR}) is supported in namedRegistries values, mirroring the .npmrc convention. - Reserved alias names (npm, jsr, github, workspace, catalog, file, git, http, https, link, patch, and related git host shorthands) cannot be redefined as user-named registries - the resolver throws ERR_PNPM_RESERVED_NAMED_REGISTRY_ALIAS at startup rather than silently shadowing another protocol. Malformed URLs throw ERR_PNPM_INVALID_NAMED_REGISTRY_URL at startup too, instead of failing as a confusing 404 during resolution. - On publish, createExportableManifest strips any named-registry prefix (both the built-in gh: and any user-configured alias) so npm and yarn consumers can still resolve the dependency via their own scope-registry configuration - mirroring the user-facing requirement when installing such a dep without the prefix. The prefix is gh: rather than github: because github: is reserved by npm-package-arg / hosted-git-info as a git host shorthand (e.g. github:owner/repo) - reusing it would be a deviation from the specs used by the npm CLI. gh: is shorter, matches vlt's convention, and cannot collide with any existing npm scheme. Unlike jsr:, gh: (and any other named-registry alias) does not rewrite the package name - gh:@acme/foo resolves @acme/foo from the GitHub Packages registry as-is. This also means npm/yarn consumers see the original name after the prefix is stripped on publish. --------- Co-authored-by: Zoltan Kochan <z@kochan.io>
301 lines
8.6 KiB
TypeScript
301 lines
8.6 KiB
TypeScript
import type { Catalogs } from '@pnpm/catalogs.types'
|
|
import type { Hooks } from '@pnpm/hooks.pnpmfile'
|
|
import type {
|
|
EngineDependency,
|
|
Finder,
|
|
Project,
|
|
ProjectManifest,
|
|
ProjectsGraph,
|
|
Registries,
|
|
RegistryConfig,
|
|
TrustPolicy,
|
|
} from '@pnpm/types'
|
|
|
|
import type { OptionsFromRootManifest } from './getOptionsFromRootManifest.js'
|
|
|
|
export type UniversalOptions = Pick<Config, 'color' | 'dir' | 'authConfig'>
|
|
|
|
|
|
export type VerifyDepsBeforeRun = 'install' | 'warn' | 'error' | 'prompt' | false
|
|
|
|
/**
|
|
* Runtime state, workspace context, and CLI metadata.
|
|
* These fields are NOT user-facing settings — they are computed at startup
|
|
* or populated later by the CLI harness (e.g. workspace filtering, hook loading).
|
|
*/
|
|
export interface ConfigContext {
|
|
// -- Runtime state --
|
|
hooks?: Hooks
|
|
finders?: Record<string, Finder>
|
|
|
|
// -- Workspace context --
|
|
allProjects?: Project[]
|
|
selectedProjectsGraph?: ProjectsGraph
|
|
allProjectsGraph?: ProjectsGraph
|
|
rootProjectManifest?: ProjectManifest
|
|
rootProjectManifestDir: string
|
|
|
|
// -- CLI metadata --
|
|
cliOptions: Record<string, any> // eslint-disable-line
|
|
/** Keys explicitly set from workspace yaml, CLI, or env vars (not defaults). */
|
|
explicitlySetKeys: Set<string>
|
|
packageManager: {
|
|
name: string
|
|
version: string
|
|
}
|
|
wantedPackageManager?: WantedPackageManager
|
|
}
|
|
|
|
/**
|
|
* The package manager requested by the root project's manifest.
|
|
* Extends {@link EngineDependency} with the source of the declaration so that
|
|
* callers can treat the legacy `packageManager` field and
|
|
* `devEngines.packageManager` differently (e.g. only the latter persists
|
|
* resolved pnpm integrity info to `pnpm-lock.yaml`).
|
|
*/
|
|
export interface WantedPackageManager extends EngineDependency {
|
|
fromDevEngines?: boolean
|
|
}
|
|
|
|
/**
|
|
* User-facing settings + auth/network config.
|
|
* Does NOT include runtime state — see {@link ConfigContext} for that.
|
|
*/
|
|
export interface Config extends OptionsFromRootManifest {
|
|
allowNew: boolean
|
|
autoConfirmAllPrompts?: boolean
|
|
autoInstallPeers?: boolean
|
|
bail: boolean
|
|
color: 'always' | 'auto' | 'never'
|
|
useBetaCli: boolean
|
|
excludeLinksFromLockfile: boolean
|
|
extraBinPaths: string[]
|
|
extraEnv: Record<string, string>
|
|
failIfNoMatch: boolean
|
|
filter: string[]
|
|
filterProd: string[]
|
|
authConfig: Record<string, any>, // eslint-disable-line
|
|
dryRun?: boolean // This option might be not supported ever
|
|
global?: boolean
|
|
dir: string
|
|
bin: string
|
|
verifyDepsBeforeRun?: VerifyDepsBeforeRun
|
|
ignoreScripts?: boolean
|
|
ignoreCompatibilityDb?: boolean
|
|
includeWorkspaceRoot?: boolean
|
|
optimisticRepeatInstall?: boolean
|
|
save?: boolean
|
|
saveProd?: boolean
|
|
saveDev?: boolean
|
|
saveOptional?: boolean
|
|
savePeer?: boolean
|
|
saveCatalogName?: string
|
|
saveWorkspaceProtocol?: boolean | 'rolling'
|
|
lockfileIncludeTarballUrl?: boolean
|
|
scriptShell?: string
|
|
stream?: boolean
|
|
pnpmExecPath: string
|
|
pnpmHomeDir: string
|
|
production?: boolean
|
|
fetchRetries?: number
|
|
fetchRetryFactor?: number
|
|
fetchRetryMintimeout?: number
|
|
fetchRetryMaxtimeout?: number
|
|
fetchTimeout?: number
|
|
saveExact?: boolean
|
|
savePrefix?: string
|
|
shellEmulator?: boolean
|
|
scriptsPrependNodePath?: boolean | 'warn-only'
|
|
force?: boolean
|
|
depth?: number
|
|
engineStrict?: boolean
|
|
nodeVersion?: string
|
|
nodeDownloadMirrors?: Record<string, string>
|
|
offline?: boolean
|
|
registry?: string
|
|
optional?: boolean
|
|
unsafePerm?: boolean
|
|
loglevel?: 'silent' | 'error' | 'warn' | 'info' | 'debug'
|
|
frozenLockfile?: boolean
|
|
preferFrozenLockfile?: boolean
|
|
only?: 'prod' | 'production' | 'dev' | 'development'
|
|
preferOffline?: boolean
|
|
sideEffectsCache?: boolean // for backward compatibility
|
|
sideEffectsCacheReadonly?: boolean // for backward compatibility
|
|
sideEffectsCacheRead?: boolean
|
|
sideEffectsCacheWrite?: boolean
|
|
shamefullyHoist?: boolean
|
|
dev?: boolean
|
|
ignoreCurrentSpecifiers?: boolean
|
|
recursive?: boolean
|
|
enablePrePostScripts?: boolean
|
|
useStderr?: boolean
|
|
nodeLinker?: 'hoisted' | 'isolated' | 'pnp'
|
|
preferSymlinkedExecutables?: boolean
|
|
resolutionMode?: 'highest' | 'time-based' | 'lowest-direct'
|
|
registrySupportsTimeField?: boolean
|
|
resolvePeersFromWorkspaceRoot?: boolean
|
|
deployAllFiles?: boolean
|
|
forceLegacyDeploy?: boolean
|
|
reporterHidePrefix?: boolean
|
|
|
|
// proxy
|
|
httpProxy?: string
|
|
httpsProxy?: string
|
|
localAddress?: string
|
|
noProxy?: string | boolean
|
|
|
|
// ssl
|
|
cert?: string | string[]
|
|
key?: string
|
|
ca?: string | string[]
|
|
strictSsl?: boolean
|
|
|
|
userAgent?: string
|
|
tag?: string
|
|
updateNotifier?: boolean
|
|
|
|
// pnpm specific configs
|
|
cacheDir: string
|
|
configDir: string
|
|
stateDir: string
|
|
storeDir?: string
|
|
virtualStoreDir?: string
|
|
virtualStoreOnly?: boolean
|
|
enableGlobalVirtualStore?: boolean
|
|
verifyStoreIntegrity?: boolean
|
|
maxSockets?: number
|
|
networkConcurrency?: number
|
|
fetchingConcurrency?: number
|
|
lockfileOnly?: boolean // like npm's --package-lock-only
|
|
childConcurrency?: number
|
|
ignorePnpmfile?: boolean
|
|
pnpmfile: string[] | string
|
|
tryLoadDefaultPnpmfile?: boolean
|
|
packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy'
|
|
hoistPattern?: string[]
|
|
publicHoistPattern?: string[] | string
|
|
hoistWorkspacePackages?: boolean
|
|
useStoreServer?: boolean
|
|
useRunningStoreServer?: boolean
|
|
workspaceConcurrency: number
|
|
workspaceDir?: string
|
|
workspacePackagePatterns?: string[]
|
|
catalogs?: Catalogs
|
|
catalogMode?: 'strict' | 'prefer' | 'manual'
|
|
cleanupUnusedCatalogs?: boolean
|
|
reporter?: string
|
|
aggregateOutput: boolean
|
|
linkWorkspacePackages: boolean | 'deep'
|
|
injectWorkspacePackages?: boolean
|
|
preferWorkspacePackages: boolean
|
|
reverse: boolean
|
|
sort: boolean
|
|
strictPeerDependencies: boolean
|
|
lockfileDir?: string
|
|
modulesDir?: string
|
|
sharedWorkspaceLockfile?: boolean
|
|
useLockfile: boolean
|
|
useGitBranchLockfile: boolean
|
|
mergeGitBranchLockfiles?: boolean
|
|
mergeGitBranchLockfilesBranchPattern?: string[]
|
|
globalPnpmfile?: string
|
|
npmPath?: string
|
|
gitChecks?: boolean
|
|
publishBranch?: string
|
|
recursiveInstall?: boolean
|
|
symlink: boolean
|
|
enablePnp?: boolean
|
|
enableModulesDir: boolean
|
|
modulesCacheMaxAge: number
|
|
dlxCacheMaxAge: number
|
|
embedReadme?: boolean
|
|
gitShallowHosts?: string[]
|
|
legacyDirFiltering?: boolean
|
|
allowBuilds?: Record<string, boolean | string>
|
|
dedupePeerDependents?: boolean
|
|
dedupePeers?: boolean
|
|
patchesDir?: string
|
|
ignoreWorkspaceCycles?: boolean
|
|
disallowWorkspaceCycles?: boolean
|
|
packGzipLevel?: number
|
|
blockExoticSubdeps?: boolean
|
|
|
|
agent?: string
|
|
|
|
registries: Registries
|
|
namedRegistries?: Record<string, string>
|
|
configByUri: Record<string, RegistryConfig>
|
|
ignoreWorkspaceRootCheck: boolean
|
|
workspaceRoot: boolean
|
|
|
|
testPattern?: string[]
|
|
changedFilesIgnorePattern?: string[]
|
|
userConfig: Record<string, string>
|
|
|
|
hoist: boolean
|
|
packageLock: boolean
|
|
pending: boolean
|
|
userconfig: string
|
|
npmrcAuthFile?: string
|
|
workspacePrefix?: string
|
|
dedupeDirectDeps?: boolean
|
|
extendNodePath?: boolean
|
|
gitBranchLockfile?: boolean
|
|
globalBinDir?: string
|
|
globalDir?: string
|
|
globalPkgDir: string
|
|
lockfile?: boolean
|
|
dedupeInjectedDeps?: boolean
|
|
nodeOptions?: string
|
|
pmOnFail?: 'download' | 'error' | 'warn' | 'ignore'
|
|
runtimeOnFail?: 'download' | 'error' | 'warn' | 'ignore'
|
|
virtualStoreDirMaxLength: number
|
|
peersSuffixMaxLength?: number
|
|
strictStorePkgContentCheck: boolean
|
|
strictDepBuilds: boolean
|
|
syncInjectedDepsAfterScripts?: string[]
|
|
initPackageManager: boolean
|
|
initType: 'commonjs' | 'module'
|
|
dangerouslyAllowAllBuilds: boolean
|
|
ci: boolean
|
|
preserveAbsolutePaths?: boolean
|
|
minimumReleaseAge?: number
|
|
minimumReleaseAgeExclude?: string[]
|
|
minimumReleaseAgeIgnoreMissingTime?: boolean
|
|
minimumReleaseAgeStrict?: boolean
|
|
fetchWarnTimeoutMs?: number
|
|
fetchMinSpeedKiBps?: number
|
|
trustPolicy?: TrustPolicy
|
|
trustPolicyExclude?: string[]
|
|
trustPolicyIgnoreAfter?: number
|
|
auditLevel?: 'info' | 'low' | 'moderate' | 'high' | 'critical'
|
|
|
|
packageConfigs?: ProjectConfigSet
|
|
}
|
|
|
|
export interface ConfigWithDeprecatedSettings extends Config {
|
|
globalPrefix?: string
|
|
proxy?: string
|
|
}
|
|
|
|
export const PROJECT_CONFIG_FIELDS = [
|
|
'hoist',
|
|
'modulesDir',
|
|
'overrides',
|
|
'saveExact',
|
|
'savePrefix',
|
|
] as const satisfies Array<keyof Config>
|
|
|
|
export type ProjectConfig = Partial<Pick<Config, typeof PROJECT_CONFIG_FIELDS[number] | 'hoistPattern'>>
|
|
|
|
/** Simple map from project names to {@link ProjectConfig} */
|
|
export type ProjectConfigRecord = Record<string, ProjectConfig>
|
|
|
|
/** Map multiple project names to a shared {@link ProjectConfig} */
|
|
export type ProjectConfigMultiMatch = { match: string[] } & ProjectConfig
|
|
|
|
export type ProjectConfigSet =
|
|
| ProjectConfigRecord
|
|
| ProjectConfigMultiMatch[]
|