@vltpkg/query 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/package.json +10 -12
  2. package/skills/dss-query/REFERENCE.md +0 -125
  3. package/skills/dss-query/SKILL.md +0 -190
  4. package/skills/dss-query/evals/README.md +0 -81
  5. package/skills/dss-query/evals/evals.json +0 -89
  6. package/skills/dss-query/evals/grade.mjs +0 -481
  7. package/src/attribute.ts +0 -190
  8. package/src/combinator.ts +0 -135
  9. package/src/error.ts +0 -78
  10. package/src/id.ts +0 -46
  11. package/src/index.ts +0 -670
  12. package/src/parser.ts +0 -122
  13. package/src/pseudo/abandoned.ts +0 -9
  14. package/src/pseudo/attr.ts +0 -92
  15. package/src/pseudo/built.ts +0 -19
  16. package/src/pseudo/confused.ts +0 -29
  17. package/src/pseudo/cve.ts +0 -93
  18. package/src/pseudo/cwe.ts +0 -97
  19. package/src/pseudo/debug.ts +0 -9
  20. package/src/pseudo/deprecated.ts +0 -9
  21. package/src/pseudo/dev.ts +0 -18
  22. package/src/pseudo/diff.ts +0 -90
  23. package/src/pseudo/dist.ts +0 -148
  24. package/src/pseudo/dynamic.ts +0 -9
  25. package/src/pseudo/empty.ts +0 -15
  26. package/src/pseudo/entropic.ts +0 -9
  27. package/src/pseudo/env.ts +0 -6
  28. package/src/pseudo/eval.ts +0 -9
  29. package/src/pseudo/fs.ts +0 -9
  30. package/src/pseudo/helpers.ts +0 -106
  31. package/src/pseudo/host.ts +0 -111
  32. package/src/pseudo/hostname.ts +0 -156
  33. package/src/pseudo/license.ts +0 -134
  34. package/src/pseudo/link.ts +0 -30
  35. package/src/pseudo/malware.ts +0 -41
  36. package/src/pseudo/minified.ts +0 -9
  37. package/src/pseudo/missing.ts +0 -16
  38. package/src/pseudo/native.ts +0 -9
  39. package/src/pseudo/network.ts +0 -9
  40. package/src/pseudo/obfuscated.ts +0 -9
  41. package/src/pseudo/optional.ts +0 -18
  42. package/src/pseudo/outdated.ts +0 -345
  43. package/src/pseudo/overridden.ts +0 -20
  44. package/src/pseudo/path.ts +0 -146
  45. package/src/pseudo/peer.ts +0 -18
  46. package/src/pseudo/prerelease.ts +0 -47
  47. package/src/pseudo/private.ts +0 -19
  48. package/src/pseudo/prod.ts +0 -18
  49. package/src/pseudo/published.ts +0 -250
  50. package/src/pseudo/registry.ts +0 -29
  51. package/src/pseudo/root.ts +0 -19
  52. package/src/pseudo/scanned.ts +0 -20
  53. package/src/pseudo/score.ts +0 -186
  54. package/src/pseudo/scripts.ts +0 -61
  55. package/src/pseudo/semver.ts +0 -320
  56. package/src/pseudo/severity.ts +0 -231
  57. package/src/pseudo/shell.ts +0 -9
  58. package/src/pseudo/shrinkwrap.ts +0 -9
  59. package/src/pseudo/skill.ts +0 -59
  60. package/src/pseudo/skills.ts +0 -29
  61. package/src/pseudo/spec.ts +0 -131
  62. package/src/pseudo/squat.ts +0 -225
  63. package/src/pseudo/suspicious.ts +0 -9
  64. package/src/pseudo/tracker.ts +0 -9
  65. package/src/pseudo/trivial.ts +0 -9
  66. package/src/pseudo/type.ts +0 -26
  67. package/src/pseudo/undesirable.ts +0 -9
  68. package/src/pseudo/unknown.ts +0 -9
  69. package/src/pseudo/unmaintained.ts +0 -9
  70. package/src/pseudo/unpopular.ts +0 -9
  71. package/src/pseudo/unstable.ts +0 -9
  72. package/src/pseudo/vuln.ts +0 -273
  73. package/src/pseudo/workspace.ts +0 -22
  74. package/src/pseudo.ts +0 -440
  75. package/src/types.ts +0 -206
  76. package/tap-snapshots/test/attribute.ts.test.cjs +0 -304
  77. package/tap-snapshots/test/combinator.ts.test.cjs +0 -333
  78. package/tap-snapshots/test/id.ts.test.cjs +0 -118
  79. package/tap-snapshots/test/parser.ts.test.cjs +0 -344
  80. package/tap-snapshots/test/pseudo/abandoned.ts.test.cjs +0 -18
  81. package/tap-snapshots/test/pseudo/attr.ts.test.cjs +0 -161
  82. package/tap-snapshots/test/pseudo/built.ts.test.cjs +0 -70
  83. package/tap-snapshots/test/pseudo/confused.ts.test.cjs +0 -32
  84. package/tap-snapshots/test/pseudo/cve.ts.test.cjs +0 -49
  85. package/tap-snapshots/test/pseudo/cwe.ts.test.cjs +0 -49
  86. package/tap-snapshots/test/pseudo/debug.ts.test.cjs +0 -18
  87. package/tap-snapshots/test/pseudo/deprecated.ts.test.cjs +0 -18
  88. package/tap-snapshots/test/pseudo/dist.ts.test.cjs +0 -30
  89. package/tap-snapshots/test/pseudo/dynamic.ts.test.cjs +0 -18
  90. package/tap-snapshots/test/pseudo/empty.ts.test.cjs +0 -50
  91. package/tap-snapshots/test/pseudo/entropic.ts.test.cjs +0 -18
  92. package/tap-snapshots/test/pseudo/env.ts.test.cjs +0 -18
  93. package/tap-snapshots/test/pseudo/eval.ts.test.cjs +0 -18
  94. package/tap-snapshots/test/pseudo/fs.ts.test.cjs +0 -18
  95. package/tap-snapshots/test/pseudo/helpers.ts.test.cjs +0 -18
  96. package/tap-snapshots/test/pseudo/hostname.ts.test.cjs +0 -148
  97. package/tap-snapshots/test/pseudo/license.ts.test.cjs +0 -41
  98. package/tap-snapshots/test/pseudo/link.ts.test.cjs +0 -36
  99. package/tap-snapshots/test/pseudo/malware.ts.test.cjs +0 -22
  100. package/tap-snapshots/test/pseudo/minified.ts.test.cjs +0 -18
  101. package/tap-snapshots/test/pseudo/missing.ts.test.cjs +0 -30
  102. package/tap-snapshots/test/pseudo/native.ts.test.cjs +0 -18
  103. package/tap-snapshots/test/pseudo/network.ts.test.cjs +0 -18
  104. package/tap-snapshots/test/pseudo/obfuscated.ts.test.cjs +0 -18
  105. package/tap-snapshots/test/pseudo/outdated.ts.test.cjs +0 -132
  106. package/tap-snapshots/test/pseudo/overridden.ts.test.cjs +0 -75
  107. package/tap-snapshots/test/pseudo/prerelease.ts.test.cjs +0 -101
  108. package/tap-snapshots/test/pseudo/private.ts.test.cjs +0 -38
  109. package/tap-snapshots/test/pseudo/published.ts.test.cjs +0 -171
  110. package/tap-snapshots/test/pseudo/registry.ts.test.cjs +0 -68
  111. package/tap-snapshots/test/pseudo/root.ts.test.cjs +0 -24
  112. package/tap-snapshots/test/pseudo/scanned.ts.test.cjs +0 -18
  113. package/tap-snapshots/test/pseudo/score.ts.test.cjs +0 -239
  114. package/tap-snapshots/test/pseudo/scripts.ts.test.cjs +0 -62
  115. package/tap-snapshots/test/pseudo/semver.ts.test.cjs +0 -575
  116. package/tap-snapshots/test/pseudo/severity.ts.test.cjs +0 -122
  117. package/tap-snapshots/test/pseudo/shell.ts.test.cjs +0 -18
  118. package/tap-snapshots/test/pseudo/shrinkwrap.ts.test.cjs +0 -18
  119. package/tap-snapshots/test/pseudo/skills.ts.test.cjs +0 -19
  120. package/tap-snapshots/test/pseudo/spec.ts.test.cjs +0 -148
  121. package/tap-snapshots/test/pseudo/squat.ts.test.cjs +0 -129
  122. package/tap-snapshots/test/pseudo/suspicious.ts.test.cjs +0 -18
  123. package/tap-snapshots/test/pseudo/tracker.ts.test.cjs +0 -18
  124. package/tap-snapshots/test/pseudo/trivial.ts.test.cjs +0 -18
  125. package/tap-snapshots/test/pseudo/type.ts.test.cjs +0 -51
  126. package/tap-snapshots/test/pseudo/undesirable.ts.test.cjs +0 -18
  127. package/tap-snapshots/test/pseudo/unknown.ts.test.cjs +0 -18
  128. package/tap-snapshots/test/pseudo/unmaintained.ts.test.cjs +0 -18
  129. package/tap-snapshots/test/pseudo/unpopular.ts.test.cjs +0 -18
  130. package/tap-snapshots/test/pseudo/unstable.ts.test.cjs +0 -18
  131. package/tap-snapshots/test/pseudo/vuln.ts.test.cjs +0 -208
  132. package/tap-snapshots/test/pseudo/vulnerable.ts.test.cjs +0 -20
  133. package/tap-snapshots/test/pseudo/workspace.ts.test.cjs +0 -19
  134. package/tap-snapshots/test/pseudo.ts.test.cjs +0 -1247
  135. package/test/attribute.ts +0 -273
  136. package/test/combinator.ts +0 -175
  137. package/test/error.ts +0 -60
  138. package/test/fixtures/graph.ts +0 -999
  139. package/test/fixtures/selector.ts +0 -103
  140. package/test/fixtures/types.ts +0 -7
  141. package/test/id.ts +0 -102
  142. package/test/index.ts +0 -1148
  143. package/test/parser.ts +0 -117
  144. package/test/pseudo/abandoned.ts +0 -98
  145. package/test/pseudo/attr.ts +0 -298
  146. package/test/pseudo/built.ts +0 -214
  147. package/test/pseudo/confused.ts +0 -160
  148. package/test/pseudo/cve.ts +0 -249
  149. package/test/pseudo/cwe.ts +0 -255
  150. package/test/pseudo/debug.ts +0 -98
  151. package/test/pseudo/deprecated.ts +0 -98
  152. package/test/pseudo/dev.ts +0 -61
  153. package/test/pseudo/diff.ts +0 -417
  154. package/test/pseudo/dist.ts +0 -215
  155. package/test/pseudo/dynamic.ts +0 -98
  156. package/test/pseudo/empty.ts +0 -108
  157. package/test/pseudo/entropic.ts +0 -101
  158. package/test/pseudo/env.ts +0 -98
  159. package/test/pseudo/eval.ts +0 -98
  160. package/test/pseudo/fs.ts +0 -98
  161. package/test/pseudo/helpers.ts +0 -370
  162. package/test/pseudo/host-context.ts +0 -276
  163. package/test/pseudo/hostname.ts +0 -314
  164. package/test/pseudo/license.ts +0 -265
  165. package/test/pseudo/link.ts +0 -94
  166. package/test/pseudo/malware.ts +0 -184
  167. package/test/pseudo/minified.ts +0 -98
  168. package/test/pseudo/missing.ts +0 -111
  169. package/test/pseudo/native.ts +0 -98
  170. package/test/pseudo/network.ts +0 -98
  171. package/test/pseudo/obfuscated.ts +0 -98
  172. package/test/pseudo/optional.ts +0 -73
  173. package/test/pseudo/outdated.ts +0 -461
  174. package/test/pseudo/overridden.ts +0 -317
  175. package/test/pseudo/path.ts +0 -680
  176. package/test/pseudo/peer.ts +0 -101
  177. package/test/pseudo/prerelease.ts +0 -279
  178. package/test/pseudo/private.ts +0 -108
  179. package/test/pseudo/prod.ts +0 -61
  180. package/test/pseudo/published.ts +0 -557
  181. package/test/pseudo/registry.ts +0 -122
  182. package/test/pseudo/root.ts +0 -66
  183. package/test/pseudo/scanned.ts +0 -144
  184. package/test/pseudo/score.ts +0 -591
  185. package/test/pseudo/scripts.ts +0 -324
  186. package/test/pseudo/semver.ts +0 -822
  187. package/test/pseudo/severity.ts +0 -342
  188. package/test/pseudo/shell.ts +0 -98
  189. package/test/pseudo/shrinkwrap.ts +0 -98
  190. package/test/pseudo/skill.ts +0 -189
  191. package/test/pseudo/skills.ts +0 -90
  192. package/test/pseudo/spec.ts +0 -525
  193. package/test/pseudo/squat.ts +0 -565
  194. package/test/pseudo/suspicious.ts +0 -98
  195. package/test/pseudo/tracker.ts +0 -98
  196. package/test/pseudo/trivial.ts +0 -98
  197. package/test/pseudo/type.ts +0 -105
  198. package/test/pseudo/undesirable.ts +0 -98
  199. package/test/pseudo/unknown.ts +0 -98
  200. package/test/pseudo/unmaintained.ts +0 -98
  201. package/test/pseudo/unpopular.ts +0 -98
  202. package/test/pseudo/unstable.ts +0 -98
  203. package/test/pseudo/vuln.ts +0 -625
  204. package/test/pseudo/vulnerable.ts +0 -137
  205. package/test/pseudo/workspace.ts +0 -111
  206. package/test/pseudo.ts +0 -584
  207. package/tsconfig.json +0 -3
  208. package/tsconfig.publish.json +0 -19
  209. package/tsconfig.publish.tsbuildinfo +0 -1
  210. package/typedoc.mjs +0 -2
