mirror of
https://github.com/pnpm/pnpm.git
synced 2025-12-23 23:29:17 -05:00
refactor: resolvers should calculate the specifiers that are saved into package.json (#9426)
* refactor: resolvers should return specifier templates * refactor: updating workspace protocol specs in package.json * refactor: move workspace selector calculation logic to npm-resolver * refactor: move workspace selector calculation logic to npm-resolver * refactor: calculating range in npm-resolver * refactor: rename normalizedPref and specifierTemplate to specifier * refactor: specifiers creation * refactor: npm-resolver * refactor: remove which-version-is-pinned package * refactor: which version is pinned * docs: add changesets * refactor: implement suggestions * refactor: revert regex usage
This commit is contained in:
5
.changeset/rude-rooms-laugh.md
Normal file
5
.changeset/rude-rooms-laugh.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/manifest-utils": major
|
||||
---
|
||||
|
||||
Moved out `createVersionSpec` to `@pnpm/npm-resolver`.
|
||||
14
.changeset/silent-cameras-take.md
Normal file
14
.changeset/silent-cameras-take.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
"@pnpm/resolve-dependencies": major
|
||||
"@pnpm/store-connection-manager": major
|
||||
"@pnpm/package-requester": major
|
||||
"@pnpm/store-controller-types": major
|
||||
"@pnpm/tarball-resolver": major
|
||||
"@pnpm/local-resolver": major
|
||||
"@pnpm/resolver-base": major
|
||||
"@pnpm/git-resolver": major
|
||||
"@pnpm/npm-resolver": major
|
||||
"@pnpm/core": patch
|
||||
---
|
||||
|
||||
Renamed `normalizedPref` to `specifiers`.
|
||||
5
.changeset/spicy-rice-drive.md
Normal file
5
.changeset/spicy-rice-drive.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/types": minor
|
||||
---
|
||||
|
||||
Added `PinnedVersion`.
|
||||
@@ -36,3 +36,9 @@ export type PkgIdWithPatchHash = string & { __brand: 'PkgIdWithPatchHash' }
|
||||
export type DepPath = string & { __brand: 'DepPath' }
|
||||
|
||||
export type ProjectId = string & { __brand: 'ProjectId' }
|
||||
|
||||
export type PinnedVersion =
|
||||
| 'none'
|
||||
| 'patch'
|
||||
| 'minor'
|
||||
| 'major'
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# @pnpm/which-version-is-pinned
|
||||
|
||||
## 6.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- 43cdd87: Node.js v16 support dropped. Use at least Node.js v18.12.
|
||||
|
||||
## 5.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 4fc497882: When updating dependencies, preserve the range prefix in aliased dependencies. So `npm:foo@1.0.0` becomes `npm:foo@1.1.0`.
|
||||
|
||||
## 5.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- eceaa8b8b: Node.js 14 support dropped.
|
||||
|
||||
## 4.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- f884689e0: Require `@pnpm/logger` v5.
|
||||
|
||||
## 3.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- f5621a42c: A new value `rolling` for option `save-workspace-protocol`. When selected, pnpm will save workspace versions using a rolling alias (e.g. `"foo": "workspace:^"`) instead of pinning the current version number (e.g. `"foo": "workspace:^1.0.0"`). Usage example:
|
||||
|
||||
```
|
||||
pnpm --save-workspace-protocol=rolling add foo
|
||||
```
|
||||
|
||||
## 2.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- 542014839: Node.js 12 is not supported.
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- ae32d313e: Initial release.
|
||||
@@ -1,22 +0,0 @@
|
||||
# @pnpm/which-version-is-pinned
|
||||
|
||||
> Takes a version spec and returns which version is pinned by it
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
pnpm add @pnpm/which-version-is-pinned
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { whichVersionIsPinned } from '@pnpm/which-version-is-pinned'
|
||||
|
||||
whichVersionIsPinned('^1.0.0')
|
||||
// major
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"name": "@pnpm/which-version-is-pinned",
|
||||
"version": "1000.0.0",
|
||||
"description": "Takes a version spec and returns which version is pinned by it",
|
||||
"keywords": [
|
||||
"pnpm",
|
||||
"pnpm10"
|
||||
],
|
||||
"license": "MIT",
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
"repository": "https://github.com/pnpm/pnpm/blob/main/packages/which-version-is-pinned",
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/main/packages/which-version-is-pinned#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/pnpm/pnpm/issues"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"exports": {
|
||||
".": "./lib/index.js"
|
||||
},
|
||||
"files": [
|
||||
"lib",
|
||||
"!*.map"
|
||||
],
|
||||
"scripts": {
|
||||
"_test": "jest",
|
||||
"test": "pnpm run compile && pnpm run _test",
|
||||
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"prepublishOnly": "pnpm run compile",
|
||||
"compile": "tsc --build && pnpm run lint --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver-utils": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@pnpm/which-version-is-pinned": "workspace:*"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.12"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "@pnpm/jest-config"
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": false,
|
||||
"outDir": "../test.lib",
|
||||
"rootDir": "."
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"../../../__typings__/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": ".."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"extends": "@pnpm/tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"../../__typings__/**/*.d.ts"
|
||||
],
|
||||
"references": []
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"test/**/*.ts",
|
||||
"../../__typings__/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
@@ -102,7 +102,6 @@
|
||||
"@pnpm/store-controller-types": "workspace:*",
|
||||
"@pnpm/symlink-dependency": "workspace:*",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"@pnpm/which-version-is-pinned": "workspace:*",
|
||||
"@zkochan/rimraf": "catalog:",
|
||||
"ci-info": "catalog:",
|
||||
"enquirer": "catalog:",
|
||||
|
||||
@@ -476,7 +476,7 @@ export async function mutateModules (
|
||||
includeDirect: opts.includeDirect,
|
||||
nodeExecPath: opts.nodeExecPath,
|
||||
})
|
||||
.map((wantedDependency) => ({ ...wantedDependency, updateSpec: true, preserveNonSemverVersionSpec: true }))
|
||||
.map((wantedDependency) => ({ ...wantedDependency, updateSpec: true }))
|
||||
|
||||
if (ctx.wantedLockfile?.importers) {
|
||||
forgetResolutionsOfPrevWantedDeps(ctx.wantedLockfile.importers[project.id], wantedDependencies, _isWantedDepPrefSame)
|
||||
@@ -898,7 +898,7 @@ export type ImporterToUpdate = {
|
||||
pruneDirectDependencies: boolean
|
||||
removePackages?: string[]
|
||||
updatePackageManifest: boolean
|
||||
wantedDependencies: Array<WantedDependency & { isNew?: boolean, updateSpec?: boolean, preserveNonSemverVersionSpec?: boolean }>
|
||||
wantedDependencies: Array<WantedDependency & { isNew?: boolean, updateSpec?: boolean }>
|
||||
} & DependenciesMutation
|
||||
|
||||
export interface UpdatedProject {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { parseWantedDependency } from '@pnpm/parse-wanted-dependency'
|
||||
import { type Dependencies } from '@pnpm/types'
|
||||
import { whichVersionIsPinned } from '@pnpm/which-version-is-pinned'
|
||||
import { type PinnedVersion, type WantedDependency } from '@pnpm/resolve-dependencies/lib/getWantedDependencies'
|
||||
import { type WantedDependency } from '@pnpm/resolve-dependencies'
|
||||
import { type Catalog } from '@pnpm/catalogs.types'
|
||||
|
||||
export function parseWantedDependencies (
|
||||
@@ -25,7 +24,6 @@ export function parseWantedDependencies (
|
||||
const parsed = parseWantedDependency(rawWantedDependency)
|
||||
const alias = parsed['alias']
|
||||
let pref = parsed['pref']
|
||||
let pinnedVersion!: PinnedVersion | undefined
|
||||
|
||||
if (!opts.allowNew && (!alias || !opts.currentPrefs[alias])) {
|
||||
return null
|
||||
@@ -39,13 +37,12 @@ export function parseWantedDependencies (
|
||||
}
|
||||
if (alias && opts.currentPrefs[alias]) {
|
||||
pref ??= opts.currentPrefs[alias]
|
||||
pinnedVersion = whichVersionIsPinned(opts.currentPrefs[alias])
|
||||
}
|
||||
const result = {
|
||||
alias,
|
||||
dev: Boolean(opts.dev || alias && !!opts.devDependencies[alias]),
|
||||
optional: Boolean(opts.optional || alias && !!opts.optionalDependencies[alias]),
|
||||
pinnedVersion,
|
||||
prevSpecifier: alias && opts.currentPrefs[alias],
|
||||
}
|
||||
if (pref) {
|
||||
return {
|
||||
|
||||
@@ -361,6 +361,7 @@ test('overwriting (magic-hook@2.0.0 and @0.1.0)', async () => {
|
||||
test('overwriting (is-positive@3.0.0 with is-positive@latest)', async () => {
|
||||
const project = prepareEmpty()
|
||||
const { updatedManifest: manifest } = await addDependenciesToPackage({}, ['is-positive@3.0.0'], testDefaults({ save: true }))
|
||||
expect(manifest.dependencies?.['is-positive']).toBe('3.0.0')
|
||||
|
||||
project.storeHas('is-positive', '3.0.0')
|
||||
|
||||
|
||||
@@ -978,7 +978,6 @@ test('adding a new dependency with the workspace: protocol', async () => {
|
||||
rootDir: path.resolve('project-1') as ProjectRootDir,
|
||||
},
|
||||
], testDefaults({
|
||||
saveWorkspaceProtocol: true,
|
||||
allProjects: [
|
||||
{
|
||||
manifest: {
|
||||
@@ -995,9 +994,11 @@ test('adding a new dependency with the workspace: protocol', async () => {
|
||||
rootDir: path.resolve('project-1') as ProjectRootDir,
|
||||
},
|
||||
],
|
||||
}, {
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
}))
|
||||
|
||||
expect(updatedProjects[0].manifest.dependencies).toStrictEqual({ foo: 'workspace:^1.0.0' })
|
||||
expect(updatedProjects[0].manifest.dependencies).toStrictEqual({ foo: 'workspace:^' })
|
||||
})
|
||||
|
||||
test('adding a new dependency with the workspace: protocol and save-workspace-protocol is "rolling"', async () => {
|
||||
@@ -1011,7 +1012,6 @@ test('adding a new dependency with the workspace: protocol and save-workspace-pr
|
||||
rootDir: path.resolve('project-1') as ProjectRootDir,
|
||||
},
|
||||
], testDefaults({
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
allProjects: [
|
||||
{
|
||||
manifest: {
|
||||
@@ -1028,6 +1028,8 @@ test('adding a new dependency with the workspace: protocol and save-workspace-pr
|
||||
rootDir: path.resolve('project-1') as ProjectRootDir,
|
||||
},
|
||||
],
|
||||
}, {
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
}))
|
||||
|
||||
expect(updatedProjects[0].manifest.dependencies).toStrictEqual({ foo: 'workspace:^' })
|
||||
@@ -1152,15 +1154,16 @@ test('update workspace range', async () => {
|
||||
rootDir: path.resolve('dep8') as ProjectRootDir,
|
||||
},
|
||||
],
|
||||
saveWorkspaceProtocol: true,
|
||||
}, {
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
}))
|
||||
|
||||
const expected = {
|
||||
dep1: 'workspace:2.0.0',
|
||||
dep2: 'workspace:~2.0.0',
|
||||
dep3: 'workspace:^2.0.0',
|
||||
dep4: 'workspace:^2.0.0',
|
||||
dep5: 'workspace:~2.0.0',
|
||||
dep1: 'workspace:*',
|
||||
dep2: 'workspace:~',
|
||||
dep3: 'workspace:^',
|
||||
dep4: 'workspace:^',
|
||||
dep5: 'workspace:~',
|
||||
dep6: 'workspace:*',
|
||||
dep7: 'workspace:^',
|
||||
dep8: 'workspace:~',
|
||||
@@ -1268,6 +1271,7 @@ test('update workspace range when save-workspace-protocol is "rolling"', async (
|
||||
rootDir: path.resolve('dep6') as ProjectRootDir,
|
||||
},
|
||||
],
|
||||
}, {
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
}))
|
||||
|
||||
|
||||
@@ -27,14 +27,14 @@ test("don't override existing spec in package.json on named installation", async
|
||||
sec: 'sindresorhus/sec#main',
|
||||
},
|
||||
}, ['is-positive'], testDefaults())
|
||||
manifest = (await addDependenciesToPackage(manifest, ['is-negative'], testDefaults())).updatedManifest
|
||||
manifest = (await addDependenciesToPackage(manifest, ['is-negative@latest'], testDefaults())).updatedManifest
|
||||
manifest = (await addDependenciesToPackage(manifest, ['sec'], testDefaults())).updatedManifest
|
||||
|
||||
expect(project.requireModule('is-positive/package.json').version).toBe('2.0.0')
|
||||
expect(project.requireModule('is-negative/package.json').version).toBe('1.0.1')
|
||||
expect(project.requireModule('is-negative/package.json').version).toBe('2.1.0')
|
||||
|
||||
expect(manifest.dependencies).toStrictEqual({
|
||||
'is-negative': '^1.0.1',
|
||||
'is-negative': '^2.1.0',
|
||||
'is-positive': '^2.0.0',
|
||||
sec: 'sindresorhus/sec#main',
|
||||
})
|
||||
|
||||
@@ -123,9 +123,6 @@
|
||||
{
|
||||
"path": "../../packages/types"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/which-version-is-pinned"
|
||||
},
|
||||
{
|
||||
"path": "../../patching/config"
|
||||
},
|
||||
|
||||
@@ -161,7 +161,7 @@ async function resolveAndFetch (
|
||||
): Promise<PackageResponse> {
|
||||
let latest: string | undefined
|
||||
let manifest: DependencyManifest | undefined
|
||||
let normalizedPref: string | undefined
|
||||
let specifier: string | undefined
|
||||
let resolution = options.currentPkg?.resolution as Resolution
|
||||
let pkgId = options.currentPkg?.id
|
||||
const skipResolution = resolution && !options.update
|
||||
@@ -188,6 +188,8 @@ async function resolveAndFetch (
|
||||
workspacePackages: options.workspacePackages,
|
||||
update: options.update,
|
||||
injectWorkspacePackages: options.injectWorkspacePackages,
|
||||
calcSpecifier: options.calcSpecifier,
|
||||
pinnedVersion: options.pinnedVersion,
|
||||
}), { priority: options.downloadPriority })
|
||||
|
||||
manifest = resolveResult.manifest
|
||||
@@ -206,7 +208,7 @@ async function resolveAndFetch (
|
||||
updated = pkgId !== resolveResult.id || !resolution || forceFetch
|
||||
resolution = resolveResult.resolution
|
||||
pkgId = resolveResult.id
|
||||
normalizedPref = resolveResult.normalizedPref
|
||||
specifier = resolveResult.specifier
|
||||
}
|
||||
|
||||
const id = pkgId!
|
||||
@@ -220,10 +222,10 @@ async function resolveAndFetch (
|
||||
id,
|
||||
isLocal: true,
|
||||
manifest,
|
||||
normalizedPref,
|
||||
resolution: resolution as DirectoryResolution,
|
||||
resolvedVia,
|
||||
updated,
|
||||
specifier,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -252,7 +254,7 @@ async function resolveAndFetch (
|
||||
isInstallable: isInstallable ?? undefined,
|
||||
latest,
|
||||
manifest,
|
||||
normalizedPref,
|
||||
specifier,
|
||||
resolution,
|
||||
resolvedVia,
|
||||
updated,
|
||||
@@ -288,7 +290,7 @@ async function resolveAndFetch (
|
||||
isInstallable: isInstallable ?? undefined,
|
||||
latest,
|
||||
manifest,
|
||||
normalizedPref,
|
||||
specifier,
|
||||
resolution,
|
||||
resolvedVia,
|
||||
updated,
|
||||
|
||||
@@ -62,7 +62,7 @@ test('request package', async () => {
|
||||
expect(pkgResponse.body.isLocal).toBe(false)
|
||||
expect(typeof pkgResponse.body.latest).toBe('string')
|
||||
expect(pkgResponse.body.manifest?.name).toBe('is-positive')
|
||||
expect(!pkgResponse.body.normalizedPref).toBeTruthy()
|
||||
expect(!pkgResponse.body.specifier).toBeTruthy()
|
||||
expect(pkgResponse.body.resolution).toStrictEqual({
|
||||
integrity: 'sha512-xxzPGZ4P2uN6rROUa5N9Z7zTX6ERuE0hs6GUOc/cKBLF2NqKc16UwqHMt3tFg4CO6EBTE5UecUasg+3jZx3Ckg==',
|
||||
tarball: `http://localhost:${REGISTRY_MOCK_PORT}/is-positive/-/is-positive-1.0.0.tgz`,
|
||||
@@ -103,7 +103,7 @@ test('request package but skip fetching', async () => {
|
||||
expect(pkgResponse.body.isLocal).toBe(false)
|
||||
expect(typeof pkgResponse.body.latest).toBe('string')
|
||||
expect(pkgResponse.body.manifest?.name).toBe('is-positive')
|
||||
expect(!pkgResponse.body.normalizedPref).toBeTruthy()
|
||||
expect(!pkgResponse.body.specifier).toBeTruthy()
|
||||
expect(pkgResponse.body.resolution).toStrictEqual({
|
||||
integrity: 'sha512-xxzPGZ4P2uN6rROUa5N9Z7zTX6ERuE0hs6GUOc/cKBLF2NqKc16UwqHMt3tFg4CO6EBTE5UecUasg+3jZx3Ckg==',
|
||||
tarball: `http://localhost:${REGISTRY_MOCK_PORT}/is-positive/-/is-positive-1.0.0.tgz`,
|
||||
@@ -155,7 +155,7 @@ test('request package but skip fetching, when resolution is already available',
|
||||
expect(pkgResponse.body.isLocal).toBe(false)
|
||||
expect(typeof pkgResponse.body.latest).toBe('string')
|
||||
expect(pkgResponse.body.manifest.name).toBe('is-positive')
|
||||
expect(!pkgResponse.body.normalizedPref).toBeTruthy()
|
||||
expect(!pkgResponse.body.specifier).toBeTruthy()
|
||||
expect(pkgResponse.body.resolution).toStrictEqual({
|
||||
integrity: 'sha512-xxzPGZ4P2uN6rROUa5N9Z7zTX6ERuE0hs6GUOc/cKBLF2NqKc16UwqHMt3tFg4CO6EBTE5UecUasg+3jZx3Ckg==',
|
||||
tarball: `http://localhost:${REGISTRY_MOCK_PORT}/is-positive/-/is-positive-1.0.0.tgz`,
|
||||
|
||||
@@ -23,7 +23,7 @@ export function createWorkspaceSpecs (specs: string[], workspacePackages: Worksp
|
||||
const parsed = parseWantedDependency(spec)
|
||||
if (!parsed.alias) throw new PnpmError('NO_PKG_NAME_IN_SPEC', `Cannot update/install from workspace through "${spec}"`)
|
||||
if (!workspacePackages.has(parsed.alias)) throw new PnpmError('WORKSPACE_PACKAGE_NOT_FOUND', `"${parsed.alias}" not found in the workspace`)
|
||||
if (!parsed.pref) return `${parsed.alias}@workspace:>=0.0.0`
|
||||
if (!parsed.pref) return `${parsed.alias}@workspace:*`
|
||||
if (parsed.pref.startsWith('workspace:')) return spec
|
||||
return `${parsed.alias}@workspace:${parsed.pref}`
|
||||
})
|
||||
|
||||
@@ -91,7 +91,7 @@ test('installing with "workspace:" should work even if link-workspace-packages i
|
||||
|
||||
const pkg = await import(path.resolve('project-1/package.json'))
|
||||
|
||||
expect(pkg?.dependencies).toStrictEqual({ 'project-2': 'workspace:^' })
|
||||
expect(pkg?.dependencies).toStrictEqual({ 'project-2': 'workspace:*' })
|
||||
|
||||
projects['project-1'].has('project-2')
|
||||
})
|
||||
@@ -208,7 +208,7 @@ test('installing with "workspace=true" with linkWorkspacePackages on and saveWor
|
||||
|
||||
const pkg = await import(path.resolve('project-1/package.json'))
|
||||
|
||||
expect(pkg?.dependencies).toStrictEqual({ 'project-2': '^2.0.0' })
|
||||
expect(pkg?.dependencies).toStrictEqual({ 'project-2': 'workspace:^2.0.0' })
|
||||
|
||||
projects['project-1'].has('project-2')
|
||||
})
|
||||
|
||||
@@ -439,6 +439,7 @@ test('recursive update with aliased workspace dependency (#7975)', async () => {
|
||||
dir: process.cwd(),
|
||||
recursive: true,
|
||||
workspaceDir: process.cwd(),
|
||||
saveWorkspaceProtocol: 'rolling',
|
||||
})
|
||||
|
||||
projects['project-1'].has('pkg')
|
||||
|
||||
@@ -73,7 +73,7 @@ test('updateToWorkspacePackagesFromManifest()', () => {
|
||||
})
|
||||
|
||||
test('createWorkspaceSpecs', () => {
|
||||
expect(createWorkspaceSpecs(['bar', 'foo@2', 'qar@workspace:3'], WORKSPACE_PACKAGES)).toStrictEqual(['bar@workspace:>=0.0.0', 'foo@workspace:2', 'qar@workspace:3'])
|
||||
expect(createWorkspaceSpecs(['bar', 'foo@2', 'qar@workspace:3'], WORKSPACE_PACKAGES)).toStrictEqual(['bar@workspace:*', 'foo@workspace:2', 'qar@workspace:3'])
|
||||
let err!: PnpmError
|
||||
try {
|
||||
createWorkspaceSpecs(['express'], WORKSPACE_PACKAGES)
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
"@pnpm/semver.peer-range": "workspace:*",
|
||||
"@pnpm/store-controller-types": "workspace:*",
|
||||
"@pnpm/types": "workspace:*",
|
||||
"@pnpm/which-version-is-pinned": "workspace:*",
|
||||
"@pnpm/workspace.spec-parser": "workspace:*",
|
||||
"@yarnpkg/core": "catalog:",
|
||||
"filenamify": "catalog:",
|
||||
|
||||
@@ -5,18 +5,15 @@ import {
|
||||
type IncludedDependencies,
|
||||
type ProjectManifest,
|
||||
} from '@pnpm/types'
|
||||
import { whichVersionIsPinned } from '@pnpm/which-version-is-pinned'
|
||||
|
||||
export type PinnedVersion = 'major' | 'minor' | 'patch' | 'none'
|
||||
|
||||
export interface WantedDependency {
|
||||
alias: string
|
||||
pref: string // package reference
|
||||
dev: boolean
|
||||
optional: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
nodeExecPath?: string
|
||||
updateSpec?: boolean
|
||||
prevSpecifier?: string
|
||||
}
|
||||
|
||||
export function getWantedDependencies (
|
||||
@@ -72,8 +69,8 @@ function getWantedDependenciesFromGivenSet (
|
||||
injected: opts.dependenciesMeta[alias]?.injected,
|
||||
optional: depType === 'optional',
|
||||
nodeExecPath: opts.nodeExecPath ?? opts.dependenciesMeta[alias]?.node,
|
||||
pinnedVersion: whichVersionIsPinned(pref),
|
||||
pref,
|
||||
prevSpecifier: pref,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import {
|
||||
getAllDependenciesFromManifest,
|
||||
getSpecFromPackageManifest,
|
||||
type PinnedVersion,
|
||||
} from '@pnpm/manifest-utils'
|
||||
import { verifyPatches } from '@pnpm/patching.config'
|
||||
import { safeReadPackageJsonFromDir } from '@pnpm/read-package-json'
|
||||
@@ -18,6 +17,7 @@ import {
|
||||
DEPENDENCIES_FIELDS,
|
||||
type DependencyManifest,
|
||||
type PeerDependencyIssuesByProjects,
|
||||
type PinnedVersion,
|
||||
type ProjectManifest,
|
||||
type ProjectId,
|
||||
type ProjectRootDir,
|
||||
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
type ReadPackageHook,
|
||||
type Registries,
|
||||
type PkgIdWithPatchHash,
|
||||
type PinnedVersion,
|
||||
} from '@pnpm/types'
|
||||
import * as dp from '@pnpm/dependency-path'
|
||||
import { getPreferredVersionsFromLockfileAndManifests } from '@pnpm/lockfile.preferred-versions'
|
||||
@@ -110,9 +111,9 @@ export interface LinkedDependency {
|
||||
pkgId: PkgResolutionId
|
||||
version: string
|
||||
name: string
|
||||
normalizedPref?: string
|
||||
alias: string
|
||||
catalogLookup?: CatalogLookupMetadata
|
||||
specifier?: string
|
||||
}
|
||||
|
||||
export interface PendingNode {
|
||||
@@ -192,7 +193,6 @@ export type PkgAddress = {
|
||||
resolvedVia?: string
|
||||
nodeId: NodeId
|
||||
pkgId: PkgResolutionId
|
||||
normalizedPref?: string // is returned only for root dependencies
|
||||
installable: boolean
|
||||
pkg: PackageManifest
|
||||
version?: string
|
||||
@@ -203,6 +203,7 @@ export type PkgAddress = {
|
||||
publishedAt?: string
|
||||
catalogLookup?: CatalogLookupMetadata
|
||||
optional: boolean
|
||||
specifier?: string
|
||||
} & ({
|
||||
isLinkedDependency: true
|
||||
version: string
|
||||
@@ -274,6 +275,7 @@ interface ResolvedDependenciesOptions {
|
||||
prefix: string
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
updateToLatest?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
|
||||
interface PostponedResolutionOpts {
|
||||
@@ -406,6 +408,7 @@ export interface ImporterToResolve {
|
||||
parentPkgAliases: ParentPkgAliases
|
||||
wantedDependencies: Array<WantedDependency & { updateDepth?: number }>
|
||||
options: ImporterToResolveOptions
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
|
||||
interface ResolveDependenciesOfImportersResult {
|
||||
@@ -570,6 +573,7 @@ async function resolveDependenciesOfImporterDependency (
|
||||
updateToLatest: catalogLookup != null
|
||||
? false
|
||||
: importer.options.updateToLatest,
|
||||
pinnedVersion: importer.pinnedVersion,
|
||||
},
|
||||
extendedWantedDep
|
||||
)
|
||||
@@ -821,6 +825,7 @@ async function resolveDependenciesOfDependency (
|
||||
updateMatching: options.updateMatching,
|
||||
supportedArchitectures: options.supportedArchitectures,
|
||||
parentIds: options.parentIds,
|
||||
pinnedVersion: options.pinnedVersion,
|
||||
}
|
||||
|
||||
// The catalog protocol is normally replaced when resolving the dependencies
|
||||
@@ -1208,6 +1213,7 @@ interface ResolveDependencyOptions {
|
||||
updateDepth: number
|
||||
updateMatching?: UpdateMatchingFunction
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
|
||||
type ResolveDependencyResult = PkgAddress | LinkedDependency | null
|
||||
@@ -1252,7 +1258,8 @@ async function resolveDependency (
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (!options.update && currentPkg.version && currentPkg.pkgId?.endsWith(`@${currentPkg.version}`)) {
|
||||
const calcSpecifier = options.currentDepth === 0
|
||||
if (!options.update && currentPkg.version && currentPkg.pkgId?.endsWith(`@${currentPkg.version}`) && !calcSpecifier) {
|
||||
wantedDependency.pref = replaceVersionInPref(wantedDependency.pref, currentPkg.version)
|
||||
}
|
||||
pkgResponse = await ctx.storeController.requestPackage(wantedDependency, {
|
||||
@@ -1288,6 +1295,8 @@ async function resolveDependency (
|
||||
return err
|
||||
},
|
||||
injectWorkspacePackages: ctx.injectWorkspacePackages,
|
||||
calcSpecifier,
|
||||
pinnedVersion: options.pinnedVersion,
|
||||
})
|
||||
} catch (err: any) { // eslint-disable-line
|
||||
const wantedDependencyDetails = {
|
||||
@@ -1346,11 +1355,11 @@ async function resolveDependency (
|
||||
dev: wantedDependency.dev,
|
||||
isLinkedDependency: true,
|
||||
name: pkgResponse.body.manifest.name,
|
||||
normalizedPref: pkgResponse.body.normalizedPref,
|
||||
optional: wantedDependency.optional,
|
||||
pkgId: pkgResponse.body.id,
|
||||
resolution: pkgResponse.body.resolution,
|
||||
version: pkgResponse.body.manifest.version,
|
||||
specifier: pkgResponse.body.specifier,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1562,7 +1571,7 @@ async function resolveDependency (
|
||||
resolvedVia: pkgResponse.body.resolvedVia,
|
||||
isNew,
|
||||
nodeId,
|
||||
normalizedPref: options.currentDepth === 0 ? pkgResponse.body.normalizedPref : undefined,
|
||||
specifier: pkgResponse.body.specifier,
|
||||
missingPeersOfChildren,
|
||||
pkgId: pkgResponse.body.id,
|
||||
rootDir,
|
||||
|
||||
@@ -7,6 +7,7 @@ import { type StoreController } from '@pnpm/store-controller-types'
|
||||
import {
|
||||
type SupportedArchitectures,
|
||||
type AllowedDeprecatedVersions,
|
||||
type PinnedVersion,
|
||||
type PkgResolutionId,
|
||||
type ProjectManifest,
|
||||
type ProjectId,
|
||||
@@ -52,8 +53,8 @@ export interface ResolvedDirectDependency {
|
||||
pkgId: PkgResolutionId
|
||||
version: string
|
||||
name: string
|
||||
normalizedPref?: string
|
||||
catalogLookup?: CatalogLookupMetadata
|
||||
specifier?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,6 +93,7 @@ export interface ImporterToResolveGeneric<WantedDepExtraProps> extends Importer<
|
||||
hasRemovedDependencies?: boolean
|
||||
preferredVersions?: PreferredVersions
|
||||
wantedDependencies: Array<WantedDepExtraProps & WantedDependency & { updateDepth: number }>
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
|
||||
export interface ResolveDependenciesOptions {
|
||||
@@ -226,6 +228,7 @@ export async function resolveDependencyTree<T> (
|
||||
preferredVersions: importer.preferredVersions ?? {},
|
||||
wantedDependencies: importer.wantedDependencies,
|
||||
options: resolveOpts,
|
||||
pinnedVersion: importer.pinnedVersion,
|
||||
}
|
||||
})
|
||||
const { pkgAddressesByImporters, time } = await resolveRootDependencies(ctx, resolveArgs)
|
||||
@@ -259,11 +262,11 @@ export async function resolveDependencyTree<T> (
|
||||
catalogLookup: dep.catalogLookup,
|
||||
dev: resolvedPackage.dev,
|
||||
name: resolvedPackage.name,
|
||||
normalizedPref: dep.normalizedPref,
|
||||
optional: resolvedPackage.optional,
|
||||
pkgId: resolvedPackage.id,
|
||||
resolution: resolvedPackage.resolution,
|
||||
version: resolvedPackage.version,
|
||||
specifier: dep.specifier,
|
||||
}
|
||||
}),
|
||||
directNodeIdsByAlias: new Map(directNonLinkedDeps.map(({ alias, nodeId }) => [alias, nodeId])),
|
||||
@@ -338,12 +341,12 @@ function buildTree (
|
||||
function dedupeSameAliasDirectDeps (directDeps: Array<PkgAddress | LinkedDependency>, wantedDependencies: Array<WantedDependency & { isNew?: boolean }>): Array<PkgAddress | LinkedDependency> {
|
||||
const deps = new Map<string, PkgAddress | LinkedDependency>()
|
||||
for (const directDep of directDeps) {
|
||||
const { alias, normalizedPref } = directDep
|
||||
const { alias, specifier } = directDep
|
||||
if (!deps.has(alias)) {
|
||||
deps.set(alias, directDep)
|
||||
} else {
|
||||
const wantedDep = wantedDependencies.find(dep =>
|
||||
dep.alias ? dep.alias === alias : dep.pref === normalizedPref
|
||||
dep.alias ? dep.alias === alias : dep.pref === specifier
|
||||
)
|
||||
if (wantedDep?.isNew) {
|
||||
deps.set(alias, directDep)
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import {
|
||||
createVersionSpec,
|
||||
type PackageSpecObject,
|
||||
type PinnedVersion,
|
||||
updateProjectManifestObject,
|
||||
} from '@pnpm/manifest-utils'
|
||||
import versionSelectorType from 'version-selector-type'
|
||||
import semver from 'semver'
|
||||
import { isGitHostedPkgUrl } from '@pnpm/pick-fetcher'
|
||||
import { type TarballResolution } from '@pnpm/resolver-base'
|
||||
import { type ProjectManifest } from '@pnpm/types'
|
||||
import { type ResolvedDirectDependency } from './resolveDependencyTree'
|
||||
import { type ImporterToResolve } from '.'
|
||||
@@ -23,25 +17,17 @@ export async function updateProjectManifest (
|
||||
if (!importer.manifest) {
|
||||
throw new Error('Cannot save because no package.json found')
|
||||
}
|
||||
const specsToUpsert = opts.directDependencies
|
||||
const specsToUpsert: PackageSpecObject[] = opts.directDependencies
|
||||
.filter((rdd, index) => importer.wantedDependencies[index]?.updateSpec)
|
||||
.map((rdd, index) => {
|
||||
const wantedDep = importer.wantedDependencies[index]!
|
||||
return resolvedDirectDepToSpecObject({
|
||||
...rdd,
|
||||
isNew:
|
||||
wantedDep.isNew,
|
||||
currentPref: wantedDep.pref,
|
||||
preserveNonSemverVersionSpec: wantedDep.preserveNonSemverVersionSpec,
|
||||
// For git-protocol dependencies that are already installed locally, there is no normalizedPref unless do force resolve,
|
||||
// so we use pref in wantedDependency here.
|
||||
normalizedPref: rdd.normalizedPref ?? (isGitHostedPkgUrl((rdd.resolution as TarballResolution).tarball ?? '') ? wantedDep.pref : undefined),
|
||||
}, importer, {
|
||||
return {
|
||||
alias: rdd.alias,
|
||||
nodeExecPath: wantedDep.nodeExecPath,
|
||||
pinnedVersion: wantedDep.pinnedVersion ?? importer.pinnedVersion ?? 'major',
|
||||
preserveWorkspaceProtocol: opts.preserveWorkspaceProtocol,
|
||||
saveWorkspaceProtocol: opts.saveWorkspaceProtocol,
|
||||
})
|
||||
peer: importer.peer,
|
||||
pref: rdd.catalogLookup?.userSpecifiedPref ?? rdd.specifier ?? wantedDep.pref,
|
||||
saveType: importer.targetDependenciesField,
|
||||
}
|
||||
})
|
||||
for (const pkgToInstall of importer.wantedDependencies) {
|
||||
if (pkgToInstall.updateSpec && pkgToInstall.alias && !specsToUpsert.some(({ alias }) => alias === pkgToInstall.alias)) {
|
||||
@@ -67,133 +53,3 @@ export async function updateProjectManifest (
|
||||
: undefined
|
||||
return [hookedManifest, originalManifest]
|
||||
}
|
||||
|
||||
function resolvedDirectDepToSpecObject (
|
||||
{
|
||||
alias,
|
||||
catalogLookup,
|
||||
isNew,
|
||||
name,
|
||||
normalizedPref,
|
||||
resolution,
|
||||
currentPref,
|
||||
version,
|
||||
preserveNonSemverVersionSpec,
|
||||
}: ResolvedDirectDependency & { isNew?: boolean, currentPref: string, preserveNonSemverVersionSpec?: boolean },
|
||||
importer: ImporterToResolve,
|
||||
opts: {
|
||||
nodeExecPath?: string
|
||||
pinnedVersion: PinnedVersion
|
||||
preserveWorkspaceProtocol: boolean
|
||||
saveWorkspaceProtocol: boolean | 'rolling'
|
||||
}
|
||||
): PackageSpecObject {
|
||||
let pref!: string
|
||||
if (catalogLookup) {
|
||||
pref = catalogLookup.userSpecifiedPref
|
||||
} else if (normalizedPref) {
|
||||
pref = normalizedPref
|
||||
} else {
|
||||
const shouldUseWorkspaceProtocol = resolution.type === 'directory' &&
|
||||
(
|
||||
Boolean(opts.saveWorkspaceProtocol) ||
|
||||
(opts.preserveWorkspaceProtocol && currentPref.startsWith('workspace:'))
|
||||
) &&
|
||||
opts.pinnedVersion !== 'none'
|
||||
|
||||
if (isNew === true) {
|
||||
pref = getPrefPreferSpecifiedSpec({
|
||||
alias,
|
||||
name,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
currentPref,
|
||||
version,
|
||||
rolling: shouldUseWorkspaceProtocol && opts.saveWorkspaceProtocol === 'rolling',
|
||||
})
|
||||
} else {
|
||||
pref = getPrefPreferSpecifiedExoticSpec({
|
||||
alias,
|
||||
name,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
currentPref,
|
||||
version,
|
||||
rolling: shouldUseWorkspaceProtocol && opts.saveWorkspaceProtocol === 'rolling',
|
||||
preserveNonSemverVersionSpec,
|
||||
})
|
||||
}
|
||||
if (
|
||||
shouldUseWorkspaceProtocol &&
|
||||
!pref.startsWith('workspace:')
|
||||
) {
|
||||
pref = pref.replace(/^npm:/, '')
|
||||
pref = `workspace:${pref}`
|
||||
}
|
||||
}
|
||||
return {
|
||||
alias,
|
||||
nodeExecPath: opts.nodeExecPath,
|
||||
peer: importer['peer'],
|
||||
pref,
|
||||
saveType: importer['targetDependenciesField'],
|
||||
}
|
||||
}
|
||||
|
||||
function getPrefPreferSpecifiedSpec (
|
||||
opts: {
|
||||
alias: string
|
||||
name: string
|
||||
version: string
|
||||
currentPref: string
|
||||
pinnedVersion?: PinnedVersion
|
||||
rolling: boolean
|
||||
}
|
||||
): string {
|
||||
const prefix = opts.currentPref.startsWith('npm:') ? `npm:${opts.name}@` : ''
|
||||
const range = opts.currentPref.slice(prefix.length)
|
||||
if (range) {
|
||||
const selector = versionSelectorType(range)
|
||||
if ((selector != null) && (selector.type === 'version' || selector.type === 'range')) {
|
||||
return opts.currentPref
|
||||
}
|
||||
}
|
||||
// A prerelease version is always added as an exact version
|
||||
if (semver.parse(opts.version)?.prerelease.length) {
|
||||
return `${prefix}${opts.version}`
|
||||
}
|
||||
return `${prefix}${createVersionSpec(opts.version, { pinnedVersion: opts.pinnedVersion, rolling: opts.rolling })}`
|
||||
}
|
||||
|
||||
function getPrefPreferSpecifiedExoticSpec (
|
||||
opts: {
|
||||
alias: string
|
||||
name: string
|
||||
version: string
|
||||
currentPref: string
|
||||
pinnedVersion: PinnedVersion
|
||||
rolling: boolean
|
||||
preserveNonSemverVersionSpec?: boolean
|
||||
}
|
||||
): string {
|
||||
let prefix = opts.currentPref.startsWith('npm:') ? `npm:${opts.name}@` : ''
|
||||
let specWithoutName = opts.currentPref.slice(prefix.length)
|
||||
if (specWithoutName.startsWith('workspace:')) {
|
||||
prefix = 'workspace:'
|
||||
specWithoutName = specWithoutName.slice(10)
|
||||
if (specWithoutName === '*' || specWithoutName === '^' || specWithoutName === '~') {
|
||||
return specWithoutName
|
||||
}
|
||||
}
|
||||
const selector = versionSelectorType(specWithoutName)
|
||||
if (
|
||||
((selector == null) || (selector.type !== 'version' && selector.type !== 'range')) &&
|
||||
opts.preserveNonSemverVersionSpec
|
||||
) {
|
||||
return opts.currentPref
|
||||
}
|
||||
// A prerelease version is always added as an exact version
|
||||
if (semver.parse(opts.version)?.prerelease.length) {
|
||||
return `${prefix}${opts.version}`
|
||||
}
|
||||
|
||||
return `${prefix}${createVersionSpec(opts.version, { pinnedVersion: opts.pinnedVersion, rolling: opts.rolling })}`
|
||||
}
|
||||
|
||||
@@ -48,9 +48,6 @@
|
||||
{
|
||||
"path": "../../packages/types"
|
||||
},
|
||||
{
|
||||
"path": "../../packages/which-version-is-pinned"
|
||||
},
|
||||
{
|
||||
"path": "../../patching/config"
|
||||
},
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { PnpmError } from '@pnpm/error'
|
||||
|
||||
export type PinnedVersion = 'major' | 'minor' | 'patch' | 'none'
|
||||
|
||||
export const getPrefix = (alias: string, name: string): string => alias !== name ? `npm:${name}@` : ''
|
||||
|
||||
export function getPref (
|
||||
alias: string,
|
||||
name: string,
|
||||
version: string | undefined,
|
||||
opts: {
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
): string {
|
||||
const prefix = getPrefix(alias, name)
|
||||
return `${prefix}${createVersionSpec(version, { pinnedVersion: opts.pinnedVersion })}`
|
||||
}
|
||||
|
||||
export function createVersionSpec (version: string | undefined, opts: { pinnedVersion?: PinnedVersion, rolling?: boolean }): string {
|
||||
switch (opts.pinnedVersion ?? 'major') {
|
||||
case 'none':
|
||||
case 'major':
|
||||
if (opts.rolling) return '^'
|
||||
return !version ? '*' : `^${version}`
|
||||
case 'minor':
|
||||
if (opts.rolling) return '~'
|
||||
return !version ? '*' : `~${version}`
|
||||
case 'patch':
|
||||
if (opts.rolling) return '*'
|
||||
return !version ? '*' : `${version}`
|
||||
default:
|
||||
throw new PnpmError('BAD_PINNED_VERSION', `Cannot pin '${opts.pinnedVersion ?? 'undefined'}'`)
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
import { getAllUniqueSpecs } from './getAllUniqueSpecs'
|
||||
import { getSpecFromPackageManifest } from './getSpecFromPackageManifest'
|
||||
|
||||
export * from './getPref'
|
||||
export * from './updateProjectManifestObject'
|
||||
export * from './getDependencyTypeFromManifest'
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { getPref } from '@pnpm/manifest-utils'
|
||||
|
||||
test('getPref()', () => {
|
||||
expect(getPref('foo', 'foo', '1.0.0', {})).toEqual('^1.0.0')
|
||||
|
||||
expect(
|
||||
getPref('foo', 'foo', '1.0.0', {
|
||||
pinnedVersion: 'major',
|
||||
})
|
||||
).toEqual('^1.0.0')
|
||||
|
||||
expect(
|
||||
getPref('foo', 'foo', '2.0.0', {
|
||||
pinnedVersion: 'minor',
|
||||
})
|
||||
).toEqual('~2.0.0')
|
||||
|
||||
expect(
|
||||
getPref('foo', 'foo', '3.0.0', {
|
||||
pinnedVersion: 'patch',
|
||||
})
|
||||
).toEqual('3.0.0')
|
||||
|
||||
expect(
|
||||
getPref('foo', 'foo', '4.0.0', {
|
||||
pinnedVersion: 'none',
|
||||
})
|
||||
).toEqual('^4.0.0')
|
||||
|
||||
expect(
|
||||
getPref('foo', 'foo', undefined, {
|
||||
pinnedVersion: 'major',
|
||||
})
|
||||
).toEqual('*')
|
||||
})
|
||||
19
pnpm-lock.yaml
generated
19
pnpm-lock.yaml
generated
@@ -4250,16 +4250,6 @@ importers:
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
|
||||
packages/which-version-is-pinned:
|
||||
dependencies:
|
||||
semver-utils:
|
||||
specifier: 'catalog:'
|
||||
version: 1.1.4
|
||||
devDependencies:
|
||||
'@pnpm/which-version-is-pinned':
|
||||
specifier: workspace:*
|
||||
version: 'link:'
|
||||
|
||||
patching/apply-patch:
|
||||
dependencies:
|
||||
'@pnpm/error':
|
||||
@@ -4638,9 +4628,6 @@ importers:
|
||||
'@pnpm/types':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/types
|
||||
'@pnpm/which-version-is-pinned':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/which-version-is-pinned
|
||||
'@pnpm/worker':
|
||||
specifier: workspace:^
|
||||
version: link:../../worker
|
||||
@@ -5786,9 +5773,6 @@ importers:
|
||||
'@pnpm/types':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/types
|
||||
'@pnpm/which-version-is-pinned':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/which-version-is-pinned
|
||||
'@pnpm/workspace.spec-parser':
|
||||
specifier: workspace:*
|
||||
version: link:../../workspace/spec-parser
|
||||
@@ -6824,6 +6808,9 @@ importers:
|
||||
semver:
|
||||
specifier: 'catalog:'
|
||||
version: 7.7.1
|
||||
semver-utils:
|
||||
specifier: 'catalog:'
|
||||
version: 1.1.4
|
||||
ssri:
|
||||
specifier: 'catalog:'
|
||||
version: 10.0.5
|
||||
|
||||
@@ -63,7 +63,7 @@ export function createGitResolver (
|
||||
|
||||
return {
|
||||
id,
|
||||
normalizedPref: parsedSpec.normalizedPref,
|
||||
specifier: parsedSpec.normalizedPref,
|
||||
resolution,
|
||||
resolvedVia: 'git-repository',
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ test('resolveFromGit() with commit', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative#163360a8d3ae6bee9524541043197ff356f8ed99' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
normalizedPref: 'github:zkochan/is-negative#163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
specifier: 'github:zkochan/is-negative#163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
},
|
||||
@@ -28,7 +28,7 @@ test('resolveFromGit() with commit', async () => {
|
||||
})
|
||||
|
||||
test('resolveFromGit() with no commit', async () => {
|
||||
// This is repeated twice because there was a bug which caused the normalizedPref
|
||||
// This is repeated twice because there was a bug which caused the specifier
|
||||
// to contain the commit hash on second call.
|
||||
// The issue occurred because .hosted field (which is class from the 'hosted-git-info' package)
|
||||
// was mutated. A 'committish' field was added to it.
|
||||
@@ -36,7 +36,7 @@ test('resolveFromGit() with no commit', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative' }) // eslint-disable-line no-await-in-loop
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c',
|
||||
normalizedPref: 'github:zkochan/is-negative',
|
||||
specifier: 'github:zkochan/is-negative',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c',
|
||||
},
|
||||
@@ -49,7 +49,7 @@ test('resolveFromGit() with no commit, when main branch is not master', async ()
|
||||
const resolveResult = await resolveFromGit({ pref: 'zoli-forks/cmd-shim' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zoli-forks/cmd-shim/tar.gz/a00a83a1593edb6e395d3ce41f2ef70edf7e2cf5',
|
||||
normalizedPref: 'github:zoli-forks/cmd-shim',
|
||||
specifier: 'github:zoli-forks/cmd-shim',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zoli-forks/cmd-shim/tar.gz/a00a83a1593edb6e395d3ce41f2ef70edf7e2cf5',
|
||||
},
|
||||
@@ -61,7 +61,7 @@ test('resolveFromGit() with partial commit', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zoli-forks/cmd-shim#a00a83a' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zoli-forks/cmd-shim/tar.gz/a00a83a',
|
||||
normalizedPref: 'github:zoli-forks/cmd-shim#a00a83a',
|
||||
specifier: 'github:zoli-forks/cmd-shim#a00a83a',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zoli-forks/cmd-shim/tar.gz/a00a83a',
|
||||
},
|
||||
@@ -73,7 +73,7 @@ test('resolveFromGit() with branch', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative#canary' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/4c39fbc124cd4944ee51cb082ad49320fab58121',
|
||||
normalizedPref: 'github:zkochan/is-negative#canary',
|
||||
specifier: 'github:zkochan/is-negative#canary',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/4c39fbc124cd4944ee51cb082ad49320fab58121',
|
||||
},
|
||||
@@ -85,7 +85,7 @@ test('resolveFromGit() with branch relative to refs', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative#heads/canary' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/4c39fbc124cd4944ee51cb082ad49320fab58121',
|
||||
normalizedPref: 'github:zkochan/is-negative#heads/canary',
|
||||
specifier: 'github:zkochan/is-negative#heads/canary',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/4c39fbc124cd4944ee51cb082ad49320fab58121',
|
||||
},
|
||||
@@ -97,7 +97,7 @@ test('resolveFromGit() with tag', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative#2.0.1' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
normalizedPref: 'github:zkochan/is-negative#2.0.1',
|
||||
specifier: 'github:zkochan/is-negative#2.0.1',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
},
|
||||
@@ -109,7 +109,7 @@ test.skip('resolveFromGit() with tag (v-prefixed tag)', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'andreineculau/npm-publish-git#v0.0.7' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/andreineculau/npm-publish-git/tar.gz/a2f8d94562884e9529cb12c0818312ac87ab7f0b',
|
||||
normalizedPref: 'github:andreineculau/npm-publish-git#v0.0.7',
|
||||
specifier: 'github:andreineculau/npm-publish-git#v0.0.7',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/andreineculau/npm-publish-git/tar.gz/a2f8d94562884e9529cb12c0818312ac87ab7f0b',
|
||||
},
|
||||
@@ -121,7 +121,7 @@ test('resolveFromGit() with strict semver', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative#semver:1.0.0' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
normalizedPref: 'github:zkochan/is-negative#semver:1.0.0',
|
||||
specifier: 'github:zkochan/is-negative#semver:1.0.0',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/163360a8d3ae6bee9524541043197ff356f8ed99',
|
||||
},
|
||||
@@ -133,7 +133,7 @@ test.skip('resolveFromGit() with strict semver (v-prefixed tag)', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'andreineculau/npm-publish-git#semver:v0.0.7' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/andreineculau/npm-publish-git/tar.gz/a2f8d94562884e9529cb12c0818312ac87ab7f0b',
|
||||
normalizedPref: 'github:andreineculau/npm-publish-git#semver:v0.0.7',
|
||||
specifier: 'github:andreineculau/npm-publish-git#semver:v0.0.7',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/andreineculau/npm-publish-git/tar.gz/a2f8d94562884e9529cb12c0818312ac87ab7f0b',
|
||||
},
|
||||
@@ -145,7 +145,7 @@ test('resolveFromGit() with range semver', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'zkochan/is-negative#semver:^1.0.0' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/9a89df745b2ec20ae7445d3d9853ceaeef5b0b72',
|
||||
normalizedPref: 'github:zkochan/is-negative#semver:^1.0.0',
|
||||
specifier: 'github:zkochan/is-negative#semver:^1.0.0',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/9a89df745b2ec20ae7445d3d9853ceaeef5b0b72',
|
||||
},
|
||||
@@ -157,7 +157,7 @@ test.skip('resolveFromGit() with range semver (v-prefixed tag)', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'andreineculau/npm-publish-git#semver:<=v0.0.7' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/andreineculau/npm-publish-git/tar.gz/a2f8d94562884e9529cb12c0818312ac87ab7f0b',
|
||||
normalizedPref: 'github:andreineculau/npm-publish-git#semver:<=v0.0.7',
|
||||
specifier: 'github:andreineculau/npm-publish-git#semver:<=v0.0.7',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/andreineculau/npm-publish-git/tar.gz/a2f8d94562884e9529cb12c0818312ac87ab7f0b',
|
||||
},
|
||||
@@ -169,7 +169,7 @@ test('resolveFromGit() with sub folder', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'github:RexSkz/test-git-subfolder-fetch.git#path:/packages/simple-react-app' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/RexSkz/test-git-subfolder-fetch/tar.gz/2b42a57a945f19f8ffab8ecbd2021fdc2c58ee22#path:/packages/simple-react-app',
|
||||
normalizedPref: 'github:RexSkz/test-git-subfolder-fetch#path:/packages/simple-react-app',
|
||||
specifier: 'github:RexSkz/test-git-subfolder-fetch#path:/packages/simple-react-app',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/RexSkz/test-git-subfolder-fetch/tar.gz/2b42a57a945f19f8ffab8ecbd2021fdc2c58ee22',
|
||||
path: '/packages/simple-react-app',
|
||||
@@ -182,7 +182,7 @@ test('resolveFromGit() with both sub folder and branch', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'github:RexSkz/test-git-subfolder-fetch.git#beta&path:/packages/simple-react-app' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/RexSkz/test-git-subfolder-fetch/tar.gz/777e8a3e78cc89bbf41fb3fd9f6cf922d5463313#path:/packages/simple-react-app',
|
||||
normalizedPref: 'github:RexSkz/test-git-subfolder-fetch#beta&path:/packages/simple-react-app',
|
||||
specifier: 'github:RexSkz/test-git-subfolder-fetch#beta&path:/packages/simple-react-app',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/RexSkz/test-git-subfolder-fetch/tar.gz/777e8a3e78cc89bbf41fb3fd9f6cf922d5463313',
|
||||
path: '/packages/simple-react-app',
|
||||
@@ -212,7 +212,7 @@ test('resolveFromGit() with commit from non-github repo', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: `git+file://${localPath}#988c61e11dc8d9ca0b5580cb15291951812549dc` })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: `git+file://${localPath}#988c61e11dc8d9ca0b5580cb15291951812549dc`,
|
||||
normalizedPref: `git+file://${localPath}#988c61e11dc8d9ca0b5580cb15291951812549dc`,
|
||||
specifier: `git+file://${localPath}#988c61e11dc8d9ca0b5580cb15291951812549dc`,
|
||||
resolution: {
|
||||
commit: '988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
repo: `file://${localPath}`,
|
||||
@@ -230,7 +230,7 @@ test.skip('resolveFromGit() with commit from non-github repo with no commit', as
|
||||
const resolveResult = await resolveFromGit({ pref: `git+file://${localPath}` })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: `git+file://${localPath}#${hash}`,
|
||||
normalizedPref: `git+file://${localPath}`,
|
||||
specifier: `git+file://${localPath}`,
|
||||
resolution: {
|
||||
commit: hash,
|
||||
repo: `file://${localPath}`,
|
||||
@@ -249,7 +249,7 @@ test.skip('resolveFromGit() bitbucket with commit', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'bitbucket:pnpmjs/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://bitbucket.org/pnpmjs/git-resolver/get/988c61e11dc8d9ca0b5580cb15291951812549dc.tar.gz',
|
||||
normalizedPref: 'bitbucket:pnpmjs/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
specifier: 'bitbucket:pnpmjs/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
resolution: {
|
||||
tarball: 'https://bitbucket.org/pnpmjs/git-resolver/get/988c61e11dc8d9ca0b5580cb15291951812549dc.tar.gz',
|
||||
},
|
||||
@@ -264,7 +264,7 @@ test.skip('resolveFromGit() bitbucket with no commit', async () => {
|
||||
const hash: string = result.stdout.trim().split('\t')[0]
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: `https://bitbucket.org/pnpmjs/git-resolver/get/${hash}.tar.gz`,
|
||||
normalizedPref: 'bitbucket:pnpmjs/git-resolver',
|
||||
specifier: 'bitbucket:pnpmjs/git-resolver',
|
||||
resolution: {
|
||||
tarball: `https://bitbucket.org/pnpmjs/git-resolver/get/${hash}.tar.gz`,
|
||||
},
|
||||
@@ -279,7 +279,7 @@ test.skip('resolveFromGit() bitbucket with branch', async () => {
|
||||
const hash: string = result.stdout.trim().split('\t')[0]
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: `https://bitbucket.org/pnpmjs/git-resolver/get/${hash}.tar.gz`,
|
||||
normalizedPref: 'bitbucket:pnpmjs/git-resolver#master',
|
||||
specifier: 'bitbucket:pnpmjs/git-resolver#master',
|
||||
resolution: {
|
||||
tarball: `https://bitbucket.org/pnpmjs/git-resolver/get/${hash}.tar.gz`,
|
||||
},
|
||||
@@ -292,7 +292,7 @@ test.skip('resolveFromGit() bitbucket with tag', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'bitbucket:pnpmjs/git-resolver#0.3.4' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://bitbucket.org/pnpmjs/git-resolver/get/87cf6a67064d2ce56e8cd20624769a5512b83ff9.tar.gz',
|
||||
normalizedPref: 'bitbucket:pnpmjs/git-resolver#0.3.4',
|
||||
specifier: 'bitbucket:pnpmjs/git-resolver#0.3.4',
|
||||
resolution: {
|
||||
tarball: 'https://bitbucket.org/pnpmjs/git-resolver/get/87cf6a67064d2ce56e8cd20624769a5512b83ff9.tar.gz',
|
||||
},
|
||||
@@ -304,7 +304,7 @@ test('resolveFromGit() gitlab with colon in the URL', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'ssh://git@gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+ssh://git@gitlab/pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
normalizedPref: 'ssh://git@gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
specifier: 'ssh://git@gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
resolution: {
|
||||
commit: '988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
repo: 'ssh://git@gitlab/pnpm/git-resolver',
|
||||
@@ -319,7 +319,7 @@ test.skip('resolveFromGit() gitlab with commit', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
normalizedPref: 'gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
specifier: 'gitlab:pnpm/git-resolver#988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
resolution: {
|
||||
tarball: 'https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=988c61e11dc8d9ca0b5580cb15291951812549dc',
|
||||
},
|
||||
@@ -334,7 +334,7 @@ test.skip('resolveFromGit() gitlab with no commit', async () => {
|
||||
const hash: string = result.stdout.trim().split('\t')[0]
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: `https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=${hash}`,
|
||||
normalizedPref: 'gitlab:pnpm/git-resolver',
|
||||
specifier: 'gitlab:pnpm/git-resolver',
|
||||
resolution: {
|
||||
tarball: `https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=${hash}`,
|
||||
},
|
||||
@@ -349,7 +349,7 @@ test.skip('resolveFromGit() gitlab with branch', async () => {
|
||||
const hash: string = result.stdout.trim().split('\t')[0]
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: `https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=${hash}`,
|
||||
normalizedPref: 'gitlab:pnpm/git-resolver#master',
|
||||
specifier: 'gitlab:pnpm/git-resolver#master',
|
||||
resolution: {
|
||||
tarball: `https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=${hash}`,
|
||||
},
|
||||
@@ -362,7 +362,7 @@ test.skip('resolveFromGit() gitlab with tag', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'gitlab:pnpm/git-resolver#0.3.4' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=87cf6a67064d2ce56e8cd20624769a5512b83ff9',
|
||||
normalizedPref: 'gitlab:pnpm/git-resolver#0.3.4',
|
||||
specifier: 'gitlab:pnpm/git-resolver#0.3.4',
|
||||
resolution: {
|
||||
tarball: 'https://gitlab.com/api/v4/projects/pnpm%2Fgit-resolver/repository/archive.tar.gz?ref=87cf6a67064d2ce56e8cd20624769a5512b83ff9',
|
||||
},
|
||||
@@ -374,7 +374,7 @@ test('resolveFromGit() normalizes full url', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+ssh://git@github.com:zkochan/is-negative.git#2.0.1' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
normalizedPref: 'github:zkochan/is-negative#2.0.1',
|
||||
specifier: 'github:zkochan/is-negative#2.0.1',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
},
|
||||
@@ -386,7 +386,7 @@ test('resolveFromGit() normalizes full url with port', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+ssh://git@github.com:22:zkochan/is-negative.git#2.0.1' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
normalizedPref: 'github:zkochan/is-negative#2.0.1',
|
||||
specifier: 'github:zkochan/is-negative#2.0.1',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
},
|
||||
@@ -398,7 +398,7 @@ test('resolveFromGit() normalizes full url (alternative form)', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+ssh://git@github.com/zkochan/is-negative.git#2.0.1' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
normalizedPref: 'github:zkochan/is-negative#2.0.1',
|
||||
specifier: 'github:zkochan/is-negative#2.0.1',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
},
|
||||
@@ -410,7 +410,7 @@ test('resolveFromGit() normalizes full url (alternative form 2)', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'https://github.com/zkochan/is-negative.git#2.0.1' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
normalizedPref: 'github:zkochan/is-negative#2.0.1',
|
||||
specifier: 'github:zkochan/is-negative#2.0.1',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/zkochan/is-negative/tar.gz/2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
},
|
||||
@@ -425,7 +425,7 @@ test('resolveFromGit() private repo with commit hash', async () => {
|
||||
const resolveResult = await resolveFromGit({ pref: 'fake/private-repo#2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+ssh://git@github.com/fake/private-repo.git#2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
normalizedPref: 'github:fake/private-repo#2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
specifier: 'github:fake/private-repo#2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
resolution: {
|
||||
commit: '2fa0531ab04e300a24ef4fd7fb3a280eccb7ccc5',
|
||||
repo: 'git+ssh://git@github.com/fake/private-repo.git',
|
||||
@@ -451,7 +451,7 @@ test('resolve a private repository using the HTTPS protocol without auth token',
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+https://github.com/foo/bar.git' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+ssh://git@github.com/foo/bar.git#0000000000000000000000000000000000000000',
|
||||
normalizedPref: 'github:foo/bar',
|
||||
specifier: 'github:foo/bar',
|
||||
resolution: {
|
||||
commit: '0000000000000000000000000000000000000000',
|
||||
repo: 'git+ssh://git@github.com/foo/bar.git',
|
||||
@@ -473,7 +473,7 @@ test('resolve a private repository using the HTTPS protocol with a commit hash',
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+https://github.com/foo/bar.git#aabbccddeeff' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+https://github.com/foo/bar.git#aabbccddeeff',
|
||||
normalizedPref: 'git+https://github.com/foo/bar.git',
|
||||
specifier: 'git+https://github.com/foo/bar.git',
|
||||
resolution: {
|
||||
// cspell:ignore aabbccddeeff
|
||||
commit: 'aabbccddeeff',
|
||||
@@ -500,7 +500,7 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\trefs/heads/master\
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git#0000000000000000000000000000000000000000',
|
||||
normalizedPref: 'git+https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git',
|
||||
specifier: 'git+https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git',
|
||||
resolution: {
|
||||
commit: '0000000000000000000000000000000000000000',
|
||||
repo: 'https://0000000000000000000000000000000000000000:x-oauth-basic@github.com/foo/bar.git',
|
||||
@@ -530,7 +530,7 @@ cba04669e621b85fbdb33371604de1a2898e68e9\trefs/tags/v0.0.39',
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+ssh://git@example.com/org/repo.git#semver:~0.0.38' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+ssh://git@example.com/org/repo.git#cba04669e621b85fbdb33371604de1a2898e68e9',
|
||||
normalizedPref: 'git+ssh://git@example.com/org/repo.git#semver:~0.0.38',
|
||||
specifier: 'git+ssh://git@example.com/org/repo.git#semver:~0.0.38',
|
||||
resolution: {
|
||||
commit: 'cba04669e621b85fbdb33371604de1a2898e68e9',
|
||||
repo: 'ssh://git@example.com/org/repo.git',
|
||||
@@ -560,7 +560,7 @@ cba04669e621b85fbdb33371604de1a2898e68e9\trefs/tags/v0.0.39',
|
||||
const resolveResult = await resolveFromGit({ pref: 'git+ssh://git@example.com:org/repo.git#semver:~0.0.38' })
|
||||
expect(resolveResult).toStrictEqual({
|
||||
id: 'git+ssh://git@example.com/org/repo.git#cba04669e621b85fbdb33371604de1a2898e68e9',
|
||||
normalizedPref: 'git+ssh://git@example.com:org/repo.git#semver:~0.0.38',
|
||||
specifier: 'git+ssh://git@example.com:org/repo.git#semver:~0.0.38',
|
||||
resolution: {
|
||||
commit: 'cba04669e621b85fbdb33371604de1a2898e68e9',
|
||||
repo: 'ssh://git@example.com/org/repo.git',
|
||||
|
||||
@@ -15,7 +15,7 @@ import { parsePref, type WantedLocalDependency } from './parsePref'
|
||||
export type { WantedLocalDependency }
|
||||
|
||||
export interface ResolveFromLocalResult extends ResolveResult {
|
||||
normalizedPref: string
|
||||
specifier: string
|
||||
resolution: TarballResolution | DirectoryResolution
|
||||
manifest?: DependencyManifest
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export async function resolveFromLocal (
|
||||
if (spec.type === 'file') {
|
||||
return {
|
||||
id: spec.id,
|
||||
normalizedPref: spec.normalizedPref,
|
||||
specifier: spec.normalizedPref,
|
||||
resolution: {
|
||||
integrity: await getTarballIntegrity(spec.fetchSpec),
|
||||
tarball: spec.id,
|
||||
@@ -84,7 +84,7 @@ export async function resolveFromLocal (
|
||||
return {
|
||||
id: spec.id,
|
||||
manifest: localDependencyManifest,
|
||||
normalizedPref: spec.normalizedPref,
|
||||
specifier: spec.normalizedPref,
|
||||
resolution: {
|
||||
directory: spec.dependencyPath,
|
||||
type: 'directory',
|
||||
|
||||
@@ -10,7 +10,7 @@ const TEST_DIR = path.dirname(require.resolve('@pnpm/tgz-fixtures/tgz/pnpm-local
|
||||
test('resolve directory', async () => {
|
||||
const resolveResult = await resolveFromLocal({ pref: '..' }, { projectDir: __dirname })
|
||||
expect(resolveResult!.id).toEqual('link:..')
|
||||
expect(resolveResult!.normalizedPref).toEqual('link:..')
|
||||
expect(resolveResult!.specifier).toEqual('link:..')
|
||||
expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).directory).toEqual(normalize(path.join(__dirname, '..')))
|
||||
expect((resolveResult!.resolution as DirectoryResolution).type).toEqual('directory')
|
||||
@@ -21,7 +21,7 @@ test('resolve directory specified using absolute path', async () => {
|
||||
const normalizedLinkedDir = normalize(linkedDir)
|
||||
const resolveResult = await resolveFromLocal({ pref: `link:${linkedDir}` }, { projectDir: __dirname })
|
||||
expect(resolveResult!.id).toEqual('link:..')
|
||||
expect(resolveResult!.normalizedPref).toEqual(`link:${normalizedLinkedDir}`)
|
||||
expect(resolveResult!.specifier).toEqual(`link:${normalizedLinkedDir}`)
|
||||
expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).directory).toEqual(normalizedLinkedDir)
|
||||
expect((resolveResult!.resolution as DirectoryResolution).type).toEqual('directory')
|
||||
@@ -30,7 +30,7 @@ test('resolve directory specified using absolute path', async () => {
|
||||
test('resolve injected directory', async () => {
|
||||
const resolveResult = await resolveFromLocal({ injected: true, pref: '..' }, { projectDir: __dirname })
|
||||
expect(resolveResult!.id).toEqual('file:..')
|
||||
expect(resolveResult!.normalizedPref).toEqual('file:..')
|
||||
expect(resolveResult!.specifier).toEqual('file:..')
|
||||
expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).directory).toEqual('..')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).type).toEqual('directory')
|
||||
@@ -39,7 +39,7 @@ test('resolve injected directory', async () => {
|
||||
test('resolve workspace directory', async () => {
|
||||
const resolveResult = await resolveFromLocal({ pref: 'workspace:..' }, { projectDir: __dirname })
|
||||
expect(resolveResult!.id).toEqual('link:..')
|
||||
expect(resolveResult!.normalizedPref).toEqual('link:..')
|
||||
expect(resolveResult!.specifier).toEqual('link:..')
|
||||
expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).directory).toEqual(normalize(path.join(__dirname, '..')))
|
||||
expect((resolveResult!.resolution as DirectoryResolution).type).toEqual('directory')
|
||||
@@ -48,7 +48,7 @@ test('resolve workspace directory', async () => {
|
||||
test('resolve directory specified using the file: protocol', async () => {
|
||||
const resolveResult = await resolveFromLocal({ pref: 'file:..' }, { projectDir: __dirname })
|
||||
expect(resolveResult!.id).toEqual('file:..')
|
||||
expect(resolveResult!.normalizedPref).toEqual('file:..')
|
||||
expect(resolveResult!.specifier).toEqual('file:..')
|
||||
expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).directory).toEqual('..')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).type).toEqual('directory')
|
||||
@@ -57,7 +57,7 @@ test('resolve directory specified using the file: protocol', async () => {
|
||||
test('resolve directory specified using the link: protocol', async () => {
|
||||
const resolveResult = await resolveFromLocal({ pref: 'link:..' }, { projectDir: __dirname })
|
||||
expect(resolveResult!.id).toEqual('link:..')
|
||||
expect(resolveResult!.normalizedPref).toEqual('link:..')
|
||||
expect(resolveResult!.specifier).toEqual('link:..')
|
||||
expect(resolveResult!['manifest']!.name).toEqual('@pnpm/local-resolver')
|
||||
expect((resolveResult!.resolution as DirectoryResolution).directory).toEqual(normalize(path.join(__dirname, '..')))
|
||||
expect((resolveResult!.resolution as DirectoryResolution).type).toEqual('directory')
|
||||
@@ -69,7 +69,7 @@ test('resolve file', async () => {
|
||||
|
||||
expect(resolveResult).toEqual({
|
||||
id: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
normalizedPref: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
specifier: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
resolution: {
|
||||
integrity: 'sha512-UHd2zKRT/w70KKzFlj4qcT81A1Q0H7NM9uKxLzIZ/VZqJXzt5Hnnp2PYPb5Ezq/hAamoYKIn5g7fuv69kP258w==',
|
||||
tarball: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
@@ -87,7 +87,7 @@ test("resolve file when lockfile directory differs from the package's dir", asyn
|
||||
|
||||
expect(resolveResult).toEqual({
|
||||
id: 'file:tgz/pnpm-local-resolver-0.1.1.tgz',
|
||||
normalizedPref: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
specifier: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
resolution: {
|
||||
integrity: 'sha512-UHd2zKRT/w70KKzFlj4qcT81A1Q0H7NM9uKxLzIZ/VZqJXzt5Hnnp2PYPb5Ezq/hAamoYKIn5g7fuv69kP258w==',
|
||||
tarball: 'file:tgz/pnpm-local-resolver-0.1.1.tgz',
|
||||
@@ -102,7 +102,7 @@ test('resolve tarball specified with file: protocol', async () => {
|
||||
|
||||
expect(resolveResult).toEqual({
|
||||
id: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
normalizedPref: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
specifier: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
resolution: {
|
||||
integrity: 'sha512-UHd2zKRT/w70KKzFlj4qcT81A1Q0H7NM9uKxLzIZ/VZqJXzt5Hnnp2PYPb5Ezq/hAamoYKIn5g7fuv69kP258w==',
|
||||
tarball: 'file:pnpm-local-resolver-0.1.1.tgz',
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
"ramda": "catalog:",
|
||||
"rename-overwrite": "catalog:",
|
||||
"semver": "catalog:",
|
||||
"semver-utils": "catalog:",
|
||||
"ssri": "catalog:",
|
||||
"version-selector-type": "catalog:"
|
||||
},
|
||||
|
||||
@@ -18,13 +18,14 @@ import {
|
||||
type WorkspacePackagesByVersion,
|
||||
type WorkspaceResolveResult,
|
||||
} from '@pnpm/resolver-base'
|
||||
import { type Registries } from '@pnpm/types'
|
||||
import { type Registries, type PinnedVersion } from '@pnpm/types'
|
||||
import { LRUCache } from 'lru-cache'
|
||||
import normalize from 'normalize-path'
|
||||
import pMemoize from 'p-memoize'
|
||||
import clone from 'ramda/src/clone'
|
||||
import semver from 'semver'
|
||||
import ssri from 'ssri'
|
||||
import versionSelectorType from 'version-selector-type'
|
||||
import {
|
||||
type PackageInRegistry,
|
||||
type PackageMeta,
|
||||
@@ -38,6 +39,7 @@ import {
|
||||
} from './parsePref'
|
||||
import { fromRegistry, RegistryResponseError } from './fetch'
|
||||
import { workspacePrefToNpm } from './workspacePrefToNpm'
|
||||
import { whichVersionIsPinned } from './whichVersionIsPinned'
|
||||
|
||||
export class NoMatchingVersionError extends PnpmError {
|
||||
public readonly packageMeta: PackageMeta
|
||||
@@ -68,6 +70,7 @@ export interface ResolverFactoryOptions {
|
||||
retry?: RetryTimeoutOptions
|
||||
timeout?: number
|
||||
registries: Registries
|
||||
saveWorkspaceProtocol?: boolean | 'rolling'
|
||||
}
|
||||
|
||||
export type NpmResolver = (wantedDependency: WantedDependency, opts: ResolveFromNpmOptions) => Promise<ResolveResult | null>
|
||||
@@ -105,6 +108,7 @@ export function createNpmResolver (
|
||||
cacheDir: opts.cacheDir,
|
||||
}),
|
||||
registries: opts.registries,
|
||||
saveWorkspaceProtocol: opts.saveWorkspaceProtocol,
|
||||
}),
|
||||
clearCache: () => {
|
||||
metaCache.clear()
|
||||
@@ -123,6 +127,8 @@ export type ResolveFromNpmOptions = {
|
||||
preferWorkspacePackages?: boolean
|
||||
update?: false | 'compatible' | 'latest'
|
||||
injectWorkspacePackages?: boolean
|
||||
calcSpecifier?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
} & ({
|
||||
projectDir?: string
|
||||
workspacePackages?: undefined
|
||||
@@ -136,6 +142,7 @@ async function resolveNpm (
|
||||
pickPackage: (spec: RegistryPackageSpec, opts: PickPackageOptions) => ReturnType<typeof pickPackage>
|
||||
getAuthHeaderValueByURI: (registry: string) => string | undefined
|
||||
registries: Registries
|
||||
saveWorkspaceProtocol?: boolean | 'rolling'
|
||||
},
|
||||
wantedDependency: WantedDependency,
|
||||
opts: ResolveFromNpmOptions
|
||||
@@ -154,6 +161,9 @@ async function resolveNpm (
|
||||
workspacePackages: opts.workspacePackages,
|
||||
injectWorkspacePackages: opts.injectWorkspacePackages,
|
||||
update: Boolean(opts.update),
|
||||
saveWorkspaceProtocol: ctx.saveWorkspaceProtocol !== false ? ctx.saveWorkspaceProtocol : true,
|
||||
calcSpecifier: opts.calcSpecifier,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
})
|
||||
if (resolvedFromWorkspace != null) {
|
||||
return resolvedFromWorkspace
|
||||
@@ -186,6 +196,9 @@ async function resolveNpm (
|
||||
lockfileDir: opts.lockfileDir,
|
||||
hardLinkLocalPackages: opts.injectWorkspacePackages === true || wantedDependency.injected,
|
||||
update: Boolean(opts.update),
|
||||
saveWorkspaceProtocol: ctx.saveWorkspaceProtocol,
|
||||
calcSpecifier: opts.calcSpecifier,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
})
|
||||
} catch {
|
||||
// ignore
|
||||
@@ -204,6 +217,9 @@ async function resolveNpm (
|
||||
lockfileDir: opts.lockfileDir,
|
||||
hardLinkLocalPackages: opts.injectWorkspacePackages === true || wantedDependency.injected,
|
||||
update: Boolean(opts.update),
|
||||
saveWorkspaceProtocol: ctx.saveWorkspaceProtocol,
|
||||
calcSpecifier: opts.calcSpecifier,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
})
|
||||
} catch {
|
||||
// ignore
|
||||
@@ -217,10 +233,14 @@ async function resolveNpm (
|
||||
const matchedPkg = workspacePkgsMatchingName.get(pickedPackage.version)
|
||||
if (matchedPkg) {
|
||||
return {
|
||||
...resolveFromLocalPackage(matchedPkg, spec.normalizedPref, {
|
||||
...resolveFromLocalPackage(matchedPkg, spec, {
|
||||
wantedDependency,
|
||||
projectDir: opts.projectDir,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
hardLinkLocalPackages: opts.injectWorkspacePackages === true || wantedDependency.injected,
|
||||
saveWorkspaceProtocol: ctx.saveWorkspaceProtocol,
|
||||
calcSpecifier: opts.calcSpecifier,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
}),
|
||||
latest: meta['dist-tags'].latest,
|
||||
}
|
||||
@@ -228,10 +248,14 @@ async function resolveNpm (
|
||||
const localVersion = pickMatchingLocalVersionOrNull(workspacePkgsMatchingName, spec)
|
||||
if (localVersion && (semver.gt(localVersion, pickedPackage.version) || opts.preferWorkspacePackages)) {
|
||||
return {
|
||||
...resolveFromLocalPackage(workspacePkgsMatchingName.get(localVersion)!, spec.normalizedPref, {
|
||||
...resolveFromLocalPackage(workspacePkgsMatchingName.get(localVersion)!, spec, {
|
||||
wantedDependency,
|
||||
projectDir: opts.projectDir,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
hardLinkLocalPackages: opts.injectWorkspacePackages === true || wantedDependency.injected,
|
||||
saveWorkspaceProtocol: ctx.saveWorkspaceProtocol,
|
||||
calcSpecifier: opts.calcSpecifier,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
}),
|
||||
latest: meta['dist-tags'].latest,
|
||||
}
|
||||
@@ -243,17 +267,55 @@ async function resolveNpm (
|
||||
integrity: getIntegrity(pickedPackage.dist),
|
||||
tarball: pickedPackage.dist.tarball,
|
||||
}
|
||||
let specifier: string | undefined
|
||||
if (opts.calcSpecifier) {
|
||||
specifier = spec.normalizedPref ?? calcSpecifier({
|
||||
wantedDependency,
|
||||
spec,
|
||||
version: pickedPackage.version,
|
||||
defaultPinnedVersion: opts.pinnedVersion,
|
||||
})
|
||||
}
|
||||
return {
|
||||
id,
|
||||
latest: meta['dist-tags'].latest,
|
||||
manifest: pickedPackage,
|
||||
normalizedPref: spec.normalizedPref,
|
||||
resolution,
|
||||
resolvedVia: 'npm-registry',
|
||||
publishedAt: meta.time?.[pickedPackage.version],
|
||||
specifier,
|
||||
}
|
||||
}
|
||||
|
||||
function calcSpecifier ({
|
||||
wantedDependency,
|
||||
spec,
|
||||
version,
|
||||
defaultPinnedVersion,
|
||||
}: {
|
||||
wantedDependency: WantedDependency
|
||||
spec: RegistryPackageSpec
|
||||
version: string
|
||||
defaultPinnedVersion?: PinnedVersion
|
||||
}): string {
|
||||
if (wantedDependency.prevSpecifier === wantedDependency.pref && wantedDependency.prevSpecifier && versionSelectorType(wantedDependency.prevSpecifier)?.type === 'tag') {
|
||||
return wantedDependency.prevSpecifier
|
||||
}
|
||||
const range = calcRange(version, wantedDependency, defaultPinnedVersion)
|
||||
if (!wantedDependency.alias || spec.name === wantedDependency.alias) return range
|
||||
return `npm:${spec.name}@${range}`
|
||||
}
|
||||
|
||||
function calcRange (version: string, wantedDependency: WantedDependency, defaultPinnedVersion?: PinnedVersion): string {
|
||||
if (semver.parse(version)?.prerelease.length) {
|
||||
return version
|
||||
}
|
||||
const pinnedVersion = (wantedDependency.prevSpecifier ? whichVersionIsPinned(wantedDependency.prevSpecifier) : undefined) ??
|
||||
(wantedDependency.pref ? whichVersionIsPinned(wantedDependency.pref) : undefined) ??
|
||||
defaultPinnedVersion
|
||||
return createVersionSpec(version, pinnedVersion)
|
||||
}
|
||||
|
||||
function tryResolveFromWorkspace (
|
||||
wantedDependency: WantedDependency,
|
||||
opts: {
|
||||
@@ -264,6 +326,9 @@ function tryResolveFromWorkspace (
|
||||
workspacePackages?: WorkspacePackages
|
||||
injectWorkspacePackages?: boolean
|
||||
update?: boolean
|
||||
saveWorkspaceProtocol?: boolean | 'rolling'
|
||||
calcSpecifier?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
): WorkspaceResolveResult | null {
|
||||
if (!wantedDependency.pref?.startsWith('workspace:')) {
|
||||
@@ -285,6 +350,9 @@ function tryResolveFromWorkspace (
|
||||
hardLinkLocalPackages: opts.injectWorkspacePackages === true || wantedDependency.injected,
|
||||
lockfileDir: opts.lockfileDir,
|
||||
update: opts.update,
|
||||
saveWorkspaceProtocol: opts.saveWorkspaceProtocol,
|
||||
calcSpecifier: opts.calcSpecifier,
|
||||
pinnedVersion: opts.pinnedVersion,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -297,6 +365,9 @@ function tryResolveFromWorkspacePackages (
|
||||
projectDir: string
|
||||
lockfileDir?: string
|
||||
update?: boolean
|
||||
saveWorkspaceProtocol?: boolean | 'rolling'
|
||||
calcSpecifier?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
): WorkspaceResolveResult {
|
||||
const workspacePkgsMatchingName = workspacePackages.get(spec.name)
|
||||
@@ -319,7 +390,7 @@ function tryResolveFromWorkspacePackages (
|
||||
`In ${path.relative(process.cwd(), opts.projectDir)}: No matching version found for ${opts.wantedDependency.alias ?? ''}@${opts.wantedDependency.pref ?? ''} inside the workspace`
|
||||
)
|
||||
}
|
||||
return resolveFromLocalPackage(workspacePkgsMatchingName.get(localVersion)!, spec.normalizedPref, opts)
|
||||
return resolveFromLocalPackage(workspacePkgsMatchingName.get(localVersion)!, spec, opts)
|
||||
}
|
||||
|
||||
function pickMatchingLocalVersionOrNull (
|
||||
@@ -342,11 +413,15 @@ function pickMatchingLocalVersionOrNull (
|
||||
|
||||
function resolveFromLocalPackage (
|
||||
localPackage: WorkspacePackage,
|
||||
normalizedPref: string | undefined,
|
||||
spec: RegistryPackageSpec,
|
||||
opts: {
|
||||
wantedDependency: WantedDependency
|
||||
hardLinkLocalPackages?: boolean
|
||||
projectDir: string
|
||||
lockfileDir?: string
|
||||
saveWorkspaceProtocol?: boolean | 'rolling'
|
||||
calcSpecifier?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
): WorkspaceResolveResult {
|
||||
let id!: PkgResolutionId
|
||||
@@ -359,18 +434,67 @@ function resolveFromLocalPackage (
|
||||
directory = localPackageDir
|
||||
id = `link:${normalize(path.relative(opts.projectDir, localPackageDir))}` as PkgResolutionId
|
||||
}
|
||||
let specifier: string | undefined
|
||||
if (opts.calcSpecifier) {
|
||||
specifier = spec.normalizedPref ?? calcSpecifierForWorkspaceDep({
|
||||
wantedDependency: opts.wantedDependency,
|
||||
spec,
|
||||
saveWorkspaceProtocol: opts.saveWorkspaceProtocol,
|
||||
version: localPackage.manifest.version,
|
||||
defaultPinnedVersion: opts.pinnedVersion,
|
||||
})
|
||||
}
|
||||
return {
|
||||
id,
|
||||
manifest: clone(localPackage.manifest),
|
||||
normalizedPref,
|
||||
resolution: {
|
||||
directory,
|
||||
type: 'directory',
|
||||
},
|
||||
resolvedVia: 'workspace',
|
||||
specifier,
|
||||
}
|
||||
}
|
||||
|
||||
function calcSpecifierForWorkspaceDep ({
|
||||
wantedDependency,
|
||||
spec,
|
||||
saveWorkspaceProtocol,
|
||||
version,
|
||||
defaultPinnedVersion,
|
||||
}: {
|
||||
wantedDependency: WantedDependency
|
||||
spec: RegistryPackageSpec
|
||||
saveWorkspaceProtocol: boolean | 'rolling' | undefined
|
||||
version: string
|
||||
defaultPinnedVersion?: PinnedVersion
|
||||
}): string {
|
||||
if (!saveWorkspaceProtocol && !wantedDependency.pref?.startsWith('workspace:')) {
|
||||
return calcSpecifier({ wantedDependency, spec, version, defaultPinnedVersion })
|
||||
}
|
||||
const prefix = (!wantedDependency.alias || spec.name === wantedDependency.alias) ? 'workspace:' : `workspace:${spec.name}@`
|
||||
if (saveWorkspaceProtocol === 'rolling') {
|
||||
const specifier = wantedDependency.prevSpecifier ?? wantedDependency.pref
|
||||
if (specifier) {
|
||||
if ([`${prefix}*`, `${prefix}^`, `${prefix}~`].includes(specifier)) return specifier
|
||||
const pinnedVersion = whichVersionIsPinned(specifier)
|
||||
switch (pinnedVersion) {
|
||||
case 'major': return `${prefix}^`
|
||||
case 'minor': return `${prefix}~`
|
||||
case 'patch':
|
||||
case 'none': return `${prefix}*`
|
||||
}
|
||||
}
|
||||
return `${prefix}^`
|
||||
}
|
||||
if (semver.parse(version)?.prerelease.length) {
|
||||
return `${prefix}${version}`
|
||||
}
|
||||
const pinnedVersion = (wantedDependency.prevSpecifier ? whichVersionIsPinned(wantedDependency.prevSpecifier) : undefined) ?? defaultPinnedVersion
|
||||
const range = createVersionSpec(version, pinnedVersion)
|
||||
return `${prefix}${range}`
|
||||
}
|
||||
|
||||
function resolveLocalPackageDir (localPackage: WorkspacePackage): string {
|
||||
if (
|
||||
localPackage.manifest.publishConfig?.directory == null ||
|
||||
@@ -404,3 +528,17 @@ function getIntegrity (dist: {
|
||||
}
|
||||
return integrity.toString()
|
||||
}
|
||||
|
||||
function createVersionSpec (version: string, pinnedVersion?: PinnedVersion): string {
|
||||
switch (pinnedVersion ?? 'major') {
|
||||
case 'none':
|
||||
case 'major':
|
||||
return `^${version}`
|
||||
case 'minor':
|
||||
return `~${version}`
|
||||
case 'patch':
|
||||
return version
|
||||
default:
|
||||
throw new PnpmError('BAD_PINNED_VERSION', `Cannot pin '${pinnedVersion ?? 'undefined'}'`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { type PinnedVersion } from '@pnpm/types'
|
||||
import { parseRange } from 'semver-utils'
|
||||
|
||||
export type PinnedVersion =
|
||||
| 'none'
|
||||
| 'patch'
|
||||
| 'minor'
|
||||
| 'major'
|
||||
|
||||
export function whichVersionIsPinned (spec: string): PinnedVersion | undefined {
|
||||
const isWorkspaceProtocol = spec.startsWith('workspace:')
|
||||
if (isWorkspaceProtocol) spec = spec.slice('workspace:'.length)
|
||||
if (spec === '*') return isWorkspaceProtocol ? 'patch' : 'none'
|
||||
if (spec.startsWith('npm:')) {
|
||||
const index = spec.lastIndexOf('@')
|
||||
const colonIndex = spec.indexOf(':')
|
||||
if (colonIndex !== -1) {
|
||||
spec = spec.substring(colonIndex + 1)
|
||||
}
|
||||
const index = spec.lastIndexOf('@')
|
||||
if (index !== -1) {
|
||||
spec = spec.slice(index + 1)
|
||||
}
|
||||
if (spec === '*') return 'none'
|
||||
const parsedRange = parseRange(spec)
|
||||
if (parsedRange.length !== 1) return undefined
|
||||
const versionObject = parsedRange[0]
|
||||
@@ -23,6 +20,7 @@ export function whichVersionIsPinned (spec: string): PinnedVersion | undefined {
|
||||
case undefined:
|
||||
if (versionObject.patch) return 'patch'
|
||||
if (versionObject.minor) return 'minor'
|
||||
if (versionObject.major) return 'major'
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
@@ -74,10 +74,11 @@ test('resolveFromNpm()', async () => {
|
||||
cacheDir,
|
||||
registries,
|
||||
})
|
||||
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: '1.0.0' }, {})
|
||||
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: '1.0.0' }, { calcSpecifier: true })
|
||||
|
||||
expect(resolveResult!.resolvedVia).toBe('npm-registry')
|
||||
expect(resolveResult!.id).toBe('is-positive@1.0.0')
|
||||
expect(resolveResult!.specifier).toBe('1.0.0')
|
||||
expect(resolveResult!.latest!.split('.').length).toBe(3)
|
||||
expect(resolveResult!.resolution).toStrictEqual({
|
||||
integrity: 'sha512-9cI+DmhNhA8ioT/3EJFnt0s1yehnAECyIOXdT+2uQGzcEEBaj8oNmVWj33+ZjPndMIFRQh8JeJlEu1uv5/J7pQ==',
|
||||
@@ -273,8 +274,10 @@ test('can resolve aliased dependency w/o version specifier to default tag', asyn
|
||||
})
|
||||
const resolveResult = await resolveFromNpm({ alias: 'positive', pref: 'npm:is-positive' }, {
|
||||
defaultTag: 'stable',
|
||||
calcSpecifier: true,
|
||||
})
|
||||
expect(resolveResult!.id).toBe('is-positive@3.0.0')
|
||||
expect(resolveResult!.specifier).toBe('npm:is-positive@^3.0.0')
|
||||
})
|
||||
|
||||
test('can resolve aliased scoped dependency', async () => {
|
||||
@@ -940,7 +943,12 @@ test('resolve when tarball URL is requested from the registry', async () => {
|
||||
cacheDir,
|
||||
registries,
|
||||
})
|
||||
const resolveResult = await resolveFromNpm({ alias: 'is-positive', pref: `${registries.default}is-positive/-/is-positive-1.0.0.tgz` }, {})
|
||||
const resolveResult = await resolveFromNpm({
|
||||
alias: 'is-positive',
|
||||
pref: `${registries.default}is-positive/-/is-positive-1.0.0.tgz`,
|
||||
}, {
|
||||
calcSpecifier: true,
|
||||
})
|
||||
|
||||
expect(resolveResult!.resolvedVia).toBe('npm-registry')
|
||||
expect(resolveResult!.id).toBe('is-positive@1.0.0')
|
||||
@@ -952,7 +960,7 @@ test('resolve when tarball URL is requested from the registry', async () => {
|
||||
expect(resolveResult!.manifest).toBeTruthy()
|
||||
expect(resolveResult!.manifest!.name).toBe('is-positive')
|
||||
expect(resolveResult!.manifest!.version).toBe('1.0.0')
|
||||
expect(resolveResult!.normalizedPref).toBe(`${registries.default}is-positive/-/is-positive-1.0.0.tgz`)
|
||||
expect(resolveResult!.specifier).toBe(`${registries.default}is-positive/-/is-positive-1.0.0.tgz`)
|
||||
|
||||
// The resolve function does not wait for the package meta cache file to be saved
|
||||
// so we must delay for a bit in order to read it
|
||||
@@ -972,7 +980,7 @@ test('resolve when tarball URL is requested from the registry and alias is not s
|
||||
cacheDir,
|
||||
registries,
|
||||
})
|
||||
const resolveResult = await resolveFromNpm({ pref: `${registries.default}is-positive/-/is-positive-1.0.0.tgz` }, {})
|
||||
const resolveResult = await resolveFromNpm({ pref: `${registries.default}is-positive/-/is-positive-1.0.0.tgz` }, { calcSpecifier: true })
|
||||
|
||||
expect(resolveResult!.resolvedVia).toBe('npm-registry')
|
||||
expect(resolveResult!.id).toBe('is-positive@1.0.0')
|
||||
@@ -984,7 +992,7 @@ test('resolve when tarball URL is requested from the registry and alias is not s
|
||||
expect(resolveResult!.manifest).toBeTruthy()
|
||||
expect(resolveResult!.manifest!.name).toBe('is-positive')
|
||||
expect(resolveResult!.manifest!.version).toBe('1.0.0')
|
||||
expect(resolveResult!.normalizedPref).toBe(`${registries.default}is-positive/-/is-positive-1.0.0.tgz`)
|
||||
expect(resolveResult!.specifier).toBe(`${registries.default}is-positive/-/is-positive-1.0.0.tgz`)
|
||||
|
||||
// The resolve function does not wait for the package meta cache file to be saved
|
||||
// so we must delay for a bit in order to read it
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { whichVersionIsPinned } from '@pnpm/which-version-is-pinned'
|
||||
import { whichVersionIsPinned } from '../lib/whichVersionIsPinned'
|
||||
|
||||
test.each([
|
||||
['^1.0.0', 'major'],
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
type ProjectRootDir,
|
||||
type DependencyManifest,
|
||||
type PkgResolutionId,
|
||||
type PinnedVersion,
|
||||
} from '@pnpm/types'
|
||||
|
||||
export { type PkgResolutionId }
|
||||
@@ -42,9 +43,9 @@ export interface ResolveResult {
|
||||
latest?: string
|
||||
publishedAt?: string
|
||||
manifest?: DependencyManifest
|
||||
normalizedPref?: string // is null for npm-hosted dependencies
|
||||
resolution: Resolution
|
||||
resolvedVia: 'npm-registry' | 'git-repository' | 'local-filesystem' | 'workspace' | 'url' | string
|
||||
specifier?: string
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,10 +100,13 @@ export interface ResolveOptions {
|
||||
workspacePackages?: WorkspacePackages
|
||||
update?: false | 'compatible' | 'latest'
|
||||
injectWorkspacePackages?: boolean
|
||||
calcSpecifier?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
|
||||
export type WantedDependency = {
|
||||
injected?: boolean
|
||||
prevSpecifier?: string
|
||||
} & ({
|
||||
alias?: string
|
||||
pref: string
|
||||
|
||||
@@ -16,7 +16,7 @@ export async function resolveFromTarball (
|
||||
|
||||
return {
|
||||
id: resolvedUrl as PkgResolutionId,
|
||||
normalizedPref: resolvedUrl,
|
||||
specifier: resolvedUrl,
|
||||
resolution: {
|
||||
tarball: resolvedUrl,
|
||||
},
|
||||
|
||||
@@ -11,7 +11,7 @@ test('tarball from npm registry', async () => {
|
||||
|
||||
expect(resolutionResult).toStrictEqual({
|
||||
id: 'https://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz',
|
||||
normalizedPref: 'https://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz',
|
||||
specifier: 'https://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz',
|
||||
resolution: {
|
||||
tarball: 'https://registry.npmjs.org/is-array/-/is-array-1.0.1.tgz',
|
||||
},
|
||||
@@ -26,7 +26,7 @@ test('tarball from URL that contain port number', async () => {
|
||||
|
||||
expect(resolutionResult).toStrictEqual({
|
||||
id: 'http://buildserver.mycompany.com:81/my-private-package-0.1.6.tgz',
|
||||
normalizedPref: 'http://buildserver.mycompany.com:81/my-private-package-0.1.6.tgz',
|
||||
specifier: 'http://buildserver.mycompany.com:81/my-private-package-0.1.6.tgz',
|
||||
resolution: {
|
||||
tarball: 'http://buildserver.mycompany.com:81/my-private-package-0.1.6.tgz',
|
||||
},
|
||||
@@ -39,7 +39,7 @@ test('tarball not from npm registry', async () => {
|
||||
|
||||
expect(resolutionResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/hegemonic/taffydb/legacy.tar.gz/refs/heads/master',
|
||||
normalizedPref: 'https://codeload.github.com/hegemonic/taffydb/legacy.tar.gz/refs/heads/master',
|
||||
specifier: 'https://codeload.github.com/hegemonic/taffydb/legacy.tar.gz/refs/heads/master',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/hegemonic/taffydb/legacy.tar.gz/refs/heads/master',
|
||||
},
|
||||
@@ -52,7 +52,7 @@ test('tarballs from GitHub (is-negative)', async () => {
|
||||
|
||||
expect(resolutionResult).toStrictEqual({
|
||||
id: 'https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c',
|
||||
normalizedPref: 'https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c',
|
||||
specifier: 'https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c',
|
||||
resolution: {
|
||||
tarball: 'https://codeload.github.com/kevva/is-negative/tar.gz/1d7e288222b53a0cab90a331f1865220ec29560c',
|
||||
},
|
||||
|
||||
@@ -37,6 +37,7 @@ export type CreateNewStoreControllerOptions = CreateResolverOptions & Pick<Confi
|
||||
| 'registries'
|
||||
| 'registrySupportsTimeField'
|
||||
| 'resolutionMode'
|
||||
| 'saveWorkspaceProtocol'
|
||||
| 'strictSsl'
|
||||
| 'unsafePerm'
|
||||
| 'userAgent'
|
||||
@@ -90,6 +91,7 @@ export async function createNewStoreController (
|
||||
gitShallowHosts: opts.gitShallowHosts,
|
||||
resolveSymlinksInInjectedDirs: opts.resolveSymlinksInInjectedDirs,
|
||||
includeOnlyPackageFiles: !opts.deployAllFiles,
|
||||
saveWorkspaceProtocol: opts.saveWorkspaceProtocol,
|
||||
})
|
||||
await fs.mkdir(opts.storeDir, { recursive: true })
|
||||
return {
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
type SupportedArchitectures,
|
||||
type DependencyManifest,
|
||||
type PackageManifest,
|
||||
type PinnedVersion,
|
||||
} from '@pnpm/types'
|
||||
|
||||
export type { PackageFileInfo, PackageFilesResponse, ImportPackageFunction, ImportPackageFunctionAsync }
|
||||
@@ -131,6 +132,8 @@ export interface RequestPackageOptions {
|
||||
supportedArchitectures?: SupportedArchitectures
|
||||
onFetchError?: OnFetchError
|
||||
injectWorkspacePackages?: boolean
|
||||
calcSpecifier?: boolean
|
||||
pinnedVersion?: PinnedVersion
|
||||
}
|
||||
|
||||
export type BundledManifestFunction = () => Promise<BundledManifest | undefined>
|
||||
@@ -144,7 +147,7 @@ export interface PackageResponse {
|
||||
resolution: Resolution
|
||||
manifest?: PackageManifest
|
||||
id: PkgResolutionId
|
||||
normalizedPref?: string
|
||||
specifier?: string
|
||||
updated: boolean
|
||||
publishedAt?: string
|
||||
resolvedVia?: string
|
||||
|
||||
Reference in New Issue
Block a user