@vltpkg/query 1.5.0 → 1.6.1

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 (211) hide show
  1. package/dist/id.js +12 -5
  2. package/package.json +10 -12
  3. package/skills/dss-query/REFERENCE.md +0 -125
  4. package/skills/dss-query/SKILL.md +0 -190
  5. package/skills/dss-query/evals/README.md +0 -81
  6. package/skills/dss-query/evals/evals.json +0 -89
  7. package/skills/dss-query/evals/grade.mjs +0 -481
  8. package/src/attribute.ts +0 -190
  9. package/src/combinator.ts +0 -135
  10. package/src/error.ts +0 -78
  11. package/src/id.ts +0 -46
  12. package/src/index.ts +0 -670
  13. package/src/parser.ts +0 -122
  14. package/src/pseudo/abandoned.ts +0 -9
  15. package/src/pseudo/attr.ts +0 -92
  16. package/src/pseudo/built.ts +0 -19
  17. package/src/pseudo/confused.ts +0 -29
  18. package/src/pseudo/cve.ts +0 -93
  19. package/src/pseudo/cwe.ts +0 -97
  20. package/src/pseudo/debug.ts +0 -9
  21. package/src/pseudo/deprecated.ts +0 -9
  22. package/src/pseudo/dev.ts +0 -18
  23. package/src/pseudo/diff.ts +0 -90
  24. package/src/pseudo/dist.ts +0 -148
  25. package/src/pseudo/dynamic.ts +0 -9
  26. package/src/pseudo/empty.ts +0 -15
  27. package/src/pseudo/entropic.ts +0 -9
  28. package/src/pseudo/env.ts +0 -6
  29. package/src/pseudo/eval.ts +0 -9
  30. package/src/pseudo/fs.ts +0 -9
  31. package/src/pseudo/helpers.ts +0 -106
  32. package/src/pseudo/host.ts +0 -111
  33. package/src/pseudo/hostname.ts +0 -156
  34. package/src/pseudo/license.ts +0 -134
  35. package/src/pseudo/link.ts +0 -30
  36. package/src/pseudo/malware.ts +0 -41
  37. package/src/pseudo/minified.ts +0 -9
  38. package/src/pseudo/missing.ts +0 -16
  39. package/src/pseudo/native.ts +0 -9
  40. package/src/pseudo/network.ts +0 -9
  41. package/src/pseudo/obfuscated.ts +0 -9
  42. package/src/pseudo/optional.ts +0 -18
  43. package/src/pseudo/outdated.ts +0 -345
  44. package/src/pseudo/overridden.ts +0 -20
  45. package/src/pseudo/path.ts +0 -146
  46. package/src/pseudo/peer.ts +0 -18
  47. package/src/pseudo/prerelease.ts +0 -47
  48. package/src/pseudo/private.ts +0 -19
  49. package/src/pseudo/prod.ts +0 -18
  50. package/src/pseudo/published.ts +0 -250
  51. package/src/pseudo/registry.ts +0 -29
  52. package/src/pseudo/root.ts +0 -19
  53. package/src/pseudo/scanned.ts +0 -20
  54. package/src/pseudo/score.ts +0 -186
  55. package/src/pseudo/scripts.ts +0 -61
  56. package/src/pseudo/semver.ts +0 -320
  57. package/src/pseudo/severity.ts +0 -231
  58. package/src/pseudo/shell.ts +0 -9
  59. package/src/pseudo/shrinkwrap.ts +0 -9
  60. package/src/pseudo/skill.ts +0 -59
  61. package/src/pseudo/skills.ts +0 -29
  62. package/src/pseudo/spec.ts +0 -131
  63. package/src/pseudo/squat.ts +0 -225
  64. package/src/pseudo/suspicious.ts +0 -9
  65. package/src/pseudo/tracker.ts +0 -9
  66. package/src/pseudo/trivial.ts +0 -9
  67. package/src/pseudo/type.ts +0 -26
  68. package/src/pseudo/undesirable.ts +0 -9
  69. package/src/pseudo/unknown.ts +0 -9
  70. package/src/pseudo/unmaintained.ts +0 -9
  71. package/src/pseudo/unpopular.ts +0 -9
  72. package/src/pseudo/unstable.ts +0 -9
  73. package/src/pseudo/vuln.ts +0 -273
  74. package/src/pseudo/workspace.ts +0 -22
  75. package/src/pseudo.ts +0 -440
  76. package/src/types.ts +0 -206
  77. package/tap-snapshots/test/attribute.ts.test.cjs +0 -304
  78. package/tap-snapshots/test/combinator.ts.test.cjs +0 -333
  79. package/tap-snapshots/test/id.ts.test.cjs +0 -118
  80. package/tap-snapshots/test/parser.ts.test.cjs +0 -344
  81. package/tap-snapshots/test/pseudo/abandoned.ts.test.cjs +0 -18
  82. package/tap-snapshots/test/pseudo/attr.ts.test.cjs +0 -161
  83. package/tap-snapshots/test/pseudo/built.ts.test.cjs +0 -70
  84. package/tap-snapshots/test/pseudo/confused.ts.test.cjs +0 -32
  85. package/tap-snapshots/test/pseudo/cve.ts.test.cjs +0 -49
  86. package/tap-snapshots/test/pseudo/cwe.ts.test.cjs +0 -49
  87. package/tap-snapshots/test/pseudo/debug.ts.test.cjs +0 -18
  88. package/tap-snapshots/test/pseudo/deprecated.ts.test.cjs +0 -18
  89. package/tap-snapshots/test/pseudo/dist.ts.test.cjs +0 -30
  90. package/tap-snapshots/test/pseudo/dynamic.ts.test.cjs +0 -18
  91. package/tap-snapshots/test/pseudo/empty.ts.test.cjs +0 -50
  92. package/tap-snapshots/test/pseudo/entropic.ts.test.cjs +0 -18
  93. package/tap-snapshots/test/pseudo/env.ts.test.cjs +0 -18
  94. package/tap-snapshots/test/pseudo/eval.ts.test.cjs +0 -18
  95. package/tap-snapshots/test/pseudo/fs.ts.test.cjs +0 -18
  96. package/tap-snapshots/test/pseudo/helpers.ts.test.cjs +0 -18
  97. package/tap-snapshots/test/pseudo/hostname.ts.test.cjs +0 -148
  98. package/tap-snapshots/test/pseudo/license.ts.test.cjs +0 -41
  99. package/tap-snapshots/test/pseudo/link.ts.test.cjs +0 -36
  100. package/tap-snapshots/test/pseudo/malware.ts.test.cjs +0 -22
  101. package/tap-snapshots/test/pseudo/minified.ts.test.cjs +0 -18
  102. package/tap-snapshots/test/pseudo/missing.ts.test.cjs +0 -30
  103. package/tap-snapshots/test/pseudo/native.ts.test.cjs +0 -18
  104. package/tap-snapshots/test/pseudo/network.ts.test.cjs +0 -18
  105. package/tap-snapshots/test/pseudo/obfuscated.ts.test.cjs +0 -18
  106. package/tap-snapshots/test/pseudo/outdated.ts.test.cjs +0 -132
  107. package/tap-snapshots/test/pseudo/overridden.ts.test.cjs +0 -75
  108. package/tap-snapshots/test/pseudo/prerelease.ts.test.cjs +0 -101
  109. package/tap-snapshots/test/pseudo/private.ts.test.cjs +0 -38
  110. package/tap-snapshots/test/pseudo/published.ts.test.cjs +0 -171
  111. package/tap-snapshots/test/pseudo/registry.ts.test.cjs +0 -68
  112. package/tap-snapshots/test/pseudo/root.ts.test.cjs +0 -24
  113. package/tap-snapshots/test/pseudo/scanned.ts.test.cjs +0 -18
  114. package/tap-snapshots/test/pseudo/score.ts.test.cjs +0 -239
  115. package/tap-snapshots/test/pseudo/scripts.ts.test.cjs +0 -62
  116. package/tap-snapshots/test/pseudo/semver.ts.test.cjs +0 -575
  117. package/tap-snapshots/test/pseudo/severity.ts.test.cjs +0 -122
  118. package/tap-snapshots/test/pseudo/shell.ts.test.cjs +0 -18
  119. package/tap-snapshots/test/pseudo/shrinkwrap.ts.test.cjs +0 -18
  120. package/tap-snapshots/test/pseudo/skills.ts.test.cjs +0 -19
  121. package/tap-snapshots/test/pseudo/spec.ts.test.cjs +0 -148
  122. package/tap-snapshots/test/pseudo/squat.ts.test.cjs +0 -129
  123. package/tap-snapshots/test/pseudo/suspicious.ts.test.cjs +0 -18
  124. package/tap-snapshots/test/pseudo/tracker.ts.test.cjs +0 -18
  125. package/tap-snapshots/test/pseudo/trivial.ts.test.cjs +0 -18
  126. package/tap-snapshots/test/pseudo/type.ts.test.cjs +0 -51
  127. package/tap-snapshots/test/pseudo/undesirable.ts.test.cjs +0 -18
  128. package/tap-snapshots/test/pseudo/unknown.ts.test.cjs +0 -18
  129. package/tap-snapshots/test/pseudo/unmaintained.ts.test.cjs +0 -18
  130. package/tap-snapshots/test/pseudo/unpopular.ts.test.cjs +0 -18
  131. package/tap-snapshots/test/pseudo/unstable.ts.test.cjs +0 -18
  132. package/tap-snapshots/test/pseudo/vuln.ts.test.cjs +0 -208
  133. package/tap-snapshots/test/pseudo/vulnerable.ts.test.cjs +0 -20
  134. package/tap-snapshots/test/pseudo/workspace.ts.test.cjs +0 -19
  135. package/tap-snapshots/test/pseudo.ts.test.cjs +0 -1247
  136. package/test/attribute.ts +0 -273
  137. package/test/combinator.ts +0 -175
  138. package/test/error.ts +0 -60
  139. package/test/fixtures/graph.ts +0 -999
  140. package/test/fixtures/selector.ts +0 -103
  141. package/test/fixtures/types.ts +0 -7
  142. package/test/id.ts +0 -102
  143. package/test/index.ts +0 -1148
  144. package/test/parser.ts +0 -117
  145. package/test/pseudo/abandoned.ts +0 -98
  146. package/test/pseudo/attr.ts +0 -298
  147. package/test/pseudo/built.ts +0 -214
  148. package/test/pseudo/confused.ts +0 -160
  149. package/test/pseudo/cve.ts +0 -249
  150. package/test/pseudo/cwe.ts +0 -255
  151. package/test/pseudo/debug.ts +0 -98
  152. package/test/pseudo/deprecated.ts +0 -98
  153. package/test/pseudo/dev.ts +0 -61
  154. package/test/pseudo/diff.ts +0 -417
  155. package/test/pseudo/dist.ts +0 -215
  156. package/test/pseudo/dynamic.ts +0 -98
  157. package/test/pseudo/empty.ts +0 -108
  158. package/test/pseudo/entropic.ts +0 -101
  159. package/test/pseudo/env.ts +0 -98
  160. package/test/pseudo/eval.ts +0 -98
  161. package/test/pseudo/fs.ts +0 -98
  162. package/test/pseudo/helpers.ts +0 -370
  163. package/test/pseudo/host-context.ts +0 -276
  164. package/test/pseudo/hostname.ts +0 -314
  165. package/test/pseudo/license.ts +0 -265
  166. package/test/pseudo/link.ts +0 -94
  167. package/test/pseudo/malware.ts +0 -184
  168. package/test/pseudo/minified.ts +0 -98
  169. package/test/pseudo/missing.ts +0 -111
  170. package/test/pseudo/native.ts +0 -98
  171. package/test/pseudo/network.ts +0 -98
  172. package/test/pseudo/obfuscated.ts +0 -98
  173. package/test/pseudo/optional.ts +0 -73
  174. package/test/pseudo/outdated.ts +0 -461
  175. package/test/pseudo/overridden.ts +0 -317
  176. package/test/pseudo/path.ts +0 -680
  177. package/test/pseudo/peer.ts +0 -101
  178. package/test/pseudo/prerelease.ts +0 -279
  179. package/test/pseudo/private.ts +0 -108
  180. package/test/pseudo/prod.ts +0 -61
  181. package/test/pseudo/published.ts +0 -557
  182. package/test/pseudo/registry.ts +0 -122
  183. package/test/pseudo/root.ts +0 -66
  184. package/test/pseudo/scanned.ts +0 -144
  185. package/test/pseudo/score.ts +0 -591
  186. package/test/pseudo/scripts.ts +0 -324
  187. package/test/pseudo/semver.ts +0 -822
  188. package/test/pseudo/severity.ts +0 -342
  189. package/test/pseudo/shell.ts +0 -98
  190. package/test/pseudo/shrinkwrap.ts +0 -98
  191. package/test/pseudo/skill.ts +0 -189
  192. package/test/pseudo/skills.ts +0 -90
  193. package/test/pseudo/spec.ts +0 -525
  194. package/test/pseudo/squat.ts +0 -565
  195. package/test/pseudo/suspicious.ts +0 -98
  196. package/test/pseudo/tracker.ts +0 -98
  197. package/test/pseudo/trivial.ts +0 -98
  198. package/test/pseudo/type.ts +0 -105
  199. package/test/pseudo/undesirable.ts +0 -98
  200. package/test/pseudo/unknown.ts +0 -98
  201. package/test/pseudo/unmaintained.ts +0 -98
  202. package/test/pseudo/unpopular.ts +0 -98
  203. package/test/pseudo/unstable.ts +0 -98
  204. package/test/pseudo/vuln.ts +0 -625
  205. package/test/pseudo/vulnerable.ts +0 -137
  206. package/test/pseudo/workspace.ts +0 -111
  207. package/test/pseudo.ts +0 -584
  208. package/tsconfig.json +0 -3
  209. package/tsconfig.publish.json +0 -19
  210. package/tsconfig.publish.tsbuildinfo +0 -1
  211. 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
- }