@0xrama/bnpm 0.0.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 (204) hide show
  1. package/README.md +83 -0
  2. package/dist/package.json +45 -0
  3. package/dist/src/cache/archive.d.ts +15 -0
  4. package/dist/src/cache/archive.js +163 -0
  5. package/dist/src/cache/archive.js.map +1 -0
  6. package/dist/src/cache/commands.d.ts +15 -0
  7. package/dist/src/cache/commands.js +168 -0
  8. package/dist/src/cache/commands.js.map +1 -0
  9. package/dist/src/cache/quarantine.d.ts +18 -0
  10. package/dist/src/cache/quarantine.js +104 -0
  11. package/dist/src/cache/quarantine.js.map +1 -0
  12. package/dist/src/cache/store.d.ts +10 -0
  13. package/dist/src/cache/store.js +155 -0
  14. package/dist/src/cache/store.js.map +1 -0
  15. package/dist/src/cli.d.ts +2 -0
  16. package/dist/src/cli.js +4 -0
  17. package/dist/src/cli.js.map +1 -0
  18. package/dist/src/commands/diff.d.ts +34 -0
  19. package/dist/src/commands/diff.js +223 -0
  20. package/dist/src/commands/diff.js.map +1 -0
  21. package/dist/src/commands/doctor.d.ts +14 -0
  22. package/dist/src/commands/doctor.js +42 -0
  23. package/dist/src/commands/doctor.js.map +1 -0
  24. package/dist/src/commands/edit.d.ts +12 -0
  25. package/dist/src/commands/edit.js +100 -0
  26. package/dist/src/commands/edit.js.map +1 -0
  27. package/dist/src/commands/fund.d.ts +10 -0
  28. package/dist/src/commands/fund.js +32 -0
  29. package/dist/src/commands/fund.js.map +1 -0
  30. package/dist/src/commands/graph.d.ts +29 -0
  31. package/dist/src/commands/graph.js +90 -0
  32. package/dist/src/commands/graph.js.map +1 -0
  33. package/dist/src/commands/index.d.ts +20 -0
  34. package/dist/src/commands/index.js +1753 -0
  35. package/dist/src/commands/index.js.map +1 -0
  36. package/dist/src/commands/navigation.d.ts +2 -0
  37. package/dist/src/commands/navigation.js +47 -0
  38. package/dist/src/commands/navigation.js.map +1 -0
  39. package/dist/src/commands/outdated.d.ts +17 -0
  40. package/dist/src/commands/outdated.js +69 -0
  41. package/dist/src/commands/outdated.js.map +1 -0
  42. package/dist/src/commands/process.d.ts +11 -0
  43. package/dist/src/commands/process.js +189 -0
  44. package/dist/src/commands/process.js.map +1 -0
  45. package/dist/src/commands/prompts.d.ts +6 -0
  46. package/dist/src/commands/prompts.js +86 -0
  47. package/dist/src/commands/prompts.js.map +1 -0
  48. package/dist/src/commands/query.d.ts +48 -0
  49. package/dist/src/commands/query.js +639 -0
  50. package/dist/src/commands/query.js.map +1 -0
  51. package/dist/src/commands/rebuild.d.ts +16 -0
  52. package/dist/src/commands/rebuild.js +44 -0
  53. package/dist/src/commands/rebuild.js.map +1 -0
  54. package/dist/src/commands/sbom.d.ts +6 -0
  55. package/dist/src/commands/sbom.js +31 -0
  56. package/dist/src/commands/sbom.js.map +1 -0
  57. package/dist/src/commands/script-approvals.d.ts +22 -0
  58. package/dist/src/commands/script-approvals.js +128 -0
  59. package/dist/src/commands/script-approvals.js.map +1 -0
  60. package/dist/src/commands/shrinkwrap.d.ts +6 -0
  61. package/dist/src/commands/shrinkwrap.js +97 -0
  62. package/dist/src/commands/shrinkwrap.js.map +1 -0
  63. package/dist/src/commands/stage.d.ts +20 -0
  64. package/dist/src/commands/stage.js +40 -0
  65. package/dist/src/commands/stage.js.map +1 -0
  66. package/dist/src/commands/token.d.ts +2 -0
  67. package/dist/src/commands/token.js +47 -0
  68. package/dist/src/commands/token.js.map +1 -0
  69. package/dist/src/commands/trust.d.ts +5 -0
  70. package/dist/src/commands/trust.js +41 -0
  71. package/dist/src/commands/trust.js.map +1 -0
  72. package/dist/src/config/commands.d.ts +5 -0
  73. package/dist/src/config/commands.js +91 -0
  74. package/dist/src/config/commands.js.map +1 -0
  75. package/dist/src/config/configuration.d.ts +40 -0
  76. package/dist/src/config/configuration.js +157 -0
  77. package/dist/src/config/configuration.js.map +1 -0
  78. package/dist/src/config/interactive.d.ts +16 -0
  79. package/dist/src/config/interactive.js +19 -0
  80. package/dist/src/config/interactive.js.map +1 -0
  81. package/dist/src/config/paths.d.ts +22 -0
  82. package/dist/src/config/paths.js +46 -0
  83. package/dist/src/config/paths.js.map +1 -0
  84. package/dist/src/config/types.d.ts +15 -0
  85. package/dist/src/config/types.js +6 -0
  86. package/dist/src/config/types.js.map +1 -0
  87. package/dist/src/core/cli-parser.d.ts +102 -0
  88. package/dist/src/core/cli-parser.js +1148 -0
  89. package/dist/src/core/cli-parser.js.map +1 -0
  90. package/dist/src/core/cli-runner.d.ts +15 -0
  91. package/dist/src/core/cli-runner.js +261 -0
  92. package/dist/src/core/cli-runner.js.map +1 -0
  93. package/dist/src/core/exit-codes.d.ts +13 -0
  94. package/dist/src/core/exit-codes.js +13 -0
  95. package/dist/src/core/exit-codes.js.map +1 -0
  96. package/dist/src/core/output.d.ts +23 -0
  97. package/dist/src/core/output.js +123 -0
  98. package/dist/src/core/output.js.map +1 -0
  99. package/dist/src/installer/install.d.ts +73 -0
  100. package/dist/src/installer/install.js +596 -0
  101. package/dist/src/installer/install.js.map +1 -0
  102. package/dist/src/installer/mutations.d.ts +5 -0
  103. package/dist/src/installer/mutations.js +160 -0
  104. package/dist/src/installer/mutations.js.map +1 -0
  105. package/dist/src/linker/project-linker.d.ts +9 -0
  106. package/dist/src/linker/project-linker.js +223 -0
  107. package/dist/src/linker/project-linker.js.map +1 -0
  108. package/dist/src/lockfile/index.d.ts +27 -0
  109. package/dist/src/lockfile/index.js +221 -0
  110. package/dist/src/lockfile/index.js.map +1 -0
  111. package/dist/src/package/authoring.d.ts +31 -0
  112. package/dist/src/package/authoring.js +125 -0
  113. package/dist/src/package/authoring.js.map +1 -0
  114. package/dist/src/package/pack.d.ts +22 -0
  115. package/dist/src/package/pack.js +238 -0
  116. package/dist/src/package/pack.js.map +1 -0
  117. package/dist/src/package/provenance.d.ts +28 -0
  118. package/dist/src/package/provenance.js +162 -0
  119. package/dist/src/package/provenance.js.map +1 -0
  120. package/dist/src/package/publish.d.ts +28 -0
  121. package/dist/src/package/publish.js +189 -0
  122. package/dist/src/package/publish.js.map +1 -0
  123. package/dist/src/package/trusted-publishing.d.ts +7 -0
  124. package/dist/src/package/trusted-publishing.js +84 -0
  125. package/dist/src/package/trusted-publishing.js.map +1 -0
  126. package/dist/src/project/dependency-error.d.ts +3 -0
  127. package/dist/src/project/dependency-error.js +7 -0
  128. package/dist/src/project/dependency-error.js.map +1 -0
  129. package/dist/src/project/dev-engines.d.ts +10 -0
  130. package/dist/src/project/dev-engines.js +70 -0
  131. package/dist/src/project/dev-engines.js.map +1 -0
  132. package/dist/src/project/discovery.d.ts +6 -0
  133. package/dist/src/project/discovery.js +51 -0
  134. package/dist/src/project/discovery.js.map +1 -0
  135. package/dist/src/project/global.d.ts +3 -0
  136. package/dist/src/project/global.js +43 -0
  137. package/dist/src/project/global.js.map +1 -0
  138. package/dist/src/project/invalidation.d.ts +3 -0
  139. package/dist/src/project/invalidation.js +21 -0
  140. package/dist/src/project/invalidation.js.map +1 -0
  141. package/dist/src/project/link.d.ts +21 -0
  142. package/dist/src/project/link.js +152 -0
  143. package/dist/src/project/link.js.map +1 -0
  144. package/dist/src/project/manifest.d.ts +27 -0
  145. package/dist/src/project/manifest.js +378 -0
  146. package/dist/src/project/manifest.js.map +1 -0
  147. package/dist/src/project/pkg.d.ts +5 -0
  148. package/dist/src/project/pkg.js +94 -0
  149. package/dist/src/project/pkg.js.map +1 -0
  150. package/dist/src/project/recovery.d.ts +2 -0
  151. package/dist/src/project/recovery.js +82 -0
  152. package/dist/src/project/recovery.js.map +1 -0
  153. package/dist/src/project/workspaces.d.ts +4 -0
  154. package/dist/src/project/workspaces.js +59 -0
  155. package/dist/src/project/workspaces.js.map +1 -0
  156. package/dist/src/registry/account.d.ts +79 -0
  157. package/dist/src/registry/account.js +305 -0
  158. package/dist/src/registry/account.js.map +1 -0
  159. package/dist/src/registry/audit.d.ts +18 -0
  160. package/dist/src/registry/audit.js +74 -0
  161. package/dist/src/registry/audit.js.map +1 -0
  162. package/dist/src/registry/client.d.ts +19 -0
  163. package/dist/src/registry/client.js +102 -0
  164. package/dist/src/registry/client.js.map +1 -0
  165. package/dist/src/registry/configuration.d.ts +36 -0
  166. package/dist/src/registry/configuration.js +133 -0
  167. package/dist/src/registry/configuration.js.map +1 -0
  168. package/dist/src/registry/operations.d.ts +163 -0
  169. package/dist/src/registry/operations.js +502 -0
  170. package/dist/src/registry/operations.js.map +1 -0
  171. package/dist/src/registry/types.d.ts +30 -0
  172. package/dist/src/registry/types.js +2 -0
  173. package/dist/src/registry/types.js.map +1 -0
  174. package/dist/src/resolver/registry-resolver.d.ts +40 -0
  175. package/dist/src/resolver/registry-resolver.js +354 -0
  176. package/dist/src/resolver/registry-resolver.js.map +1 -0
  177. package/dist/src/resolver/source-provider.d.ts +17 -0
  178. package/dist/src/resolver/source-provider.js +336 -0
  179. package/dist/src/resolver/source-provider.js.map +1 -0
  180. package/dist/src/resolver/types.d.ts +28 -0
  181. package/dist/src/resolver/types.js +2 -0
  182. package/dist/src/resolver/types.js.map +1 -0
  183. package/dist/src/security/analyzer.d.ts +38 -0
  184. package/dist/src/security/analyzer.js +241 -0
  185. package/dist/src/security/analyzer.js.map +1 -0
  186. package/dist/src/security/audit.d.ts +19 -0
  187. package/dist/src/security/audit.js +61 -0
  188. package/dist/src/security/audit.js.map +1 -0
  189. package/dist/src/security/findings.d.ts +23 -0
  190. package/dist/src/security/findings.js +2 -0
  191. package/dist/src/security/findings.js.map +1 -0
  192. package/dist/src/security/integrity.d.ts +14 -0
  193. package/dist/src/security/integrity.js +40 -0
  194. package/dist/src/security/integrity.js.map +1 -0
  195. package/dist/src/security/policy.d.ts +16 -0
  196. package/dist/src/security/policy.js +24 -0
  197. package/dist/src/security/policy.js.map +1 -0
  198. package/dist/src/security/recent-release.d.ts +19 -0
  199. package/dist/src/security/recent-release.js +27 -0
  200. package/dist/src/security/recent-release.js.map +1 -0
  201. package/dist/src/security/script-runner.d.ts +13 -0
  202. package/dist/src/security/script-runner.js +73 -0
  203. package/dist/src/security/script-runner.js.map +1 -0
  204. package/package.json +45 -0
