@socketsecurity/lib 5.26.0 → 5.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/CHANGELOG.md +371 -1185
  2. package/README.md +1 -1
  3. package/dist/abort.js +7 -6
  4. package/dist/agent.js +16 -15
  5. package/dist/ansi.js +3 -2
  6. package/dist/archives.js +18 -17
  7. package/dist/argv/flags.js +29 -28
  8. package/dist/argv/parse.js +4 -3
  9. package/dist/arrays.js +3 -2
  10. package/dist/bin.js +12 -11
  11. package/dist/cacache.js +16 -11
  12. package/dist/cache-with-ttl.js +26 -21
  13. package/dist/colors.js +2 -1
  14. package/dist/constants/licenses.js +2 -1
  15. package/dist/constants/lifecycle-script-names.js +2 -1
  16. package/dist/constants/maintained-node-versions.js +2 -1
  17. package/dist/constants/node.js +4 -3
  18. package/dist/constants/package-default-socket-categories.js +2 -1
  19. package/dist/constants/packages.js +4 -3
  20. package/dist/constants/socket.js +1 -1
  21. package/dist/cover/code.js +9 -8
  22. package/dist/cover/formatters.js +12 -11
  23. package/dist/cover/type.js +5 -4
  24. package/dist/crypto.d.ts +36 -0
  25. package/dist/{effects/ultra.js → crypto.js} +26 -37
  26. package/dist/debug.js +12 -15
  27. package/dist/dlx/arborist.js +10 -9
  28. package/dist/dlx/binary.js +27 -24
  29. package/dist/dlx/cache.js +2 -10
  30. package/dist/dlx/detect.js +6 -5
  31. package/dist/dlx/integrity.js +13 -11
  32. package/dist/dlx/lockfile.js +7 -6
  33. package/dist/dlx/manifest.js +6 -5
  34. package/dist/dlx/package.js +17 -16
  35. package/dist/dlx/packages.js +6 -5
  36. package/dist/dlx/paths.d.ts +1 -1
  37. package/dist/dlx/paths.js +2 -1
  38. package/dist/effects/pulse-frames.js +4 -3
  39. package/dist/effects/shimmer-keyframes.d.ts +62 -0
  40. package/dist/effects/shimmer-keyframes.js +55 -0
  41. package/dist/effects/shimmer-terminal.d.ts +66 -0
  42. package/dist/effects/shimmer-terminal.js +57 -0
  43. package/dist/effects/shimmer.d.ts +293 -0
  44. package/dist/effects/shimmer.js +180 -0
  45. package/dist/env/rewire.js +4 -3
  46. package/dist/env.js +5 -4
  47. package/dist/errors.js +1 -1
  48. package/dist/external/@npmcli/package-json/lib/read-package.js +10 -10
  49. package/dist/external/@npmcli/package-json.js +372 -372
  50. package/dist/external/@npmcli/promise-spawn.js +24 -24
  51. package/dist/external/@socketregistry/packageurl-js.js +19 -18
  52. package/dist/external/@socketregistry/yocto-spinner.js +4 -3
  53. package/dist/external/@yarnpkg/extensions.js +2 -1
  54. package/dist/external/adm-zip.js +71 -71
  55. package/dist/external/debug.js +22 -22
  56. package/dist/external/external-pack.js +45 -45
  57. package/dist/external/fast-sort.js +5 -5
  58. package/dist/external/libnpmexec.js +4 -3
  59. package/dist/external/npm-pack.js +369 -369
  60. package/dist/external/p-map.js +9 -9
  61. package/dist/external/pico-pack.js +190 -190
  62. package/dist/external/pony-cause.js +2 -1
  63. package/dist/external/spdx-pack.js +11 -10
  64. package/dist/external/tar-fs.js +58 -58
  65. package/dist/external/which.js +13 -13
  66. package/dist/external/yargs-parser.js +71 -71
  67. package/dist/fs.js +50 -68
  68. package/dist/git.js +14 -13
  69. package/dist/github.d.ts +34 -0
  70. package/dist/github.js +248 -23
  71. package/dist/globs.d.ts +20 -0
  72. package/dist/globs.js +134 -25
  73. package/dist/http-request.d.ts +4 -3
  74. package/dist/http-request.js +39 -32
  75. package/dist/ipc-cli.js +2 -1
  76. package/dist/ipc.js +5 -4
  77. package/dist/json/edit.js +4 -3
  78. package/dist/json/format.js +3 -2
  79. package/dist/json/parse.js +7 -6
  80. package/dist/links.js +2 -1
  81. package/dist/logger.js +21 -14
  82. package/dist/memoization.js +16 -15
  83. package/dist/node/async-hooks.d.ts +6 -0
  84. package/dist/node/async-hooks.js +34 -0
  85. package/dist/node/child-process.d.ts +11 -0
  86. package/dist/node/child-process.js +34 -0
  87. package/dist/node/crypto.d.ts +6 -0
  88. package/dist/node/crypto.js +34 -0
  89. package/dist/node/events.d.ts +6 -0
  90. package/dist/node/events.js +34 -0
  91. package/dist/node/fs-promises.d.ts +6 -0
  92. package/dist/node/fs-promises.js +34 -0
  93. package/dist/node/fs.d.ts +14 -0
  94. package/dist/node/fs.js +34 -0
  95. package/dist/node/http.d.ts +6 -0
  96. package/dist/node/http.js +34 -0
  97. package/dist/node/https.d.ts +6 -0
  98. package/dist/node/https.js +34 -0
  99. package/dist/node/os.d.ts +6 -0
  100. package/dist/node/os.js +34 -0
  101. package/dist/node/path.d.ts +6 -0
  102. package/dist/node/path.js +34 -0
  103. package/dist/node/timers-promises.d.ts +6 -0
  104. package/dist/node/timers-promises.js +34 -0
  105. package/dist/node/url.d.ts +6 -0
  106. package/dist/node/url.js +34 -0
  107. package/dist/node/util.d.ts +6 -0
  108. package/dist/node/util.js +34 -0
  109. package/dist/objects.js +2 -2
  110. package/dist/packages/edit.js +8 -7
  111. package/dist/packages/exports.js +17 -16
  112. package/dist/packages/isolation.js +20 -13
  113. package/dist/packages/licenses.js +6 -3
  114. package/dist/packages/manifest.js +2 -1
  115. package/dist/packages/normalize.js +8 -4
  116. package/dist/packages/operations.js +5 -4
  117. package/dist/packages/provenance.js +7 -6
  118. package/dist/packages/specs.js +2 -1
  119. package/dist/packages/validation.js +2 -1
  120. package/dist/paths/normalize.js +32 -40
  121. package/dist/paths/packages.js +2 -1
  122. package/dist/paths/rewire.js +3 -2
  123. package/dist/performance.js +19 -18
  124. package/dist/primordials.d.ts +85 -2
  125. package/dist/primordials.js +311 -23
  126. package/dist/process-lock.js +14 -13
  127. package/dist/promise-queue.js +17 -9
  128. package/dist/promises.d.ts +29 -6
  129. package/dist/promises.js +19 -15
  130. package/dist/regexps.js +9 -8
  131. package/dist/releases/github-api.d.ts +56 -0
  132. package/dist/releases/github-api.js +275 -0
  133. package/dist/releases/github-archives.d.ts +60 -0
  134. package/dist/releases/github-archives.js +136 -0
  135. package/dist/releases/github-assets.d.ts +21 -0
  136. package/dist/releases/github-assets.js +52 -0
  137. package/dist/releases/github-auth.d.ts +16 -0
  138. package/dist/releases/github-auth.js +51 -0
  139. package/dist/releases/github-downloads.d.ts +42 -0
  140. package/dist/releases/github-downloads.js +155 -0
  141. package/dist/releases/github-types.d.ts +66 -0
  142. package/dist/{effects/types.js → releases/github-types.js} +2 -2
  143. package/dist/releases/socket-btm.d.ts +1 -1
  144. package/dist/releases/socket-btm.js +17 -17
  145. package/dist/schema/parse.js +2 -1
  146. package/dist/schema/validate.js +6 -5
  147. package/dist/sea/util.d.ts +43 -0
  148. package/dist/{sea.js → sea/util.js} +7 -7
  149. package/dist/shadow.js +2 -1
  150. package/dist/signal-exit.js +2 -2
  151. package/dist/smol/primordial.d.ts +80 -0
  152. package/dist/smol/primordial.js +46 -0
  153. package/dist/smol/util.d.ts +87 -0
  154. package/dist/smol/util.js +59 -0
  155. package/dist/smol/versions.d.ts +46 -0
  156. package/dist/smol/versions.js +46 -0
  157. package/dist/spawn.js +58 -63
  158. package/dist/spinner.d.ts +13 -6
  159. package/dist/spinner.js +75 -57
  160. package/dist/ssri.js +8 -7
  161. package/dist/stdio/footer.js +13 -12
  162. package/dist/stdio/header.js +5 -4
  163. package/dist/stdio/progress.js +13 -12
  164. package/dist/strings.js +19 -18
  165. package/dist/suppress-warnings.js +2 -2
  166. package/dist/tables.js +16 -13
  167. package/dist/temporary-executor.js +2 -1
  168. package/dist/themes/context.js +2 -1
  169. package/dist/themes/types.d.ts +1 -1
  170. package/dist/themes/utils.d.ts +8 -3
  171. package/dist/themes/utils.js +29 -5
  172. package/dist/url.js +4 -3
  173. package/dist/versions.js +27 -22
  174. package/package.json +120 -26
  175. package/dist/effects/text-shimmer.d.ts +0 -58
  176. package/dist/effects/text-shimmer.js +0 -192
  177. package/dist/effects/types.d.ts +0 -47
  178. package/dist/effects/ultra.d.ts +0 -22
  179. package/dist/releases/github.d.ts +0 -234
  180. package/dist/releases/github.js +0 -417
  181. package/dist/sea.d.ts +0 -30
  182. package/dist/themes/index.d.ts +0 -49
  183. package/dist/themes/index.js +0 -60
