@socketsecurity/lib 5.20.1 → 5.23.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 +116 -95
- package/README.md +24 -181
- package/dist/archives.js +13 -0
- package/dist/cacache.js +6 -8
- package/dist/cache-with-ttl.js +1 -1
- package/dist/constants/socket.js +1 -1
- package/dist/dlx/detect.js +25 -8
- package/dist/dlx/manifest.js +8 -19
- package/dist/dlx/package.js +16 -2
- package/dist/env/socket-cli.d.ts +4 -3
- package/dist/env/socket-cli.js +1 -1
- package/dist/errors.d.ts +96 -2
- package/dist/errors.js +55 -0
- package/dist/external/pony-cause.js +12 -11
- package/dist/fs.js +8 -2
- package/dist/github.js +3 -2
- package/dist/globs.js +5 -1
- package/dist/ipc.js +2 -2
- package/dist/json/edit.js +3 -2
- package/dist/json/parse.d.ts +47 -2
- package/dist/json/parse.js +40 -2
- package/dist/json/types.d.ts +49 -0
- package/dist/memoization.d.ts +4 -23
- package/dist/memoization.js +14 -54
- package/dist/packages/isolation.js +4 -4
- package/dist/packages/specs.js +9 -2
- package/dist/performance.js +3 -2
- package/dist/process-lock.js +4 -12
- package/dist/promise-queue.d.ts +9 -4
- package/dist/promise-queue.js +9 -7
- package/dist/promises.d.ts +41 -0
- package/dist/promises.js +19 -2
- package/dist/regexps.d.ts +4 -13
- package/dist/regexps.js +60 -3
- package/dist/releases/github.js +3 -2
- package/dist/releases/socket-btm.d.ts +61 -5
- package/dist/releases/socket-btm.js +2 -2
- package/dist/schema/parse.d.ts +26 -0
- package/dist/schema/parse.js +38 -0
- package/dist/schema/types.d.ts +121 -0
- package/dist/schema/validate.d.ts +35 -0
- package/dist/{validation/validate-schema.js → schema/validate.js} +4 -14
- package/dist/suppress-warnings.js +0 -2
- package/dist/url.js +5 -1
- package/dist/versions.js +2 -2
- package/dist/words.js +4 -7
- package/package.json +15 -15
- package/dist/validation/json-parser.d.ts +0 -58
- package/dist/validation/json-parser.js +0 -63
- package/dist/validation/types.d.ts +0 -118
- package/dist/validation/validate-schema.d.ts +0 -124
- /package/dist/{validation → schema}/types.js +0 -0
package/dist/cache-with-ttl.js
CHANGED
|
@@ -84,7 +84,7 @@ function createTtlCache(options) {
|
|
|
84
84
|
}
|
|
85
85
|
const escaped = fullPattern.replaceAll(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
86
86
|
const regexPattern = escaped.replaceAll("*", ".*");
|
|
87
|
-
const regex = new RegExp(`^${regexPattern}
|
|
87
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
88
88
|
return (key) => regex.test(key);
|
|
89
89
|
}
|
|
90
90
|
async function get(key) {
|
package/dist/constants/socket.js
CHANGED
|
@@ -77,7 +77,7 @@ const SOCKET_FIREWALL_APP_NAME = "sfw";
|
|
|
77
77
|
const SOCKET_REGISTRY_APP_NAME = "registry";
|
|
78
78
|
const SOCKET_APP_PREFIX = "_";
|
|
79
79
|
const SOCKET_LIB_NAME = "@socketsecurity/lib";
|
|
80
|
-
const SOCKET_LIB_VERSION = "5.
|
|
80
|
+
const SOCKET_LIB_VERSION = "5.23.0";
|
|
81
81
|
const SOCKET_LIB_URL = "https://github.com/SocketDev/socket-lib";
|
|
82
82
|
const SOCKET_LIB_USER_AGENT = `socketsecurity-lib/${SOCKET_LIB_VERSION} (${SOCKET_LIB_URL})`;
|
|
83
83
|
const SOCKET_IPC_HANDSHAKE = "SOCKET_IPC_HANDSHAKE";
|
package/dist/dlx/detect.js
CHANGED
|
@@ -33,7 +33,20 @@ var import_socket = require("../paths/socket");
|
|
|
33
33
|
let _fs;
|
|
34
34
|
let _path;
|
|
35
35
|
const NODE_JS_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs"]);
|
|
36
|
+
const PACKAGE_JSON_PATH_CACHE_MAX_SIZE = 200;
|
|
37
|
+
const PACKAGE_JSON_NEGATIVE_TTL_MS = 1e4;
|
|
36
38
|
const packageJsonPathCache = /* @__PURE__ */ new Map();
|
|
39
|
+
function packageJsonPathCacheSet(key, value) {
|
|
40
|
+
if (packageJsonPathCache.has(key)) {
|
|
41
|
+
packageJsonPathCache.delete(key);
|
|
42
|
+
} else if (packageJsonPathCache.size >= PACKAGE_JSON_PATH_CACHE_MAX_SIZE) {
|
|
43
|
+
const oldest = packageJsonPathCache.keys().next().value;
|
|
44
|
+
if (oldest !== void 0) {
|
|
45
|
+
packageJsonPathCache.delete(oldest);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
packageJsonPathCache.set(key, { path: value, at: Date.now() });
|
|
49
|
+
}
|
|
37
50
|
const packageJsonContentCache = /* @__PURE__ */ new Map();
|
|
38
51
|
function findPackageJson(filePath) {
|
|
39
52
|
const fs = /* @__PURE__ */ getFs();
|
|
@@ -41,25 +54,29 @@ function findPackageJson(filePath) {
|
|
|
41
54
|
const startDir = path.dirname(path.resolve(filePath));
|
|
42
55
|
const cached = packageJsonPathCache.get(startDir);
|
|
43
56
|
if (cached !== void 0) {
|
|
44
|
-
if (cached === null) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
57
|
+
if (cached.path === null) {
|
|
58
|
+
if (Date.now() - cached.at < PACKAGE_JSON_NEGATIVE_TTL_MS) {
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
packageJsonPathCache.delete(startDir);
|
|
62
|
+
} else if (fs.existsSync(cached.path)) {
|
|
63
|
+
packageJsonPathCacheSet(startDir, cached.path);
|
|
64
|
+
return cached.path;
|
|
65
|
+
} else {
|
|
66
|
+
packageJsonPathCache.delete(startDir);
|
|
49
67
|
}
|
|
50
|
-
packageJsonPathCache.delete(startDir);
|
|
51
68
|
}
|
|
52
69
|
let currentDir = startDir;
|
|
53
70
|
const root = path.parse(currentDir).root;
|
|
54
71
|
while (currentDir !== root) {
|
|
55
72
|
const packageJsonPath = path.join(currentDir, "package.json");
|
|
56
73
|
if (fs.existsSync(packageJsonPath)) {
|
|
57
|
-
|
|
74
|
+
packageJsonPathCacheSet(startDir, packageJsonPath);
|
|
58
75
|
return packageJsonPath;
|
|
59
76
|
}
|
|
60
77
|
currentDir = path.dirname(currentDir);
|
|
61
78
|
}
|
|
62
|
-
|
|
79
|
+
packageJsonPathCacheSet(startDir, null);
|
|
63
80
|
return void 0;
|
|
64
81
|
}
|
|
65
82
|
// @__NO_SIDE_EFFECTS__
|
package/dist/dlx/manifest.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(manifest_exports, {
|
|
|
26
26
|
isPackageEntry: () => isPackageEntry
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(manifest_exports);
|
|
29
|
+
var import_errors = require("../errors");
|
|
29
30
|
var import_fs = require("../fs");
|
|
30
31
|
var import_logger = require("../logger");
|
|
31
32
|
var import_socket = require("../paths/socket");
|
|
@@ -79,9 +80,7 @@ class DlxManifest {
|
|
|
79
80
|
}
|
|
80
81
|
return JSON.parse(content);
|
|
81
82
|
} catch (error) {
|
|
82
|
-
logger.warn(
|
|
83
|
-
`Failed to read manifest: ${error instanceof Error ? error.message : String(error)}`
|
|
84
|
-
);
|
|
83
|
+
logger.warn(`Failed to read manifest: ${(0, import_errors.errorMessage)(error)}`);
|
|
85
84
|
return { __proto__: null };
|
|
86
85
|
}
|
|
87
86
|
}
|
|
@@ -94,9 +93,7 @@ class DlxManifest {
|
|
|
94
93
|
try {
|
|
95
94
|
(0, import_fs.safeMkdirSync)(manifestDir, { recursive: true });
|
|
96
95
|
} catch (error) {
|
|
97
|
-
logger.warn(
|
|
98
|
-
`Failed to create manifest directory: ${error instanceof Error ? error.message : String(error)}`
|
|
99
|
-
);
|
|
96
|
+
logger.warn(`Failed to create manifest directory: ${(0, import_errors.errorMessage)(error)}`);
|
|
100
97
|
}
|
|
101
98
|
const content = JSON.stringify(data, null, 2);
|
|
102
99
|
const tempPath = `${this.manifestPath}.tmp`;
|
|
@@ -130,9 +127,7 @@ class DlxManifest {
|
|
|
130
127
|
delete data[name];
|
|
131
128
|
await this.writeManifest(data);
|
|
132
129
|
} catch (error) {
|
|
133
|
-
logger.warn(
|
|
134
|
-
`Failed to clear cache for ${name}: ${error instanceof Error ? error.message : String(error)}`
|
|
135
|
-
);
|
|
130
|
+
logger.warn(`Failed to clear cache for ${name}: ${(0, import_errors.errorMessage)(error)}`);
|
|
136
131
|
}
|
|
137
132
|
});
|
|
138
133
|
}
|
|
@@ -146,9 +141,7 @@ class DlxManifest {
|
|
|
146
141
|
fs.unlinkSync(this.manifestPath);
|
|
147
142
|
}
|
|
148
143
|
} catch (error) {
|
|
149
|
-
logger.warn(
|
|
150
|
-
`Failed to clear all cache: ${error instanceof Error ? error.message : String(error)}`
|
|
151
|
-
);
|
|
144
|
+
logger.warn(`Failed to clear all cache: ${(0, import_errors.errorMessage)(error)}`);
|
|
152
145
|
}
|
|
153
146
|
});
|
|
154
147
|
}
|
|
@@ -180,9 +173,7 @@ class DlxManifest {
|
|
|
180
173
|
const data = JSON.parse(content);
|
|
181
174
|
return Object.keys(data);
|
|
182
175
|
} catch (error) {
|
|
183
|
-
logger.warn(
|
|
184
|
-
`Failed to get package list: ${error instanceof Error ? error.message : String(error)}`
|
|
185
|
-
);
|
|
176
|
+
logger.warn(`Failed to get package list: ${(0, import_errors.errorMessage)(error)}`);
|
|
186
177
|
return [];
|
|
187
178
|
}
|
|
188
179
|
}
|
|
@@ -224,9 +215,7 @@ class DlxManifest {
|
|
|
224
215
|
}
|
|
225
216
|
}
|
|
226
217
|
} catch (error) {
|
|
227
|
-
logger.warn(
|
|
228
|
-
`Failed to read existing manifest: ${error instanceof Error ? error.message : String(error)}`
|
|
229
|
-
);
|
|
218
|
+
logger.warn(`Failed to read existing manifest: ${(0, import_errors.errorMessage)(error)}`);
|
|
230
219
|
}
|
|
231
220
|
data[name] = record;
|
|
232
221
|
const manifestDir = path.dirname(this.manifestPath);
|
|
@@ -234,7 +223,7 @@ class DlxManifest {
|
|
|
234
223
|
(0, import_fs.safeMkdirSync)(manifestDir, { recursive: true });
|
|
235
224
|
} catch (error) {
|
|
236
225
|
logger.warn(
|
|
237
|
-
`Failed to create manifest directory: ${
|
|
226
|
+
`Failed to create manifest directory: ${(0, import_errors.errorMessage)(error)}`
|
|
238
227
|
);
|
|
239
228
|
}
|
|
240
229
|
const content = JSON.stringify(data, null, 2);
|
package/dist/dlx/package.js
CHANGED
|
@@ -43,6 +43,7 @@ __export(package_exports, {
|
|
|
43
43
|
module.exports = __toCommonJS(package_exports);
|
|
44
44
|
var import_platform = require("../constants/platform");
|
|
45
45
|
var import_socket = require("../constants/socket");
|
|
46
|
+
var import_errors = require("../errors");
|
|
46
47
|
var import_arborist = __toESM(require("../external/@npmcli/arborist"));
|
|
47
48
|
var import_libnpmexec = __toESM(require("../external/libnpmexec"));
|
|
48
49
|
var import_npm_package_arg = __toESM(require("../external/npm-package-arg"));
|
|
@@ -62,7 +63,19 @@ const FIREWALL_BLOCK_SEVERITIES = /* @__PURE__ */ new Set([
|
|
|
62
63
|
"critical",
|
|
63
64
|
"high"
|
|
64
65
|
]);
|
|
66
|
+
const BINARY_PATH_CACHE_MAX_SIZE = 200;
|
|
65
67
|
const binaryPathCache = /* @__PURE__ */ new Map();
|
|
68
|
+
function binaryPathCacheSet(key, value) {
|
|
69
|
+
if (binaryPathCache.has(key)) {
|
|
70
|
+
binaryPathCache.delete(key);
|
|
71
|
+
} else if (binaryPathCache.size >= BINARY_PATH_CACHE_MAX_SIZE) {
|
|
72
|
+
const oldest = binaryPathCache.keys().next().value;
|
|
73
|
+
if (oldest !== void 0) {
|
|
74
|
+
binaryPathCache.delete(oldest);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
binaryPathCache.set(key, value);
|
|
78
|
+
}
|
|
66
79
|
async function checkFirewallPurls(arb, requestedPackage) {
|
|
67
80
|
const idealTree = arb.idealTree;
|
|
68
81
|
if (!idealTree) {
|
|
@@ -264,7 +277,7 @@ Ensure the filesystem is writable or set SOCKET_DLX_DIR to a writable location.`
|
|
|
264
277
|
await checkFirewallPurls(arb, packageName);
|
|
265
278
|
await arb.reify({ save: true });
|
|
266
279
|
} catch (e) {
|
|
267
|
-
if (e
|
|
280
|
+
if ((0, import_errors.isError)(e) && e.message.startsWith("Socket Firewall blocked")) {
|
|
268
281
|
throw e;
|
|
269
282
|
}
|
|
270
283
|
const code = e?.code;
|
|
@@ -431,6 +444,7 @@ function resolveBinaryPath(basePath) {
|
|
|
431
444
|
const cached = binaryPathCache.get(basePath);
|
|
432
445
|
if (cached) {
|
|
433
446
|
if (fs.existsSync(cached)) {
|
|
447
|
+
binaryPathCacheSet(basePath, cached);
|
|
434
448
|
return cached;
|
|
435
449
|
}
|
|
436
450
|
binaryPathCache.delete(basePath);
|
|
@@ -439,7 +453,7 @@ function resolveBinaryPath(basePath) {
|
|
|
439
453
|
for (const ext of extensions) {
|
|
440
454
|
const testPath = basePath + ext;
|
|
441
455
|
if (fs.existsSync(testPath)) {
|
|
442
|
-
|
|
456
|
+
binaryPathCacheSet(basePath, testPath);
|
|
443
457
|
return testPath;
|
|
444
458
|
}
|
|
445
459
|
}
|
package/dist/env/socket-cli.d.ts
CHANGED
|
@@ -63,9 +63,10 @@ export declare function getSocketCliApiProxy(): string | undefined;
|
|
|
63
63
|
*/
|
|
64
64
|
export declare function getSocketCliApiTimeout(): number;
|
|
65
65
|
/**
|
|
66
|
-
* Socket CLI API authentication token
|
|
67
|
-
* Checks
|
|
68
|
-
*
|
|
66
|
+
* Socket CLI API authentication token.
|
|
67
|
+
* Checks SOCKET_API_TOKEN (canonical), then the legacy names
|
|
68
|
+
* SOCKET_CLI_API_TOKEN, SOCKET_CLI_API_KEY, SOCKET_SECURITY_API_TOKEN,
|
|
69
|
+
* SOCKET_SECURITY_API_KEY. Maintains full v1.x backward compatibility.
|
|
69
70
|
*
|
|
70
71
|
* @returns API token or undefined
|
|
71
72
|
*
|
package/dist/env/socket-cli.js
CHANGED
|
@@ -56,7 +56,7 @@ function getSocketCliApiTimeout() {
|
|
|
56
56
|
}
|
|
57
57
|
// @__NO_SIDE_EFFECTS__
|
|
58
58
|
function getSocketCliApiToken() {
|
|
59
|
-
return (0, import_rewire.getEnvValue)("SOCKET_CLI_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_CLI_API_KEY") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_KEY");
|
|
59
|
+
return (0, import_rewire.getEnvValue)("SOCKET_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_CLI_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_CLI_API_KEY") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_TOKEN") || (0, import_rewire.getEnvValue)("SOCKET_SECURITY_API_KEY");
|
|
60
60
|
}
|
|
61
61
|
// @__NO_SIDE_EFFECTS__
|
|
62
62
|
function getSocketCliBootstrapCacheDir() {
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,6 +1,100 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Error utilities with cause chain support.
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - `isError(value)` — cross-realm-safe Error check (ES2025 `Error.isError`
|
|
6
|
+
* when available, `@@toStringTag` fallback otherwise).
|
|
7
|
+
* - `errorMessage(value)` — read the message (with cause chain) from any
|
|
8
|
+
* caught value, falling back to the shared `UNKNOWN_ERROR` sentinel.
|
|
9
|
+
* - `errorStack(value)` — read the stack (with cause chain) from any
|
|
10
|
+
* caught value, or `undefined` for non-Errors.
|
|
11
|
+
*
|
|
12
|
+
* `messageWithCauses` / `stackWithCauses` are re-exported from pony-cause;
|
|
13
|
+
* a patched copy recognizes cross-realm Errors via `isError`.
|
|
4
14
|
*/
|
|
15
|
+
import { UNKNOWN_ERROR } from './constants/core';
|
|
5
16
|
import { messageWithCauses, stackWithCauses } from './external/pony-cause';
|
|
6
|
-
export { messageWithCauses, stackWithCauses };
|
|
17
|
+
export { UNKNOWN_ERROR, messageWithCauses, stackWithCauses };
|
|
18
|
+
/**
|
|
19
|
+
* Spec-compliant [`Error.isError`](https://tc39.es/ecma262/#sec-error.iserror)
|
|
20
|
+
* with a fallback shim for engines that don't ship it yet.
|
|
21
|
+
*
|
|
22
|
+
* Returns `true` for Errors from any realm (worker threads, vm contexts,
|
|
23
|
+
* iframes) — things same-realm `instanceof Error` misses. Plain objects
|
|
24
|
+
* with `name` + `message` properties are **not** recognized.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* try {
|
|
28
|
+
* await doWork()
|
|
29
|
+
* } catch (e) {
|
|
30
|
+
* if (isError(e)) {
|
|
31
|
+
* logger.error(e.message)
|
|
32
|
+
* } else {
|
|
33
|
+
* logger.error(String(e))
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* `Error.isError` fallback shim — the in-language approximation used
|
|
39
|
+
* when the native ES2025 method isn't available.
|
|
40
|
+
*
|
|
41
|
+
* Exported separately so test suites on engines that ship the native
|
|
42
|
+
* method can still exercise the shim branch directly. Consumers should
|
|
43
|
+
* prefer {@link isError}, which picks the native method when present.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isErrorShim(value: unknown): value is Error;
|
|
46
|
+
/**
|
|
47
|
+
* Reference to the native ES2025 `Error.isError` when the running
|
|
48
|
+
* engine ships it, otherwise `undefined`. Exposed separately so tests
|
|
49
|
+
* and callers can detect the fast-path without re-probing.
|
|
50
|
+
*/
|
|
51
|
+
export declare const isErrorBuiltin: ((value: unknown) => value is Error) | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Prefer the native ES2025 `Error.isError` when available (exact
|
|
54
|
+
* `[[ErrorData]]` slot check, cross-realm-safe); fall back to
|
|
55
|
+
* {@link isErrorShim} otherwise.
|
|
56
|
+
*/
|
|
57
|
+
export declare const isError: (value: unknown) => value is Error;
|
|
58
|
+
/**
|
|
59
|
+
* Narrow a caught value to a Node.js `ErrnoException` — an Error with a
|
|
60
|
+
* `.code` string set by libuv/syscall failures (e.g. `'ENOENT'`,
|
|
61
|
+
* `'EACCES'`, `'EBUSY'`, `'EPERM'`). Cross-realm safe (builds on
|
|
62
|
+
* {@link isError}), and checks that `code` is a string so a merely
|
|
63
|
+
* branded Error without a real errno code returns `false`.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* try {
|
|
67
|
+
* await fsPromises.readFile(path)
|
|
68
|
+
* } catch (e) {
|
|
69
|
+
* if (isErrnoException(e) && e.code === 'ENOENT') {
|
|
70
|
+
* // … retry, or return default …
|
|
71
|
+
* } else {
|
|
72
|
+
* throw e
|
|
73
|
+
* }
|
|
74
|
+
* }
|
|
75
|
+
*/
|
|
76
|
+
export declare function isErrnoException(value: unknown): value is NodeJS.ErrnoException;
|
|
77
|
+
/**
|
|
78
|
+
* Extract a human-readable message from any caught value.
|
|
79
|
+
*
|
|
80
|
+
* Walks the `cause` chain for Errors (via {@link messageWithCauses});
|
|
81
|
+
* coerces primitives and objects to string; returns
|
|
82
|
+
* {@link UNKNOWN_ERROR} for `null`, `undefined`, empty strings,
|
|
83
|
+
* `[object Object]`, or Errors with no message.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* try {
|
|
87
|
+
* await readConfig(path)
|
|
88
|
+
* } catch (e) {
|
|
89
|
+
* throw new Error(`Failed to read ${path}: ${errorMessage(e)}`, { cause: e })
|
|
90
|
+
* }
|
|
91
|
+
*/
|
|
92
|
+
export declare function errorMessage(value: unknown): string;
|
|
93
|
+
/**
|
|
94
|
+
* Extract a stack trace (with causes) from any caught value.
|
|
95
|
+
*
|
|
96
|
+
* Returns the cause-aware stack via {@link stackWithCauses} for Errors;
|
|
97
|
+
* returns `undefined` for non-Error values, so callers can
|
|
98
|
+
* `logger.error(msg, { stack: errorStack(e) })` safely.
|
|
99
|
+
*/
|
|
100
|
+
export declare function errorStack(value: unknown): string | undefined;
|
package/dist/errors.js
CHANGED
|
@@ -20,13 +20,68 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
21
|
var errors_exports = {};
|
|
22
22
|
__export(errors_exports, {
|
|
23
|
+
UNKNOWN_ERROR: () => import_core.UNKNOWN_ERROR,
|
|
24
|
+
errorMessage: () => errorMessage,
|
|
25
|
+
errorStack: () => errorStack,
|
|
26
|
+
isErrnoException: () => isErrnoException,
|
|
27
|
+
isError: () => isError,
|
|
28
|
+
isErrorBuiltin: () => isErrorBuiltin,
|
|
29
|
+
isErrorShim: () => isErrorShim,
|
|
23
30
|
messageWithCauses: () => import_pony_cause.messageWithCauses,
|
|
24
31
|
stackWithCauses: () => import_pony_cause.stackWithCauses
|
|
25
32
|
});
|
|
26
33
|
module.exports = __toCommonJS(errors_exports);
|
|
34
|
+
var import_core = require("./constants/core");
|
|
27
35
|
var import_pony_cause = require("./external/pony-cause");
|
|
36
|
+
const ObjectPrototypeToString = Object.prototype.toString;
|
|
37
|
+
const ReflectApply = Reflect.apply;
|
|
38
|
+
function isErrorShim(value) {
|
|
39
|
+
if (value === null || typeof value !== "object") {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return ReflectApply(ObjectPrototypeToString, value, []) === "[object Error]";
|
|
43
|
+
}
|
|
44
|
+
const isErrorBuiltin = Error.isError;
|
|
45
|
+
const isError = isErrorBuiltin ?? isErrorShim;
|
|
46
|
+
function isErrnoException(value) {
|
|
47
|
+
if (!isError(value)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const code = value.code;
|
|
51
|
+
if (typeof code !== "string" || code.length === 0) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const first = code.charCodeAt(0);
|
|
55
|
+
return first >= 65 && first <= 90;
|
|
56
|
+
}
|
|
57
|
+
function errorMessage(value) {
|
|
58
|
+
if (isError(value)) {
|
|
59
|
+
return (0, import_pony_cause.messageWithCauses)(value) || import_core.UNKNOWN_ERROR;
|
|
60
|
+
}
|
|
61
|
+
if (value === null || value === void 0) {
|
|
62
|
+
return import_core.UNKNOWN_ERROR;
|
|
63
|
+
}
|
|
64
|
+
const s = String(value);
|
|
65
|
+
if (s === "" || s === "[object Object]") {
|
|
66
|
+
return import_core.UNKNOWN_ERROR;
|
|
67
|
+
}
|
|
68
|
+
return s;
|
|
69
|
+
}
|
|
70
|
+
function errorStack(value) {
|
|
71
|
+
if (isError(value)) {
|
|
72
|
+
return (0, import_pony_cause.stackWithCauses)(value);
|
|
73
|
+
}
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
28
76
|
// Annotate the CommonJS export names for ESM import in node:
|
|
29
77
|
0 && (module.exports = {
|
|
78
|
+
UNKNOWN_ERROR,
|
|
79
|
+
errorMessage,
|
|
80
|
+
errorStack,
|
|
81
|
+
isErrnoException,
|
|
82
|
+
isError,
|
|
83
|
+
isErrorBuiltin,
|
|
84
|
+
isErrorShim,
|
|
30
85
|
messageWithCauses,
|
|
31
86
|
stackWithCauses
|
|
32
87
|
});
|
|
@@ -11,9 +11,9 @@ var __commonJS = (cb, mod) => function __require() {
|
|
|
11
11
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
// node_modules/.pnpm/pony-cause@2.1.
|
|
14
|
+
// node_modules/.pnpm/pony-cause@2.1.11_patch_hash=39b2eb2567818b7c60126d03e252dbbabd8738082fca850582300d45b0a8cfb8/node_modules/pony-cause/lib/error-with-cause.js
|
|
15
15
|
var require_error_with_cause = __commonJS({
|
|
16
|
-
"node_modules/.pnpm/pony-cause@2.1.
|
|
16
|
+
"node_modules/.pnpm/pony-cause@2.1.11_patch_hash=39b2eb2567818b7c60126d03e252dbbabd8738082fca850582300d45b0a8cfb8/node_modules/pony-cause/lib/error-with-cause.js"(exports2, module2) {
|
|
17
17
|
"use strict";
|
|
18
18
|
var ErrorWithCause = class _ErrorWithCause extends Error {
|
|
19
19
|
static {
|
|
@@ -41,13 +41,14 @@ var require_error_with_cause = __commonJS({
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
// node_modules/.pnpm/pony-cause@2.1.
|
|
44
|
+
// node_modules/.pnpm/pony-cause@2.1.11_patch_hash=39b2eb2567818b7c60126d03e252dbbabd8738082fca850582300d45b0a8cfb8/node_modules/pony-cause/lib/helpers.js
|
|
45
45
|
var require_helpers = __commonJS({
|
|
46
|
-
"node_modules/.pnpm/pony-cause@2.1.
|
|
46
|
+
"node_modules/.pnpm/pony-cause@2.1.11_patch_hash=39b2eb2567818b7c60126d03e252dbbabd8738082fca850582300d45b0a8cfb8/node_modules/pony-cause/lib/helpers.js"(exports2, module2) {
|
|
47
47
|
"use strict";
|
|
48
|
+
var isError = typeof Error.isError === "function" ? Error.isError : (v) => v !== null && typeof v === "object" && Object.prototype.toString.call(v) === "[object Error]";
|
|
48
49
|
var findCauseByReference = /* @__PURE__ */ __name((err, reference) => {
|
|
49
50
|
if (!err || !reference) return;
|
|
50
|
-
if (!(err
|
|
51
|
+
if (!isError(err)) return;
|
|
51
52
|
if (!(reference.prototype instanceof Error) && // @ts-ignore
|
|
52
53
|
reference !== Error) return;
|
|
53
54
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -66,13 +67,13 @@ var require_helpers = __commonJS({
|
|
|
66
67
|
}
|
|
67
68
|
if (typeof err.cause === "function") {
|
|
68
69
|
const causeResult = err.cause();
|
|
69
|
-
return causeResult
|
|
70
|
+
return isError(causeResult) ? causeResult : void 0;
|
|
70
71
|
} else {
|
|
71
|
-
return err.cause
|
|
72
|
+
return isError(err.cause) ? err.cause : void 0;
|
|
72
73
|
}
|
|
73
74
|
}, "getErrorCause");
|
|
74
75
|
var _stackWithCauses = /* @__PURE__ */ __name((err, seen) => {
|
|
75
|
-
if (!(err
|
|
76
|
+
if (!isError(err)) return "";
|
|
76
77
|
const stack = err.stack || "";
|
|
77
78
|
if (seen.has(err)) {
|
|
78
79
|
return stack + "\ncauses have become circular...";
|
|
@@ -87,7 +88,7 @@ var require_helpers = __commonJS({
|
|
|
87
88
|
}, "_stackWithCauses");
|
|
88
89
|
var stackWithCauses = /* @__PURE__ */ __name((err) => _stackWithCauses(err, /* @__PURE__ */ new Set()), "stackWithCauses");
|
|
89
90
|
var _messageWithCauses = /* @__PURE__ */ __name((err, seen, skip) => {
|
|
90
|
-
if (!(err
|
|
91
|
+
if (!isError(err)) return "";
|
|
91
92
|
const message = skip ? "" : err.message || "";
|
|
92
93
|
if (seen.has(err)) {
|
|
93
94
|
return message + ": ...";
|
|
@@ -116,9 +117,9 @@ var require_helpers = __commonJS({
|
|
|
116
117
|
}
|
|
117
118
|
});
|
|
118
119
|
|
|
119
|
-
// node_modules/.pnpm/pony-cause@2.1.
|
|
120
|
+
// node_modules/.pnpm/pony-cause@2.1.11_patch_hash=39b2eb2567818b7c60126d03e252dbbabd8738082fca850582300d45b0a8cfb8/node_modules/pony-cause/index.js
|
|
120
121
|
var require_pony_cause = __commonJS({
|
|
121
|
-
"node_modules/.pnpm/pony-cause@2.1.
|
|
122
|
+
"node_modules/.pnpm/pony-cause@2.1.11_patch_hash=39b2eb2567818b7c60126d03e252dbbabd8738082fca850582300d45b0a8cfb8/node_modules/pony-cause/index.js"(exports2, module2) {
|
|
122
123
|
"use strict";
|
|
123
124
|
var { ErrorWithCause } = require_error_with_cause();
|
|
124
125
|
var {
|
package/dist/fs.js
CHANGED
|
@@ -167,7 +167,7 @@ async function findUp(name, options) {
|
|
|
167
167
|
let dir = path.resolve(cwd);
|
|
168
168
|
const { root } = path.parse(dir);
|
|
169
169
|
const names = (0, import_arrays.isArray)(name) ? name : [name];
|
|
170
|
-
while (dir
|
|
170
|
+
while (dir) {
|
|
171
171
|
for (const n of names) {
|
|
172
172
|
if (signal?.aborted) {
|
|
173
173
|
return void 0;
|
|
@@ -184,6 +184,9 @@ async function findUp(name, options) {
|
|
|
184
184
|
} catch {
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
|
+
if (dir === root) {
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
187
190
|
dir = path.dirname(dir);
|
|
188
191
|
}
|
|
189
192
|
return void 0;
|
|
@@ -210,7 +213,7 @@ function findUpSync(name, options) {
|
|
|
210
213
|
const { root } = path.parse(dir);
|
|
211
214
|
const stopDir = stopAt ? path.resolve(stopAt) : void 0;
|
|
212
215
|
const names = (0, import_arrays.isArray)(name) ? name : [name];
|
|
213
|
-
while (dir
|
|
216
|
+
while (dir) {
|
|
214
217
|
if (stopDir && dir === stopDir) {
|
|
215
218
|
for (const n of names) {
|
|
216
219
|
const thePath = path.join(dir, n);
|
|
@@ -240,6 +243,9 @@ function findUpSync(name, options) {
|
|
|
240
243
|
} catch {
|
|
241
244
|
}
|
|
242
245
|
}
|
|
246
|
+
if (dir === root) {
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
243
249
|
dir = path.dirname(dir);
|
|
244
250
|
}
|
|
245
251
|
return void 0;
|
package/dist/github.js
CHANGED
|
@@ -45,6 +45,7 @@ var import_node_process = __toESM(require("node:process"));
|
|
|
45
45
|
var import_cache_with_ttl = require("./cache-with-ttl");
|
|
46
46
|
var import_github = require("./env/github");
|
|
47
47
|
var import_socket_cli = require("./env/socket-cli");
|
|
48
|
+
var import_errors = require("./errors");
|
|
48
49
|
var import_http_request = require("./http-request");
|
|
49
50
|
var import_spawn = require("./spawn");
|
|
50
51
|
const GITHUB_API_BASE_URL = "https://api.github.com";
|
|
@@ -80,7 +81,7 @@ async function fetchRefSha(owner, repo, ref, options) {
|
|
|
80
81
|
return commitData.sha;
|
|
81
82
|
} catch (e) {
|
|
82
83
|
throw new Error(
|
|
83
|
-
`failed to resolve ref "${ref}" for ${owner}/${repo}: ${
|
|
84
|
+
`failed to resolve ref "${ref}" for ${owner}/${repo}: ${(0, import_errors.errorMessage)(e)}`
|
|
84
85
|
);
|
|
85
86
|
}
|
|
86
87
|
}
|
|
@@ -165,7 +166,7 @@ async function fetchGitHub(url, options) {
|
|
|
165
166
|
return JSON.parse(response.body.toString("utf8"));
|
|
166
167
|
} catch (error) {
|
|
167
168
|
throw new Error(
|
|
168
|
-
`Failed to parse GitHub API response: ${
|
|
169
|
+
`Failed to parse GitHub API response: ${(0, import_errors.errorMessage)(error)}
|
|
169
170
|
URL: ${url}
|
|
170
171
|
Response may be malformed or incomplete.`,
|
|
171
172
|
{ cause: error }
|
package/dist/globs.js
CHANGED
|
@@ -91,7 +91,11 @@ function getPicomatch() {
|
|
|
91
91
|
function getGlobMatcher(glob2, options) {
|
|
92
92
|
const patterns = Array.isArray(glob2) ? glob2 : [glob2];
|
|
93
93
|
const sortedPatterns = [...patterns].sort();
|
|
94
|
-
const sortedOptions = options ? Object.keys(options).sort().map((k) =>
|
|
94
|
+
const sortedOptions = options ? Object.keys(options).sort().map((k) => {
|
|
95
|
+
const value = options[k];
|
|
96
|
+
const normalized = Array.isArray(value) ? [...value].sort() : value;
|
|
97
|
+
return `${k}:${JSON.stringify(normalized)}`;
|
|
98
|
+
}).join(",") : "";
|
|
95
99
|
const key = `${sortedPatterns.join("|")}:${sortedOptions}`;
|
|
96
100
|
const existing = matcherCache.get(key);
|
|
97
101
|
if (existing) {
|
package/dist/ipc.js
CHANGED
|
@@ -37,7 +37,7 @@ module.exports = __toCommonJS(ipc_exports);
|
|
|
37
37
|
var import_node_process = __toESM(require("node:process"));
|
|
38
38
|
var import_typebox = require("./external/@sinclair/typebox");
|
|
39
39
|
var import_socket = require("./paths/socket");
|
|
40
|
-
var
|
|
40
|
+
var import_parse = require("./schema/parse");
|
|
41
41
|
const IpcStubSchema = import_typebox.Type.Object({
|
|
42
42
|
/** Process ID that created the stub. */
|
|
43
43
|
pid: import_typebox.Type.Integer({ minimum: 1 }),
|
|
@@ -100,7 +100,7 @@ async function writeIpcStub(appName, data) {
|
|
|
100
100
|
pid: import_node_process.default.pid,
|
|
101
101
|
timestamp: Date.now()
|
|
102
102
|
};
|
|
103
|
-
const validated = (0,
|
|
103
|
+
const validated = (0, import_parse.parseSchema)(IpcStubSchema, ipcData);
|
|
104
104
|
const fs = /* @__PURE__ */ getFs();
|
|
105
105
|
const flags = fs.constants.O_CREAT | fs.constants.O_WRONLY | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW;
|
|
106
106
|
let handle;
|
package/dist/json/edit.js
CHANGED
|
@@ -35,6 +35,7 @@ __export(edit_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(edit_exports);
|
|
36
36
|
var import_node_process = __toESM(require("node:process"));
|
|
37
37
|
var import_promises = require("node:timers/promises");
|
|
38
|
+
var import_errors = require("../errors");
|
|
38
39
|
var import_format = require("./format");
|
|
39
40
|
const identSymbol = import_format.INDENT_SYMBOL;
|
|
40
41
|
const newlineSymbol = import_format.NEWLINE_SYMBOL;
|
|
@@ -59,7 +60,7 @@ async function readFile(filepath) {
|
|
|
59
60
|
return await fsPromises.readFile(filepath, "utf8");
|
|
60
61
|
} catch (err) {
|
|
61
62
|
const isLastAttempt = attempt === maxRetries;
|
|
62
|
-
const isEnoent =
|
|
63
|
+
const isEnoent = (0, import_errors.isErrnoException)(err) && err.code === "ENOENT";
|
|
63
64
|
if (!isEnoent || isLastAttempt) {
|
|
64
65
|
throw err;
|
|
65
66
|
}
|
|
@@ -92,7 +93,7 @@ async function retryWrite(filepath, content, retries = 3, baseDelay = 10) {
|
|
|
92
93
|
return;
|
|
93
94
|
} catch (err) {
|
|
94
95
|
const isLastAttempt = attempt === retries;
|
|
95
|
-
const isRetriableError =
|
|
96
|
+
const isRetriableError = (0, import_errors.isErrnoException)(err) && (err.code === "EPERM" || err.code === "EBUSY" || err.code === "ENOENT");
|
|
96
97
|
if (!isRetriableError || isLastAttempt) {
|
|
97
98
|
throw err;
|
|
98
99
|
}
|
package/dist/json/parse.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview JSON parsing utilities with Buffer detection and BOM stripping.
|
|
3
|
-
* Provides safe JSON parsing with automatic encoding handling
|
|
3
|
+
* Provides safe JSON parsing with automatic encoding handling, plus
|
|
4
|
+
* `safeJsonParse` for untrusted input (prototype-pollution protection +
|
|
5
|
+
* size limits + optional schema validation).
|
|
4
6
|
*/
|
|
5
|
-
import type {
|
|
7
|
+
import type { Schema } from '../schema/types';
|
|
8
|
+
import type { JsonParseOptions, JsonPrimitive, JsonValue, SafeJsonParseOptions } from './types';
|
|
6
9
|
/**
|
|
7
10
|
* Check if a value is a JSON primitive type.
|
|
8
11
|
* JSON primitives are: `null`, `boolean`, `number`, or `string`.
|
|
@@ -76,3 +79,45 @@ export declare function isJsonPrimitive(value: unknown): value is JsonPrimitive;
|
|
|
76
79
|
* ```
|
|
77
80
|
*/
|
|
78
81
|
export declare function jsonParse(content: string | Buffer, options?: JsonParseOptions | undefined): JsonValue | undefined;
|
|
82
|
+
/**
|
|
83
|
+
* Safely parse JSON with optional schema validation and security controls.
|
|
84
|
+
* Throws on parse failure, validation failure, or security violation.
|
|
85
|
+
*
|
|
86
|
+
* Recommended for parsing untrusted JSON (user input, network payloads,
|
|
87
|
+
* anything beyond a trust boundary). Layers:
|
|
88
|
+
* 1. Size cap (default 10 MB) prevents memory exhaustion.
|
|
89
|
+
* 2. Prototype-pollution reviver rejects `__proto__` / `constructor` /
|
|
90
|
+
* `prototype` keys at any depth (unless `allowPrototype: true`).
|
|
91
|
+
* 3. Optional Zod-shaped schema validation via
|
|
92
|
+
* `@socketsecurity/lib/schema/validate`.
|
|
93
|
+
*
|
|
94
|
+
* For trusted-source reads (package.json, local config files), prefer
|
|
95
|
+
* `jsonParse()` — it offers Buffer/BOM handling and filepath-aware error
|
|
96
|
+
* messages, without the untrusted-input overhead.
|
|
97
|
+
*
|
|
98
|
+
* @throws {Error} When `jsonString` exceeds `maxSize`.
|
|
99
|
+
* @throws {Error} When JSON parsing fails.
|
|
100
|
+
* @throws {Error} When prototype-pollution keys are detected (and
|
|
101
|
+
* `allowPrototype` is not `true`).
|
|
102
|
+
* @throws {Error} When schema validation fails.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```ts
|
|
106
|
+
* // Basic parsing with type inference.
|
|
107
|
+
* const data = safeJsonParse<User>('{"name":"Alice","age":30}')
|
|
108
|
+
*
|
|
109
|
+
* // With schema validation.
|
|
110
|
+
* import { z } from 'zod'
|
|
111
|
+
* const userSchema = z.object({ name: z.string(), age: z.number() })
|
|
112
|
+
* const user = safeJsonParse('{"name":"Alice","age":30}', userSchema)
|
|
113
|
+
*
|
|
114
|
+
* // With size limit.
|
|
115
|
+
* const data = safeJsonParse(jsonString, undefined, { maxSize: 1024 })
|
|
116
|
+
*
|
|
117
|
+
* // Allow prototype keys (DANGEROUS — only for trusted sources).
|
|
118
|
+
* const data = safeJsonParse('{"__proto__":{}}', undefined, {
|
|
119
|
+
* allowPrototype: true,
|
|
120
|
+
* })
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare function safeJsonParse<T = unknown>(jsonString: string, schema?: Schema<T> | undefined, options?: SafeJsonParseOptions): T;
|