@socketsecurity/lib 5.26.0 → 5.26.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.
- package/CHANGELOG.md +345 -1185
- package/README.md +1 -1
- package/dist/abort.js +7 -6
- package/dist/agent.js +16 -15
- package/dist/ansi.js +3 -2
- package/dist/archives.js +18 -17
- package/dist/argv/flags.js +29 -28
- package/dist/argv/parse.js +4 -3
- package/dist/arrays.js +3 -2
- package/dist/bin.js +12 -11
- package/dist/cacache.js +16 -11
- package/dist/cache-with-ttl.js +26 -21
- package/dist/colors.js +2 -1
- package/dist/constants/licenses.js +2 -1
- package/dist/constants/lifecycle-script-names.js +2 -1
- package/dist/constants/maintained-node-versions.js +2 -1
- package/dist/constants/node.js +4 -3
- package/dist/constants/package-default-socket-categories.js +2 -1
- package/dist/constants/packages.js +4 -3
- package/dist/constants/socket.js +1 -1
- package/dist/cover/code.js +9 -8
- package/dist/cover/formatters.js +12 -11
- package/dist/cover/type.js +5 -4
- package/dist/crypto.d.ts +36 -0
- package/dist/{effects/ultra.js → crypto.js} +33 -37
- package/dist/debug.js +12 -15
- package/dist/dlx/arborist.js +10 -9
- package/dist/dlx/binary.js +27 -24
- package/dist/dlx/cache.js +2 -10
- package/dist/dlx/detect.js +6 -5
- package/dist/dlx/integrity.js +13 -11
- package/dist/dlx/lockfile.js +7 -6
- package/dist/dlx/manifest.js +6 -5
- package/dist/dlx/package.js +17 -16
- package/dist/dlx/packages.js +6 -5
- package/dist/dlx/paths.d.ts +1 -1
- package/dist/dlx/paths.js +2 -1
- package/dist/effects/pulse-frames.js +4 -3
- package/dist/effects/shimmer-keyframes.d.ts +62 -0
- package/dist/effects/shimmer-keyframes.js +55 -0
- package/dist/effects/shimmer-terminal.d.ts +66 -0
- package/dist/effects/shimmer-terminal.js +57 -0
- package/dist/effects/shimmer.d.ts +293 -0
- package/dist/effects/shimmer.js +180 -0
- package/dist/env/rewire.js +4 -3
- package/dist/env.js +5 -4
- package/dist/errors.js +1 -1
- package/dist/external/@npmcli/package-json/lib/read-package.js +10 -10
- package/dist/external/@npmcli/package-json.js +372 -372
- package/dist/external/@npmcli/promise-spawn.js +24 -24
- package/dist/external/@socketregistry/packageurl-js.js +19 -18
- package/dist/external/@socketregistry/yocto-spinner.js +4 -3
- package/dist/external/@yarnpkg/extensions.js +2 -1
- package/dist/external/adm-zip.js +70 -70
- package/dist/external/debug.js +22 -22
- package/dist/external/external-pack.js +45 -45
- package/dist/external/fast-sort.js +5 -5
- package/dist/external/libnpmexec.js +4 -3
- package/dist/external/npm-pack.js +369 -369
- package/dist/external/p-map.js +9 -9
- package/dist/external/pico-pack.js +190 -190
- package/dist/external/pony-cause.js +2 -1
- package/dist/external/spdx-pack.js +11 -10
- package/dist/external/tar-fs.js +58 -58
- package/dist/external/which.js +13 -13
- package/dist/external/yargs-parser.js +71 -71
- package/dist/fs.js +19 -23
- package/dist/git.js +14 -13
- package/dist/github.d.ts +34 -0
- package/dist/github.js +248 -23
- package/dist/globs.d.ts +20 -0
- package/dist/globs.js +134 -25
- package/dist/http-request.d.ts +4 -3
- package/dist/http-request.js +39 -32
- package/dist/ipc-cli.js +2 -1
- package/dist/ipc.js +5 -4
- package/dist/json/edit.js +4 -3
- package/dist/json/format.js +3 -2
- package/dist/json/parse.js +7 -6
- package/dist/links.js +2 -1
- package/dist/logger.js +21 -14
- package/dist/memoization.js +16 -15
- package/dist/objects.js +2 -2
- package/dist/packages/edit.js +8 -7
- package/dist/packages/exports.js +17 -16
- package/dist/packages/isolation.js +20 -13
- package/dist/packages/licenses.js +6 -3
- package/dist/packages/manifest.js +2 -1
- package/dist/packages/normalize.js +8 -4
- package/dist/packages/operations.js +5 -4
- package/dist/packages/provenance.js +7 -6
- package/dist/packages/specs.js +2 -1
- package/dist/packages/validation.js +2 -1
- package/dist/paths/normalize.js +32 -40
- package/dist/paths/packages.js +2 -1
- package/dist/paths/rewire.js +3 -2
- package/dist/performance.js +19 -18
- package/dist/primordials.d.ts +9 -0
- package/dist/primordials.js +17 -0
- package/dist/process-lock.js +14 -13
- package/dist/promise-queue.js +17 -9
- package/dist/promises.d.ts +29 -6
- package/dist/promises.js +19 -15
- package/dist/regexps.js +9 -8
- package/dist/releases/github-api.d.ts +56 -0
- package/dist/releases/github-api.js +275 -0
- package/dist/releases/github-archives.d.ts +60 -0
- package/dist/releases/github-archives.js +136 -0
- package/dist/releases/github-assets.d.ts +21 -0
- package/dist/releases/github-assets.js +52 -0
- package/dist/releases/github-auth.d.ts +16 -0
- package/dist/releases/github-auth.js +51 -0
- package/dist/releases/github-downloads.d.ts +42 -0
- package/dist/releases/github-downloads.js +155 -0
- package/dist/releases/github-types.d.ts +66 -0
- package/dist/{effects/types.js → releases/github-types.js} +2 -2
- package/dist/releases/socket-btm.d.ts +1 -1
- package/dist/releases/socket-btm.js +17 -17
- package/dist/schema/parse.js +2 -1
- package/dist/schema/validate.js +6 -5
- package/dist/shadow.js +2 -1
- package/dist/signal-exit.js +2 -2
- package/dist/spawn.js +45 -35
- package/dist/spinner.d.ts +13 -6
- package/dist/spinner.js +75 -57
- package/dist/ssri.js +8 -7
- package/dist/stdio/footer.js +13 -12
- package/dist/stdio/header.js +5 -4
- package/dist/stdio/progress.js +13 -12
- package/dist/strings.js +19 -18
- package/dist/suppress-warnings.js +2 -2
- package/dist/tables.js +16 -13
- package/dist/temporary-executor.js +2 -1
- package/dist/themes/context.js +2 -1
- package/dist/themes/types.d.ts +1 -1
- package/dist/themes/utils.d.ts +8 -3
- package/dist/themes/utils.js +29 -5
- package/dist/url.js +4 -3
- package/package.json +44 -20
- package/dist/effects/text-shimmer.d.ts +0 -58
- package/dist/effects/text-shimmer.js +0 -192
- package/dist/effects/types.d.ts +0 -47
- package/dist/effects/ultra.d.ts +0 -22
- package/dist/releases/github.d.ts +0 -234
- package/dist/releases/github.js +0 -417
- package/dist/themes/index.d.ts +0 -49
- package/dist/themes/index.js +0 -60
package/dist/git.js
CHANGED
|
@@ -52,13 +52,14 @@ var import_globs = require("./globs");
|
|
|
52
52
|
var import_normalize = require("./paths/normalize");
|
|
53
53
|
var import_spawn = require("./spawn");
|
|
54
54
|
var import_strings = require("./strings");
|
|
55
|
+
var import_primordials = require("./primordials");
|
|
55
56
|
let _fs;
|
|
56
57
|
let _path;
|
|
57
|
-
const gitDiffCache =
|
|
58
|
+
const gitDiffCache = new import_primordials.MapCtor();
|
|
58
59
|
const GIT_CACHE_MAX_SIZE = 100;
|
|
59
60
|
let _gitPath;
|
|
60
|
-
const realpathCache =
|
|
61
|
-
const gitRootCache =
|
|
61
|
+
const realpathCache = new import_primordials.MapCtor();
|
|
62
|
+
const gitRootCache = new import_primordials.MapCtor();
|
|
62
63
|
function getCachedGitDiff(key) {
|
|
63
64
|
const result = gitDiffCache.get(key);
|
|
64
65
|
if (result) {
|
|
@@ -68,7 +69,7 @@ function getCachedGitDiff(key) {
|
|
|
68
69
|
return result;
|
|
69
70
|
}
|
|
70
71
|
function stableKey(value) {
|
|
71
|
-
return
|
|
72
|
+
return (0, import_primordials.JSONStringify)(value, (_key, val) => {
|
|
72
73
|
if (val && typeof val === "object" && !Array.isArray(val)) {
|
|
73
74
|
const sorted = {};
|
|
74
75
|
for (const k of Object.keys(val).sort()) {
|
|
@@ -166,7 +167,7 @@ async function innerDiff(args, options) {
|
|
|
166
167
|
...args[2],
|
|
167
168
|
stdioString: false
|
|
168
169
|
});
|
|
169
|
-
const stdout =
|
|
170
|
+
const stdout = (0, import_primordials.BufferIsBuffer)(spawnResult.stdout) ? spawnResult.stdout.toString("utf8") : String(spawnResult.stdout);
|
|
170
171
|
const spawnCwd = typeof args[2]["cwd"] === "string" ? args[2]["cwd"] : void 0;
|
|
171
172
|
result = parseGitDiffStdout(stdout, parseOptions, spawnCwd);
|
|
172
173
|
} catch (e) {
|
|
@@ -196,7 +197,7 @@ function innerDiffSync(args, options) {
|
|
|
196
197
|
...args[2],
|
|
197
198
|
stdioString: false
|
|
198
199
|
});
|
|
199
|
-
const stdout =
|
|
200
|
+
const stdout = (0, import_primordials.BufferIsBuffer)(spawnResult.stdout) ? spawnResult.stdout.toString("utf8") : String(spawnResult.stdout);
|
|
200
201
|
const spawnCwd = typeof args[2]["cwd"] === "string" ? args[2]["cwd"] : void 0;
|
|
201
202
|
result = parseGitDiffStdout(stdout, parseOptions, spawnCwd);
|
|
202
203
|
} catch (e) {
|
|
@@ -225,7 +226,7 @@ function parseGitDiffStdout(stdout, options, spawnCwd) {
|
|
|
225
226
|
let rawFiles = stdout ? (0, import_strings.stripAnsi)(stdout).split(/\r?\n/).map((line) => line.trimEnd()).filter((line) => line) : [];
|
|
226
227
|
if (porcelain) {
|
|
227
228
|
rawFiles = rawFiles.map((line) => {
|
|
228
|
-
return line.length > 3 ?
|
|
229
|
+
return line.length > 3 ? (0, import_primordials.StringPrototypeSubstring)(line, 3) : line;
|
|
229
230
|
});
|
|
230
231
|
}
|
|
231
232
|
const files = absolute ? rawFiles.map((relPath2) => (0, import_normalize.normalizePath)(path.join(rootPath, relPath2))) : rawFiles.map((relPath2) => (0, import_normalize.normalizePath)(relPath2));
|
|
@@ -324,7 +325,7 @@ async function isChanged(pathname, options) {
|
|
|
324
325
|
const resolvedPathname = getCachedRealpath(pathname);
|
|
325
326
|
const baseCwd = options?.cwd ? getCachedRealpath(options["cwd"]) : getCwd();
|
|
326
327
|
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
327
|
-
return
|
|
328
|
+
return (0, import_primordials.ArrayPrototypeIncludes)(files, relativePath);
|
|
328
329
|
}
|
|
329
330
|
function isChangedSync(pathname, options) {
|
|
330
331
|
const files = getChangedFilesSync({
|
|
@@ -337,7 +338,7 @@ function isChangedSync(pathname, options) {
|
|
|
337
338
|
const resolvedPathname = getCachedRealpath(pathname);
|
|
338
339
|
const baseCwd = options?.cwd ? getCachedRealpath(options["cwd"]) : getCwd();
|
|
339
340
|
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
340
|
-
return
|
|
341
|
+
return (0, import_primordials.ArrayPrototypeIncludes)(files, relativePath);
|
|
341
342
|
} catch {
|
|
342
343
|
return false;
|
|
343
344
|
}
|
|
@@ -352,7 +353,7 @@ async function isStaged(pathname, options) {
|
|
|
352
353
|
const resolvedPathname = getCachedRealpath(pathname);
|
|
353
354
|
const baseCwd = options?.cwd ? getCachedRealpath(options["cwd"]) : getCwd();
|
|
354
355
|
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
355
|
-
return
|
|
356
|
+
return (0, import_primordials.ArrayPrototypeIncludes)(files, relativePath);
|
|
356
357
|
}
|
|
357
358
|
function isStagedSync(pathname, options) {
|
|
358
359
|
const files = getStagedFilesSync({
|
|
@@ -364,7 +365,7 @@ function isStagedSync(pathname, options) {
|
|
|
364
365
|
const resolvedPathname = getCachedRealpath(pathname);
|
|
365
366
|
const baseCwd = options?.cwd ? getCachedRealpath(options["cwd"]) : getCwd();
|
|
366
367
|
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
367
|
-
return
|
|
368
|
+
return (0, import_primordials.ArrayPrototypeIncludes)(files, relativePath);
|
|
368
369
|
}
|
|
369
370
|
async function isUnstaged(pathname, options) {
|
|
370
371
|
const files = await getUnstagedFiles({
|
|
@@ -376,7 +377,7 @@ async function isUnstaged(pathname, options) {
|
|
|
376
377
|
const resolvedPathname = getCachedRealpath(pathname);
|
|
377
378
|
const baseCwd = options?.cwd ? getCachedRealpath(options["cwd"]) : getCwd();
|
|
378
379
|
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
379
|
-
return
|
|
380
|
+
return (0, import_primordials.ArrayPrototypeIncludes)(files, relativePath);
|
|
380
381
|
}
|
|
381
382
|
function isUnstagedSync(pathname, options) {
|
|
382
383
|
const files = getUnstagedFilesSync({
|
|
@@ -388,7 +389,7 @@ function isUnstagedSync(pathname, options) {
|
|
|
388
389
|
const resolvedPathname = getCachedRealpath(pathname);
|
|
389
390
|
const baseCwd = options?.cwd ? getCachedRealpath(options["cwd"]) : getCwd();
|
|
390
391
|
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
391
|
-
return
|
|
392
|
+
return (0, import_primordials.ArrayPrototypeIncludes)(files, relativePath);
|
|
392
393
|
}
|
|
393
394
|
// Annotate the CommonJS export names for ESM import in node:
|
|
394
395
|
0 && (module.exports = {
|
package/dist/github.d.ts
CHANGED
|
@@ -21,6 +21,40 @@
|
|
|
21
21
|
* - Cache to minimize API calls
|
|
22
22
|
*/
|
|
23
23
|
import type { SpawnOptions } from './spawn';
|
|
24
|
+
/**
|
|
25
|
+
* Thrown by `fetchGitHub` when GitHub returns HTTP 200 OK with a
|
|
26
|
+
* zero-byte body — the "successful empty response" pattern.
|
|
27
|
+
*
|
|
28
|
+
* Why this exists (background for new contributors):
|
|
29
|
+
* GitHub's REST API has a documented failure mode that is *very*
|
|
30
|
+
* easy to miss in code review. During incidents where the search
|
|
31
|
+
* / Elasticsearch backing index is degraded (see GitHub status
|
|
32
|
+
* pages with titles like "search is degraded" or "Pull Requests
|
|
33
|
+
* degraded"), the REST `/repos/...` GET endpoints return:
|
|
34
|
+
* - HTTP status: 200 OK ← looks like success
|
|
35
|
+
* - Body: "" ← but the payload is empty
|
|
36
|
+
* - Headers: no Retry-After, no rate-limit signal, nothing
|
|
37
|
+
*
|
|
38
|
+
* Without a typed error, calling code does
|
|
39
|
+
* `JSON.parse(response.body.toString('utf8'))`
|
|
40
|
+
* on an empty string, which throws a confusing
|
|
41
|
+
* `SyntaxError: Unexpected end of JSON input`. That error has
|
|
42
|
+
* nothing to do with our code — but it's the only signal upstream
|
|
43
|
+
* sees. This class wraps that case in a *named* error so callers
|
|
44
|
+
* can `instanceof GitHubEmptyBodyError` and choose what to do:
|
|
45
|
+
* retry the same endpoint later, fall back to GraphQL (which uses
|
|
46
|
+
* a different backend and is unaffected by ES outages), or surface
|
|
47
|
+
* a clean message to the user.
|
|
48
|
+
*
|
|
49
|
+
* The HTTP status is hard-coded to 200 because that's *exactly*
|
|
50
|
+
* what makes this insidious — a real 4xx/5xx would already be
|
|
51
|
+
* handled by the rate-limit / status-code branch above.
|
|
52
|
+
*/
|
|
53
|
+
export declare class GitHubEmptyBodyError extends Error {
|
|
54
|
+
/** HTTP status (always 200 — that's what makes this case insidious). */
|
|
55
|
+
status: number;
|
|
56
|
+
constructor(url: string);
|
|
57
|
+
}
|
|
24
58
|
/**
|
|
25
59
|
* Options for GitHub API fetch requests.
|
|
26
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 (
|
|
83
|
-
|
|
84
|
-
|
|
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
|
-
|
|
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:
|
|
120
|
-
summary:
|
|
121
|
-
details:
|
|
122
|
-
severity
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
|
153
|
-
const error = new
|
|
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
|
|
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
|
|
390
|
+
return (0, import_primordials.JSONParse)(response.body.toString("utf8"));
|
|
167
391
|
} catch (e) {
|
|
168
|
-
throw new
|
|
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.
|