@vltpkg/query 0.0.0-0.1730724342581 → 0.0.0-10

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 (218) hide show
  1. package/README.md +8 -74
  2. package/dist/esm/attribute.d.ts +2 -2
  3. package/dist/esm/attribute.d.ts.map +1 -1
  4. package/dist/esm/attribute.js +14 -5
  5. package/dist/esm/attribute.js.map +1 -1
  6. package/dist/esm/combinator.d.ts +1 -1
  7. package/dist/esm/combinator.d.ts.map +1 -1
  8. package/dist/esm/combinator.js +6 -2
  9. package/dist/esm/combinator.js.map +1 -1
  10. package/dist/esm/id.d.ts +1 -1
  11. package/dist/esm/id.d.ts.map +1 -1
  12. package/dist/esm/id.js +21 -7
  13. package/dist/esm/id.js.map +1 -1
  14. package/dist/esm/index.d.ts +23 -5
  15. package/dist/esm/index.d.ts.map +1 -1
  16. package/dist/esm/index.js +250 -17
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/parser.d.ts +15 -0
  19. package/dist/esm/parser.d.ts.map +1 -0
  20. package/dist/esm/parser.js +92 -0
  21. package/dist/esm/parser.js.map +1 -0
  22. package/dist/esm/pseudo/abandoned.d.ts +7 -0
  23. package/dist/esm/pseudo/abandoned.d.ts.map +1 -0
  24. package/dist/esm/pseudo/abandoned.js +6 -0
  25. package/dist/esm/pseudo/abandoned.js.map +1 -0
  26. package/dist/esm/pseudo/attr.d.ts +18 -0
  27. package/dist/esm/pseudo/attr.d.ts.map +1 -0
  28. package/dist/esm/pseudo/attr.js +58 -0
  29. package/dist/esm/pseudo/attr.js.map +1 -0
  30. package/dist/esm/pseudo/confused.d.ts +7 -0
  31. package/dist/esm/pseudo/confused.d.ts.map +1 -0
  32. package/dist/esm/pseudo/confused.js +6 -0
  33. package/dist/esm/pseudo/confused.js.map +1 -0
  34. package/dist/esm/pseudo/cve.d.ts +12 -0
  35. package/dist/esm/pseudo/cve.d.ts.map +1 -0
  36. package/dist/esm/pseudo/cve.js +44 -0
  37. package/dist/esm/pseudo/cve.js.map +1 -0
  38. package/dist/esm/pseudo/cwe.d.ts +12 -0
  39. package/dist/esm/pseudo/cwe.d.ts.map +1 -0
  40. package/dist/esm/pseudo/cwe.js +43 -0
  41. package/dist/esm/pseudo/cwe.js.map +1 -0
  42. package/dist/esm/pseudo/debug.d.ts +7 -0
  43. package/dist/esm/pseudo/debug.d.ts.map +1 -0
  44. package/dist/esm/pseudo/debug.js +6 -0
  45. package/dist/esm/pseudo/debug.js.map +1 -0
  46. package/dist/esm/pseudo/deprecated.d.ts +7 -0
  47. package/dist/esm/pseudo/deprecated.d.ts.map +1 -0
  48. package/dist/esm/pseudo/deprecated.js +6 -0
  49. package/dist/esm/pseudo/deprecated.js.map +1 -0
  50. package/dist/esm/pseudo/dev.d.ts +6 -0
  51. package/dist/esm/pseudo/dev.d.ts.map +1 -0
  52. package/dist/esm/pseudo/dev.js +15 -0
  53. package/dist/esm/pseudo/dev.js.map +1 -0
  54. package/dist/esm/pseudo/dynamic.d.ts +7 -0
  55. package/dist/esm/pseudo/dynamic.d.ts.map +1 -0
  56. package/dist/esm/pseudo/dynamic.js +6 -0
  57. package/dist/esm/pseudo/dynamic.js.map +1 -0
  58. package/dist/esm/pseudo/empty.d.ts +7 -0
  59. package/dist/esm/pseudo/empty.d.ts.map +1 -0
  60. package/dist/esm/pseudo/empty.js +14 -0
  61. package/dist/esm/pseudo/empty.js.map +1 -0
  62. package/dist/esm/pseudo/entropic.d.ts +7 -0
  63. package/dist/esm/pseudo/entropic.d.ts.map +1 -0
  64. package/dist/esm/pseudo/entropic.js +6 -0
  65. package/dist/esm/pseudo/entropic.js.map +1 -0
  66. package/dist/esm/pseudo/env.d.ts +7 -0
  67. package/dist/esm/pseudo/env.d.ts.map +1 -0
  68. package/dist/esm/pseudo/env.js +6 -0
  69. package/dist/esm/pseudo/env.js.map +1 -0
  70. package/dist/esm/pseudo/eval.d.ts +7 -0
  71. package/dist/esm/pseudo/eval.d.ts.map +1 -0
  72. package/dist/esm/pseudo/eval.js +6 -0
  73. package/dist/esm/pseudo/eval.js.map +1 -0
  74. package/dist/esm/pseudo/fs.d.ts +7 -0
  75. package/dist/esm/pseudo/fs.d.ts.map +1 -0
  76. package/dist/esm/pseudo/fs.js +6 -0
  77. package/dist/esm/pseudo/fs.js.map +1 -0
  78. package/dist/esm/pseudo/helpers.d.ts +35 -0
  79. package/dist/esm/pseudo/helpers.d.ts.map +1 -0
  80. package/dist/esm/pseudo/helpers.js +69 -0
  81. package/dist/esm/pseudo/helpers.js.map +1 -0
  82. package/dist/esm/pseudo/license.d.ts +12 -0
  83. package/dist/esm/pseudo/license.d.ts.map +1 -0
  84. package/dist/esm/pseudo/license.js +58 -0
  85. package/dist/esm/pseudo/license.js.map +1 -0
  86. package/dist/esm/pseudo/link.d.ts +9 -0
  87. package/dist/esm/pseudo/link.d.ts.map +1 -0
  88. package/dist/esm/pseudo/link.js +25 -0
  89. package/dist/esm/pseudo/link.js.map +1 -0
  90. package/dist/esm/pseudo/malware.d.ts +14 -0
  91. package/dist/esm/pseudo/malware.d.ts.map +1 -0
  92. package/dist/esm/pseudo/malware.js +165 -0
  93. package/dist/esm/pseudo/malware.js.map +1 -0
  94. package/dist/esm/pseudo/minified.d.ts +7 -0
  95. package/dist/esm/pseudo/minified.d.ts.map +1 -0
  96. package/dist/esm/pseudo/minified.js +6 -0
  97. package/dist/esm/pseudo/minified.js.map +1 -0
  98. package/dist/esm/pseudo/missing.d.ts +8 -0
  99. package/dist/esm/pseudo/missing.d.ts.map +1 -0
  100. package/dist/esm/pseudo/missing.js +15 -0
  101. package/dist/esm/pseudo/missing.js.map +1 -0
  102. package/dist/esm/pseudo/native.d.ts +7 -0
  103. package/dist/esm/pseudo/native.d.ts.map +1 -0
  104. package/dist/esm/pseudo/native.js +6 -0
  105. package/dist/esm/pseudo/native.js.map +1 -0
  106. package/dist/esm/pseudo/network.d.ts +7 -0
  107. package/dist/esm/pseudo/network.d.ts.map +1 -0
  108. package/dist/esm/pseudo/network.js +6 -0
  109. package/dist/esm/pseudo/network.js.map +1 -0
  110. package/dist/esm/pseudo/obfuscated.d.ts +7 -0
  111. package/dist/esm/pseudo/obfuscated.d.ts.map +1 -0
  112. package/dist/esm/pseudo/obfuscated.js +6 -0
  113. package/dist/esm/pseudo/obfuscated.js.map +1 -0
  114. package/dist/esm/pseudo/optional.d.ts +6 -0
  115. package/dist/esm/pseudo/optional.d.ts.map +1 -0
  116. package/dist/esm/pseudo/optional.js +15 -0
  117. package/dist/esm/pseudo/optional.js.map +1 -0
  118. package/dist/esm/pseudo/outdated.d.ts +54 -0
  119. package/dist/esm/pseudo/outdated.d.ts.map +1 -0
  120. package/dist/esm/pseudo/outdated.js +212 -0
  121. package/dist/esm/pseudo/outdated.js.map +1 -0
  122. package/dist/esm/pseudo/peer.d.ts +6 -0
  123. package/dist/esm/pseudo/peer.d.ts.map +1 -0
  124. package/dist/esm/pseudo/peer.js +15 -0
  125. package/dist/esm/pseudo/peer.js.map +1 -0
  126. package/dist/esm/pseudo/private.d.ts +7 -0
  127. package/dist/esm/pseudo/private.d.ts.map +1 -0
  128. package/dist/esm/pseudo/private.js +16 -0
  129. package/dist/esm/pseudo/private.js.map +1 -0
  130. package/dist/esm/pseudo/prod.d.ts +6 -0
  131. package/dist/esm/pseudo/prod.d.ts.map +1 -0
  132. package/dist/esm/pseudo/prod.js +15 -0
  133. package/dist/esm/pseudo/prod.js.map +1 -0
  134. package/dist/esm/pseudo/published.d.ts +40 -0
  135. package/dist/esm/pseudo/published.d.ts.map +1 -0
  136. package/dist/esm/pseudo/published.js +159 -0
  137. package/dist/esm/pseudo/published.js.map +1 -0
  138. package/dist/esm/pseudo/scanned.d.ts +9 -0
  139. package/dist/esm/pseudo/scanned.d.ts.map +1 -0
  140. package/dist/esm/pseudo/scanned.js +17 -0
  141. package/dist/esm/pseudo/scanned.js.map +1 -0
  142. package/dist/esm/pseudo/score.d.ts +15 -0
  143. package/dist/esm/pseudo/score.d.ts.map +1 -0
  144. package/dist/esm/pseudo/score.js +119 -0
  145. package/dist/esm/pseudo/score.js.map +1 -0
  146. package/dist/esm/pseudo/scripts.d.ts +7 -0
  147. package/dist/esm/pseudo/scripts.d.ts.map +1 -0
  148. package/dist/esm/pseudo/scripts.js +6 -0
  149. package/dist/esm/pseudo/scripts.js.map +1 -0
  150. package/dist/esm/pseudo/semver.d.ts +16 -0
  151. package/dist/esm/pseudo/semver.d.ts.map +1 -0
  152. package/dist/esm/pseudo/semver.js +166 -0
  153. package/dist/esm/pseudo/semver.js.map +1 -0
  154. package/dist/esm/pseudo/severity.d.ts +14 -0
  155. package/dist/esm/pseudo/severity.d.ts.map +1 -0
  156. package/dist/esm/pseudo/severity.js +160 -0
  157. package/dist/esm/pseudo/severity.js.map +1 -0
  158. package/dist/esm/pseudo/shell.d.ts +7 -0
  159. package/dist/esm/pseudo/shell.d.ts.map +1 -0
  160. package/dist/esm/pseudo/shell.js +6 -0
  161. package/dist/esm/pseudo/shell.js.map +1 -0
  162. package/dist/esm/pseudo/shrinkwrap.d.ts +7 -0
  163. package/dist/esm/pseudo/shrinkwrap.d.ts.map +1 -0
  164. package/dist/esm/pseudo/shrinkwrap.js +6 -0
  165. package/dist/esm/pseudo/shrinkwrap.js.map +1 -0
  166. package/dist/esm/pseudo/squat.d.ts +14 -0
  167. package/dist/esm/pseudo/squat.d.ts.map +1 -0
  168. package/dist/esm/pseudo/squat.js +161 -0
  169. package/dist/esm/pseudo/squat.js.map +1 -0
  170. package/dist/esm/pseudo/suspicious.d.ts +7 -0
  171. package/dist/esm/pseudo/suspicious.d.ts.map +1 -0
  172. package/dist/esm/pseudo/suspicious.js +6 -0
  173. package/dist/esm/pseudo/suspicious.js.map +1 -0
  174. package/dist/esm/pseudo/tracker.d.ts +7 -0
  175. package/dist/esm/pseudo/tracker.d.ts.map +1 -0
  176. package/dist/esm/pseudo/tracker.js +6 -0
  177. package/dist/esm/pseudo/tracker.js.map +1 -0
  178. package/dist/esm/pseudo/trivial.d.ts +7 -0
  179. package/dist/esm/pseudo/trivial.d.ts.map +1 -0
  180. package/dist/esm/pseudo/trivial.js +6 -0
  181. package/dist/esm/pseudo/trivial.js.map +1 -0
  182. package/dist/esm/pseudo/undesirable.d.ts +7 -0
  183. package/dist/esm/pseudo/undesirable.d.ts.map +1 -0
  184. package/dist/esm/pseudo/undesirable.js +6 -0
  185. package/dist/esm/pseudo/undesirable.js.map +1 -0
  186. package/dist/esm/pseudo/unknown.d.ts +7 -0
  187. package/dist/esm/pseudo/unknown.d.ts.map +1 -0
  188. package/dist/esm/pseudo/unknown.js +6 -0
  189. package/dist/esm/pseudo/unknown.js.map +1 -0
  190. package/dist/esm/pseudo/unmaintained.d.ts +7 -0
  191. package/dist/esm/pseudo/unmaintained.d.ts.map +1 -0
  192. package/dist/esm/pseudo/unmaintained.js +6 -0
  193. package/dist/esm/pseudo/unmaintained.js.map +1 -0
  194. package/dist/esm/pseudo/unpopular.d.ts +7 -0
  195. package/dist/esm/pseudo/unpopular.d.ts.map +1 -0
  196. package/dist/esm/pseudo/unpopular.js +6 -0
  197. package/dist/esm/pseudo/unpopular.js.map +1 -0
  198. package/dist/esm/pseudo/unstable.d.ts +7 -0
  199. package/dist/esm/pseudo/unstable.d.ts.map +1 -0
  200. package/dist/esm/pseudo/unstable.js +6 -0
  201. package/dist/esm/pseudo/unstable.js.map +1 -0
  202. package/dist/esm/pseudo/workspace.d.ts +6 -0
  203. package/dist/esm/pseudo/workspace.d.ts.map +1 -0
  204. package/dist/esm/pseudo/workspace.js +15 -0
  205. package/dist/esm/pseudo/workspace.js.map +1 -0
  206. package/dist/esm/pseudo.d.ts +1 -8
  207. package/dist/esm/pseudo.d.ts.map +1 -1
  208. package/dist/esm/pseudo.js +115 -122
  209. package/dist/esm/pseudo.js.map +1 -1
  210. package/dist/esm/types.d.ts +83 -6
  211. package/dist/esm/types.d.ts.map +1 -1
  212. package/dist/esm/types.js +25 -13
  213. package/dist/esm/types.js.map +1 -1
  214. package/package.json +28 -19
  215. package/dist/esm/class.d.ts +0 -6
  216. package/dist/esm/class.d.ts.map +0 -1
  217. package/dist/esm/class.js +0 -127
  218. package/dist/esm/class.js.map +0 -1