@@ -0,0 +1,639 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { relative, sep } from "node:path";
3
+ import semver from "semver";
4
+ import npa from "npm-package-arg";
5
+ import { createBnpmPaths } from "../config/paths.js";
6
+ import { readLockfileGraph } from "../lockfile/index.js";
7
+ import { discoverProject } from "../project/discovery.js";
8
+ import { fetchBulkAdvisories } from "../registry/audit.js";
9
+ import { loadRegistryConfiguration, RoutedRegistryClient } from "../registry/configuration.js";
10
+ export class QueryError extends Error {
11
+ constructor(message) {
12
+ super(`Invalid dependency selector: ${message}`);
13
+ this.name = "QueryError";
14
+ }
15
+ }
16
+ const kinds = new Set(["dependency", "dev", "optional", "peer", "workspace", "bundled"]);
17
+ function unquote(value) {
18
+ const trimmed = value.trim();
19
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) || (trimmed.startsWith("'") && trimmed.endsWith("'")))
20
+ return trimmed.slice(1, -1);
21
+ return trimmed;
22
+ }
23
+ function splitTopLevel(value, delimiter) {
24
+ const values = [];
25
+ let start = 0;
26
+ let round = 0;
27
+ let square = 0;
28
+ let quote = "";
29
+ for (let index = 0; index < value.length; index += 1) {
30
+ const character = value[index] ?? "";
31
+ if (quote) {
32
+ if (character === quote && value[index - 1] !== "\\")
33
+ quote = "";
34
+ continue;
35
+ }
36
+ if (character === '"' || character === "'") {
37
+ quote = character;
38
+ continue;
39
+ }
40
+ if (character === "(")
41
+ round += 1;
42
+ else if (character === ")")
43
+ round -= 1;
44
+ else if (character === "[")
45
+ square += 1;
46
+ else if (character === "]")
47
+ square -= 1;
48
+ else if (character === delimiter && round === 0 && square === 0) {
49
+ values.push(value.slice(start, index).trim());
50
+ start = index + 1;
51
+ }
52
+ if (round < 0 || square < 0)
53
+ throw new QueryError(`unbalanced selector ${value}`);
54
+ }
55
+ if (round !== 0 || square !== 0 || quote)
56
+ throw new QueryError(`unbalanced selector ${value}`);
57
+ values.push(value.slice(start).trim());
58
+ return values;
59
+ }
60
+ function attributeExpression(expression) {
61
+ const match = /^\[\s*([A-Za-z0-9_.-]*)\s*(?:(~=|\*=|\|=|\^=|\$=|=)\s*(.*?)\s*)?\]$/.exec(expression);
62
+ if (!match)
63
+ throw new QueryError(`invalid attribute selector ${expression}`);
64
+ return { ...(match[1] ? { key: match[1] } : {}), ...(match[2] ? { operator: match[2] } : {}), ...(match[3] !== undefined ? { expected: unquote(match[3]) } : {}) };
65
+ }
66
+ function primitiveMatches(actual, operator, expected) {
67
+ if (operator === undefined)
68
+ return actual !== undefined;
69
+ if (Array.isArray(actual))
70
+ return actual.some((value) => primitiveMatches(value, operator, expected));
71
+ if (actual === null || actual === undefined || (typeof actual !== "string" && typeof actual !== "number" && typeof actual !== "boolean"))
72
+ return false;
73
+ const value = String(actual);
74
+ const wanted = expected ?? "";
75
+ if (operator === "=")
76
+ return value === wanted;
77
+ if (operator === "~=")
78
+ return value.split(/\s+/).includes(wanted);
79
+ if (operator === "*=")
80
+ return value.includes(wanted);
81
+ if (operator === "^=")
82
+ return value.startsWith(wanted);
83
+ if (operator === "$=")
84
+ return value.endsWith(wanted);
85
+ return value === wanted || value.startsWith(`${wanted}-`);
86
+ }
87
+ function derivedValue(node, key) {
88
+ if (key === "id")
89
+ return node.id;
90
+ if (key === "source")
91
+ return node.source;
92
+ if (key === "type")
93
+ return node.types;
94
+ if (key === "path")
95
+ return node.path;
96
+ if (key === "dangerous")
97
+ return node.dangerous;
98
+ return node.manifest[key];
99
+ }
100
+ function matchesAttribute(node, expression) {
101
+ const { key, operator, expected } = attributeExpression(expression);
102
+ if (!key)
103
+ return Object.values(node.manifest).some((value) => primitiveMatches(value, operator, expected));
104
+ return primitiveMatches(derivedValue(node, key), operator, expected);
105
+ }
106
+ function nestedAttribute(value, parts, expression) {
107
+ if (parts.length === 0) {
108
+ if (Array.isArray(value))
109
+ return value.some((item) => nestedAttribute(item, [], expression));
110
+ if (typeof value !== "object" || value === null)
111
+ return false;
112
+ const { key, operator, expected } = attributeExpression(expression);
113
+ if (!key)
114
+ return Object.values(value).some((item) => primitiveMatches(item, operator, expected));
115
+ const selected = value[key];
116
+ return primitiveMatches(selected, operator, expected);
117
+ }
118
+ if (Array.isArray(value))
119
+ return value.some((item) => nestedAttribute(item, parts, expression));
120
+ if (typeof value !== "object" || value === null)
121
+ return false;
122
+ const [head, ...tail] = parts;
123
+ return head !== undefined && nestedAttribute(value[head], tail, expression);
124
+ }
125
+ function nestedValues(value, parts, expression) {
126
+ if (Array.isArray(value))
127
+ return value.flatMap((item) => nestedValues(item, parts, expression));
128
+ if (typeof value !== "object" || value === null)
129
+ return [];
130
+ if (parts.length > 0) {
131
+ const [head, ...tail] = parts;
132
+ return head === undefined ? [] : nestedValues(value[head], tail, expression);
133
+ }
134
+ const { key } = attributeExpression(expression);
135
+ if (!key)
136
+ return [];
137
+ const selected = value[key];
138
+ return Array.isArray(selected) ? selected.filter((item) => typeof item === "string") : typeof selected === "string" ? [selected] : [];
139
+ }
140
+ function semverMatch(actual, spec, operation) {
141
+ const validActual = semver.valid(actual);
142
+ const validSpec = semver.valid(spec);
143
+ const rangeActual = semver.validRange(actual);
144
+ const rangeSpec = semver.validRange(spec);
145
+ try {
146
+ if (operation === "infer") {
147
+ if (validActual && validSpec)
148
+ return semver.eq(validActual, validSpec);
149
+ if (!validActual && !validSpec && rangeActual && rangeSpec)
150
+ return semver.intersects(rangeActual, rangeSpec);
151
+ if (validActual && rangeSpec)
152
+ return semver.satisfies(validActual, rangeSpec);
153
+ if (validSpec && rangeActual)
154
+ return semver.satisfies(validSpec, rangeActual);
155
+ return false;
156
+ }
157
+ if (operation === "satisfies")
158
+ return Boolean((validActual && rangeSpec && semver.satisfies(validActual, rangeSpec)) || (validSpec && rangeActual && semver.satisfies(validSpec, rangeActual)));
159
+ if (operation === "intersects")
160
+ return Boolean(rangeActual && rangeSpec && semver.intersects(rangeActual, rangeSpec));
161
+ if (operation === "subset")
162
+ return Boolean(rangeActual && rangeSpec && semver.subset(rangeActual, rangeSpec));
163
+ if (!validActual || !validSpec)
164
+ return false;
165
+ if (operation === "gt")
166
+ return semver.gt(validActual, validSpec);
167
+ if (operation === "gte")
168
+ return semver.gte(validActual, validSpec);
169
+ if (operation === "lt")
170
+ return semver.lt(validActual, validSpec);
171
+ if (operation === "lte")
172
+ return semver.lte(validActual, validSpec);
173
+ if (operation === "eq")
174
+ return semver.eq(validActual, validSpec);
175
+ if (operation === "neq")
176
+ return semver.neq(validActual, validSpec);
177
+ if (operation === "gtr")
178
+ return Boolean(rangeSpec && semver.gtr(validActual, rangeSpec));
179
+ if (operation === "ltr")
180
+ return Boolean(rangeSpec && semver.ltr(validActual, rangeSpec));
181
+ }
182
+ catch {
183
+ return false;
184
+ }
185
+ throw new QueryError(`unknown semver function ${operation}`);
186
+ }
187
+ function pseudoArguments(rest) {
188
+ const name = /^:([A-Za-z-]+)/.exec(rest)?.[1];
189
+ if (!name)
190
+ throw new QueryError(`invalid pseudo selector near ${rest}`);
191
+ let consumed = name.length + 1;
192
+ if (rest[consumed] !== "(")
193
+ return { name, consumed };
194
+ let depth = 0;
195
+ let quote = "";
196
+ for (let index = consumed; index < rest.length; index += 1) {
197
+ const character = rest[index] ?? "";
198
+ if (quote) {
199
+ if (character === quote && rest[index - 1] !== "\\")
200
+ quote = "";
201
+ continue;
202
+ }
203
+ if (character === '"' || character === "'") {
204
+ quote = character;
205
+ continue;
206
+ }
207
+ if (character === "(")
208
+ depth += 1;
209
+ if (character === ")" && --depth === 0)
210
+ return { name, body: rest.slice(consumed + 1, index), consumed: index + 1 };
211
+ }
212
+ throw new QueryError(`unclosed :${name}()`);
213
+ }
214
+ function descendants(node, context) {
215
+ const found = [];
216
+ const seen = new Set();
217
+ const pending = [...node.dependencyIds];
218
+ while (pending.length > 0) {
219
+ const id = pending.shift();
220
+ if (!id || seen.has(id))
221
+ continue;
222
+ seen.add(id);
223
+ const value = context.nodes.get(id);
224
+ if (!value)
225
+ continue;
226
+ found.push(value);
227
+ pending.push(...value.dependencyIds);
228
+ }
229
+ return found;
230
+ }
231
+ function compound(selector) {
232
+ let rest = selector.trim();
233
+ if (!rest)
234
+ throw new QueryError("empty compound selector");
235
+ const tests = [];
236
+ if (rest.startsWith("*"))
237
+ rest = rest.slice(1);
238
+ const packageSelector = /^#((?:@[^/\s]+\/)?[^@.[\]:,\s>~]+)(?:@([A-Za-z0-9*+_.<>=|^~-]+))?/.exec(rest);
239
+ if (packageSelector?.[1]) {
240
+ const name = packageSelector[1];
241
+ const range = packageSelector[2];
242
+ tests.push((node) => (node.name === name || node.aliases.includes(name)) && (range === undefined || semverMatch(node.version, range, "infer")));
243
+ rest = rest.slice(packageSelector[0].length);
244
+ }
245
+ while (rest.length > 0) {
246
+ const type = /^\.(prod|dependency|dev|optional|peer|workspace|bundled)/.exec(rest);
247
+ if (type?.[1]) {
248
+ const kind = type[1] === "prod" ? "dependency" : type[1];
249
+ tests.push((node) => node.types.includes(kind));
250
+ rest = rest.slice(type[0].length);
251
+ continue;
252
+ }
253
+ if (rest.startsWith("[")) {
254
+ const end = rest.indexOf("]");
255
+ if (end < 0)
256
+ throw new QueryError(`unclosed attribute selector ${rest}`);
257
+ const expression = rest.slice(0, end + 1);
258
+ const parsed = attributeExpression(expression);
259
+ if (parsed.key === "type" && parsed.operator === "=" && parsed.expected !== undefined && !kinds.has(parsed.expected))
260
+ throw new QueryError(`unknown dependency type ${parsed.expected}`);
261
+ tests.push((node) => matchesAttribute(node, expression));
262
+ rest = rest.slice(end + 1);
263
+ continue;
264
+ }
265
+ if (rest.startsWith(":")) {
266
+ const pseudo = pseudoArguments(rest);
267
+ const body = pseudo.body?.trim();
268
+ if (pseudo.name === "root")
269
+ tests.push((node) => node.root);
270
+ else if (pseudo.name === "scope")
271
+ tests.push((node, context) => node.id === context.scope);
272
+ else if (pseudo.name === "direct")
273
+ tests.push((node) => node.direct);
274
+ else if (pseudo.name === "dangerous")
275
+ tests.push((node) => node.dangerous);
276
+ else if (pseudo.name === "empty")
277
+ tests.push((node) => node.dependencyIds.length === 0);
278
+ else if (pseudo.name === "private")
279
+ tests.push((node) => node.manifest.private === true);
280
+ else if (pseudo.name === "link")
281
+ tests.push((node) => node.linked);
282
+ else if (pseudo.name === "deduped")
283
+ tests.push((node) => node.parentIds.length > 1);
284
+ else if (["extraneous", "invalid", "missing"].includes(pseudo.name))
285
+ tests.push(() => false);
286
+ else if (pseudo.name === "overridden")
287
+ tests.push((node) => node.id.includes("(override:"));
288
+ else if (pseudo.name === "not" || pseudo.name === "is") {
289
+ if (!body)
290
+ throw new QueryError(`:${pseudo.name} requires a selector`);
291
+ const nested = selectorList(body);
292
+ const expected = pseudo.name === "is";
293
+ tests.push((node, context) => nested.some((sequence) => matchSequence(node, sequence, context)) === expected);
294
+ }
295
+ else if (pseudo.name === "has") {
296
+ if (!body)
297
+ throw new QueryError(":has requires a selector");
298
+ const relativeSelector = body.startsWith(">") || body.startsWith("~") ? `:scope${body}` : `:scope ${body}`;
299
+ const nested = selectorList(relativeSelector);
300
+ tests.push((node, context) => [...context.nodes.values()].some((candidate) => nested.some((sequence) => matchSequence(candidate, sequence, { ...context, scope: node.id }))));
301
+ }
302
+ else if (pseudo.name === "type") {
303
+ if (!body)
304
+ throw new QueryError(":type requires a source type");
305
+ const expected = unquote(body);
306
+ const accepted = new Set(["registry", "git", "directory", "file", "remote", "tarball", "tag", "range", "version", "alias"]);
307
+ if (!accepted.has(expected))
308
+ throw new QueryError(`unknown package source type ${expected}`);
309
+ tests.push((node) => expected === "registry" ? node.source === "registry" : expected === "file" ? node.source === "directory" : expected === "remote" ? node.source === "tarball" : ["tag", "range", "version", "alias"].includes(expected) ? node.source === "registry" : node.source === expected);
310
+ }
311
+ else if (pseudo.name === "semver") {
312
+ const args = splitTopLevel(body ?? "", ",");
313
+ const spec = unquote(args[0] ?? "");
314
+ if (!spec || args.length > 3)
315
+ throw new QueryError(":semver requires a spec and at most two optional arguments");
316
+ const fieldExpression = args[1] || "[version]";
317
+ let values;
318
+ if (fieldExpression.startsWith(":attr(")) {
319
+ const attribute = pseudoArguments(fieldExpression);
320
+ if (attribute.name !== "attr" || attribute.consumed !== fieldExpression.length)
321
+ throw new QueryError(":semver has an invalid :attr field selector");
322
+ const attributeArgs = splitTopLevel(attribute.body ?? "", ",");
323
+ const expression = attributeArgs.at(-1) ?? "";
324
+ attributeExpression(expression);
325
+ const parts = attributeArgs.slice(0, -1).map(unquote);
326
+ values = (node) => nestedValues(node.manifest, parts, expression);
327
+ }
328
+ else {
329
+ const field = attributeExpression(fieldExpression).key;
330
+ if (!field)
331
+ throw new QueryError(":semver field selector requires an attribute name");
332
+ values = (node) => { const actual = derivedValue(node, field); return typeof actual === "string" ? [actual] : []; };
333
+ }
334
+ const operation = unquote(args[2] || "infer");
335
+ tests.push((node) => values(node).some((actual) => semverMatch(actual, spec, operation)));
336
+ }
337
+ else if (pseudo.name === "attr") {
338
+ const args = splitTopLevel(body ?? "", ",");
339
+ const expression = args.at(-1) ?? "";
340
+ attributeExpression(expression);
341
+ const parts = args.slice(0, -1).map(unquote);
342
+ tests.push((node) => nestedAttribute(node.manifest, parts, expression));
343
+ }
344
+ else if (pseudo.name === "path") {
345
+ if (!body)
346
+ throw new QueryError(":path requires a pattern");
347
+ const pattern = unquote(body);
348
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replaceAll("**", "\u0000").replaceAll("*", "[^/]*").replaceAll("\u0000", ".*");
349
+ const matcher = new RegExp(`^${escaped}$`);
350
+ tests.push((node) => matcher.test(node.path));
351
+ }
352
+ else if (pseudo.name === "outdated") {
353
+ const category = body || "any";
354
+ if (!["any", "in-range", "out-of-range", "major", "minor", "patch"].includes(category))
355
+ throw new QueryError(`unknown outdated category ${category}`);
356
+ tests.push((node) => (node.queryContext?.outdated?.categories ?? []).includes(category));
357
+ }
358
+ else if (pseudo.name === "vuln") {
359
+ const filters = body ? splitTopLevel(body, ",").map(attributeExpression) : [];
360
+ for (const filter of filters)
361
+ if (!filter.key || filter.operator !== "=" || !["severity", "cwe"].includes(filter.key))
362
+ throw new QueryError(":vuln filters support only [severity=value] or [cwe=value]");
363
+ tests.push((node) => (node.queryContext?.advisories ?? []).some((advisory) => filters.length === 0 || filters.some((filter) => filter.key === "severity" ? advisory.severity === filter.expected : (advisory.cwe ?? []).some((cwe) => cwe === filter.expected || cwe === `CWE-${filter.expected}`))));
364
+ }
365
+ else
366
+ throw new QueryError(`unsupported pseudo selector :${pseudo.name}`);
367
+ rest = rest.slice(pseudo.consumed);
368
+ continue;
369
+ }
370
+ throw new QueryError(`unsupported selector near ${rest}`);
371
+ }
372
+ return { tests };
373
+ }
374
+ function sequence(selector) {
375
+ const compounds = [];
376
+ const combinators = [];
377
+ let buffer = "";
378
+ let round = 0;
379
+ let square = 0;
380
+ let quote = "";
381
+ let pending;
382
+ const flush = () => { const value = buffer.trim(); buffer = ""; if (!value)
383
+ return; if (compounds.length > 0)
384
+ combinators.push(pending ?? " "); compounds.push(compound(value)); pending = undefined; };
385
+ for (let index = 0; index < selector.length; index += 1) {
386
+ const character = selector[index] ?? "";
387
+ if (quote) {
388
+ buffer += character;
389
+ if (character === quote && selector[index - 1] !== "\\")
390
+ quote = "";
391
+ continue;
392
+ }
393
+ if (character === '"' || character === "'") {
394
+ quote = character;
395
+ buffer += character;
396
+ continue;
397
+ }
398
+ if (character === "(")
399
+ round += 1;
400
+ else if (character === ")")
401
+ round -= 1;
402
+ else if (character === "[")
403
+ square += 1;
404
+ else if (character === "]")
405
+ square -= 1;
406
+ if (round === 0 && square === 0 && (character === ">" || character === "~")) {
407
+ flush();
408
+ pending = character;
409
+ continue;
410
+ }
411
+ if (round === 0 && square === 0 && /\s/.test(character)) {
412
+ flush();
413
+ if (compounds.length > 0 && pending === undefined)
414
+ pending = " ";
415
+ continue;
416
+ }
417
+ buffer += character;
418
+ }
419
+ flush();
420
+ if (compounds.length === 0 || combinators.length !== compounds.length - 1)
421
+ throw new QueryError(`invalid selector sequence ${selector}`);
422
+ return { compounds, combinators };
423
+ }
424
+ function selectorList(selector) {
425
+ return splitTopLevel(selector, ",").map((value) => { if (!value)
426
+ throw new QueryError("empty selector"); return sequence(value); });
427
+ }
428
+ function matchesCompound(node, value, context) { return value.tests.every((test) => test(node, context)); }
429
+ function matchSequence(node, value, context, index = value.compounds.length - 1) {
430
+ const current = value.compounds[index];
431
+ if (!current || !matchesCompound(node, current, context))
432
+ return false;
433
+ if (index === 0)
434
+ return true;
435
+ const relation = value.combinators[index - 1];
436
+ if (relation === ">")
437
+ return node.parentIds.some((id) => { const parent = context.nodes.get(id); return parent !== undefined && matchSequence(parent, value, context, index - 1); });
438
+ if (relation === " ") {
439
+ const seen = new Set();
440
+ const pending = [...node.parentIds];
441
+ while (pending.length > 0) {
442
+ const id = pending.shift();
443
+ if (!id || seen.has(id))
444
+ continue;
445
+ seen.add(id);
446
+ const parent = context.nodes.get(id);
447
+ if (!parent)
448
+ continue;
449
+ if (matchSequence(parent, value, context, index - 1))
450
+ return true;
451
+ pending.push(...parent.parentIds);
452
+ }
453
+ return false;
454
+ }
455
+ for (const parentId of node.parentIds) {
456
+ const parent = context.nodes.get(parentId);
457
+ if (!parent)
458
+ continue;
459
+ for (const siblingId of parent.dependencyIds) {
460
+ if (siblingId === node.id)
461
+ continue;
462
+ const sibling = context.nodes.get(siblingId);
463
+ if (sibling && matchSequence(sibling, value, context, index - 1))
464
+ return true;
465
+ }
466
+ }
467
+ return false;
468
+ }
469
+ function propagateTypes(graph, roots, requirements) {
470
+ const result = new Map();
471
+ const add = (id, kind) => {
472
+ const seen = new Set();
473
+ const pending = [id];
474
+ while (pending.length > 0) {
475
+ const current = pending.shift();
476
+ if (!current || seen.has(current))
477
+ continue;
478
+ seen.add(current);
479
+ const values = result.get(current) ?? new Set();
480
+ values.add(kind);
481
+ result.set(current, values);
482
+ pending.push(...(graph.packages.get(current)?.dependencies.values() ?? []));
483
+ }
484
+ };
485
+ for (const [alias, id] of roots)
486
+ add(id, requirements.find((requirement) => requirement.name === alias)?.kind ?? "dependency");
487
+ for (const pkg of graph.packages.values()) {
488
+ const raw = pkg.manifest;
489
+ for (const name of raw.bundleDependencies ?? raw.bundledDependencies ?? []) {
490
+ const id = pkg.dependencies.get(name);
491
+ if (id)
492
+ add(id, "bundled");
493
+ }
494
+ }
495
+ return result;
496
+ }
497
+ export function queryResolutionGraph(graph, roots, requirements, dangerousIds, selector, rootManifest = { name: "(root)", version: "0.0.0", private: true }, enrichment = {}) {
498
+ const selectors = selectorList(selector);
499
+ const aliases = new Map();
500
+ for (const [alias, id] of roots) {
501
+ const names = aliases.get(id) ?? [];
502
+ names.push(alias);
503
+ aliases.set(id, names);
504
+ }
505
+ const parents = new Map();
506
+ for (const pkg of graph.packages.values())
507
+ for (const dependency of pkg.dependencies.values()) {
508
+ const values = parents.get(dependency) ?? new Set();
509
+ values.add(pkg.id);
510
+ parents.set(dependency, values);
511
+ }
512
+ const rootId = "\u0000root";
513
+ for (const id of roots.values()) {
514
+ const values = parents.get(id) ?? new Set();
515
+ values.add(rootId);
516
+ parents.set(id, values);
517
+ }
518
+ const types = propagateTypes(graph, roots, requirements);
519
+ const nodes = new Map();
520
+ const rootNode = { ...rootManifest, id: rootId, name: typeof rootManifest.name === "string" ? rootManifest.name : "(root)", version: typeof rootManifest.version === "string" ? rootManifest.version : "0.0.0", source: "project", direct: false, aliases: [], types: ["dependency"], dangerous: false, dependencies: [...roots.keys()].sort(), dependents: [], manifest: rootManifest, dependencyIds: [...new Set(roots.values())].sort(), parentIds: [], root: true, linked: false, path: "." };
521
+ nodes.set(rootId, rootNode);
522
+ for (const pkg of [...graph.packages.values()].sort((left, right) => left.id.localeCompare(right.id))) {
523
+ const manifest = pkg.manifest;
524
+ const outdated = enrichment.outdated?.get(pkg.id);
525
+ const advisories = enrichment.advisories?.get(pkg.id) ?? [];
526
+ const queryContext = { ...(outdated === undefined ? {} : { outdated: { categories: [...outdated.categories].sort() }, versions: outdated.versions }), ...(advisories.length === 0 ? {} : { advisories }) };
527
+ const node = { ...manifest, id: pkg.id, name: pkg.name, version: pkg.version, source: pkg.source ?? "registry", direct: aliases.has(pkg.id), aliases: [...(aliases.get(pkg.id) ?? [])].sort(), types: [...(types.get(pkg.id) ?? [])].sort(), dangerous: dangerousIds.has(pkg.id), dependencies: [...pkg.dependencies.keys()].sort(), dependents: [...(parents.get(pkg.id) ?? [])].filter((id) => id !== rootId).sort(), ...(Object.keys(queryContext).length === 0 ? {} : { queryContext }), manifest, dependencyIds: [...new Set(pkg.dependencies.values())].sort(), parentIds: [...(parents.get(pkg.id) ?? [])].sort(), root: false, linked: pkg.source === "directory", path: `node_modules/${(aliases.get(pkg.id)?.[0] ?? pkg.name).replaceAll("/", "/node_modules/")}` };
528
+ nodes.set(pkg.id, node);
529
+ }
530
+ const context = { nodes, scope: rootId };
531
+ return [...nodes.values()].filter((node) => selectors.some((value) => matchSequence(node, value, context))).map(({ manifest: _manifest, dependencyIds: _dependencyIds, parentIds: _parentIds, root: _root, linked: _linked, path: _path, ...result }) => result);
532
+ }
533
+ function declaredRanges(graph, roots, requirements) {
534
+ const values = new Map();
535
+ const add = (id, specifier) => { let range = semver.validRange(specifier); if (!range) {
536
+ try {
537
+ const parsed = npa(specifier);
538
+ const request = parsed.type === "alias" ? parsed.subSpec : parsed;
539
+ range = semver.validRange(request.rawSpec);
540
+ }
541
+ catch { }
542
+ } if (range) {
543
+ const entries = values.get(id) ?? [];
544
+ entries.push(range);
545
+ values.set(id, entries);
546
+ } };
547
+ for (const requirement of requirements) {
548
+ const id = roots.get(requirement.name);
549
+ if (id)
550
+ add(id, requirement.specifier);
551
+ }
552
+ for (const pkg of graph.packages.values())
553
+ for (const [alias, id] of pkg.dependencies) {
554
+ const manifest = pkg.manifest;
555
+ const specifier = manifest.optionalDependencies?.[alias] ?? manifest.dependencies?.[alias] ?? manifest.devDependencies?.[alias] ?? manifest.peerDependencies?.[alias];
556
+ if (specifier)
557
+ add(id, specifier);
558
+ }
559
+ return values;
560
+ }
561
+ export async function enrichQuery(options) {
562
+ const needsOutdated = options.selector.includes(":outdated");
563
+ const needsVulnerability = options.selector.includes(":vuln");
564
+ if (!needsOutdated && !needsVulnerability)
565
+ return {};
566
+ const configuration = await loadRegistryConfiguration({ userNpmrc: options.paths.userNpmrc, projectNpmrc: options.paths.projectNpmrc, ...(options.registry === undefined ? {} : { defaultRegistry: options.registry }) });
567
+ let outdated;
568
+ if (needsOutdated) {
569
+ const client = new RoutedRegistryClient(configuration, options.fetch ?? globalThis.fetch);
570
+ const documents = new Map();
571
+ const names = [...new Set([...options.graph.packages.values()].filter((pkg) => (pkg.source ?? "registry") === "registry").map((pkg) => pkg.name))].sort();
572
+ let cursor = 0;
573
+ await Promise.all(Array.from({ length: Math.min(8, names.length) }, async () => { while (cursor < names.length) {
574
+ const name = names[cursor++];
575
+ if (name)
576
+ documents.set(name, await client.packageDocument(name, options.signal));
577
+ } }));
578
+ const ranges = declaredRanges(options.graph, options.roots, options.requirements);
579
+ outdated = new Map();
580
+ for (const pkg of options.graph.packages.values()) {
581
+ const document = documents.get(pkg.name);
582
+ if (!document)
583
+ continue;
584
+ const versions = Object.keys(document.versions).filter((version) => semver.valid(version)).sort(semver.compare);
585
+ const greater = versions.filter((version) => semver.gt(version, pkg.version));
586
+ if (greater.length === 0)
587
+ continue;
588
+ const categories = new Set(["any"]);
589
+ const current = semver.parse(pkg.version);
590
+ if (current && greater.some((version) => semver.major(version) > current.major))
591
+ categories.add("major");
592
+ if (current && greater.some((version) => semver.major(version) === current.major && semver.minor(version) > current.minor))
593
+ categories.add("minor");
594
+ if (current && greater.some((version) => semver.major(version) === current.major && semver.minor(version) === current.minor && semver.patch(version) > current.patch))
595
+ categories.add("patch");
596
+ const declared = ranges.get(pkg.id) ?? [];
597
+ if (declared.some((range) => greater.some((version) => semver.satisfies(version, range))))
598
+ categories.add("in-range");
599
+ if (declared.some((range) => greater.some((version) => !semver.satisfies(version, range))))
600
+ categories.add("out-of-range");
601
+ outdated.set(pkg.id, { categories, versions });
602
+ }
603
+ }
604
+ let advisories;
605
+ if (needsVulnerability) {
606
+ const groups = new Map();
607
+ for (const [id, pkg] of options.graph.packages) {
608
+ const registry = configuration.registryForPackage(pkg.name).href;
609
+ const values = groups.get(registry) ?? new Map();
610
+ values.set(id, pkg);
611
+ groups.set(registry, values);
612
+ }
613
+ const found = (await Promise.all([...groups].map(([registry, packages]) => fetchBulkAdvisories({ graph: { roots: new Map(), packages }, registry: new URL(registry), headers: (url) => configuration.headersFor(url), ...(options.fetch === undefined ? {} : { fetch: options.fetch }), ...(options.signal === undefined ? {} : { signal: options.signal }) })))).flat();
614
+ advisories = new Map();
615
+ for (const pkg of options.graph.packages.values()) {
616
+ const matches = found.filter((advisory) => advisory.packageName === pkg.name && semver.satisfies(pkg.version, advisory.vulnerableVersions));
617
+ if (matches.length > 0)
618
+ advisories.set(pkg.id, matches);
619
+ }
620
+ }
621
+ return { ...(outdated === undefined ? {} : { outdated }), ...(advisories === undefined ? {} : { advisories }) };
622
+ }
623
+ export async function queryInstalledPackages(options) {
624
+ const discovered = await discoverProject(options.cwd);
625
+ const root = discovered?.projectRoot ?? options.cwd;
626
+ const importerRoot = discovered?.importerRoot ?? options.cwd;
627
+ const paths = options.paths ?? createBnpmPaths({ cwd: root });
628
+ const locked = await readLockfileGraph(paths.lockfile, paths.store);
629
+ const importer = relative(root, importerRoot).split(sep).join("/") || ".";
630
+ const roots = options.allWorkspaces
631
+ ? new Map([...(locked.graph.importers ?? new Map([[".", locked.graph.roots]])).values()].flatMap((values) => [...values]))
632
+ : locked.graph.importers?.get(importer) ?? (importer === "." ? locked.graph.roots : new Map());
633
+ const requirements = options.allWorkspaces ? locked.requirements : locked.requirements.filter((requirement) => (requirement.importer ?? ".") === importer);
634
+ const manifestPath = `${importerRoot}${sep}package.json`;
635
+ const rootManifest = JSON.parse(await readFile(manifestPath, "utf8"));
636
+ const enrichment = await enrichQuery({ selector: options.selector, graph: locked.graph, roots, requirements, paths, ...(options.registry === undefined ? {} : { registry: options.registry }), ...(options.fetch === undefined ? {} : { fetch: options.fetch }), ...(options.signal === undefined ? {} : { signal: options.signal }) });
637
+ return queryResolutionGraph(locked.graph, roots, requirements, locked.dangerousPackageIds, options.selector, rootManifest, enrichment);
638
+ }
639
+ //# sourceMappingURL=query.js.map