mirror of
https://github.com/pnpm/pnpm.git
synced 2026-04-27 10:30:58 -04:00
refactor: move overrides parsing to a separate package (#4075)
This commit is contained in:
5
.changeset/purple-rocks-hear.md
Normal file
5
.changeset/purple-rocks-hear.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@pnpm/parse-overrides": major
|
||||
---
|
||||
|
||||
Initial release.
|
||||
@@ -34,6 +34,7 @@
|
||||
"@pnpm/modules-yaml": "workspace:9.0.6",
|
||||
"@pnpm/normalize-registries": "workspace:2.0.8",
|
||||
"@pnpm/package-requester": "workspace:15.2.3",
|
||||
"@pnpm/parse-overrides": "workspace:^0.0.0",
|
||||
"@pnpm/parse-wanted-dependency": "workspace:2.0.0",
|
||||
"@pnpm/prune-lockfile": "workspace:3.0.10",
|
||||
"@pnpm/read-modules-dir": "workspace:3.0.1",
|
||||
|
||||
@@ -1,46 +1,31 @@
|
||||
import path from 'path'
|
||||
import partition from 'ramda/src/partition'
|
||||
import { Dependencies, PackageManifest, ReadPackageHook } from '@pnpm/types'
|
||||
import parseWantedDependency from '@pnpm/parse-wanted-dependency'
|
||||
import parseOverrides from '@pnpm/parse-overrides'
|
||||
import normalizePath from 'normalize-path'
|
||||
import semver from 'semver'
|
||||
|
||||
const DELIMITER_REGEX = /[^ |@]>/
|
||||
|
||||
export default function (
|
||||
overrides: Record<string, string>,
|
||||
rootDir: string
|
||||
): ReadPackageHook {
|
||||
const genericVersionOverrides = [] as VersionOverride[]
|
||||
const versionOverrides = [] as VersionOverrideWithParent[]
|
||||
Object.entries(overrides)
|
||||
.forEach(([selector, newPref]) => {
|
||||
let linkTarget: string | undefined
|
||||
if (newPref.startsWith('link:')) {
|
||||
linkTarget = path.join(rootDir, newPref.substring(5))
|
||||
}
|
||||
let delimiterIndex = selector.search(DELIMITER_REGEX)
|
||||
if (delimiterIndex !== -1) {
|
||||
delimiterIndex++
|
||||
const parentSelector = selector.substring(0, delimiterIndex)
|
||||
const childSelector = selector.substring(delimiterIndex + 1)
|
||||
versionOverrides.push({
|
||||
const [versionOverrides, genericVersionOverrides] = partition(({ parentPkg }) => parentPkg != null,
|
||||
parseOverrides(overrides)
|
||||
.map((override) => {
|
||||
let linkTarget: string | undefined
|
||||
if (override.newPref.startsWith('link:')) {
|
||||
linkTarget = path.join(rootDir, override.newPref.substring(5))
|
||||
}
|
||||
return {
|
||||
...override,
|
||||
linkTarget,
|
||||
newPref,
|
||||
parentWantedDependency: parseWantedDependency(parentSelector),
|
||||
wantedDependency: parseWantedDependency(childSelector),
|
||||
} as VersionOverrideWithParent)
|
||||
return
|
||||
}
|
||||
genericVersionOverrides.push({
|
||||
linkTarget,
|
||||
newPref,
|
||||
wantedDependency: parseWantedDependency(selector),
|
||||
} as VersionOverride)
|
||||
})
|
||||
}
|
||||
})
|
||||
) as [VersionOverrideWithParent[], VersionOverride[]]
|
||||
return ((manifest: PackageManifest, dir?: string) => {
|
||||
overrideDepsOfPkg({ manifest, dir }, versionOverrides.filter(({ parentWantedDependency }) => {
|
||||
return parentWantedDependency.alias === manifest.name && (
|
||||
!parentWantedDependency.pref || semver.satisfies(manifest.version, parentWantedDependency.pref)
|
||||
overrideDepsOfPkg({ manifest, dir }, versionOverrides.filter(({ parentPkg }) => {
|
||||
return parentPkg.name === manifest.name && (
|
||||
!parentPkg.pref || semver.satisfies(manifest.version, parentPkg.pref)
|
||||
)
|
||||
}))
|
||||
overrideDepsOfPkg({ manifest, dir }, genericVersionOverrides)
|
||||
@@ -49,12 +34,12 @@ export default function (
|
||||
}
|
||||
|
||||
interface VersionOverride {
|
||||
parentWantedDependency?: {
|
||||
alias: string
|
||||
parentPkg?: {
|
||||
name: string
|
||||
pref?: string
|
||||
}
|
||||
wantedDependency: {
|
||||
alias: string
|
||||
targetPkg: {
|
||||
name: string
|
||||
pref?: string
|
||||
}
|
||||
newPref: string
|
||||
@@ -62,8 +47,8 @@ interface VersionOverride {
|
||||
}
|
||||
|
||||
interface VersionOverrideWithParent extends VersionOverride {
|
||||
parentWantedDependency: {
|
||||
alias: string
|
||||
parentPkg: {
|
||||
name: string
|
||||
pref?: string
|
||||
}
|
||||
}
|
||||
@@ -80,14 +65,14 @@ function overrideDepsOfPkg (
|
||||
|
||||
function overrideDeps (versionOverrides: VersionOverride[], deps: Dependencies, dir: string | undefined) {
|
||||
for (const versionOverride of versionOverrides) {
|
||||
const actual = deps[versionOverride.wantedDependency.alias]
|
||||
const actual = deps[versionOverride.targetPkg.name]
|
||||
if (actual == null) continue
|
||||
if (!isSubRange(versionOverride.wantedDependency.pref, actual)) continue
|
||||
if (!isSubRange(versionOverride.targetPkg.pref, actual)) continue
|
||||
if (versionOverride.linkTarget && dir) {
|
||||
deps[versionOverride.wantedDependency.alias] = `link:${normalizePath(path.relative(dir, versionOverride.linkTarget))}`
|
||||
deps[versionOverride.targetPkg.name] = `link:${normalizePath(path.relative(dir, versionOverride.linkTarget))}`
|
||||
continue
|
||||
}
|
||||
deps[versionOverride.wantedDependency.alias] = versionOverride.newPref
|
||||
deps[versionOverride.targetPkg.name] = versionOverride.newPref
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
{
|
||||
"path": "../package-store"
|
||||
},
|
||||
{
|
||||
"path": "../parse-overrides"
|
||||
},
|
||||
{
|
||||
"path": "../parse-wanted-dependency"
|
||||
},
|
||||
|
||||
27
packages/parse-overrides/README.md
Normal file
27
packages/parse-overrides/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# @pnpm/parse-overrides
|
||||
|
||||
> Parse overrides
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
pnpm add @pnpm/parse-overrides
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
import { parseOverrides } from '@pnpm/parse-overrides'
|
||||
|
||||
parseOverrides({
|
||||
'foo': '^1.0.0',
|
||||
'quux': 'npm:@myorg/quux@^1.0.0',
|
||||
'bar@^2.1.0': '3.0.0',
|
||||
'qar@1>zoo': '2',
|
||||
})
|
||||
// Returns an array of parsed overrides
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
1
packages/parse-overrides/jest.config.js
Normal file
1
packages/parse-overrides/jest.config.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('../../jest.config')
|
||||
35
packages/parse-overrides/package.json
Normal file
35
packages/parse-overrides/package.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@pnpm/parse-overrides",
|
||||
"description": "Parse overrides",
|
||||
"version": "0.0.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/pnpm/pnpm/issues"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"!*.map"
|
||||
],
|
||||
"keywords": [
|
||||
"pnpm6"
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
},
|
||||
"repository": "https://github.com/pnpm/pnpm/blob/master/packages/parse-overrides",
|
||||
"scripts": {
|
||||
"_test": "jest",
|
||||
"test": "pnpm run compile && pnpm run _test",
|
||||
"lint": "eslint src/**/*.ts test/**/*.ts",
|
||||
"prepublishOnly": "pnpm run compile",
|
||||
"compile": "rimraf lib tsconfig.tsbuildinfo && tsc --build && pnpm run lint -- --fix"
|
||||
},
|
||||
"homepage": "https://github.com/pnpm/pnpm/blob/master/packages/parse-overrides#readme",
|
||||
"funding": "https://opencollective.com/pnpm",
|
||||
"dependencies": {
|
||||
"@pnpm/error": "workspace:2.0.0",
|
||||
"@pnpm/parse-wanted-dependency": "workspace:2.0.0"
|
||||
}
|
||||
}
|
||||
50
packages/parse-overrides/src/index.ts
Normal file
50
packages/parse-overrides/src/index.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import PnpmError from '@pnpm/error'
|
||||
import parseWantedDependency from '@pnpm/parse-wanted-dependency'
|
||||
|
||||
const DELIMITER_REGEX = /[^ |@]>/
|
||||
|
||||
interface VersionOverride {
|
||||
parentPkg?: {
|
||||
name: string
|
||||
pref?: string
|
||||
}
|
||||
targetPkg: {
|
||||
name: string
|
||||
pref?: string
|
||||
}
|
||||
newPref: string
|
||||
}
|
||||
|
||||
export default function parseOverrides (
|
||||
overrides: Record<string, string>
|
||||
): VersionOverride[] {
|
||||
return Object.entries(overrides)
|
||||
.map(([selector, newPref]) => {
|
||||
let delimiterIndex = selector.search(DELIMITER_REGEX)
|
||||
if (delimiterIndex !== -1) {
|
||||
delimiterIndex++
|
||||
const parentSelector = selector.substring(0, delimiterIndex)
|
||||
const childSelector = selector.substring(delimiterIndex + 1)
|
||||
return {
|
||||
newPref,
|
||||
parentPkg: parsePkgSelector(parentSelector),
|
||||
targetPkg: parsePkgSelector(childSelector),
|
||||
}
|
||||
}
|
||||
return {
|
||||
newPref,
|
||||
targetPkg: parsePkgSelector(selector),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function parsePkgSelector (selector: string) {
|
||||
const wantedDep = parseWantedDependency(selector)
|
||||
if (!wantedDep.alias) {
|
||||
throw new PnpmError('INVALID_OVERRIDE_SELECTOR', `Cannot parse the "${selector}" selector in the overrides`)
|
||||
}
|
||||
return {
|
||||
name: wantedDep.alias,
|
||||
pref: wantedDep.pref,
|
||||
}
|
||||
}
|
||||
52
packages/parse-overrides/test/index.ts
Normal file
52
packages/parse-overrides/test/index.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import parseOverrides from '@pnpm/parse-overrides'
|
||||
|
||||
test.each([
|
||||
[
|
||||
{ foo: '1' },
|
||||
[{ newPref: '1', targetPkg: { name: 'foo' } }],
|
||||
],
|
||||
[
|
||||
{ 'foo@2': '1' },
|
||||
[{ newPref: '1', targetPkg: { name: 'foo', pref: '2' } }],
|
||||
],
|
||||
[
|
||||
{
|
||||
'foo@>2': '1',
|
||||
'foo@3 || >=2': '1',
|
||||
},
|
||||
[
|
||||
{ newPref: '1', targetPkg: { name: 'foo', pref: '>2' } },
|
||||
{ newPref: '1', targetPkg: { name: 'foo', pref: '3 || >=2' } },
|
||||
],
|
||||
],
|
||||
[
|
||||
{
|
||||
'bar>foo': '2',
|
||||
'bar@1>foo': '2',
|
||||
'bar>foo@1': '2',
|
||||
'bar@1>foo@1': '2',
|
||||
},
|
||||
[
|
||||
{ newPref: '2', parentPkg: { name: 'bar' }, targetPkg: { name: 'foo' } },
|
||||
{ newPref: '2', parentPkg: { name: 'bar', pref: '1' }, targetPkg: { name: 'foo' } },
|
||||
{ newPref: '2', parentPkg: { name: 'bar' }, targetPkg: { name: 'foo', pref: '1' } },
|
||||
{ newPref: '2', parentPkg: { name: 'bar', pref: '1' }, targetPkg: { name: 'foo', pref: '1' } },
|
||||
],
|
||||
],
|
||||
[
|
||||
{
|
||||
'foo@>2>bar@>2': '1',
|
||||
'foo@3 || >=2>bar@3 || >=2': '1',
|
||||
},
|
||||
[
|
||||
{ newPref: '1', parentPkg: { name: 'foo', pref: '>2' }, targetPkg: { name: 'bar', pref: '>2' } },
|
||||
{ newPref: '1', parentPkg: { name: 'foo', pref: '3 || >=2' }, targetPkg: { name: 'bar', pref: '3 || >=2' } },
|
||||
],
|
||||
],
|
||||
])('parseOverrides()', (overrides, expectedResult) => {
|
||||
expect(parseOverrides(overrides)).toEqual(expectedResult)
|
||||
})
|
||||
|
||||
test('parseOverrides() throws an exception on invalid selector', () => {
|
||||
expect(() => parseOverrides({ '%': '2' })).toThrow('Cannot parse the "%" selector in the overrides')
|
||||
})
|
||||
19
packages/parse-overrides/tsconfig.json
Normal file
19
packages/parse-overrides/tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "@pnpm/tsconfig",
|
||||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"../../typings/**/*.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../error"
|
||||
},
|
||||
{
|
||||
"path": "../parse-wanted-dependency"
|
||||
}
|
||||
]
|
||||
}
|
||||
8
packages/parse-overrides/tsconfig.lint.json
Normal file
8
packages/parse-overrides/tsconfig.lint.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"test/**/*.ts",
|
||||
"../../typings/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@@ -397,6 +397,7 @@ importers:
|
||||
'@pnpm/normalize-registries': workspace:2.0.8
|
||||
'@pnpm/package-requester': workspace:15.2.3
|
||||
'@pnpm/package-store': workspace:12.1.3
|
||||
'@pnpm/parse-overrides': workspace:^0.0.0
|
||||
'@pnpm/parse-wanted-dependency': workspace:2.0.0
|
||||
'@pnpm/prepare': workspace:0.0.28
|
||||
'@pnpm/prune-lockfile': workspace:3.0.10
|
||||
@@ -472,6 +473,7 @@ importers:
|
||||
'@pnpm/modules-yaml': link:../modules-yaml
|
||||
'@pnpm/normalize-registries': link:../normalize-registries
|
||||
'@pnpm/package-requester': link:../package-requester
|
||||
'@pnpm/parse-overrides': link:../parse-overrides
|
||||
'@pnpm/parse-wanted-dependency': link:../parse-wanted-dependency
|
||||
'@pnpm/prune-lockfile': link:../prune-lockfile
|
||||
'@pnpm/read-modules-dir': link:../read-modules-dir
|
||||
@@ -1938,6 +1940,17 @@ importers:
|
||||
'@pnpm/parse-cli-args': 'link:'
|
||||
tempy: 1.0.1
|
||||
|
||||
packages/parse-overrides:
|
||||
specifiers:
|
||||
'@pnpm/error': workspace:2.0.0
|
||||
'@pnpm/parse-overrides': 'link:'
|
||||
'@pnpm/parse-wanted-dependency': workspace:2.0.0
|
||||
dependencies:
|
||||
'@pnpm/error': link:../error
|
||||
'@pnpm/parse-wanted-dependency': link:../parse-wanted-dependency
|
||||
devDependencies:
|
||||
'@pnpm/parse-overrides': 'link:'
|
||||
|
||||
packages/parse-wanted-dependency:
|
||||
specifiers:
|
||||
'@pnpm/parse-wanted-dependency': 'link:'
|
||||
|
||||
Reference in New Issue
Block a user