refactor: move overrides parsing to a separate package (#4075)

This commit is contained in:
Zoltan Kochan
2021-12-05 23:18:01 +02:00
committed by GitHub
parent d00e1fc6af
commit 613211b16e
12 changed files with 241 additions and 42 deletions

View File

@@ -0,0 +1,5 @@
---
"@pnpm/parse-overrides": major
---
Initial release.

View File

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

View File

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

View File

@@ -90,6 +90,9 @@
{
"path": "../package-store"
},
{
"path": "../parse-overrides"
},
{
"path": "../parse-wanted-dependency"
},

View 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)

View File

@@ -0,0 +1 @@
module.exports = require('../../jest.config')

View 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"
}
}

View 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,
}
}

View 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')
})

View 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"
}
]
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts",
"test/**/*.ts",
"../../typings/**/*.d.ts"
]
}

13
pnpm-lock.yaml generated
View File

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