package/dist/github.js CHANGED
@@ -30,6 +30,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
31
  var github_exports = {};
32
32
  __export(github_exports, {
33
+ GitHubEmptyBodyError: () => GitHubEmptyBodyError,
33
34
  cacheFetchGhsa: () => cacheFetchGhsa,
34
35
  clearRefCache: () => clearRefCache,
35
36
  fetchGhsaDetails: () => fetchGhsaDetails,
@@ -47,14 +48,32 @@ var import_github = require("./env/github");
47
48
  var import_socket_cli = require("./env/socket-cli");
48
49
  var import_errors = require("./errors");
49
50
  var import_http_request = require("./http-request");
51
+ var import_primordials = require("./primordials");
50
52
  var import_spawn = require("./spawn");
51
53
  const GITHUB_API_BASE_URL = "https://api.github.com";
54
+ const GITHUB_GRAPHQL_URL = "https://api.github.com/graphql";
52
55
  const DEFAULT_CACHE_TTL_MS = 5 * 60 * 1e3;
53
56
  let _githubCache;
57
+ class GitHubEmptyBodyError extends Error {
58
+ /** HTTP status (always 200 — that's what makes this case insidious). */
59
+ status;
60
+ constructor(url) {
61
+ super(`GitHub API returned HTTP 200 with empty body: ${url}`);
62
+ this.name = "GitHubEmptyBodyError";
63
+ this.status = 200;
64
+ }
65
+ }
54
66
  async function fetchRefSha(owner, repo, ref, options) {
55
67
  const fetchOptions = {
56
68
  token: options.token
57
69
  };
70
+ let sawEmptyBody = false;
71
+ const note404 = (e) => {
72
+ if (e instanceof GitHubEmptyBodyError) {
73
+ sawEmptyBody = true;
74
+ }
75
+ return e;
76
+ };
58
77
  try {
59
78
  const tagUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/tags/${ref}`;
60
79
  const tagData = await fetchGitHub(tagUrl, fetchOptions);
@@ -66,12 +85,14 @@ async function fetchRefSha(owner, repo, ref, options) {
66
85
  return tagObject.object.sha;
67
86
  }
68
87
  return tagData.object.sha;
69
- } catch {
88
+ } catch (e) {
89
+ note404(e);
70
90
  try {
71
91
  const branchUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/git/refs/heads/${ref}`;
72
92
  const branchData = await fetchGitHub(branchUrl, fetchOptions);
73
93
  return branchData.object.sha;
74
- } catch {
94
+ } catch (e2) {
95
+ note404(e2);
75
96
  try {
76
97
  const commitUrl = `${GITHUB_API_BASE_URL}/repos/${owner}/${repo}/commits/${ref}`;
77
98
  const commitData = await fetchGitHub(
@@ -79,14 +100,114 @@ async function fetchRefSha(owner, repo, ref, options) {
79
100
  fetchOptions
80
101
  );
81
102
  return commitData.sha;
82
- } catch (e) {
83
- throw new Error(
84
- `failed to resolve ref "${ref}" for ${owner}/${repo}: ${(0, import_errors.errorMessage)(e)}`
103
+ } catch (e3) {
104
+ note404(e3);
105
+ if (sawEmptyBody) {
106
+ let graphqlSha;
107
+ let graphqlErr;
108
+ try {
109
+ graphqlSha = await fetchRefShaViaGraphQL(
110
+ owner,
111
+ repo,
112
+ ref,
113
+ fetchOptions
114
+ );
115
+ } catch (cause) {
116
+ graphqlErr = cause;
117
+ }
118
+ if (graphqlSha) {
119
+ return graphqlSha;
120
+ }
121
+ if (graphqlErr !== void 0) {
122
+ throw new import_primordials.ErrorCtor(
123
+ `Failed to resolve ref "${ref}" for ${owner}/${repo}: both REST and GraphQL backends degraded`,
124
+ { cause: graphqlErr }
125
+ );
126
+ }
127
+ }
128
+ throw new import_primordials.ErrorCtor(
129
+ `Failed to resolve ref "${ref}" for ${owner}/${repo}: ${(0, import_errors.errorMessage)(e3)}`
85
130
  );
86
131
  }
87
132
  }
88
133
  }
89
134
  }
135
+ async function fetchRefShaViaGraphQL(owner, repo, ref, options) {
136
+ const token = options.token || getGitHubToken();
137
+ const headers = {
138
+ Accept: "application/vnd.github.v3+json",
139
+ "Content-Type": "application/json",
140
+ "User-Agent": "socket-registry-github-client",
141
+ ...options.headers
142
+ };
143
+ if (token) {
144
+ headers["Authorization"] = `Bearer ${token}`;
145
+ }
146
+ const query = `query($owner: String!, $repo: String!, $tag: String!, $branch: String!, $oid: GitObjectID!) {
147
+ repository(owner: $owner, name: $repo) {
148
+ tagRef: ref(qualifiedName: $tag) {
149
+ target {
150
+ __typename
151
+ ... on Tag { target { oid } }
152
+ ... on Commit { oid }
153
+ }
154
+ }
155
+ branchRef: ref(qualifiedName: $branch) {
156
+ target { oid }
157
+ }
158
+ commit: object(oid: $oid) {
159
+ __typename
160
+ ... on Commit { oid }
161
+ }
162
+ }
163
+ }`;
164
+ const looksLikeSha = /^[a-f0-9]{40}$/i.test(ref);
165
+ const oidArg = looksLikeSha ? ref : "0000000000000000000000000000000000000000";
166
+ const response = await (0, import_http_request.httpRequest)(GITHUB_GRAPHQL_URL, {
167
+ body: (0, import_primordials.JSONStringify)({
168
+ query,
169
+ variables: {
170
+ branch: `refs/heads/${ref}`,
171
+ oid: oidArg,
172
+ owner,
173
+ repo,
174
+ tag: `refs/tags/${ref}`
175
+ }
176
+ }),
177
+ headers,
178
+ method: "POST"
179
+ });
180
+ if (!response.ok || response.body.byteLength === 0) {
181
+ return void 0;
182
+ }
183
+ let parsed;
184
+ try {
185
+ parsed = (0, import_primordials.JSONParse)(response.body.toString("utf8"));
186
+ } catch {
187
+ return void 0;
188
+ }
189
+ const repoData = parsed.data?.repository;
190
+ if (!repoData) {
191
+ return void 0;
192
+ }
193
+ const tagTarget = repoData.tagRef?.target;
194
+ if (tagTarget) {
195
+ if (tagTarget.__typename === "Tag") {
196
+ return tagTarget.target?.oid ?? void 0;
197
+ }
198
+ if (tagTarget.__typename === "Commit") {
199
+ return tagTarget.oid ?? void 0;
200
+ }
201
+ }
202
+ const branchOid = repoData.branchRef?.target?.oid;
203
+ if (branchOid) {
204
+ return branchOid;
205
+ }
206
+ if (repoData.commit?.__typename === "Commit" && repoData.commit.oid) {
207
+ return repoData.commit.oid;
208
+ }
209
+ return void 0;
210
+ }
90
211
  function getGithubCache() {
91
212
  if (_githubCache === void 0) {
92
213
  _githubCache = (0, import_cache_with_ttl.createTtlCache)({
@@ -114,20 +235,120 @@ async function clearRefCache() {
114
235
  }
115
236
  async function fetchGhsaDetails(ghsaId, options) {
116
237
  const url = `https://api.github.com/advisories/${ghsaId}`;
117
- const data = await fetchGitHub(url, options);
238
+ try {
239
+ const data = await fetchGitHub(url, options);
240
+ return {
241
+ ghsaId: data.ghsa_id,
242
+ summary: data.summary,
243
+ details: data.details,
244
+ severity: data.severity,
245
+ aliases: data.aliases || [],
246
+ publishedAt: data.published_at,
247
+ updatedAt: data.updated_at,
248
+ withdrawnAt: data.withdrawn_at,
249
+ references: data.references || [],
250
+ vulnerabilities: data.vulnerabilities || [],
251
+ cvss: data.cvss,
252
+ cwes: data.cwes || []
253
+ };
254
+ } catch (e) {
255
+ if (e instanceof GitHubEmptyBodyError) {
256
+ try {
257
+ return await fetchGhsaDetailsViaGraphQL(ghsaId, options);
258
+ } catch (cause) {
259
+ throw new import_primordials.ErrorCtor(
260
+ `Failed to fetch advisory ${ghsaId}: both REST and GraphQL backends degraded`,
261
+ { cause }
262
+ );
263
+ }
264
+ }
265
+ throw e;
266
+ }
267
+ }
268
+ async function fetchGhsaDetailsViaGraphQL(ghsaId, options) {
269
+ const opts = { __proto__: null, ...options };
270
+ const token = opts.token || getGitHubToken();
271
+ const headers = {
272
+ Accept: "application/vnd.github.v3+json",
273
+ "Content-Type": "application/json",
274
+ "User-Agent": "socket-registry-github-client",
275
+ ...opts.headers
276
+ };
277
+ if (token) {
278
+ headers["Authorization"] = `Bearer ${token}`;
279
+ }
280
+ const query = `query($ghsaId: String!) {
281
+ securityAdvisory(ghsaId: $ghsaId) {
282
+ ghsaId
283
+ summary
284
+ description
285
+ severity
286
+ publishedAt
287
+ updatedAt
288
+ withdrawnAt
289
+ cvss { score vectorString }
290
+ cwes(first: 50) { nodes { cweId name description } }
291
+ references { url }
292
+ vulnerabilities(first: 100) {
293
+ nodes {
294
+ package { ecosystem name }
295
+ vulnerableVersionRange
296
+ firstPatchedVersion { identifier }
297
+ }
298
+ }
299
+ identifiers { type value }
300
+ }
301
+ }`;
302
+ const response = await (0, import_http_request.httpRequest)(GITHUB_GRAPHQL_URL, {
303
+ body: (0, import_primordials.JSONStringify)({ query, variables: { ghsaId } }),
304
+ headers,
305
+ method: "POST"
306
+ });
307
+ if (!response.ok) {
308
+ throw new import_primordials.ErrorCtor(
309
+ `GitHub GraphQL API error ${response.status}: ${response.statusText}`
310
+ );
311
+ }
312
+ if (response.body.byteLength === 0) {
313
+ throw new GitHubEmptyBodyError(GITHUB_GRAPHQL_URL);
314
+ }
315
+ let parsed;
316
+ try {
317
+ parsed = (0, import_primordials.JSONParse)(response.body.toString("utf8"));
318
+ } catch (cause) {
319
+ throw new import_primordials.ErrorCtor(
320
+ `Failed to parse GitHub GraphQL response for advisory ${ghsaId}`,
321
+ { cause }
322
+ );
323
+ }
324
+ if (parsed.errors?.length) {
325
+ throw new import_primordials.ErrorCtor(
326
+ `GraphQL securityAdvisory(${ghsaId}) returned errors: ${parsed.errors.map((e) => e.message).join("; ")}`
327
+ );
328
+ }
329
+ const adv = parsed.data?.securityAdvisory;
330
+ if (!adv) {
331
+ throw new import_primordials.ErrorCtor(`GHSA ${ghsaId} not found`);
332
+ }
118
333
  return {
119
- ghsaId: data.ghsa_id,
120
- summary: data.summary,
121
- details: data.details,
122
- severity: data.severity,
123
- aliases: data.aliases || [],
124
- publishedAt: data.published_at,
125
- updatedAt: data.updated_at,
126
- withdrawnAt: data.withdrawn_at,
127
- references: data.references || [],
128
- vulnerabilities: data.vulnerabilities || [],
129
- cvss: data.cvss,
130
- cwes: data.cwes || []
334
+ ghsaId: adv.ghsaId,
335
+ summary: adv.summary,
336
+ details: adv.description,
337
+ // REST returns severity lowercase ("moderate"); GraphQL uppercases
338
+ // ("MODERATE"). Normalize so callers can compare against a single
339
+ // canonical form regardless of which transport ran.
340
+ severity: adv.severity.toLowerCase(),
341
+ // REST `aliases` is the list of non-GHSA identifiers (CVE ids,
342
+ // typically). GraphQL `identifiers` includes the advisory's own
343
+ // GHSA id alongside CVE ids; filter it out to match REST shape.
344
+ aliases: adv.identifiers?.filter((i) => i.type !== "GHSA").map((i) => i.value) ?? [],
345
+ publishedAt: adv.publishedAt,
346
+ updatedAt: adv.updatedAt,
347
+ withdrawnAt: adv.withdrawnAt ?? "",
348
+ references: adv.references ?? [],
349
+ vulnerabilities: adv.vulnerabilities?.nodes ?? [],
350
+ cvss: adv.cvss ?? null,
351
+ cwes: adv.cwes?.nodes ?? []
131
352
  };
132
353
  }
133
354
  async function fetchGitHub(url, options) {
@@ -149,8 +370,8 @@ async function fetchGitHub(url, options) {
149
370
  if (rateLimitStr === "0") {
150
371
  const resetTime = response.headers["x-ratelimit-reset"];
151
372
  const resetTimeStr = typeof resetTime === "string" ? resetTime : resetTime?.[0];
152
- const resetDate = resetTimeStr ? new Date(Number(resetTimeStr) * 1e3) : void 0;
153
- const error = new Error(
373
+ const resetDate = resetTimeStr ? new import_primordials.DateCtor(Number(resetTimeStr) * 1e3) : void 0;
374
+ const error = new import_primordials.ErrorCtor(
154
375
  `GitHub API rate limit exceeded${resetDate ? `. Resets at ${resetDate.toLocaleString()}` : ""}. Use GITHUB_TOKEN environment variable to increase rate limit.`
155
376
  );
156
377
  error.status = 403;
@@ -158,14 +379,17 @@ async function fetchGitHub(url, options) {
158
379
  throw error;
159
380
  }
160
381
  }
161
- throw new Error(
382
+ throw new import_primordials.ErrorCtor(
162
383
  `GitHub API error ${response.status}: ${response.statusText}`
163
384
  );
164
385
  }
386
+ if (response.body.byteLength === 0) {
387
+ throw new GitHubEmptyBodyError(url);
388
+ }
165
389
  try {
166
- return JSON.parse(response.body.toString("utf8"));
390
+ return (0, import_primordials.JSONParse)(response.body.toString("utf8"));
167
391
  } catch (e) {
168
- throw new Error(
392
+ throw new import_primordials.ErrorCtor(
169
393
  `Failed to parse GitHub API response: ${(0, import_errors.errorMessage)(e)}
170
394
  URL: ${url}
171
395
  Response may be malformed or incomplete.`,
@@ -211,6 +435,7 @@ async function resolveRefToSha(owner, repo, ref, options) {
211
435
  }
212
436
  // Annotate the CommonJS export names for ESM import in node:
213
437
  0 && (module.exports = {
438
+ GitHubEmptyBodyError,
214
439
  cacheFetchGhsa,
215
440
  clearRefCache,
216
441
  fetchGhsaDetails,
package/dist/globs.d.ts CHANGED
@@ -32,6 +32,16 @@ export interface GlobOptions extends FastGlobOptions {
32
32
  recursive?: boolean;
33
33
  }
34
34
  export type { Pattern, FastGlobOptions };
35
+ /**
36
+ * Resolve `path.matchesGlob` (or `undefined` if the runtime predates
37
+ * it). Probes once and caches the result for every subsequent call.
38
+ *
39
+ * Used by `getGlobMatcher`'s narrow fast-path — see the conditions
40
+ * spelled out at the call site. Exported for unit tests.
41
+ *
42
+ * @internal
43
+ */
44
+ export declare function getMatchesGlob(): ((p: string, pattern: string) => boolean) | undefined;
35
45
  export declare const defaultIgnore: readonly string[];
36
46
  /**
37
47
  * Return a glob-matcher function, memoized by pattern + options.
@@ -73,6 +83,16 @@ export declare function getGlobMatcher(glob: Pattern | Pattern[], options?: {
73
83
  * console.log(files) // ['src/index.ts', 'src/utils.ts']
74
84
  * ```
75
85
  */
86
+ /**
87
+ * Whether the caller's option bag is fully expressible with
88
+ * `node:fs.glob` (`cwd` + `exclude`). Any other option means we must
89
+ * fall back to fast-glob, which exposes the wider surface.
90
+ *
91
+ * Exported for unit tests; not part of the public API.
92
+ *
93
+ * @internal
94
+ */
95
+ export declare function canUseNodeFsGlob(options: FastGlobOptions | undefined): boolean;
76
96
  export declare function glob(patterns: Pattern | Pattern[], options?: FastGlobOptions): Promise<string[]>;
77
97
  /**
78
98
  * Create a stream of license file paths matching glob patterns.
package/dist/globs.js CHANGED
@@ -20,8 +20,10 @@ var __copyProps = (to, from, except, desc) => {
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
  var globs_exports = {};
22
22
  __export(globs_exports, {
23
+ canUseNodeFsGlob: () => canUseNodeFsGlob,
23
24
  defaultIgnore: () => defaultIgnore,
24
25
  getGlobMatcher: () => getGlobMatcher,
26
+ getMatchesGlob: () => getMatchesGlob,
25
27
  glob: () => glob,
26
28
  globStreamLicenses: () => globStreamLicenses,
27
29
  globSync: () => globSync
@@ -29,10 +31,42 @@ __export(globs_exports, {
29
31
  module.exports = __toCommonJS(globs_exports);
30
32
  var import_objects = require("./objects");
31
33
  var import_globs = require("./paths/globs");
34
+ var import_normalize = require("./paths/normalize");
35
+ var import_promises = require("./promises");
36
+ var import_primordials = require("./primordials");
32
37
  let _fastGlob;
38
+ let _fs;
39
+ let _fsPromises;
33
40
  let _picomatch;
41
+ let _matchesGlob;
42
+ let _matchesGlobProbed = false;
43
+ // @__NO_SIDE_EFFECTS__
44
+ function getFs() {
45
+ if (_fs === void 0) {
46
+ _fs = require("node:fs");
47
+ }
48
+ return _fs;
49
+ }
50
+ // @__NO_SIDE_EFFECTS__
51
+ function getFsPromises() {
52
+ if (_fsPromises === void 0) {
53
+ _fsPromises = require("node:fs/promises");
54
+ }
55
+ return _fsPromises;
56
+ }
57
+ // @__NO_SIDE_EFFECTS__
58
+ function getMatchesGlob() {
59
+ if (!_matchesGlobProbed) {
60
+ const fn = require("node:path").matchesGlob;
61
+ if (typeof fn === "function") {
62
+ _matchesGlob = fn;
63
+ }
64
+ _matchesGlobProbed = true;
65
+ }
66
+ return _matchesGlob;
67
+ }
34
68
  const MATCHER_CACHE_MAX_SIZE = 100;
35
- const matcherCache = /* @__PURE__ */ new Map();
69
+ const matcherCache = new import_primordials.MapCtor();
36
70
  const defaultIgnore = (0, import_objects.objectFreeze)([
37
71
  // Most of these ignored files can be included specifically if included in the
38
72
  // files globs. Exceptions to this are:
@@ -80,6 +114,30 @@ function getFastGlob() {
80
114
  }
81
115
  return _fastGlob;
82
116
  }
117
+ function stripTrailingSlash(pattern) {
118
+ if (pattern.length > 1 && (0, import_primordials.StringPrototypeCharCodeAt)(pattern, pattern.length - 1) === 47) {
119
+ return pattern.slice(0, -1);
120
+ }
121
+ return pattern;
122
+ }
123
+ function normalizeGlobResults(out) {
124
+ for (let i = 0; i < out.length; i += 1) {
125
+ out[i] = (0, import_normalize.normalizePath)(out[i]);
126
+ }
127
+ return out;
128
+ }
129
+ function normalizeIgnorePatterns(ignore) {
130
+ if (!(0, import_primordials.ArrayIsArray)(ignore)) {
131
+ return void 0;
132
+ }
133
+ const source = ignore;
134
+ const { length } = source;
135
+ const normalized = new import_primordials.ArrayCtor(length);
136
+ for (let i = 0; i < length; i++) {
137
+ normalized[i] = stripTrailingSlash(source[i]);
138
+ }
139
+ return normalized;
140
+ }
83
141
  // @__NO_SIDE_EFFECTS__
84
142
  function getPicomatch() {
85
143
  if (_picomatch === void 0) {
@@ -89,12 +147,12 @@ function getPicomatch() {
89
147
  }
90
148
  // @__NO_SIDE_EFFECTS__
91
149
  function getGlobMatcher(glob2, options) {
92
- const patterns = Array.isArray(glob2) ? glob2 : [glob2];
150
+ const patterns = (0, import_primordials.ArrayIsArray)(glob2) ? glob2 : [glob2];
93
151
  const sortedPatterns = [...patterns].sort();
94
- const sortedOptions = options ? Object.keys(options).sort().map((k) => {
152
+ const sortedOptions = options ? (0, import_primordials.ObjectKeys)(options).sort().map((k) => {
95
153
  const value = options[k];
96
- const normalized = Array.isArray(value) ? [...value].sort() : value;
97
- return `${k}:${JSON.stringify(normalized)}`;
154
+ const normalized = (0, import_primordials.ArrayIsArray)(value) ? [...value].sort() : value;
155
+ return `${k}:${(0, import_primordials.JSONStringify)(normalized)}`;
98
156
  }).join(",") : "";
99
157
  const key = `${sortedPatterns.join("|")}:${sortedOptions}`;
100
158
  const existing = matcherCache.get(key);
@@ -109,26 +167,63 @@ function getGlobMatcher(glob2, options) {
109
167
  matcherCache.delete(oldest);
110
168
  }
111
169
  }
112
- const positivePatterns = patterns.filter((p) => !p.startsWith("!"));
113
- const negativePatterns = patterns.filter((p) => p.startsWith("!")).map((p) => p.slice(1));
114
- const matchOptions = {
115
- dot: true,
116
- nocase: true,
117
- ...options,
118
- ...negativePatterns.length > 0 ? { ignore: negativePatterns } : {}
119
- };
120
- const picomatch = /* @__PURE__ */ getPicomatch();
121
- const matcher = picomatch(
122
- positivePatterns.length > 0 ? positivePatterns : patterns,
123
- matchOptions
124
- );
170
+ let matcher;
171
+ if (patterns.length === 1 && !(0, import_primordials.StringPrototypeStartsWith)(patterns[0], "!") && options !== void 0 && options.nocase === false && options.dot === false && (options.ignore === void 0 || options.ignore.length === 0)) {
172
+ const matchesGlob = /* @__PURE__ */ getMatchesGlob();
173
+ if (matchesGlob !== void 0) {
174
+ const pattern = patterns[0];
175
+ matcher = (p) => matchesGlob(p, pattern);
176
+ }
177
+ }
178
+ if (matcher === void 0) {
179
+ const positivePatterns = patterns.filter(
180
+ (p) => !(0, import_primordials.StringPrototypeStartsWith)(p, "!")
181
+ );
182
+ const negativePatterns = patterns.filter((p) => (0, import_primordials.StringPrototypeStartsWith)(p, "!")).map((p) => p.slice(1));
183
+ const matchOptions = {
184
+ dot: true,
185
+ nocase: true,
186
+ ...options,
187
+ ...negativePatterns.length > 0 ? { ignore: negativePatterns } : {}
188
+ };
189
+ const picomatch = /* @__PURE__ */ getPicomatch();
190
+ matcher = picomatch(
191
+ positivePatterns.length > 0 ? positivePatterns : patterns,
192
+ matchOptions
193
+ );
194
+ }
125
195
  matcherCache.set(key, matcher);
126
196
  return matcher;
127
197
  }
198
+ function canUseNodeFsGlob(options) {
199
+ if (!options) {
200
+ return true;
201
+ }
202
+ for (const key of (0, import_primordials.ObjectKeys)(options)) {
203
+ if (key !== "cwd" && key !== "ignore") {
204
+ return false;
205
+ }
206
+ }
207
+ return true;
208
+ }
128
209
  // @__NO_SIDE_EFFECTS__
129
- function glob(patterns, options) {
210
+ async function glob(patterns, options) {
211
+ const normalizedIgnore = normalizeIgnorePatterns(options?.ignore);
212
+ if (canUseNodeFsGlob(options)) {
213
+ const out2 = await (0, import_promises.fromAsync)(
214
+ (/* @__PURE__ */ getFsPromises()).glob(patterns, {
215
+ ...options?.cwd ? { cwd: options.cwd } : {},
216
+ ...normalizedIgnore ? { exclude: normalizedIgnore } : {}
217
+ })
218
+ );
219
+ return normalizeGlobResults(out2);
220
+ }
130
221
  const fastGlob = /* @__PURE__ */ getFastGlob();
131
- return fastGlob.glob(patterns, options);
222
+ const out = await fastGlob.glob(patterns, {
223
+ ...options,
224
+ ...normalizedIgnore ? { ignore: normalizedIgnore } : {}
225
+ });
226
+ return normalizeGlobResults(out);
132
227
  }
133
228
  // @__NO_SIDE_EFFECTS__
134
229
  function globStreamLicenses(dirname, options) {
@@ -138,10 +233,8 @@ function globStreamLicenses(dirname, options) {
138
233
  recursive,
139
234
  ...globOptions
140
235
  } = { __proto__: null, ...options };
141
- const ignore = [
142
- ...Array.isArray(ignoreOpt) ? ignoreOpt : defaultIgnore,
143
- "**/*.{cjs,cts,js,json,mjs,mts,ts}"
144
- ];
236
+ const baseIgnore = (0, import_primordials.ArrayIsArray)(ignoreOpt) ? normalizeIgnorePatterns(ignoreOpt) : defaultIgnore;
237
+ const ignore = [...baseIgnore, "**/*.{cjs,cts,js,json,mjs,mts,ts}"];
145
238
  if (ignoreOriginals) {
146
239
  ignore.push(import_globs.LICENSE_ORIGINAL_GLOB_RECURSIVE);
147
240
  }
@@ -160,13 +253,29 @@ function globStreamLicenses(dirname, options) {
160
253
  }
161
254
  // @__NO_SIDE_EFFECTS__
162
255
  function globSync(patterns, options) {
256
+ const normalizedIgnore = normalizeIgnorePatterns(options?.ignore);
257
+ if (canUseNodeFsGlob(options)) {
258
+ return normalizeGlobResults([
259
+ ...(/* @__PURE__ */ getFs()).globSync(patterns, {
260
+ ...options?.cwd ? { cwd: options.cwd } : {},
261
+ ...normalizedIgnore ? { exclude: normalizedIgnore } : {}
262
+ })
263
+ ]);
264
+ }
163
265
  const fastGlob = /* @__PURE__ */ getFastGlob();
164
- return fastGlob.globSync(patterns, options);
266
+ return normalizeGlobResults(
267
+ fastGlob.globSync(patterns, {
268
+ ...options,
269
+ ...normalizedIgnore ? { ignore: normalizedIgnore } : {}
270
+ })
271
+ );
165
272
  }
166
273
  // Annotate the CommonJS export names for ESM import in node:
167
274
  0 && (module.exports = {
275
+ canUseNodeFsGlob,
168
276
  defaultIgnore,
169
277
  getGlobMatcher,
278
+ getMatchesGlob,
170
279
  glob,
171
280
  globStreamLicenses,
172
281
  globSync
@@ -905,9 +905,10 @@ export declare function parseChecksums(text: string): Checksums;
905
905
  *
906
906
  * @example
907
907
  * ```ts
908
- * const delay = parseRetryAfterHeader(response.headers['retry-after'])
909
- * if (delay !== undefined) {
910
- * await new Promise(resolve => setTimeout(resolve, delay))
908
+ * import { setTimeout as delay } from 'node:timers/promises'
909
+ * const ms = parseRetryAfterHeader(response.headers['retry-after'])
910
+ * if (ms !== undefined) {
911
+ * await delay(ms)
911
912
  * }
912
913
  * ```
913
914
  */