-
-
Notifications
You must be signed in to change notification settings - Fork 936
/
yarnUtil.ts
90 lines (85 loc) · 2.48 KB
/
yarnUtil.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
86
87
88
89
90
/**
* https://github.com/snyk/nodejs-lockfile-parser/blob/master/lib/parsers/yarn-utils.ts
*/
import { structUtils } from '@yarnpkg/core'
const BUILTIN_PLACEHOLDER = 'builtin'
const MULTIPLE_KEYS_REGEXP = / *, */g
export type ParseDescriptor = typeof structUtils.parseDescriptor
export type ParseRange = typeof structUtils.parseRange
const keyNormalizer = (
parseDescriptor: ParseDescriptor,
parseRange: ParseRange
) => (rawDescriptor: string): string[] => {
// See https://yarnpkg.com/features/protocols
const descriptors: string[] = [rawDescriptor]
const descriptor = parseDescriptor(rawDescriptor)
const name = `${descriptor.scope ? '@' + descriptor.scope + '/' : ''}${
descriptor.name
}`
const range = parseRange(descriptor.range)
const protocol = range.protocol
switch (protocol) {
case 'npm:':
case 'file:':
descriptors.push(`${name}@${range.selector}`)
descriptors.push(`${name}@${protocol}${range.selector}`)
break
case 'git:':
case 'git+ssh:':
case 'git+http:':
case 'git+https:':
case 'github:':
if (range.source) {
descriptors.push(
`${name}@${protocol}${range.source}${
range.selector ? '#' + range.selector : ''
}`
)
} else {
descriptors.push(`${name}@${protocol}${range.selector}`)
}
break
case 'patch:':
if (range.source && range.selector.indexOf(BUILTIN_PLACEHOLDER) === 0) {
descriptors.push(range.source)
} else {
descriptors.push(
// eslint-disable-next-line
`${name}@${protocol}${range.source}${
range.selector ? '#' + range.selector : ''
}`
)
}
break
case null:
case undefined:
if (range.source) {
descriptors.push(`${name}@${range.source}#${range.selector}`)
} else {
descriptors.push(`${name}@${range.selector}`)
}
break
case 'http:':
case 'https:':
case 'link:':
case 'portal:':
case 'exec:':
case 'workspace:':
case 'virtual:':
default:
// For user defined plugins
descriptors.push(`${name}@${protocol}${range.selector}`)
break
}
return descriptors
}
export type YarnLockFileKeyNormalizer = (fullDescriptor: string) => Set<string>
export const yarnLockFileKeyNormalizer = (
parseDescriptor: ParseDescriptor,
parseRange: ParseRange
): YarnLockFileKeyNormalizer => (fullDescriptor: string) => {
const allKeys = fullDescriptor
.split(MULTIPLE_KEYS_REGEXP)
.map(keyNormalizer(parseDescriptor, parseRange))
return new Set<string>(allKeys.flat(5))
}