@socketsecurity/lib 5.6.0 → 5.8.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.
- package/CHANGELOG.md +92 -2
- package/README.md +190 -18
- package/dist/archives.d.ts +58 -0
- package/dist/archives.js +313 -0
- package/dist/arrays.js +2 -3
- package/dist/cache-with-ttl.js +25 -6
- package/dist/constants/node.js +2 -1
- package/dist/cover/formatters.js +5 -3
- package/dist/dlx/binary.d.ts +20 -0
- package/dist/dlx/binary.js +115 -99
- package/dist/dlx/detect.d.ts +8 -8
- package/dist/dlx/detect.js +18 -18
- package/dist/dlx/manifest.d.ts +32 -31
- package/dist/dlx/manifest.js +114 -112
- package/dist/dlx/package.d.ts +55 -0
- package/dist/dlx/package.js +90 -80
- package/dist/env/ci.js +1 -2
- package/dist/env/rewire.d.ts +33 -22
- package/dist/env/rewire.js +20 -7
- package/dist/env/socket-cli.d.ts +24 -24
- package/dist/env/socket-cli.js +12 -12
- package/dist/env/temp-dir.d.ts +6 -6
- package/dist/env/temp-dir.js +4 -4
- package/dist/env/windows.d.ts +6 -6
- package/dist/env/windows.js +4 -4
- package/dist/external/@npmcli/package-json.js +352 -824
- package/dist/external/adm-zip.js +2695 -0
- package/dist/external/debug.js +183 -7
- package/dist/external/external-pack.js +19 -1409
- package/dist/external/libnpmexec.js +2 -2
- package/dist/external/npm-pack.js +18777 -19997
- package/dist/external/pico-pack.js +29 -5
- package/dist/external/spdx-pack.js +41 -263
- package/dist/external/tar-fs.js +3053 -0
- package/dist/git.js +22 -4
- package/dist/github.js +17 -9
- package/dist/globs.js +20 -1
- package/dist/http-request.js +1 -1
- package/dist/memoization.js +22 -13
- package/dist/package-extensions.js +4 -2
- package/dist/packages/normalize.js +3 -0
- package/dist/packages/specs.js +1 -1
- package/dist/process-lock.js +4 -2
- package/dist/releases/github.d.ts +55 -4
- package/dist/releases/github.js +203 -101
- package/dist/spawn.js +1 -1
- package/dist/spinner.js +1 -1
- package/dist/stdio/progress.js +2 -2
- package/package.json +38 -15
package/dist/git.js
CHANGED
|
@@ -56,6 +56,16 @@ function getPath() {
|
|
|
56
56
|
return _path;
|
|
57
57
|
}
|
|
58
58
|
const gitDiffCache = /* @__PURE__ */ new Map();
|
|
59
|
+
const gitDiffAccessOrder = [];
|
|
60
|
+
const GIT_CACHE_MAX_SIZE = 100;
|
|
61
|
+
function evictLRUGitCache() {
|
|
62
|
+
if (gitDiffCache.size >= GIT_CACHE_MAX_SIZE && gitDiffAccessOrder.length > 0) {
|
|
63
|
+
const oldest = gitDiffAccessOrder.shift();
|
|
64
|
+
if (oldest) {
|
|
65
|
+
gitDiffCache.delete(oldest);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
59
69
|
function getGitPath() {
|
|
60
70
|
return "git";
|
|
61
71
|
}
|
|
@@ -114,7 +124,9 @@ async function innerDiff(args, options) {
|
|
|
114
124
|
return [];
|
|
115
125
|
}
|
|
116
126
|
if (cache && cacheKey) {
|
|
127
|
+
evictLRUGitCache();
|
|
117
128
|
gitDiffCache.set(cacheKey, result);
|
|
129
|
+
gitDiffAccessOrder.push(cacheKey);
|
|
118
130
|
}
|
|
119
131
|
return result;
|
|
120
132
|
}
|
|
@@ -144,7 +156,9 @@ function innerDiffSync(args, options) {
|
|
|
144
156
|
return [];
|
|
145
157
|
}
|
|
146
158
|
if (cache && cacheKey) {
|
|
159
|
+
evictLRUGitCache();
|
|
147
160
|
gitDiffCache.set(cacheKey, result);
|
|
161
|
+
gitDiffAccessOrder.push(cacheKey);
|
|
148
162
|
}
|
|
149
163
|
return result;
|
|
150
164
|
}
|
|
@@ -256,10 +270,14 @@ function isChangedSync(pathname, options) {
|
|
|
256
270
|
});
|
|
257
271
|
const fs = /* @__PURE__ */ getFs();
|
|
258
272
|
const path = /* @__PURE__ */ getPath();
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
273
|
+
try {
|
|
274
|
+
const resolvedPathname = fs.realpathSync(pathname);
|
|
275
|
+
const baseCwd = options?.cwd ? fs.realpathSync(options["cwd"]) : getCwd();
|
|
276
|
+
const relativePath = (0, import_normalize.normalizePath)(path.relative(baseCwd, resolvedPathname));
|
|
277
|
+
return files.includes(relativePath);
|
|
278
|
+
} catch {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
263
281
|
}
|
|
264
282
|
async function isUnstaged(pathname, options) {
|
|
265
283
|
const files = await getUnstagedFiles({
|
package/dist/github.js
CHANGED
|
@@ -83,7 +83,16 @@ async function fetchGitHub(url, options) {
|
|
|
83
83
|
`GitHub API error ${response.status}: ${response.statusText}`
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
|
-
|
|
86
|
+
try {
|
|
87
|
+
return JSON.parse(response.body.toString("utf8"));
|
|
88
|
+
} catch (error) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
`Failed to parse GitHub API response: ${error instanceof Error ? error.message : String(error)}
|
|
91
|
+
URL: ${url}
|
|
92
|
+
Response may be malformed or incomplete.`,
|
|
93
|
+
{ cause: error }
|
|
94
|
+
);
|
|
95
|
+
}
|
|
87
96
|
}
|
|
88
97
|
async function resolveRefToSha(owner, repo, ref, options) {
|
|
89
98
|
const opts = {
|
|
@@ -180,15 +189,14 @@ async function fetchGhsaDetails(ghsaId, options) {
|
|
|
180
189
|
async function cacheFetchGhsa(ghsaId, options) {
|
|
181
190
|
const cache = getGithubCache();
|
|
182
191
|
const key = `ghsa:${ghsaId}`;
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
-
if (cached) {
|
|
186
|
-
return JSON.parse(cached);
|
|
187
|
-
}
|
|
192
|
+
if (process.env["DISABLE_GITHUB_CACHE"]) {
|
|
193
|
+
return await fetchGhsaDetails(ghsaId, options);
|
|
188
194
|
}
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
195
|
+
const cached = await cache.getOrFetch(key, async () => {
|
|
196
|
+
const data = await fetchGhsaDetails(ghsaId, options);
|
|
197
|
+
return JSON.stringify(data);
|
|
198
|
+
});
|
|
199
|
+
return JSON.parse(cached);
|
|
192
200
|
}
|
|
193
201
|
// Annotate the CommonJS export names for ESM import in node:
|
|
194
202
|
0 && (module.exports = {
|
package/dist/globs.js
CHANGED
|
@@ -107,15 +107,33 @@ function globStreamLicenses(dirname, options) {
|
|
|
107
107
|
}
|
|
108
108
|
);
|
|
109
109
|
}
|
|
110
|
+
const MATCHER_CACHE_MAX_SIZE = 100;
|
|
110
111
|
const matcherCache = /* @__PURE__ */ new Map();
|
|
112
|
+
const matcherAccessOrder = [];
|
|
113
|
+
function evictLRUMatcher() {
|
|
114
|
+
if (matcherCache.size >= MATCHER_CACHE_MAX_SIZE && matcherAccessOrder.length > 0) {
|
|
115
|
+
const oldest = matcherAccessOrder.shift();
|
|
116
|
+
if (oldest) {
|
|
117
|
+
matcherCache.delete(oldest);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
111
121
|
// @__NO_SIDE_EFFECTS__
|
|
112
122
|
function getGlobMatcher(glob2, options) {
|
|
113
123
|
const patterns = Array.isArray(glob2) ? glob2 : [glob2];
|
|
114
|
-
const
|
|
124
|
+
const sortedPatterns = [...patterns].sort();
|
|
125
|
+
const sortedOptions = options ? Object.keys(options).sort().map((k) => `${k}:${JSON.stringify(options[k])}`).join(",") : "";
|
|
126
|
+
const key = `${sortedPatterns.join("|")}:${sortedOptions}`;
|
|
115
127
|
let matcher = matcherCache.get(key);
|
|
116
128
|
if (matcher) {
|
|
129
|
+
const index = matcherAccessOrder.indexOf(key);
|
|
130
|
+
if (index !== -1) {
|
|
131
|
+
matcherAccessOrder.splice(index, 1);
|
|
132
|
+
matcherAccessOrder.push(key);
|
|
133
|
+
}
|
|
117
134
|
return matcher;
|
|
118
135
|
}
|
|
136
|
+
evictLRUMatcher();
|
|
119
137
|
const positivePatterns = patterns.filter((p) => !p.startsWith("!"));
|
|
120
138
|
const negativePatterns = patterns.filter((p) => p.startsWith("!")).map((p) => p.slice(1));
|
|
121
139
|
const matchOptions = {
|
|
@@ -129,6 +147,7 @@ function getGlobMatcher(glob2, options) {
|
|
|
129
147
|
matchOptions
|
|
130
148
|
);
|
|
131
149
|
matcherCache.set(key, matcher);
|
|
150
|
+
matcherAccessOrder.push(key);
|
|
132
151
|
return matcher;
|
|
133
152
|
}
|
|
134
153
|
// @__NO_SIDE_EFFECTS__
|
package/dist/http-request.js
CHANGED
|
@@ -299,7 +299,7 @@ async function httpDownload(url, destPath, options) {
|
|
|
299
299
|
} else if (logger) {
|
|
300
300
|
let lastPercent = 0;
|
|
301
301
|
progressCallback = (downloaded, total) => {
|
|
302
|
-
const percent = Math.floor(downloaded / total * 100);
|
|
302
|
+
const percent = total === 0 ? 0 : Math.floor(downloaded / total * 100);
|
|
303
303
|
if (percent >= lastPercent + progressInterval) {
|
|
304
304
|
logger.log(
|
|
305
305
|
` Progress: ${percent}% (${(downloaded / 1024 / 1024).toFixed(1)} MB / ${(total / 1024 / 1024).toFixed(1)} MB)`
|
package/dist/memoization.js
CHANGED
|
@@ -36,6 +36,9 @@ function memoize(fn, options = {}) {
|
|
|
36
36
|
name = fn.name || "anonymous",
|
|
37
37
|
ttl = Number.POSITIVE_INFINITY
|
|
38
38
|
} = options;
|
|
39
|
+
if (ttl < 0) {
|
|
40
|
+
throw new TypeError("TTL must be non-negative");
|
|
41
|
+
}
|
|
39
42
|
const cache = /* @__PURE__ */ new Map();
|
|
40
43
|
const accessOrder = [];
|
|
41
44
|
function evictLRU() {
|
|
@@ -123,7 +126,24 @@ function memoizeAsync(fn, options = {}) {
|
|
|
123
126
|
return await cached.value;
|
|
124
127
|
}
|
|
125
128
|
(0, import_debug.debugLog)(`[memoizeAsync:${name}] miss`, { key });
|
|
126
|
-
const promise = fn(...args)
|
|
129
|
+
const promise = fn(...args).then(
|
|
130
|
+
(result) => {
|
|
131
|
+
const entry = cache.get(key);
|
|
132
|
+
if (entry) {
|
|
133
|
+
entry.value = Promise.resolve(result);
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
},
|
|
137
|
+
(error) => {
|
|
138
|
+
cache.delete(key);
|
|
139
|
+
const index = accessOrder.indexOf(key);
|
|
140
|
+
if (index !== -1) {
|
|
141
|
+
accessOrder.splice(index, 1);
|
|
142
|
+
}
|
|
143
|
+
(0, import_debug.debugLog)(`[memoizeAsync:${name}] error`, { key, error });
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
);
|
|
127
147
|
evictLRU();
|
|
128
148
|
cache.set(key, {
|
|
129
149
|
value: promise,
|
|
@@ -132,18 +152,7 @@ function memoizeAsync(fn, options = {}) {
|
|
|
132
152
|
});
|
|
133
153
|
accessOrder.push(key);
|
|
134
154
|
(0, import_debug.debugLog)(`[memoizeAsync:${name}] set`, { key, cacheSize: cache.size });
|
|
135
|
-
|
|
136
|
-
const result = await promise;
|
|
137
|
-
return result;
|
|
138
|
-
} catch (e) {
|
|
139
|
-
cache.delete(key);
|
|
140
|
-
const orderIndex = accessOrder.indexOf(key);
|
|
141
|
-
if (orderIndex !== -1) {
|
|
142
|
-
accessOrder.splice(orderIndex, 1);
|
|
143
|
-
}
|
|
144
|
-
(0, import_debug.debugLog)(`[memoizeAsync:${name}] clear`, { key, reason: "error" });
|
|
145
|
-
throw e;
|
|
146
|
-
}
|
|
155
|
+
return await promise;
|
|
147
156
|
};
|
|
148
157
|
}
|
|
149
158
|
function Memoize(options = {}) {
|
|
@@ -64,8 +64,10 @@ const packageExtensions = ObjectFreeze(
|
|
|
64
64
|
}
|
|
65
65
|
]
|
|
66
66
|
].sort((a_, b_) => {
|
|
67
|
-
const
|
|
68
|
-
const
|
|
67
|
+
const aIndex = a_[0].lastIndexOf("@");
|
|
68
|
+
const bIndex = b_[0].lastIndexOf("@");
|
|
69
|
+
const a = aIndex === -1 ? a_[0] : a_[0].slice(0, aIndex);
|
|
70
|
+
const b = bIndex === -1 ? b_[0] : b_[0].slice(0, bIndex);
|
|
69
71
|
if (a < b) {
|
|
70
72
|
return -1;
|
|
71
73
|
}
|
|
@@ -91,6 +91,9 @@ function resolveOriginalPackageName(sockRegPkgName) {
|
|
|
91
91
|
}
|
|
92
92
|
// @__NO_SIDE_EFFECTS__
|
|
93
93
|
function unescapeScope(escapedScope) {
|
|
94
|
+
if (escapedScope.length < import_socket.REGISTRY_SCOPE_DELIMITER.length) {
|
|
95
|
+
return `@${escapedScope}`;
|
|
96
|
+
}
|
|
94
97
|
return `@${escapedScope.slice(0, -import_socket.REGISTRY_SCOPE_DELIMITER.length)}`;
|
|
95
98
|
}
|
|
96
99
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/packages/specs.js
CHANGED
|
@@ -43,7 +43,7 @@ var import_strings = require("../strings");
|
|
|
43
43
|
function getRepoUrlDetails(repoUrl = "") {
|
|
44
44
|
const userAndRepo = repoUrl.replace(/^.+github.com\//, "").split("/");
|
|
45
45
|
const user = userAndRepo[0] || "";
|
|
46
|
-
const project = userAndRepo.length > 1 ? userAndRepo[1]?.slice(0, -
|
|
46
|
+
const project = userAndRepo.length > 1 ? (userAndRepo[1]?.endsWith(".git") ? userAndRepo[1].slice(0, -4) : userAndRepo[1]) || "" : "";
|
|
47
47
|
return { user, project };
|
|
48
48
|
}
|
|
49
49
|
// @__NO_SIDE_EFFECTS__
|
package/dist/process-lock.js
CHANGED
|
@@ -204,7 +204,8 @@ class ProcessLockManager {
|
|
|
204
204
|
);
|
|
205
205
|
}
|
|
206
206
|
if (code === "ENOTDIR") {
|
|
207
|
-
const
|
|
207
|
+
const lastSlashIndex = lockPath.lastIndexOf("/");
|
|
208
|
+
const parentDir = lastSlashIndex === -1 ? "." : lockPath.slice(0, lastSlashIndex);
|
|
208
209
|
throw new Error(
|
|
209
210
|
`Cannot create lock directory: ${lockPath}
|
|
210
211
|
A path component is a file when it should be a directory.
|
|
@@ -217,7 +218,8 @@ To resolve:
|
|
|
217
218
|
);
|
|
218
219
|
}
|
|
219
220
|
if (code === "ENOENT") {
|
|
220
|
-
const
|
|
221
|
+
const lastSlashIndex = lockPath.lastIndexOf("/");
|
|
222
|
+
const parentDir = lastSlashIndex === -1 ? "." : lockPath.slice(0, lastSlashIndex);
|
|
221
223
|
throw new Error(
|
|
222
224
|
`Cannot create lock directory: ${lockPath}
|
|
223
225
|
Parent directory does not exist: ${parentDir}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ArchiveFormat } from '../archives.js';
|
|
1
2
|
/**
|
|
2
3
|
* Pattern for matching release assets.
|
|
3
4
|
* Can be either:
|
|
@@ -68,6 +69,24 @@ export declare const SOCKET_BTM_REPO: {
|
|
|
68
69
|
readonly owner: "SocketDev";
|
|
69
70
|
readonly repo: "socket-btm";
|
|
70
71
|
};
|
|
72
|
+
/**
|
|
73
|
+
* Create a matcher function for a pattern using picomatch for glob patterns
|
|
74
|
+
* or simple prefix/suffix matching for object patterns.
|
|
75
|
+
*
|
|
76
|
+
* @param pattern - Pattern to match (string glob, prefix/suffix object, or RegExp)
|
|
77
|
+
* @returns Function that tests if a string matches the pattern
|
|
78
|
+
*/
|
|
79
|
+
export declare function createAssetMatcher(pattern: string | {
|
|
80
|
+
prefix: string;
|
|
81
|
+
suffix: string;
|
|
82
|
+
} | RegExp): (input: string) => boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Download a binary from any GitHub repository with version caching.
|
|
85
|
+
*
|
|
86
|
+
* @param config - Download configuration
|
|
87
|
+
* @returns Path to the downloaded binary
|
|
88
|
+
*/
|
|
89
|
+
export declare function downloadGitHubRelease(config: DownloadGitHubReleaseConfig): Promise<string>;
|
|
71
90
|
/**
|
|
72
91
|
* Download a specific release asset.
|
|
73
92
|
* Supports pattern matching for dynamic asset discovery.
|
|
@@ -116,9 +135,41 @@ export declare function getReleaseAssetUrl(tag: string, assetPattern: string | A
|
|
|
116
135
|
quiet?: boolean;
|
|
117
136
|
}): Promise<string | null>;
|
|
118
137
|
/**
|
|
119
|
-
* Download a
|
|
138
|
+
* Download and extract a zip file from a GitHub release.
|
|
139
|
+
* Automatically handles downloading, extracting, and cleanup.
|
|
120
140
|
*
|
|
121
|
-
* @param
|
|
122
|
-
* @
|
|
141
|
+
* @param tag - Release tag name
|
|
142
|
+
* @param assetPattern - Asset name or pattern (glob string, prefix/suffix object, or RegExp)
|
|
143
|
+
* @param outputDir - Directory to extract the zip contents to
|
|
144
|
+
* @param repoConfig - Repository configuration (owner/repo)
|
|
145
|
+
* @param options - Additional options
|
|
146
|
+
* @param options.quiet - Suppress log messages
|
|
147
|
+
* @param options.cleanup - Remove downloaded zip file after extraction (default: true)
|
|
148
|
+
* @returns Path to the extraction directory
|
|
123
149
|
*/
|
|
124
|
-
export declare function
|
|
150
|
+
export declare function downloadAndExtractZip(tag: string, assetPattern: string | AssetPattern, outputDir: string, repoConfig: RepoConfig, options?: {
|
|
151
|
+
cleanup?: boolean;
|
|
152
|
+
quiet?: boolean;
|
|
153
|
+
}): Promise<string>;
|
|
154
|
+
/**
|
|
155
|
+
* Download and extract an archive from a GitHub release.
|
|
156
|
+
* Supports zip, tar, tar.gz, and tgz formats.
|
|
157
|
+
* Automatically handles downloading, extracting, and cleanup.
|
|
158
|
+
*
|
|
159
|
+
* @param tag - Release tag name
|
|
160
|
+
* @param assetPattern - Asset name or pattern (glob string, prefix/suffix object, or RegExp)
|
|
161
|
+
* @param outputDir - Directory to extract the archive contents to
|
|
162
|
+
* @param repoConfig - Repository configuration (owner/repo)
|
|
163
|
+
* @param options - Additional options
|
|
164
|
+
* @param options.quiet - Suppress log messages
|
|
165
|
+
* @param options.cleanup - Remove downloaded archive after extraction (default: true)
|
|
166
|
+
* @param options.strip - Strip leading path components (like tar --strip-components)
|
|
167
|
+
* @param options.format - Archive format (auto-detected if not specified)
|
|
168
|
+
* @returns Path to the extraction directory
|
|
169
|
+
*/
|
|
170
|
+
export declare function downloadAndExtractArchive(tag: string, assetPattern: string | AssetPattern, outputDir: string, repoConfig: RepoConfig, options?: {
|
|
171
|
+
cleanup?: boolean;
|
|
172
|
+
format?: ArchiveFormat;
|
|
173
|
+
quiet?: boolean;
|
|
174
|
+
strip?: number;
|
|
175
|
+
}): Promise<string>;
|