@@ -1,186 +0,0 @@
1
- import { error } from '@vltpkg/error-cause'
2
- import { asError } from '@vltpkg/types'
3
- import {
4
- asPostcssNodeWithChildren,
5
- asStringNode,
6
- asTagNode,
7
- isStringNode,
8
- isTagNode,
9
- } from '@vltpkg/dss-parser'
10
- import {
11
- assertSecurityArchive,
12
- removeDanglingEdges,
13
- removeNode,
14
- removeQuotes,
15
- } from './helpers.ts'
16
- import type { PackageScore } from '@vltpkg/security-archive'
17
- import type { ParserState } from '../types.ts'
18
- import type { PostcssNode } from '@vltpkg/dss-parser'
19
-
20
- export type ScoreKinds = keyof PackageScore
21
-
22
- export type ScoreComparator =
23
- '>' | '<' | '>=' | '<=' | '=' | undefined
24
-
25
- const kinds = new Set<ScoreKinds | undefined>([
26
- 'overall',
27
- 'license',
28
- 'maintenance',
29
- 'quality',
30
- 'supplyChain',
31
- 'vulnerability',
32
- undefined,
33
- ])
34
-
35
- export const isScoreKind = (value?: string): value is ScoreKinds =>
36
- kinds.has(value as ScoreKinds)
37
-
38
- export const asScoreKind = (value?: string): ScoreKinds => {
39
- if (!isScoreKind(value)) {
40
- throw error('Expected a valid score kind', {
41
- found: value,
42
- validOptions: Array.from(kinds),
43
- })
44
- }
45
- return value
46
- }
47
-
48
- export const parseInternals = (
49
- nodes: PostcssNode[],
50
- ): {
51
- comparator: ScoreComparator
52
- rate: number
53
- kind: ScoreKinds
54
- } => {
55
- let rateStr = ''
56
- let comparator: ScoreComparator = '='
57
- let kind: ScoreKinds = 'overall'
58
-
59
- // Parse the first parameter (rate with optional comparator)
60
- if (isStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])) {
61
- rateStr = removeQuotes(
62
- asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
63
- .value,
64
- )
65
- } else if (
66
- isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
67
- ) {
68
- const tagNode = asTagNode(
69
- asPostcssNodeWithChildren(nodes[0]).nodes[0],
70
- )
71
- rateStr = tagNode.value
72
- }
73
-
74
- // Extract comparator if present
75
- if (rateStr.startsWith('>=')) {
76
- comparator = '>='
77
- rateStr = rateStr.substring(2)
78
- } else if (rateStr.startsWith('<=')) {
79
- comparator = '<='
80
- rateStr = rateStr.substring(2)
81
- } else if (rateStr.startsWith('>')) {
82
- comparator = '>'
83
- rateStr = rateStr.substring(1)
84
- } else if (rateStr.startsWith('<')) {
85
- comparator = '<'
86
- rateStr = rateStr.substring(1)
87
- }
88
-
89
- // Parse rate as number
90
- let rate = parseFloat(rateStr)
91
-
92
- // Normalize to 0-1 range if needed
93
- if (rate > 1) {
94
- rate = rate / 100
95
- }
96
-
97
- // Validate rate is in acceptable range
98
- if (rate < 0 || rate > 1) {
99
- throw error('Expected rate to be between 0 and 100', {
100
- found: rateStr,
101
- })
102
- }
103
-
104
- // Parse the second parameter (kind) if present
105
- if (nodes.length > 1) {
106
- if (isStringNode(asPostcssNodeWithChildren(nodes[1]).nodes[0])) {
107
- kind = asScoreKind(
108
- removeQuotes(
109
- asStringNode(asPostcssNodeWithChildren(nodes[1]).nodes[0])
110
- .value,
111
- ),
112
- )
113
- } else if (
114
- isTagNode(asPostcssNodeWithChildren(nodes[1]).nodes[0])
115
- ) {
116
- kind = asScoreKind(
117
- asTagNode(asPostcssNodeWithChildren(nodes[1]).nodes[0]).value,
118
- )
119
- }
120
- }
121
-
122
- return { comparator, rate, kind }
123
- }
124
-
125
- export const score = async (state: ParserState) => {
126
- assertSecurityArchive(state, 'score')
127
-
128
- let internals
129
- try {
130
- internals = parseInternals(
131
- asPostcssNodeWithChildren(state.current).nodes,
132
- )
133
- } catch (err) {
134
- if (asError(err).message === 'Expected a query node') {
135
- // No parameters provided - pseudo state form: match ANY score (scanned packages)
136
- for (const node of state.partial.nodes) {
137
- const report = state.securityArchive.get(node.id)
138
- if (!report) {
139
- removeNode(state, node)
140
- }
141
- }
142
- removeDanglingEdges(state)
143
- return state
144
- } else {
145
- throw error('Failed to parse :score selector', { cause: err })
146
- }
147
- }
148
-
149
- const { comparator, rate, kind } = internals
150
- for (const node of state.partial.nodes) {
151
- const report = state.securityArchive.get(node.id)
152
- if (!report) {
153
- removeNode(state, node)
154
- continue
155
- }
156
-
157
- const scoreValue = report.score[kind]
158
-
159
- let exclude = false
160
- switch (comparator) {
161
- case '>':
162
- exclude = scoreValue <= rate
163
- break
164
- case '<':
165
- exclude = scoreValue >= rate
166
- break
167
- case '>=':
168
- exclude = scoreValue < rate
169
- break
170
- case '<=':
171
- exclude = scoreValue > rate
172
- break
173
- default: // '='
174
- exclude = scoreValue !== rate
175
- break
176
- }
177
-
178
- if (exclude) {
179
- removeNode(state, node)
180
- }
181
- }
182
-
183
- removeDanglingEdges(state)
184
-
185
- return state
186
- }
@@ -1,61 +0,0 @@
1
- import type { NodeLike } from '@vltpkg/types'
2
- import type { ParserState } from '../types.ts'
3
- import { removeNode, removeDanglingEdges } from './helpers.ts'
4
-
5
- /**
6
- * Checks if a node needs to be built based on the conditions from the reify build process:
7
- * 1. Has install lifecycle scripts (install, preinstall, postinstall)
8
- * 2. Is an importer or git dependency with prepare scripts (prepare, preprepare, postprepare)
9
- * 3. Was marked as needing a build by install (e.g. a binding.gyp-only package)
10
- */
11
- const nodeNeedsBuild = (node: NodeLike): boolean => {
12
- if (node.buildState === 'needed') return true
13
-
14
- const { manifest } = node
15
- /* c8 ignore next */
16
- if (!manifest) return false
17
-
18
- // abbreviated registry manifests replace `scripts` with this flag
19
- if (manifest.hasInstallScript) return true
20
-
21
- const { scripts = {} } = manifest
22
-
23
- // Check for install lifecycle scripts
24
- const runInstall = !!(
25
- scripts.install ||
26
- scripts.preinstall ||
27
- scripts.postinstall
28
- )
29
- if (runInstall) return true
30
-
31
- // Check for prepare scripts on importers or git dependencies
32
- const prepable = node.id.startsWith('git') || node.importer
33
- const runPrepare =
34
- !!(
35
- scripts.prepare || scripts.preprepare || scripts.postprepare
36
- /* c8 ignore next 2 */
37
- ) && prepable
38
- if (runPrepare) return true
39
-
40
- return false
41
- }
42
-
43
- /**
44
- * :scripts Pseudo-Selector filters nodes based on whether they need to be built.
45
- *
46
- * A node needs to be built if it has:
47
- * - Install lifecycle scripts (install, preinstall, postinstall)
48
- * - Prepare scripts on importers or git dependencies (prepare, preprepare, postprepare)
49
- * - A `buildState` of 'needed', set by install
50
- */
51
- export const scripts = async (state: ParserState) => {
52
- for (const node of state.partial.nodes) {
53
- if (!nodeNeedsBuild(node)) {
54
- removeNode(state, node)
55
- }
56
- }
57
-
58
- removeDanglingEdges(state)
59
-
60
- return state
61
- }
@@ -1,320 +0,0 @@
1
- import {
2
- satisfies,
3
- gt,
4
- gte,
5
- lt,
6
- lte,
7
- eq,
8
- neq,
9
- intersects,
10
- subset,
11
- parse,
12
- parseRange,
13
- } from '@vltpkg/semver'
14
- import type { Version } from '@vltpkg/semver'
15
- import { error } from '@vltpkg/error-cause'
16
- import { asError } from '@vltpkg/types'
17
- import { parseInternals as parseAttrInternals } from './attr.ts'
18
- import type { AttrInternals } from './attr.ts'
19
- import { getManifestPropertyValues } from '../attribute.ts'
20
- import {
21
- asAttributeNode,
22
- asPostcssNodeWithChildren,
23
- asPseudoNode,
24
- asStringNode,
25
- asTagNode,
26
- isAttributeNode,
27
- isPseudoNode,
28
- isStringNode,
29
- isTagNode,
30
- } from '@vltpkg/dss-parser'
31
- import {
32
- removeEdge,
33
- removeNode,
34
- removeQuotes,
35
- removeUnlinkedNodes,
36
- } from './helpers.ts'
37
- import type { ParserState } from '../types.ts'
38
- import type { PostcssNode } from '@vltpkg/dss-parser'
39
-
40
- export type SemverInternals = {
41
- semverValue: string
42
- semverFunction: SemverComparatorFn
43
- semverRangeFunction: SemverRangeComparatorFn | undefined
44
- compareAttribute: SemverCompareAttribute
45
- }
46
-
47
- export type SemverFunctionNames =
48
- | 'satisfies'
49
- | 'gt'
50
- | 'gte'
51
- | 'lt'
52
- | 'lte'
53
- | 'eq'
54
- | 'neq'
55
- | 'intersects'
56
- | 'subset'
57
- export type SemverComparatorFn = (
58
- version: Version | string,
59
- range: string,
60
- ) => boolean
61
- export type SemverRangeComparatorFn = (
62
- r1: string,
63
- r2: string,
64
- ) => boolean
65
- export type SemverCompareAttribute =
66
- Pick<AttrInternals, 'attribute' | 'properties'> | undefined
67
-
68
- const semverFunctionNames = new Set([
69
- 'satisfies',
70
- 'gt',
71
- 'gte',
72
- 'lt',
73
- 'lte',
74
- 'eq',
75
- 'neq',
76
- 'intersects',
77
- 'subset',
78
- ])
79
- export const isSemverFunctionName = (
80
- name: string,
81
- ): name is SemverFunctionNames => semverFunctionNames.has(name)
82
-
83
- export const asSemverFunctionName = (
84
- name: string,
85
- ): SemverFunctionNames => {
86
- if (!isSemverFunctionName(name)) {
87
- throw error('Invalid semver function name', {
88
- found: name,
89
- validOptions: Array.from(semverFunctionNames),
90
- })
91
- }
92
- return name
93
- }
94
-
95
- const semverFunctions = new Map<
96
- SemverFunctionNames,
97
- SemverComparatorFn
98
- >([
99
- ['satisfies', satisfies],
100
- ['gt', gt],
101
- ['gte', gte],
102
- ['lt', lt],
103
- ['lte', lte],
104
- ['eq', eq],
105
- ['neq', neq],
106
- ])
107
-
108
- const semverRangeFunctions = new Map<
109
- SemverFunctionNames,
110
- SemverRangeComparatorFn
111
- >([
112
- ['intersects', intersects],
113
- ['subset', subset],
114
- ])
115
-
116
- export const parseInternals = (
117
- nodes: PostcssNode[],
118
- loose: boolean,
119
- ): SemverInternals => {
120
- // tries to parse the first param as a string node, otherwise defaults
121
- // to reading all postcss nodes as just strings, since it just means
122
- // the value was defined as an unquoted string
123
- let semverValue = ''
124
- try {
125
- semverValue = removeQuotes(
126
- asStringNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
127
- .value,
128
- )
129
- } catch (err) {
130
- if (
131
- asError(err).message === 'Mismatching query node' &&
132
- isTagNode(asPostcssNodeWithChildren(nodes[0]).nodes[0])
133
- ) {
134
- // Handle tag node (unquoted values like >=2.0.0)
135
- const tagNode = asTagNode(
136
- asPostcssNodeWithChildren(nodes[0]).nodes[0],
137
- )
138
- semverValue = tagNode.value
139
- } else {
140
- throw err
141
- }
142
- }
143
-
144
- // second param is the function name
145
- let fnName: SemverFunctionNames = 'satisfies'
146
- try {
147
- // if there is a second node defined, try to parse it as a string node
148
- // first and if that fails, then parse it as a tag node which just means
149
- // it was defined as an unquoted string
150
- if (nodes[1]) {
151
- try {
152
- fnName = asSemverFunctionName(
153
- removeQuotes(
154
- asStringNode(asPostcssNodeWithChildren(nodes[1]).nodes[0])
155
- .value,
156
- ),
157
- )
158
- } catch (err) {
159
- if (asError(err).message === 'Mismatching query node') {
160
- fnName = asSemverFunctionName(
161
- asTagNode(asPostcssNodeWithChildren(nodes[1]).nodes[0])
162
- .value,
163
- )
164
- } else {
165
- throw err
166
- }
167
- }
168
- }
169
- } catch (e) {
170
- // allow invalid semver function names in loose mode, defaults to satisfies
171
- if (!loose) {
172
- throw e
173
- }
174
- }
175
-
176
- const semverFunction = semverFunctions.get(fnName)
177
- const semverRangeFunction = semverRangeFunctions.get(fnName)
178
- // the following should never happen as long as the semver function names
179
- // type and Set are correctly mirroring each other values
180
- /* c8 ignore start */
181
- if (!semverFunction && !semverRangeFunction) {
182
- throw error('Invalid semver function name', {
183
- found: fnName,
184
- validOptions: [
185
- ...Array.from(semverFunctions.keys()),
186
- ...Array.from(semverRangeFunctions.keys()),
187
- ],
188
- })
189
- }
190
- /* c8 ignore stop */
191
-
192
- // optional third param is the compare value
193
- let compareAttribute: SemverCompareAttribute
194
- if (nodes[2]) {
195
- const parentNode = asPostcssNodeWithChildren(nodes[2])
196
- const currNode = parentNode.nodes[0]
197
- if (isAttributeNode(currNode)) {
198
- const { attribute } = asAttributeNode(currNode)
199
- compareAttribute = {
200
- attribute,
201
- properties: [attribute],
202
- }
203
- } else if (isPseudoNode(currNode)) {
204
- compareAttribute = parseAttrInternals(
205
- asPseudoNode(currNode).nodes,
206
- )
207
- } else if (isStringNode(currNode)) {
208
- const attribute = removeQuotes(asStringNode(currNode).value)
209
- compareAttribute = {
210
- attribute,
211
- properties: [attribute],
212
- }
213
- }
214
- }
215
-
216
- return {
217
- semverValue,
218
- semverFunction: semverFunction ?? satisfies,
219
- semverRangeFunction,
220
- compareAttribute,
221
- }
222
- }
223
-
224
- export const semverParser = async (state: ParserState) => {
225
- let internals
226
- try {
227
- internals = parseInternals(
228
- asPostcssNodeWithChildren(state.current).nodes,
229
- !!state.loose,
230
- )
231
- } catch (err) {
232
- throw error('Failed to parse :semver selector', {
233
- cause: err,
234
- })
235
- }
236
-
237
- const {
238
- semverValue,
239
- semverFunction,
240
- semverRangeFunction,
241
- compareAttribute,
242
- } = internals
243
-
244
- // Range-vs-range functions (subset, intersects) operate on edges by default
245
- if (semverRangeFunction) {
246
- if (compareAttribute) {
247
- // Compare the semverValue against a manifest property value as ranges
248
- for (const node of state.partial.nodes) {
249
- const compareValues = getManifestPropertyValues(
250
- node,
251
- compareAttribute.properties,
252
- compareAttribute.attribute,
253
- )
254
- const compareValue = compareValues?.[0]
255
- if (
256
- !compareValue ||
257
- !semverRangeFunction(compareValue, semverValue)
258
- ) {
259
- removeNode(state, node)
260
- }
261
- }
262
- } else {
263
- // Default: operate on edges using bareSpec
264
- for (const edge of state.partial.edges) {
265
- const edgeRange = edge.spec.semver ?? edge.spec.bareSpec
266
- if (
267
- !edgeRange ||
268
- !semverRangeFunction(edgeRange, semverValue)
269
- ) {
270
- removeEdge(state, edge)
271
- }
272
- }
273
- removeUnlinkedNodes(state)
274
- }
275
- return state
276
- }
277
-
278
- for (const node of state.partial.nodes) {
279
- if (compareAttribute) {
280
- const compareValues = getManifestPropertyValues(
281
- node,
282
- compareAttribute.properties,
283
- compareAttribute.attribute,
284
- )
285
-
286
- // if the provided semver value is a fixed semver version and the
287
- // compare attribute is resolving to a range value, then we flip the
288
- // order of comparison, in case it's a "satisfies" function check
289
- const compareValue = compareValues?.[0]
290
- const semverValueVersion = parse(semverValue)
291
- const compareValueRange =
292
- compareValue && parseRange(compareValue)
293
- if (
294
- semverFunction === satisfies &&
295
- semverValueVersion &&
296
- compareValueRange
297
- ) {
298
- if (!satisfies(semverValueVersion, compareValueRange)) {
299
- removeNode(state, node)
300
- }
301
- // otherwise just compares the read attribute to the semver value
302
- } else if (
303
- !compareValue ||
304
- !semverFunction(compareValue, semverValue)
305
- ) {
306
- removeNode(state, node)
307
- }
308
- } else {
309
- const manifestVersion = node.manifest?.version
310
- if (
311
- !manifestVersion ||
312
- !semverFunction(manifestVersion, semverValue)
313
- ) {
314
- removeNode(state, node)
315
- }
316
- }
317
- }
318
-
319
- return state
320
- }