/
createVersionsOverrider.ts
85 lines (79 loc) · 2.78 KB
/
createVersionsOverrider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import path from 'path'
import partition from 'ramda/src/partition'
import { Dependencies, PackageManifest, ReadPackageHook } from '@pnpm/types'
import parseOverrides from '@pnpm/parse-overrides'
import normalizePath from 'normalize-path'
import semver from 'semver'
export default function (
overrides: Record<string, string>,
rootDir: string
): ReadPackageHook {
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,
}
})
) as [VersionOverrideWithParent[], VersionOverride[]]
return ((manifest: PackageManifest, dir?: string) => {
overrideDepsOfPkg({ manifest, dir }, versionOverrides.filter(({ parentPkg }) => {
return parentPkg.name === manifest.name && (
!parentPkg.pref || semver.satisfies(manifest.version, parentPkg.pref)
)
}))
overrideDepsOfPkg({ manifest, dir }, genericVersionOverrides)
return manifest
}) as ReadPackageHook
}
interface VersionOverride {
parentPkg?: {
name: string
pref?: string
}
targetPkg: {
name: string
pref?: string
}
newPref: string
linkTarget?: string
}
interface VersionOverrideWithParent extends VersionOverride {
parentPkg: {
name: string
pref?: string
}
}
function overrideDepsOfPkg (
{ manifest, dir }: { manifest: PackageManifest, dir: string | undefined },
versionOverrides: VersionOverride[]
) {
if (manifest.dependencies != null) overrideDeps(versionOverrides, manifest.dependencies, dir)
if (manifest.optionalDependencies != null) overrideDeps(versionOverrides, manifest.optionalDependencies, dir)
if (manifest.devDependencies != null) overrideDeps(versionOverrides, manifest.devDependencies, dir)
return manifest
}
function overrideDeps (versionOverrides: VersionOverride[], deps: Dependencies, dir: string | undefined) {
for (const versionOverride of versionOverrides) {
const actual = deps[versionOverride.targetPkg.name]
if (actual == null) continue
if (!isSubRange(versionOverride.targetPkg.pref, actual)) continue
if (versionOverride.linkTarget && dir) {
deps[versionOverride.targetPkg.name] = `link:${normalizePath(path.relative(dir, versionOverride.linkTarget))}`
continue
}
deps[versionOverride.targetPkg.name] = versionOverride.newPref
}
}
function isSubRange (superRange: string | undefined, subRange: string) {
return !superRange ||
subRange === superRange ||
semver.validRange(subRange) != null &&
semver.validRange(superRange) != null &&
semver.subset(subRange, superRange)
}