package/dist/esm/index.js CHANGED
@@ -1,16 +1,19 @@
1
1
  import { error } from '@vltpkg/error-cause';
2
- import postcssSelectorParser from 'postcss-selector-parser';
3
- import { attribute } from './attribute.js';
4
- import { classFn } from './class.js';
5
- import { combinator } from './combinator.js';
6
- import { id } from './id.js';
7
- import { pseudo } from './pseudo.js';
8
- import { isPostcssNodeWithChildren, asPostcssNodeWithChildren, isSelectorNode, } from './types.js';
9
- export * from './types.js';
2
+ import { parse } from "./parser.js";
3
+ import { attribute } from "./attribute.js";
4
+ import { combinator } from "./combinator.js";
5
+ import { id } from "./id.js";
6
+ import { pseudo } from "./pseudo.js";
7
+ import { isPostcssNodeWithChildren, asPostcssNodeWithChildren, isSelectorNode, isPseudoNode, isIdentifierNode, isAttributeNode, } from "./types.js";
8
+ export * from "./types.js";
10
9
  const noopFn = async (state) => state;
11
10
  const selectors = {
12
11
  attribute,
13
- class: classFn,
12
+ /* c8 ignore start */
13
+ class: async (state) => {
14
+ throw error('Unsupported selector', { found: state.current });
15
+ },
16
+ /* c8 ignore end */
14
17
  combinator,
15
18
  comment: noopFn,
16
19
  id,
@@ -35,12 +38,15 @@ const selectors = {
35
38
  };
36
39
  const selectorsMap = new Map(Object.entries(selectors));
37
40
  export const walk = async (state) => {
41
+ await state.cancellable();
38
42
  const parserFn = selectorsMap.get(state.current.type);
39
43
  if (!parserFn) {
40
44
  if (state.loose) {
41
45
  return state;
42
46
  }
43
- throw new Error(`Missing parser for query node: ${state.current.type}`);
47
+ throw error(`Missing parser for query node: ${state.current.type}`, {
48
+ found: state.current,
49
+ });
44
50
  }
45
51
  state = await parserFn(state);
46
52
  // pseudo selectors handle their own sub selectors
@@ -73,17 +79,164 @@ export const walk = async (state) => {
73
79
  }
74
80
  return state;
75
81
  };
82
+ // A list of known security selectors that rely on
83
+ // data from the security-archive in order to work
84
+ const securitySelectors = new Set([
85
+ ':abandoned',
86
+ ':confused',
87
+ ':cve',
88
+ ':cwe',
89
+ ':debug',
90
+ ':deprecated',
91
+ ':dynamic',
92
+ ':entropic',
93
+ ':env',
94
+ ':eval',
95
+ ':fs',
96
+ ':license',
97
+ ':malware',
98
+ ':minified',
99
+ ':native',
100
+ ':network',
101
+ ':obfuscated',
102
+ ':scanned',
103
+ ':score',
104
+ ':scripts',
105
+ ':sev',
106
+ ':severity',
107
+ ':shell',
108
+ ':shrinkwrap',
109
+ ':squat',
110
+ ':suspicious',
111
+ ':tracker',
112
+ ':trivial',
113
+ ':undesirable',
114
+ ':unknown',
115
+ ':unmaintained',
116
+ ':unpopular',
117
+ ':unstable',
118
+ ]);
119
+ const setMethodToJSON = (node) => {
120
+ const { toJSON } = node;
121
+ const insights = node.insights;
122
+ node.toJSON = () => ({
123
+ ...toJSON.call(node),
124
+ insights,
125
+ });
126
+ };
76
127
  export class Query {
77
128
  #cache;
78
129
  #graph;
79
- constructor({ graph }) {
130
+ #retries;
131
+ #specOptions;
132
+ #securityArchive;
133
+ /**
134
+ * Helper method to determine if a given query string is using any of
135
+ * the known security selectors. This is useful so that operations can
136
+ * skip hydrating the security archive if it's not needed.
137
+ */
138
+ static hasSecuritySelectors(query) {
139
+ for (const selector of securitySelectors) {
140
+ if (query.includes(selector)) {
141
+ return true;
142
+ }
143
+ }
144
+ return false;
145
+ }
146
+ constructor({ graph, retries, specOptions, securityArchive, }) {
80
147
  this.#cache = new Map();
81
148
  this.#graph = graph;
149
+ this.#retries = retries ?? 3;
150
+ this.#specOptions = specOptions;
151
+ this.#securityArchive = securityArchive;
152
+ }
153
+ #getQueryResponseEdges(_edges) {
154
+ return Array.from(_edges);
82
155
  }
83
- async search(query) {
84
- if (typeof query !== 'string') {
85
- throw new TypeError('Query search argument needs to be a string');
156
+ #getQueryResponseNodes(_nodes) {
157
+ const nodes = Array.from(_nodes);
158
+ for (const node of nodes) {
159
+ const securityArchiveEntry = this.#securityArchive?.get(node.id);
160
+ // if a security archive entry is not found then the insights object
161
+ // should just be empty with scanned=false
162
+ if (!securityArchiveEntry) {
163
+ node.insights = {
164
+ scanned: false,
165
+ };
166
+ setMethodToJSON(node);
167
+ continue;
168
+ }
169
+ // if a security archive entry is found then we can populate the insights
170
+ node.insights = {
171
+ scanned: true,
172
+ score: securityArchiveEntry.score,
173
+ abandoned: securityArchiveEntry.alerts.some(i => i.type === 'missingAuthor'),
174
+ confused: securityArchiveEntry.alerts.some(i => i.type === 'manifestConfusion'),
175
+ cve: securityArchiveEntry.alerts
176
+ .filter(i => i.props?.cveId)
177
+ // can not be undefined because of the filter above but TS doesn't know that
178
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain
179
+ .map(i => i.props?.cveId),
180
+ cwe: Array.from(new Set(securityArchiveEntry.alerts
181
+ .filter(i => i.props?.cveId)
182
+ .flatMap(i => i.props?.cwes?.map(j => j.id)))),
183
+ debug: securityArchiveEntry.alerts.some(i => i.type === 'debugAccess'),
184
+ deprecated: securityArchiveEntry.alerts.some(i => i.type === 'deprecated'),
185
+ dynamic: securityArchiveEntry.alerts.some(i => i.type === 'dynamicRequire'),
186
+ entropic: securityArchiveEntry.alerts.some(i => i.type === 'highEntropyStrings'),
187
+ env: securityArchiveEntry.alerts.some(i => i.type === 'envVars'),
188
+ eval: securityArchiveEntry.alerts.some(i => i.type === 'usesEval'),
189
+ fs: securityArchiveEntry.alerts.some(i => i.type === 'filesystemAccess'),
190
+ license: {
191
+ unlicensed: securityArchiveEntry.alerts.some(i => i.type === 'explicitlyUnlicensedItem'),
192
+ misc: securityArchiveEntry.alerts.some(i => i.type === 'miscLicenseIssues'),
193
+ restricted: securityArchiveEntry.alerts.some(i => i.type === 'nonpermissiveLicense'),
194
+ ambiguous: securityArchiveEntry.alerts.some(i => i.type === 'ambiguousClassifier'),
195
+ copyleft: securityArchiveEntry.alerts.some(i => i.type === 'copyleftLicense'),
196
+ unknown: securityArchiveEntry.alerts.some(i => i.type === 'unidentifiedLicense'),
197
+ none: securityArchiveEntry.alerts.some(i => i.type === 'noLicenseFound'),
198
+ exception: securityArchiveEntry.alerts.some(i => i.type === 'licenseException'),
199
+ },
200
+ malware: {
201
+ low: securityArchiveEntry.alerts.some(i => i.type === 'gptAnomaly'),
202
+ medium: securityArchiveEntry.alerts.some(i => i.type === 'gptSecurity'),
203
+ high: securityArchiveEntry.alerts.some(i => i.type === 'gptMalware'),
204
+ critical: securityArchiveEntry.alerts.some(i => i.type === 'malware'),
205
+ },
206
+ minified: securityArchiveEntry.alerts.some(i => i.type === 'minifiedFile'),
207
+ native: securityArchiveEntry.alerts.some(i => i.type === 'hasNativeCode'),
208
+ network: securityArchiveEntry.alerts.some(i => i.type === 'networkAccess'),
209
+ obfuscated: securityArchiveEntry.alerts.some(i => i.type === 'obfuscatedFile'),
210
+ scripts: securityArchiveEntry.alerts.some(i => i.type === 'installScripts'),
211
+ severity: {
212
+ low: securityArchiveEntry.alerts.some(i => i.type === 'mildCVE'),
213
+ medium: securityArchiveEntry.alerts.some(i => i.type === 'potentialVulnerability'),
214
+ high: securityArchiveEntry.alerts.some(i => i.type === 'cve'),
215
+ critical: securityArchiveEntry.alerts.some(i => i.type === 'criticalCVE'),
216
+ },
217
+ shell: securityArchiveEntry.alerts.some(i => i.type === 'shellAccess'),
218
+ shrinkwrap: securityArchiveEntry.alerts.some(i => i.type === 'shrinkwrap'),
219
+ squat: {
220
+ medium: securityArchiveEntry.alerts.some(i => i.type === 'gptDidYouMean'),
221
+ critical: securityArchiveEntry.alerts.some(i => i.type === 'didYouMean'),
222
+ },
223
+ suspicious: securityArchiveEntry.alerts.some(i => i.type === 'suspiciousStarActivity'),
224
+ tracker: securityArchiveEntry.alerts.some(i => i.type === 'telemetry'),
225
+ trivial: securityArchiveEntry.alerts.some(i => i.type === 'trivialPackage'),
226
+ undesirable: securityArchiveEntry.alerts.some(i => i.type === 'troll'),
227
+ unknown: securityArchiveEntry.alerts.some(i => i.type === 'newAuthor'),
228
+ unmaintained: securityArchiveEntry.alerts.some(i => i.type === 'unmaintained'),
229
+ unpopular: securityArchiveEntry.alerts.some(i => i.type === 'unpopularPackage'),
230
+ unstable: securityArchiveEntry.alerts.some(i => i.type === 'unstableOwnership'),
231
+ };
232
+ setMethodToJSON(node);
86
233
  }
234
+ return nodes;
235
+ }
236
+ /**
237
+ * Search the graph for nodes and edges that match the given query.
238
+ */
239
+ async search(query, signal) {
87
240
  if (!query)
88
241
  return { edges: [], nodes: [] };
89
242
  const cachedResult = this.#cache.get(query);
@@ -92,10 +245,24 @@ export class Query {
92
245
  }
93
246
  const nodes = new Set(Array.from(this.#graph.nodes.values()));
94
247
  const edges = new Set(Array.from(this.#graph.edges));
248
+ // parse the query string into AST
249
+ const current = parse(query);
250
+ // set loose mode for the entire parse in case there are multiple selectors
251
+ // so that using invalid pseudo selectors or other query language parser
252
+ // errors won't throw an error,
253
+ // e.g: `:root > *, #a, :foo` still returns results for `:root > ` and `#a`
254
+ // while :foo is ignored
255
+ const loose = asPostcssNodeWithChildren(current).nodes.length > 1;
95
256
  // builds initial state and walks over it,
96
257
  // retrieving the collected result
97
258
  const { collect } = await walk({
98
- current: postcssSelectorParser().astSync(query),
259
+ cancellable: async () => {
260
+ await new Promise(resolve => {
261
+ setTimeout(resolve, 0);
262
+ });
263
+ signal?.throwIfAborted();
264
+ },
265
+ current,
99
266
  initial: {
100
267
  nodes: new Set(nodes),
101
268
  edges: new Set(edges),
@@ -104,15 +271,81 @@ export class Query {
104
271
  nodes: new Set(),
105
272
  edges: new Set(),
106
273
  },
274
+ loose,
107
275
  partial: { nodes, edges },
276
+ retries: this.#retries,
277
+ signal,
278
+ securityArchive: this.#securityArchive,
279
+ specOptions: this.#specOptions,
108
280
  walk,
109
281
  });
110
282
  const res = {
111
- edges: Array.from(collect.edges),
112
- nodes: Array.from(collect.nodes),
283
+ edges: this.#getQueryResponseEdges(collect.edges),
284
+ nodes: this.#getQueryResponseNodes(collect.nodes),
113
285
  };
114
286
  this.#cache.set(query, res);
115
287
  return res;
116
288
  }
289
+ /**
290
+ * Parses a query string in order to retrieve an array of tokens.
291
+ */
292
+ static getQueryTokens(query) {
293
+ if (!query)
294
+ return [];
295
+ const tokens = [];
296
+ const ast = (q) => {
297
+ try {
298
+ return parse(q);
299
+ }
300
+ catch (_e) {
301
+ return ast(q.slice(0, -1));
302
+ }
303
+ };
304
+ const processNode = (node) => {
305
+ for (const key of selectorsMap.keys()) {
306
+ if (node.type === key && node.type !== 'root') {
307
+ let token = `${node.spaces.before}${node.value}${node.spaces.after}`;
308
+ if (isIdentifierNode(node)) {
309
+ token = `${node.spaces.before}#${node.value}${node.spaces.after}`;
310
+ }
311
+ else if (isSelectorNode(node)) {
312
+ token = `${node.spaces.before},${node.spaces.after}`;
313
+ }
314
+ else if (isAttributeNode(node)) {
315
+ token = String(node.source?.start?.column &&
316
+ node.source.end?.column &&
317
+ `${node.spaces.before}${query.slice(node.source.start.column - 1, node.source.end.column)}${node.spaces.after}`);
318
+ }
319
+ if (isPostcssNodeWithChildren(node) &&
320
+ isPseudoNode(node) &&
321
+ node.nodes.length) {
322
+ token = String(token.split('(')[0]);
323
+ token += '(';
324
+ }
325
+ if (!isSelectorNode(node) ||
326
+ node.parent?.nodes.indexOf(node) !== 0) {
327
+ tokens.push({
328
+ ...node,
329
+ token,
330
+ });
331
+ }
332
+ }
333
+ }
334
+ if (isPostcssNodeWithChildren(node)) {
335
+ for (const child of node.nodes) {
336
+ processNode(child);
337
+ }
338
+ if (isPseudoNode(node) && node.nodes.length) {
339
+ tokens.push({
340
+ ...node,
341
+ token: ')' + node.spaces.after,
342
+ type: 'pseudo',
343
+ });
344
+ }
345
+ }
346
+ };
347
+ processNode(ast(query));
348
+ return tokens;
349
+ }
117
350
  }
118
351
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport {\n type EdgeLike,\n type GraphLike,\n type NodeLike,\n} from '@vltpkg/graph'\nimport postcssSelectorParser from 'postcss-selector-parser'\nimport { attribute } from './attribute.js'\nimport { classFn } from './class.js'\nimport { combinator } from './combinator.js'\nimport { id } from './id.js'\nimport { pseudo } from './pseudo.js'\nimport {\n type PostcssNodeWithChildren,\n type ParserState,\n type ParserFn,\n isPostcssNodeWithChildren,\n asPostcssNodeWithChildren,\n isSelectorNode,\n type QueryResponse,\n} from './types.js'\n\nexport * from './types.js'\n\nconst noopFn = async (state: ParserState) => state\n\nconst selectors = {\n attribute,\n class: classFn,\n combinator,\n comment: noopFn,\n id,\n nesting: noopFn,\n pseudo,\n root: noopFn,\n selector: async (state: ParserState) => {\n state.partial.nodes = new Set(state.initial.nodes)\n state.partial.edges = new Set(state.initial.edges)\n return state\n },\n string: async (state: ParserState) => {\n throw error('Unsupported selector', { found: state.current })\n },\n tag: async (state: ParserState) => {\n if (state.current.value !== '{' && state.current.value !== '}') {\n throw error('Unsupported selector', { found: state.current })\n }\n return state\n },\n universal: noopFn,\n}\nconst selectorsMap = new Map<string, ParserFn>(\n Object.entries(selectors),\n)\n\nexport const walk = async (\n state: ParserState,\n): Promise<ParserState> => {\n const parserFn = selectorsMap.get(state.current.type)\n\n if (!parserFn) {\n if (state.loose) {\n return state\n }\n\n throw new Error(\n `Missing parser for query node: ${state.current.type}`,\n )\n }\n state = await parserFn(state)\n\n // pseudo selectors handle their own sub selectors\n if (\n isPostcssNodeWithChildren(state.current) &&\n state.current.type !== 'pseudo'\n ) {\n const node: PostcssNodeWithChildren = asPostcssNodeWithChildren(\n state.current,\n )\n\n if (node.nodes.length) {\n for (let i = 0; i < node.nodes.length; i++) {\n const current = node.nodes[i]\n /* c8 ignore next -- impossible but TS doesn't know that */\n if (!current) continue\n\n const childState: ParserState = {\n ...state,\n current,\n next: node.nodes[i + 1],\n prev: node.nodes[i - 1],\n }\n state = await walk(childState)\n }\n }\n\n if (isSelectorNode(node)) {\n for (const edge of state.partial.edges) {\n state.collect.edges.add(edge)\n }\n for (const node of state.partial.nodes) {\n state.collect.nodes.add(node)\n }\n }\n }\n return state\n}\n\nexport type QueryOptions = {\n graph: GraphLike\n}\n\nexport class Query {\n #cache: Map<string, QueryResponse>\n #graph: GraphLike\n\n constructor({ graph }: QueryOptions) {\n this.#cache = new Map()\n this.#graph = graph\n }\n\n async search(query: string): Promise<QueryResponse> {\n if (typeof query !== 'string') {\n throw new TypeError(\n 'Query search argument needs to be a string',\n )\n }\n\n if (!query) return { edges: [], nodes: [] }\n\n const cachedResult = this.#cache.get(query)\n if (cachedResult) {\n return cachedResult\n }\n\n const nodes = new Set<NodeLike>(\n Array.from(this.#graph.nodes.values()),\n )\n const edges = new Set<EdgeLike>(Array.from(this.#graph.edges))\n\n // builds initial state and walks over it,\n // retrieving the collected result\n const { collect } = await walk({\n current: postcssSelectorParser().astSync(query),\n initial: {\n nodes: new Set(nodes),\n edges: new Set(edges),\n },\n collect: {\n nodes: new Set<NodeLike>(),\n edges: new Set<EdgeLike>(),\n },\n partial: { nodes, edges },\n walk,\n })\n\n const res: QueryResponse = {\n edges: Array.from(collect.edges),\n nodes: Array.from(collect.nodes),\n }\n this.#cache.set(query, res)\n return res\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { error } from '@vltpkg/error-cause'\nimport type { EdgeLike, GraphLike, NodeLike } from '@vltpkg/graph'\nimport type { SpecOptions } from '@vltpkg/spec/browser'\nimport type { SecurityArchiveLike } from '@vltpkg/security-archive'\nimport { parse } from './parser.ts'\nimport { attribute } from './attribute.ts'\nimport { combinator } from './combinator.ts'\nimport { id } from './id.ts'\nimport { pseudo } from './pseudo.ts'\nimport {\n isPostcssNodeWithChildren,\n asPostcssNodeWithChildren,\n isSelectorNode,\n isPseudoNode,\n isIdentifierNode,\n isAttributeNode,\n} from './types.ts'\nimport type {\n PostcssNode,\n ParsedSelectorToken,\n PostcssNodeWithChildren,\n ParserState,\n ParserFn,\n QueryResponse,\n QueryResponseNode,\n QueryResponseEdge,\n} from './types.ts'\n\nexport * from './types.ts'\n\nconst noopFn = async (state: ParserState) => state\n\nconst selectors = {\n attribute,\n /* c8 ignore start */\n class: async (state: ParserState) => {\n throw error('Unsupported selector', { found: state.current })\n },\n /* c8 ignore end */\n combinator,\n comment: noopFn,\n id,\n nesting: noopFn,\n pseudo,\n root: noopFn,\n selector: async (state: ParserState) => {\n state.partial.nodes = new Set(state.initial.nodes)\n state.partial.edges = new Set(state.initial.edges)\n return state\n },\n string: async (state: ParserState) => {\n throw error('Unsupported selector', { found: state.current })\n },\n tag: async (state: ParserState) => {\n if (state.current.value !== '{' && state.current.value !== '}') {\n throw error('Unsupported selector', { found: state.current })\n }\n return state\n },\n universal: noopFn,\n}\nconst selectorsMap = new Map<string, ParserFn>(\n Object.entries(selectors),\n)\n\nexport const walk = async (\n state: ParserState,\n): Promise<ParserState> => {\n await state.cancellable()\n\n const parserFn = selectorsMap.get(state.current.type)\n\n if (!parserFn) {\n if (state.loose) {\n return state\n }\n\n throw error(\n `Missing parser for query node: ${state.current.type}`,\n {\n found: state.current,\n },\n )\n }\n state = await parserFn(state)\n\n // pseudo selectors handle their own sub selectors\n if (\n isPostcssNodeWithChildren(state.current) &&\n state.current.type !== 'pseudo'\n ) {\n const node: PostcssNodeWithChildren = asPostcssNodeWithChildren(\n state.current,\n )\n\n if (node.nodes.length) {\n for (let i = 0; i < node.nodes.length; i++) {\n const current = node.nodes[i]\n /* c8 ignore next -- impossible but TS doesn't know that */\n if (!current) continue\n\n const childState: ParserState = {\n ...state,\n current,\n next: node.nodes[i + 1],\n prev: node.nodes[i - 1],\n }\n state = await walk(childState)\n }\n }\n\n if (isSelectorNode(node)) {\n for (const edge of state.partial.edges) {\n state.collect.edges.add(edge)\n }\n for (const node of state.partial.nodes) {\n state.collect.nodes.add(node)\n }\n }\n }\n return state\n}\n\nexport type QueryOptions = {\n graph: GraphLike\n retries?: number\n specOptions: SpecOptions\n securityArchive: SecurityArchiveLike | undefined\n}\n\n// A list of known security selectors that rely on\n// data from the security-archive in order to work\nconst securitySelectors = new Set([\n ':abandoned',\n ':confused',\n ':cve',\n ':cwe',\n ':debug',\n ':deprecated',\n ':dynamic',\n ':entropic',\n ':env',\n ':eval',\n ':fs',\n ':license',\n ':malware',\n ':minified',\n ':native',\n ':network',\n ':obfuscated',\n ':scanned',\n ':score',\n ':scripts',\n ':sev',\n ':severity',\n ':shell',\n ':shrinkwrap',\n ':squat',\n ':suspicious',\n ':tracker',\n ':trivial',\n ':undesirable',\n ':unknown',\n ':unmaintained',\n ':unpopular',\n ':unstable',\n])\n\nconst setMethodToJSON = (node: QueryResponseNode) => {\n const { toJSON } = node\n const insights = node.insights\n node.toJSON = () => ({\n ...toJSON.call(node),\n insights,\n })\n}\n\nexport class Query {\n #cache: Map<string, QueryResponse>\n #graph: GraphLike\n #retries: number\n #specOptions: SpecOptions\n #securityArchive: SecurityArchiveLike | undefined\n\n /**\n * Helper method to determine if a given query string is using any of\n * the known security selectors. This is useful so that operations can\n * skip hydrating the security archive if it's not needed.\n */\n static hasSecuritySelectors(query: string): boolean {\n for (const selector of securitySelectors) {\n if (query.includes(selector)) {\n return true\n }\n }\n return false\n }\n\n constructor({\n graph,\n retries,\n specOptions,\n securityArchive,\n }: QueryOptions) {\n this.#cache = new Map()\n this.#graph = graph\n this.#retries = retries ?? 3\n this.#specOptions = specOptions\n this.#securityArchive = securityArchive\n }\n\n #getQueryResponseEdges(_edges: Set<EdgeLike>): QueryResponseEdge[] {\n return Array.from(_edges) as QueryResponseEdge[]\n }\n\n #getQueryResponseNodes(_nodes: Set<NodeLike>): QueryResponseNode[] {\n const nodes = Array.from(_nodes) as QueryResponseNode[]\n for (const node of nodes) {\n const securityArchiveEntry = this.#securityArchive?.get(node.id)\n\n // if a security archive entry is not found then the insights object\n // should just be empty with scanned=false\n if (!securityArchiveEntry) {\n node.insights = {\n scanned: false,\n }\n\n setMethodToJSON(node)\n continue\n }\n\n // if a security archive entry is found then we can populate the insights\n node.insights = {\n scanned: true,\n score: securityArchiveEntry.score,\n abandoned: securityArchiveEntry.alerts.some(\n i => i.type === 'missingAuthor',\n ),\n confused: securityArchiveEntry.alerts.some(\n i => i.type === 'manifestConfusion',\n ),\n cve: securityArchiveEntry.alerts\n .filter(i => i.props?.cveId)\n // can not be undefined because of the filter above but TS doesn't know that\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, @typescript-eslint/no-non-null-asserted-optional-chain\n .map(i => i.props?.cveId!),\n cwe: Array.from(\n new Set(\n securityArchiveEntry.alerts\n .filter(i => i.props?.cveId)\n .flatMap(i => i.props?.cwes?.map(j => j.id)),\n ),\n ) as `CWE-${string}`[],\n debug: securityArchiveEntry.alerts.some(\n i => i.type === 'debugAccess',\n ),\n deprecated: securityArchiveEntry.alerts.some(\n i => i.type === 'deprecated',\n ),\n dynamic: securityArchiveEntry.alerts.some(\n i => i.type === 'dynamicRequire',\n ),\n entropic: securityArchiveEntry.alerts.some(\n i => i.type === 'highEntropyStrings',\n ),\n env: securityArchiveEntry.alerts.some(\n i => i.type === 'envVars',\n ),\n eval: securityArchiveEntry.alerts.some(\n i => i.type === 'usesEval',\n ),\n fs: securityArchiveEntry.alerts.some(\n i => i.type === 'filesystemAccess',\n ),\n license: {\n unlicensed: securityArchiveEntry.alerts.some(\n i => i.type === 'explicitlyUnlicensedItem',\n ),\n misc: securityArchiveEntry.alerts.some(\n i => i.type === 'miscLicenseIssues',\n ),\n restricted: securityArchiveEntry.alerts.some(\n i => i.type === 'nonpermissiveLicense',\n ),\n ambiguous: securityArchiveEntry.alerts.some(\n i => i.type === 'ambiguousClassifier',\n ),\n copyleft: securityArchiveEntry.alerts.some(\n i => i.type === 'copyleftLicense',\n ),\n unknown: securityArchiveEntry.alerts.some(\n i => i.type === 'unidentifiedLicense',\n ),\n none: securityArchiveEntry.alerts.some(\n i => i.type === 'noLicenseFound',\n ),\n exception: securityArchiveEntry.alerts.some(\n i => i.type === 'licenseException',\n ),\n },\n malware: {\n low: securityArchiveEntry.alerts.some(\n i => i.type === 'gptAnomaly',\n ),\n medium: securityArchiveEntry.alerts.some(\n i => i.type === 'gptSecurity',\n ),\n high: securityArchiveEntry.alerts.some(\n i => i.type === 'gptMalware',\n ),\n critical: securityArchiveEntry.alerts.some(\n i => i.type === 'malware',\n ),\n },\n minified: securityArchiveEntry.alerts.some(\n i => i.type === 'minifiedFile',\n ),\n native: securityArchiveEntry.alerts.some(\n i => i.type === 'hasNativeCode',\n ),\n network: securityArchiveEntry.alerts.some(\n i => i.type === 'networkAccess',\n ),\n obfuscated: securityArchiveEntry.alerts.some(\n i => i.type === 'obfuscatedFile',\n ),\n scripts: securityArchiveEntry.alerts.some(\n i => i.type === 'installScripts',\n ),\n severity: {\n low: securityArchiveEntry.alerts.some(\n i => i.type === 'mildCVE',\n ),\n medium: securityArchiveEntry.alerts.some(\n i => i.type === 'potentialVulnerability',\n ),\n high: securityArchiveEntry.alerts.some(\n i => i.type === 'cve',\n ),\n critical: securityArchiveEntry.alerts.some(\n i => i.type === 'criticalCVE',\n ),\n },\n shell: securityArchiveEntry.alerts.some(\n i => i.type === 'shellAccess',\n ),\n shrinkwrap: securityArchiveEntry.alerts.some(\n i => i.type === 'shrinkwrap',\n ),\n squat: {\n medium: securityArchiveEntry.alerts.some(\n i => i.type === 'gptDidYouMean',\n ),\n critical: securityArchiveEntry.alerts.some(\n i => i.type === 'didYouMean',\n ),\n },\n suspicious: securityArchiveEntry.alerts.some(\n i => i.type === 'suspiciousStarActivity',\n ),\n tracker: securityArchiveEntry.alerts.some(\n i => i.type === 'telemetry',\n ),\n trivial: securityArchiveEntry.alerts.some(\n i => i.type === 'trivialPackage',\n ),\n undesirable: securityArchiveEntry.alerts.some(\n i => i.type === 'troll',\n ),\n unknown: securityArchiveEntry.alerts.some(\n i => i.type === 'newAuthor',\n ),\n unmaintained: securityArchiveEntry.alerts.some(\n i => i.type === 'unmaintained',\n ),\n unpopular: securityArchiveEntry.alerts.some(\n i => i.type === 'unpopularPackage',\n ),\n unstable: securityArchiveEntry.alerts.some(\n i => i.type === 'unstableOwnership',\n ),\n }\n\n setMethodToJSON(node)\n }\n return nodes\n }\n\n /**\n * Search the graph for nodes and edges that match the given query.\n */\n async search(\n query: string,\n signal?: AbortSignal,\n ): Promise<QueryResponse> {\n if (!query) return { edges: [], nodes: [] }\n\n const cachedResult = this.#cache.get(query)\n if (cachedResult) {\n return cachedResult\n }\n\n const nodes = new Set<NodeLike>(\n Array.from(this.#graph.nodes.values()),\n )\n const edges = new Set<EdgeLike>(Array.from(this.#graph.edges))\n\n // parse the query string into AST\n const current = parse(query)\n // set loose mode for the entire parse in case there are multiple selectors\n // so that using invalid pseudo selectors or other query language parser\n // errors won't throw an error,\n // e.g: `:root > *, #a, :foo` still returns results for `:root > ` and `#a`\n // while :foo is ignored\n const loose = asPostcssNodeWithChildren(current).nodes.length > 1\n // builds initial state and walks over it,\n // retrieving the collected result\n const { collect } = await walk({\n cancellable: async () => {\n await new Promise(resolve => {\n setTimeout(resolve, 0)\n })\n signal?.throwIfAborted()\n },\n current,\n initial: {\n nodes: new Set(nodes),\n edges: new Set(edges),\n },\n collect: {\n nodes: new Set<NodeLike>(),\n edges: new Set<EdgeLike>(),\n },\n loose,\n partial: { nodes, edges },\n retries: this.#retries,\n signal,\n securityArchive: this.#securityArchive,\n specOptions: this.#specOptions,\n walk,\n })\n\n const res: QueryResponse = {\n edges: this.#getQueryResponseEdges(collect.edges),\n nodes: this.#getQueryResponseNodes(collect.nodes),\n }\n this.#cache.set(query, res)\n return res\n }\n\n /**\n * Parses a query string in order to retrieve an array of tokens.\n */\n static getQueryTokens(query: string): ParsedSelectorToken[] {\n if (!query) return []\n\n const tokens: ParsedSelectorToken[] = []\n\n const ast = (q: string) => {\n try {\n return parse(q)\n } catch (_e) {\n return ast(q.slice(0, -1))\n }\n }\n\n const processNode = (node: PostcssNode) => {\n for (const key of selectorsMap.keys()) {\n if (node.type === key && node.type !== 'root') {\n let token = `${node.spaces.before}${node.value}${node.spaces.after}`\n\n if (isIdentifierNode(node)) {\n token = `${node.spaces.before}#${node.value}${node.spaces.after}`\n } else if (isSelectorNode(node)) {\n token = `${node.spaces.before},${node.spaces.after}`\n } else if (isAttributeNode(node)) {\n token = String(\n node.source?.start?.column &&\n node.source.end?.column &&\n `${node.spaces.before}${query.slice(node.source.start.column - 1, node.source.end.column)}${node.spaces.after}`,\n )\n }\n\n if (\n isPostcssNodeWithChildren(node) &&\n isPseudoNode(node) &&\n node.nodes.length\n ) {\n token = String(token.split('(')[0])\n token += '('\n }\n\n if (\n !isSelectorNode(node) ||\n node.parent?.nodes.indexOf(node) !== 0\n ) {\n tokens.push({\n ...node,\n token,\n } as ParsedSelectorToken)\n }\n }\n }\n if (isPostcssNodeWithChildren(node)) {\n for (const child of node.nodes) {\n processNode(child)\n }\n if (isPseudoNode(node) && node.nodes.length) {\n tokens.push({\n ...node,\n token: ')' + node.spaces.after,\n type: 'pseudo',\n } as ParsedSelectorToken)\n }\n }\n }\n\n processNode(ast(query))\n return tokens\n }\n}\n"]}
@@ -0,0 +1,15 @@
1
+ import type { Root } from 'postcss-selector-parser';
2
+ /**
3
+ * Escapes forward slashes in specific patterns matching @scoped/name paths
4
+ * This will allow usage of unescaped forward slashes necessary for scoped
5
+ * package names in the id selector.
6
+ */
7
+ export declare const escapeScopedNamesSlashes: (query: string) => string;
8
+ export declare const escapeDots: (query: string) => string;
9
+ export declare const unescapeDots: (query: string) => string;
10
+ /**
11
+ * Parses a CSS selector string into an AST
12
+ * Handles escaping of forward slashes in specific patterns
13
+ */
14
+ export declare const parse: (query: string) => Root;
15
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,IAAI,EAAE,MAAM,yBAAyB,CAAA;AAS3D;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,UAAW,MAAM,KAAG,MAItD,CAAA;AAEH,eAAO,MAAM,UAAU,UAAW,MAAM,KAAG,MACb,CAAA;AAE9B,eAAO,MAAM,YAAY,UAAW,MAAM,KAAG,MACf,CAAA;AAgB9B;;;GAGG;AACH,eAAO,MAAM,KAAK,UAAW,MAAM,KAAG,IA0ErC,CAAA"}
@@ -0,0 +1,92 @@
1
+ import postcssSelectorParser from 'postcss-selector-parser';
2
+ import { asSelectorNode, isCombinatorNode, isPseudoNode, isTagNode, } from "./types.js";
3
+ /**
4
+ * Escapes forward slashes in specific patterns matching @scoped/name paths
5
+ * This will allow usage of unescaped forward slashes necessary for scoped
6
+ * package names in the id selector.
7
+ */
8
+ export const escapeScopedNamesSlashes = (query) => query.replace(/(#@(\w|-|\.)+)\//gm, (_, scope) => `${scope}\\/`);
9
+ export const escapeDots = (query) => query.replaceAll('.', '\\.');
10
+ export const unescapeDots = (query) => query.replaceAll('\\.', '.');
11
+ const pseudoCleanUpNeeded = new Set([
12
+ ':published',
13
+ ':score',
14
+ ':malware',
15
+ ':severity',
16
+ ':sev',
17
+ ':squat',
18
+ ':semver',
19
+ ':v',
20
+ ]);
21
+ const hasParamsToEscape = (node) => pseudoCleanUpNeeded.has(node.value);
22
+ /**
23
+ * Parses a CSS selector string into an AST
24
+ * Handles escaping of forward slashes in specific patterns
25
+ */
26
+ export const parse = (query) => {
27
+ const escapedQuery = escapeDots(escapeScopedNamesSlashes(query));
28
+ const transformAst = (root) => {
29
+ root.walk((node) => {
30
+ // clean up the escaped dots
31
+ if (node.value && typeof node.value === 'string') {
32
+ node.value = unescapeDots(node.value);
33
+ }
34
+ if (isPseudoNode(node) && hasParamsToEscape(node)) {
35
+ // these are pseudo nodes that should only take strings as
36
+ // parameters, so in this preparse step we clean up anything
37
+ // that was recognized as a postcss node and transform that
38
+ // into something that can be most likely parsed as a string
39
+ for (const n of node.nodes) {
40
+ // the parameters have a selector node that wraps them up
41
+ const selector = asSelectorNode(n);
42
+ selector.nodes.forEach((currentNode, index, arr) => {
43
+ // get the next node, we'll update it later
44
+ const nextNode = arr[index + 1];
45
+ // if the current node is a combinator node, we'll need to
46
+ // escape it, we do so by removing the node entirely and
47
+ // updating the contents of the next node with its value
48
+ if (isCombinatorNode(currentNode) &&
49
+ isTagNode(nextNode)) {
50
+ nextNode.value = `${currentNode.spaces.before}${currentNode.value}${currentNode.spaces.after}${nextNode.value}`;
51
+ // make sure to also update the source position
52
+ // references, those are used by the syntax highlighter
53
+ if (nextNode.source?.start?.line &&
54
+ currentNode.source?.start?.line) {
55
+ nextNode.source.start.line =
56
+ currentNode.source.start.line;
57
+ }
58
+ if (nextNode.source?.start?.column &&
59
+ currentNode.source?.start?.column) {
60
+ nextNode.source.start.column =
61
+ currentNode.source.start.column;
62
+ }
63
+ // removes the current node from the selector node
64
+ arr.splice(index, 1);
65
+ }
66
+ });
67
+ // after removing combinator nodes, if we end up with multiple
68
+ // tags in the selector node, we need to smush them together
69
+ selector.nodes.reduce((acc, currentNode) => {
70
+ if (currentNode === acc)
71
+ return acc;
72
+ acc.value = `${acc.value}${currentNode.spaces.before}${currentNode.value}${currentNode.spaces.after}`;
73
+ // make sure to also update the source position refs
74
+ if (currentNode.source?.end?.line &&
75
+ acc.source?.end?.line) {
76
+ acc.source.end.line = currentNode.source.end.line;
77
+ }
78
+ if (currentNode.source?.end?.column &&
79
+ acc.source?.end?.column) {
80
+ acc.source.end.column = currentNode.source.end.column;
81
+ }
82
+ return acc;
83
+ }, selector.first);
84
+ // the selector wrapper node should have a single node
85
+ selector.nodes.length = 1;
86
+ }
87
+ }
88
+ });
89
+ };
90
+ return postcssSelectorParser(transformAst).astSync(escapedQuery);
91
+ };
92
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/parser.ts"],"names":[],"mappings":"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","sourcesContent":["import postcssSelectorParser from 'postcss-selector-parser'\nimport type { Pseudo, Root } from 'postcss-selector-parser'\nimport {\n asSelectorNode,\n isCombinatorNode,\n isPseudoNode,\n isTagNode,\n} from './types.ts'\nimport type { PostcssNode } from './types.ts'\n\n/**\n * Escapes forward slashes in specific patterns matching @scoped/name paths\n * This will allow usage of unescaped forward slashes necessary for scoped\n * package names in the id selector.\n */\nexport const escapeScopedNamesSlashes = (query: string): string =>\n query.replace(\n /(#@(\\w|-|\\.)+)\\//gm,\n (_, scope: string) => `${scope}\\\\/`,\n )\n\nexport const escapeDots = (query: string): string =>\n query.replaceAll('.', '\\\\.')\n\nexport const unescapeDots = (query: string): string =>\n query.replaceAll('\\\\.', '.')\n\nconst pseudoCleanUpNeeded = new Set([\n ':published',\n ':score',\n ':malware',\n ':severity',\n ':sev',\n ':squat',\n ':semver',\n ':v',\n])\n\nconst hasParamsToEscape = (node: Pseudo) =>\n pseudoCleanUpNeeded.has(node.value)\n\n/**\n * Parses a CSS selector string into an AST\n * Handles escaping of forward slashes in specific patterns\n */\nexport const parse = (query: string): Root => {\n const escapedQuery = escapeDots(escapeScopedNamesSlashes(query))\n const transformAst = (root: Root) => {\n root.walk((node: PostcssNode) => {\n // clean up the escaped dots\n if (node.value && typeof node.value === 'string') {\n node.value = unescapeDots(node.value)\n }\n if (isPseudoNode(node) && hasParamsToEscape(node)) {\n // these are pseudo nodes that should only take strings as\n // parameters, so in this preparse step we clean up anything\n // that was recognized as a postcss node and transform that\n // into something that can be most likely parsed as a string\n for (const n of node.nodes) {\n // the parameters have a selector node that wraps them up\n const selector = asSelectorNode(n)\n selector.nodes.forEach((currentNode, index, arr) => {\n // get the next node, we'll update it later\n const nextNode = arr[index + 1]\n // if the current node is a combinator node, we'll need to\n // escape it, we do so by removing the node entirely and\n // updating the contents of the next node with its value\n if (\n isCombinatorNode(currentNode) &&\n isTagNode(nextNode)\n ) {\n nextNode.value = `${currentNode.spaces.before}${currentNode.value}${currentNode.spaces.after}${nextNode.value}`\n // make sure to also update the source position\n // references, those are used by the syntax highlighter\n if (\n nextNode.source?.start?.line &&\n currentNode.source?.start?.line\n ) {\n nextNode.source.start.line =\n currentNode.source.start.line\n }\n if (\n nextNode.source?.start?.column &&\n currentNode.source?.start?.column\n ) {\n nextNode.source.start.column =\n currentNode.source.start.column\n }\n // removes the current node from the selector node\n arr.splice(index, 1)\n }\n })\n // after removing combinator nodes, if we end up with multiple\n // tags in the selector node, we need to smush them together\n selector.nodes.reduce((acc, currentNode) => {\n if (currentNode === acc) return acc\n acc.value = `${acc.value}${currentNode.spaces.before}${currentNode.value}${currentNode.spaces.after}`\n // make sure to also update the source position refs\n if (\n currentNode.source?.end?.line &&\n acc.source?.end?.line\n ) {\n acc.source.end.line = currentNode.source.end.line\n }\n if (\n currentNode.source?.end?.column &&\n acc.source?.end?.column\n ) {\n acc.source.end.column = currentNode.source.end.column\n }\n return acc\n }, selector.first)\n // the selector wrapper node should have a single node\n selector.nodes.length = 1\n }\n }\n })\n }\n return postcssSelectorParser(transformAst).astSync(escapedQuery)\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Filters out any node that does not have a **missingAuthor** report alert.
3
+ */
4
+ export declare const abandoned: (state: import("../types.ts").ParserState) => Promise<import("../types.ts").ParserState & {
5
+ securityArchive: NonNullable<import("../types.ts").ParserState["securityArchive"]>;
6
+ }>;
7
+ //# sourceMappingURL=abandoned.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandoned.d.ts","sourceRoot":"","sources":["../../../src/pseudo/abandoned.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,SAAS;;EAGrB,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { createSecuritySelectorFilter } from "./helpers.js";
2
+ /**
3
+ * Filters out any node that does not have a **missingAuthor** report alert.
4
+ */
5
+ export const abandoned = createSecuritySelectorFilter('abandoned', 'missingAuthor');
6
+ //# sourceMappingURL=abandoned.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abandoned.js","sourceRoot":"","sources":["../../../src/pseudo/abandoned.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAA;AAE3D;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,4BAA4B,CACnD,WAAW,EACX,eAAe,CAChB,CAAA","sourcesContent":["import { createSecuritySelectorFilter } from './helpers.ts'\n\n/**\n * Filters out any node that does not have a **missingAuthor** report alert.\n */\nexport const abandoned = createSecuritySelectorFilter(\n 'abandoned',\n 'missingAuthor',\n)\n"]}
@@ -0,0 +1,18 @@
1
+ import type { ParserState, PostcssNode } from '../types.ts';
2
+ export type AttrInternals = {
3
+ attribute: string;
4
+ insensitive: boolean;
5
+ operator?: string;
6
+ value?: string;
7
+ properties: string[];
8
+ };
9
+ /**
10
+ * Parses the internal / nested selectors of a `:attr` selector.
11
+ */
12
+ export declare const parseInternals: (nodes: PostcssNode[]) => AttrInternals;
13
+ /**
14
+ * :attr Pseudo-Selector, allows for retrieving nodes based on nested
15
+ * properties of the `package.json` metadata.
16
+ */
17
+ export declare const attr: (state: ParserState) => Promise<ParserState>;
18
+ //# sourceMappingURL=attr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attr.d.ts","sourceRoot":"","sources":["../../../src/pseudo/attr.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAO3D,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,UAClB,WAAW,EAAE,KACnB,aA0BF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,IAAI,UAAiB,WAAW,yBA8B5C,CAAA"}