@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/regexps.js
CHANGED
|
@@ -23,10 +23,67 @@ __export(regexps_exports, {
|
|
|
23
23
|
escapeRegExp: () => escapeRegExp
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(regexps_exports);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const SYNTAX_CHARACTERS = new Set("^$\\.*+?()[]{}|/");
|
|
27
|
+
const CONTROL_ESCAPES = /* @__PURE__ */ new Map([
|
|
28
|
+
[9, "\\t"],
|
|
29
|
+
[10, "\\n"],
|
|
30
|
+
[11, "\\v"],
|
|
31
|
+
[12, "\\f"],
|
|
32
|
+
[13, "\\r"]
|
|
33
|
+
]);
|
|
34
|
+
const OTHER_PUNCTUATORS = new Set(",-=<>#&!%:;@~'`\"");
|
|
35
|
+
function isSpecHexEscapeCp(cp) {
|
|
36
|
+
if (OTHER_PUNCTUATORS.has(String.fromCodePoint(cp))) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
if (cp === 10 || cp === 13 || cp === 8232 || cp === 8233) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (cp === 9 || cp === 11 || cp === 12 || cp === 32 || cp === 160 || cp === 65279) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
if (cp >= 55296 && cp <= 57343) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
function hex2(n) {
|
|
51
|
+
return n.toString(16).padStart(2, "0");
|
|
52
|
+
}
|
|
53
|
+
function hex4(n) {
|
|
54
|
+
return n.toString(16).padStart(4, "0");
|
|
55
|
+
}
|
|
56
|
+
function escapeRegExpFallback(str) {
|
|
57
|
+
let out = "";
|
|
58
|
+
let isFirst = true;
|
|
59
|
+
for (const char of str) {
|
|
60
|
+
const cp = char.codePointAt(0);
|
|
61
|
+
if (isFirst && (cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122)) {
|
|
62
|
+
out += "\\x" + hex2(cp);
|
|
63
|
+
} else if (SYNTAX_CHARACTERS.has(char)) {
|
|
64
|
+
out += "\\" + char;
|
|
65
|
+
} else {
|
|
66
|
+
const ctrl = CONTROL_ESCAPES.get(cp);
|
|
67
|
+
if (ctrl !== void 0) {
|
|
68
|
+
out += ctrl;
|
|
69
|
+
} else if (isSpecHexEscapeCp(cp)) {
|
|
70
|
+
if (cp <= 255) {
|
|
71
|
+
out += "\\x" + hex2(cp);
|
|
72
|
+
} else {
|
|
73
|
+
for (let i = 0; i < char.length; i++) {
|
|
74
|
+
out += "\\u" + hex4(char.charCodeAt(i));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
out += char;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
isFirst = false;
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
29
84
|
}
|
|
85
|
+
const maybeNativeEscape = RegExp.escape;
|
|
86
|
+
const escapeRegExp = typeof maybeNativeEscape === "function" ? maybeNativeEscape : escapeRegExpFallback;
|
|
30
87
|
// Annotate the CommonJS export names for ESM import in node:
|
|
31
88
|
0 && (module.exports = {
|
|
32
89
|
escapeRegExp
|
package/dist/releases/github.js
CHANGED
|
@@ -43,6 +43,7 @@ module.exports = __toCommonJS(github_exports);
|
|
|
43
43
|
var import_node_process = __toESM(require("node:process"));
|
|
44
44
|
var import_picomatch = __toESM(require("../external/picomatch"));
|
|
45
45
|
var import_archives = require("../archives");
|
|
46
|
+
var import_errors = require("../errors");
|
|
46
47
|
var import_fs = require("../fs");
|
|
47
48
|
var import_http_request = require("../http-request");
|
|
48
49
|
var import_logger = require("../logger");
|
|
@@ -341,7 +342,7 @@ async function getLatestRelease(toolPrefix, repoConfig, options = {}) {
|
|
|
341
342
|
`Retry attempt ${attempt + 1}/${RETRY_CONFIG.retries + 1} for ${toolPrefix} release...`
|
|
342
343
|
);
|
|
343
344
|
logger.warn(
|
|
344
|
-
`Attempt ${attempt + 1}/${RETRY_CONFIG.retries + 1} failed: ${
|
|
345
|
+
`Attempt ${attempt + 1}/${RETRY_CONFIG.retries + 1} failed: ${(0, import_errors.errorMessage)(error)}`
|
|
345
346
|
);
|
|
346
347
|
}
|
|
347
348
|
return void 0;
|
|
@@ -395,7 +396,7 @@ async function getReleaseAssetUrl(tag, assetPattern, repoConfig, options = {}) {
|
|
|
395
396
|
`Retry attempt ${attempt + 1}/${RETRY_CONFIG.retries + 1} for asset URL...`
|
|
396
397
|
);
|
|
397
398
|
logger.warn(
|
|
398
|
-
`Attempt ${attempt + 1}/${RETRY_CONFIG.retries + 1} failed: ${
|
|
399
|
+
`Attempt ${attempt + 1}/${RETRY_CONFIG.retries + 1} failed: ${(0, import_errors.errorMessage)(error)}`
|
|
399
400
|
);
|
|
400
401
|
}
|
|
401
402
|
return void 0;
|
|
@@ -126,18 +126,74 @@ export declare function getBinaryAssetName(binaryBaseName: string, platform: Pla
|
|
|
126
126
|
*/
|
|
127
127
|
export declare function getBinaryName(binaryBaseName: string, platform: Platform): string;
|
|
128
128
|
/**
|
|
129
|
-
* Get platform-arch identifier for directory structure.
|
|
130
|
-
*
|
|
129
|
+
* Get platform-arch identifier for directory structure and asset names.
|
|
130
|
+
*
|
|
131
|
+
* # Format: `<os>-<arch>[-<libc>]`
|
|
132
|
+
*
|
|
133
|
+
* The OS segment is `process.platform` verbatim: `darwin` / `linux` /
|
|
134
|
+
* `win32`. The arch segment is `process.arch` verbatim: `x64` / `arm64`.
|
|
135
|
+
* The optional libc suffix is `-musl` (Linux only; the glibc default is
|
|
136
|
+
* unsuffixed to match Node.js's own linuxstatic convention).
|
|
137
|
+
*
|
|
138
|
+
* # Why these specific conventions
|
|
139
|
+
*
|
|
140
|
+
* ## Why `win32`, not `win`
|
|
141
|
+
*
|
|
142
|
+
* `win32` is what `process.platform` returns on every Windows host. Every
|
|
143
|
+
* npm package whose install-time platform filter uses the standard
|
|
144
|
+
* `os` / `cpu` / `libc` manifest fields must match `process.platform`
|
|
145
|
+
* strings exactly (npm compares them verbatim — there's no shorthand
|
|
146
|
+
* layer). Using `win` internally here would have forced a translation
|
|
147
|
+
* every time we constructed an install filter or a target triple, and
|
|
148
|
+
* reviewers would have to remember "we abbreviate on disk but not in
|
|
149
|
+
* package filters." Since the two now match, there's no translation
|
|
150
|
+
* step to get wrong.
|
|
151
|
+
*
|
|
152
|
+
* pnpm's pack-app (v11+) accepts `<os>-<arch>[-<libc>]` target strings
|
|
153
|
+
* and its shards are `@pnpm/exe.<os>-<arch>` (with `win32`, not `win` —
|
|
154
|
+
* see pnpm#11314). Our naming matches so asset names we emit can flow
|
|
155
|
+
* directly into pack-app's `--target` arg, `pnpm.app.targets` config,
|
|
156
|
+
* and sibling-package-name construction without a translation map.
|
|
157
|
+
*
|
|
158
|
+
* ## Why `-musl` is the suffix (and glibc is unsuffixed)
|
|
159
|
+
*
|
|
160
|
+
* Node.js's own linuxstatic tarballs historically used the unqualified
|
|
161
|
+
* `linux` for glibc and a separate download channel for musl. The pnpm
|
|
162
|
+
* ecosystem codified that as `linux-<arch>` (glibc, default) and
|
|
163
|
+
* `linux-<arch>-musl` (the libc outlier), matching the asymmetric
|
|
164
|
+
* reality of Linux distros — glibc is the majority case, musl is
|
|
165
|
+
* Alpine-and-similar. Adding `-glibc` for the default would be
|
|
166
|
+
* redundant noise in the name.
|
|
167
|
+
*
|
|
168
|
+
* ## Why libc is only appended for Linux
|
|
169
|
+
*
|
|
170
|
+
* macOS and Windows have exactly one system libc each (Apple libSystem,
|
|
171
|
+
* Microsoft UCRT). A hypothetical `darwin-arm64-libsystem` conveys no
|
|
172
|
+
* information. Node.js, npm, and pnpm all treat libc as a Linux-only
|
|
173
|
+
* axis; we follow the same convention so callers don't have to special-
|
|
174
|
+
* case `'darwin-arm64'.startsWith('darwin-arm64')` style matches.
|
|
175
|
+
*
|
|
176
|
+
* ## Why this function exists at all (vs. inlining)
|
|
177
|
+
*
|
|
178
|
+
* Two upstream APIs that socket-btm consumers end up calling — the
|
|
179
|
+
* npm manifest filter (`os`/`cpu`/`libc`) and pnpm's pack-app
|
|
180
|
+
* `--target` — both need the exact same triple format. Centralizing
|
|
181
|
+
* the construction here means a future schema change (e.g. Node
|
|
182
|
+
* introducing `riscv64`) gets one edit, and the error message for an
|
|
183
|
+
* unsupported platform is uniform across downloaders, pack-app
|
|
184
|
+
* invocations, and the `@socketbin/*` resolver logic.
|
|
131
185
|
*
|
|
132
186
|
* @param platform - Target platform
|
|
133
187
|
* @param arch - Target architecture
|
|
134
|
-
* @param libc - Linux libc variant (optional)
|
|
135
|
-
* @returns Platform-arch identifier (e.g., 'darwin-arm64', 'linux-x64-musl', '
|
|
188
|
+
* @param libc - Linux libc variant (optional; non-linux platforms ignore)
|
|
189
|
+
* @returns Platform-arch identifier (e.g., 'darwin-arm64', 'linux-x64-musl', 'win32-x64')
|
|
136
190
|
*
|
|
137
191
|
* @example
|
|
138
192
|
* ```typescript
|
|
139
193
|
* getPlatformArch('linux', 'x64', 'musl') // 'linux-x64-musl'
|
|
140
|
-
* getPlatformArch('darwin', 'arm64')
|
|
194
|
+
* getPlatformArch('darwin', 'arm64') // 'darwin-arm64'
|
|
195
|
+
* getPlatformArch('win32', 'x64') // 'win32-x64'
|
|
196
|
+
* getPlatformArch('darwin', 'x64', 'musl') // 'darwin-x64' — libc ignored
|
|
141
197
|
* ```
|
|
142
198
|
*/
|
|
143
199
|
export declare function getPlatformArch(platform: Platform, arch: Arch, libc?: Libc | undefined): string;
|
|
@@ -38,7 +38,7 @@ const PLATFORM_MAP = {
|
|
|
38
38
|
__proto__: null,
|
|
39
39
|
darwin: "darwin",
|
|
40
40
|
linux: "linux",
|
|
41
|
-
win32: "
|
|
41
|
+
win32: "win32"
|
|
42
42
|
};
|
|
43
43
|
const ARCH_MAP = {
|
|
44
44
|
__proto__: null,
|
|
@@ -185,7 +185,7 @@ function getBinaryAssetName(binaryBaseName, platform, arch, libc) {
|
|
|
185
185
|
return `${binaryBaseName}-linux-${mappedArch}${muslSuffix}${ext}`;
|
|
186
186
|
}
|
|
187
187
|
if (platform === "win32") {
|
|
188
|
-
return `${binaryBaseName}-
|
|
188
|
+
return `${binaryBaseName}-win32-${mappedArch}${ext}`;
|
|
189
189
|
}
|
|
190
190
|
throw new Error(`Unsupported platform: ${platform}`);
|
|
191
191
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Throwing twin of `validateSchema`.
|
|
3
|
+
*
|
|
4
|
+
* Use `parseSchema(schema, data)` for fail-fast trust boundaries (app
|
|
5
|
+
* startup, config files, internal assertions). Use the non-throwing
|
|
6
|
+
* `validateSchema` for recoverable input (form fields, API request bodies,
|
|
7
|
+
* anywhere errors need to surface to a user).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { z } from 'zod'
|
|
12
|
+
* import { parseSchema } from '@socketsecurity/lib/schema/parse'
|
|
13
|
+
*
|
|
14
|
+
* const Config = z.object({ host: z.string(), port: z.number() })
|
|
15
|
+
* const config = parseSchema(Config, json) // throws on invalid
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
import type { Infer } from './types';
|
|
19
|
+
/**
|
|
20
|
+
* Parse `data` against `schema` and return the validated value.
|
|
21
|
+
*
|
|
22
|
+
* @throws {Error} When validation fails. The message lists all issues as
|
|
23
|
+
* `path: message, path: message, ...`. Use `validateSchema` if you need
|
|
24
|
+
* structured access to the error list.
|
|
25
|
+
*/
|
|
26
|
+
export declare function parseSchema<S>(schema: S, data: unknown): Infer<S>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* Socket Lib - Built with esbuild */
|
|
3
|
+
"use strict";
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
+
var parse_exports = {};
|
|
22
|
+
__export(parse_exports, {
|
|
23
|
+
parseSchema: () => parseSchema
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(parse_exports);
|
|
26
|
+
var import_validate = require("./validate");
|
|
27
|
+
function parseSchema(schema, data) {
|
|
28
|
+
const result = (0, import_validate.validateSchema)(schema, data);
|
|
29
|
+
if (result.ok) {
|
|
30
|
+
return result.value;
|
|
31
|
+
}
|
|
32
|
+
const summary = result.errors.map((e) => `${e.path.join(".") || "(root)"}: ${e.message}`).join(", ");
|
|
33
|
+
throw new Error(`Validation failed: ${summary}`);
|
|
34
|
+
}
|
|
35
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
36
|
+
0 && (module.exports = {
|
|
37
|
+
parseSchema
|
|
38
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared types for schema validation.
|
|
3
|
+
*
|
|
4
|
+
* `Schema<T>` is the Zod-shaped duck-type contract — any validator with
|
|
5
|
+
* a `.safeParse(data)` method returning `{ success, data?, error? }`
|
|
6
|
+
* satisfies it. socket-lib detects Zod (v3 and v4) structurally via this
|
|
7
|
+
* interface; consumers bring their own Zod.
|
|
8
|
+
*
|
|
9
|
+
* `ValidateResult<T>` / `ValidationIssue` / `Infer<S>` / `AnySchema` are
|
|
10
|
+
* the normalized shapes produced by `@socketsecurity/lib/schema/validate`
|
|
11
|
+
* and `@socketsecurity/lib/schema/parse`.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Result of a Zod-shaped schema's `.safeParse()` call.
|
|
15
|
+
*
|
|
16
|
+
* @template T - The expected type of the parsed data
|
|
17
|
+
*/
|
|
18
|
+
export interface ParseResult<T> {
|
|
19
|
+
/** Indicates whether parsing was successful */
|
|
20
|
+
success: boolean;
|
|
21
|
+
/** Parsed and validated data (only present when `success` is `true`) */
|
|
22
|
+
data?: T | undefined;
|
|
23
|
+
/** Error information (only present when `success` is `false`) */
|
|
24
|
+
error?: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Zod-shaped duck-type for any validator exposing `safeParse` / `parse`.
|
|
28
|
+
*
|
|
29
|
+
* @template T - The expected output type after validation
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { z } from 'zod'
|
|
34
|
+
*
|
|
35
|
+
* const userSchema = z.object({ name: z.string(), age: z.number() })
|
|
36
|
+
*
|
|
37
|
+
* // Schema satisfies this interface
|
|
38
|
+
* const schema: Schema<User> = userSchema
|
|
39
|
+
* const result = schema.safeParse({ name: 'Alice', age: 30 })
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export interface Schema<T = unknown> {
|
|
43
|
+
/** Non-throwing parse. */
|
|
44
|
+
safeParse(data: unknown): ParseResult<T>;
|
|
45
|
+
/** Throwing parse. */
|
|
46
|
+
parse(data: unknown): T;
|
|
47
|
+
/** Optional schema name for debugging. */
|
|
48
|
+
_name?: string | undefined;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Internal structural shape of a Zod v4 schema — carries the inferred
|
|
52
|
+
* output type on `_zod.output`. Used for type-only detection in `Infer<S>`.
|
|
53
|
+
*
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
interface ZodV4LikeSchema<O = unknown> {
|
|
57
|
+
_zod: {
|
|
58
|
+
output: O;
|
|
59
|
+
};
|
|
60
|
+
safeParse(data: unknown): unknown;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Internal structural shape of a Zod v3 schema — carries the inferred
|
|
64
|
+
* output type on `_output`. Used for type-only detection in `Infer<S>`.
|
|
65
|
+
*
|
|
66
|
+
* @internal
|
|
67
|
+
*/
|
|
68
|
+
interface ZodV3LikeSchema<O = unknown> {
|
|
69
|
+
_output: O;
|
|
70
|
+
safeParse(data: unknown): unknown;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Internal structural shape of a TypeBox `TSchema` — carries the inferred
|
|
74
|
+
* output type on the phantom `static` field. Only used inside socket-lib
|
|
75
|
+
* for type-only detection in `Infer<S>`; external callers should pass
|
|
76
|
+
* Zod schemas.
|
|
77
|
+
*
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
interface TypeBoxLikeSchema {
|
|
81
|
+
static: unknown;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Any schema kind the validators accept.
|
|
85
|
+
*/
|
|
86
|
+
export type AnySchema = ZodV4LikeSchema<unknown> | ZodV3LikeSchema<unknown> | TypeBoxLikeSchema | Schema<unknown>;
|
|
87
|
+
/**
|
|
88
|
+
* Infer the validated output type from any supported schema kind.
|
|
89
|
+
*
|
|
90
|
+
* Order matters: TypeBox schemas carry a phantom `static` field, so we
|
|
91
|
+
* check for TypeBox before falling through to Zod and the duck-type.
|
|
92
|
+
*/
|
|
93
|
+
export type Infer<S> = S extends {
|
|
94
|
+
static: infer Static;
|
|
95
|
+
} ? Static : S extends {
|
|
96
|
+
_zod: {
|
|
97
|
+
output: infer O;
|
|
98
|
+
};
|
|
99
|
+
} ? O : S extends {
|
|
100
|
+
_output: infer O;
|
|
101
|
+
} ? O : S extends Schema<infer T> ? T : unknown;
|
|
102
|
+
/**
|
|
103
|
+
* A single normalized validation error.
|
|
104
|
+
*/
|
|
105
|
+
export interface ValidationIssue {
|
|
106
|
+
/** Array path into the value (e.g. `['user', 'age']`). */
|
|
107
|
+
path: Array<string | number>;
|
|
108
|
+
/** Human-readable description of the failure. */
|
|
109
|
+
message: string;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Tagged-union result of `validateSchema`. Callers narrow on `ok`.
|
|
113
|
+
*/
|
|
114
|
+
export type ValidateResult<T> = {
|
|
115
|
+
ok: true;
|
|
116
|
+
value: T;
|
|
117
|
+
} | {
|
|
118
|
+
ok: false;
|
|
119
|
+
errors: ValidationIssue[];
|
|
120
|
+
};
|
|
121
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Universal schema validator — non-throwing.
|
|
3
|
+
*
|
|
4
|
+
* Accepts any Zod-shaped schema (`.safeParse`-exposing) and returns a tagged
|
|
5
|
+
* result `{ ok: true, value } | { ok: false, errors }` with normalized
|
|
6
|
+
* `{ path, message }` issues. No runtime dependency on `zod` — detection
|
|
7
|
+
* is purely structural.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
* socket-lib additionally recognizes TypeBox schemas for its own internal
|
|
11
|
+
* use (e.g. `src/ipc.ts`'s stub-file validation). That path is not a
|
|
12
|
+
* supported consumer API.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { z } from 'zod'
|
|
17
|
+
* import { validateSchema } from '@socketsecurity/lib/schema/validate'
|
|
18
|
+
*
|
|
19
|
+
* const User = z.object({ name: z.string() })
|
|
20
|
+
* const r = validateSchema(User, data)
|
|
21
|
+
* if (r.ok) r.value.name // string
|
|
22
|
+
* else r.errors // ValidationIssue[]
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
import type { Infer, ValidateResult } from './types';
|
|
26
|
+
/**
|
|
27
|
+
* Validate `data` against a Zod-style `schema`. Non-throwing.
|
|
28
|
+
*
|
|
29
|
+
* The return type narrows `value` to `Infer<S>`, so callers get
|
|
30
|
+
* `z.infer<typeof S>` with no casts. Errors are normalized to
|
|
31
|
+
* `{ path, message }` regardless of the underlying validator.
|
|
32
|
+
*
|
|
33
|
+
* @throws {TypeError} When `schema` is not a recognized validator kind.
|
|
34
|
+
*/
|
|
35
|
+
export declare function validateSchema<S>(schema: S, data: unknown): ValidateResult<Infer<S>>;
|
|
@@ -18,12 +18,11 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
20
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
21
|
-
var
|
|
22
|
-
__export(
|
|
23
|
-
parseSchema: () => parseSchema,
|
|
21
|
+
var validate_exports = {};
|
|
22
|
+
__export(validate_exports, {
|
|
24
23
|
validateSchema: () => validateSchema
|
|
25
24
|
});
|
|
26
|
-
module.exports = __toCommonJS(
|
|
25
|
+
module.exports = __toCommonJS(validate_exports);
|
|
27
26
|
function isTypeBoxSchema(schema) {
|
|
28
27
|
if (schema === null || typeof schema !== "object") {
|
|
29
28
|
return false;
|
|
@@ -90,19 +89,10 @@ function validateSchema(schema, data) {
|
|
|
90
89
|
};
|
|
91
90
|
}
|
|
92
91
|
throw new TypeError(
|
|
93
|
-
"validateSchema: unsupported schema kind. Expected a
|
|
92
|
+
"validateSchema: unsupported schema kind. Expected a Zod schema or an object with a safeParse method."
|
|
94
93
|
);
|
|
95
94
|
}
|
|
96
|
-
function parseSchema(schema, data) {
|
|
97
|
-
const result = validateSchema(schema, data);
|
|
98
|
-
if (result.ok) {
|
|
99
|
-
return result.value;
|
|
100
|
-
}
|
|
101
|
-
const summary = result.errors.map((e) => `${e.path.join(".") || "(root)"}: ${e.message}`).join(", ");
|
|
102
|
-
throw new Error(`Validation failed: ${summary}`);
|
|
103
|
-
}
|
|
104
95
|
// Annotate the CommonJS export names for ESM import in node:
|
|
105
96
|
0 && (module.exports = {
|
|
106
|
-
parseSchema,
|
|
107
97
|
validateSchema
|
|
108
98
|
});
|
|
@@ -95,7 +95,6 @@ function suppressWarningType(warningType) {
|
|
|
95
95
|
}
|
|
96
96
|
async function withSuppressedWarnings(warningType, callback) {
|
|
97
97
|
const wasAlreadySuppressed = suppressedWarnings.has(warningType);
|
|
98
|
-
const original = import_node_process.default.emitWarning;
|
|
99
98
|
suppressWarningType(warningType);
|
|
100
99
|
try {
|
|
101
100
|
return await callback();
|
|
@@ -103,7 +102,6 @@ async function withSuppressedWarnings(warningType, callback) {
|
|
|
103
102
|
if (!wasAlreadySuppressed) {
|
|
104
103
|
suppressedWarnings.delete(warningType);
|
|
105
104
|
}
|
|
106
|
-
import_node_process.default.emitWarning = original;
|
|
107
105
|
}
|
|
108
106
|
}
|
|
109
107
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/url.js
CHANGED
|
@@ -73,7 +73,11 @@ function urlSearchParamAsBoolean(value, options) {
|
|
|
73
73
|
};
|
|
74
74
|
if (typeof value === "string") {
|
|
75
75
|
const trimmed = value.trim();
|
|
76
|
-
|
|
76
|
+
if (trimmed === "") {
|
|
77
|
+
return !!defaultValue;
|
|
78
|
+
}
|
|
79
|
+
const lowered = trimmed.toLowerCase();
|
|
80
|
+
return lowered === "1" || lowered === "true" || lowered === "yes" || lowered === "on";
|
|
77
81
|
}
|
|
78
82
|
if (value === null || value === void 0) {
|
|
79
83
|
return !!defaultValue;
|
package/dist/versions.js
CHANGED
|
@@ -111,11 +111,11 @@ function isValidVersion(version) {
|
|
|
111
111
|
}
|
|
112
112
|
function maxVersion(versions) {
|
|
113
113
|
const semver = getSemver();
|
|
114
|
-
return semver.maxSatisfying(versions, "*") || void 0;
|
|
114
|
+
return semver.maxSatisfying(versions, "*", { includePrerelease: true }) || void 0;
|
|
115
115
|
}
|
|
116
116
|
function minVersion(versions) {
|
|
117
117
|
const semver = getSemver();
|
|
118
|
-
return semver.minSatisfying(versions, "*") || void 0;
|
|
118
|
+
return semver.minSatisfying(versions, "*", { includePrerelease: true }) || void 0;
|
|
119
119
|
}
|
|
120
120
|
function parseVersion(version) {
|
|
121
121
|
const semver = getSemver();
|
package/dist/words.js
CHANGED
|
@@ -27,18 +27,15 @@ __export(words_exports, {
|
|
|
27
27
|
module.exports = __toCommonJS(words_exports);
|
|
28
28
|
// @__NO_SIDE_EFFECTS__
|
|
29
29
|
function capitalize(word) {
|
|
30
|
-
|
|
31
|
-
if (length === 0) {
|
|
30
|
+
if (word.length === 0) {
|
|
32
31
|
return word;
|
|
33
32
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
return `${word.charAt(0).toUpperCase()}${word.slice(1).toLowerCase()}`;
|
|
33
|
+
const [first, ...rest] = [...word];
|
|
34
|
+
return (first ?? "").toUpperCase() + rest.join("").toLowerCase();
|
|
38
35
|
}
|
|
39
36
|
// @__NO_SIDE_EFFECTS__
|
|
40
37
|
function determineArticle(word) {
|
|
41
|
-
return /^[aeiou]
|
|
38
|
+
return /^[aeiou]/i.test(word) ? "an" : "a";
|
|
42
39
|
}
|
|
43
40
|
// @__NO_SIDE_EFFECTS__
|
|
44
41
|
function pluralize(word, options) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/lib",
|
|
3
|
-
"version": "5.
|
|
4
|
-
"packageManager": "pnpm@11.0.0-rc.
|
|
3
|
+
"version": "5.23.0",
|
|
4
|
+
"packageManager": "pnpm@11.0.0-rc.5",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Core utilities and infrastructure for Socket.dev security tools",
|
|
7
7
|
"keywords": [
|
|
@@ -547,6 +547,18 @@
|
|
|
547
547
|
"types": "./dist/releases/socket-btm.d.ts",
|
|
548
548
|
"default": "./dist/releases/socket-btm.js"
|
|
549
549
|
},
|
|
550
|
+
"./schema/parse": {
|
|
551
|
+
"types": "./dist/schema/parse.d.ts",
|
|
552
|
+
"default": "./dist/schema/parse.js"
|
|
553
|
+
},
|
|
554
|
+
"./schema/types": {
|
|
555
|
+
"types": "./dist/schema/types.d.ts",
|
|
556
|
+
"default": "./dist/schema/types.js"
|
|
557
|
+
},
|
|
558
|
+
"./schema/validate": {
|
|
559
|
+
"types": "./dist/schema/validate.d.ts",
|
|
560
|
+
"default": "./dist/schema/validate.js"
|
|
561
|
+
},
|
|
550
562
|
"./sea": {
|
|
551
563
|
"types": "./dist/sea.d.ts",
|
|
552
564
|
"default": "./dist/sea.js"
|
|
@@ -655,18 +667,6 @@
|
|
|
655
667
|
"types": "./dist/url.d.ts",
|
|
656
668
|
"default": "./dist/url.js"
|
|
657
669
|
},
|
|
658
|
-
"./validation/json-parser": {
|
|
659
|
-
"types": "./dist/validation/json-parser.d.ts",
|
|
660
|
-
"default": "./dist/validation/json-parser.js"
|
|
661
|
-
},
|
|
662
|
-
"./validation/types": {
|
|
663
|
-
"types": "./dist/validation/types.d.ts",
|
|
664
|
-
"default": "./dist/validation/types.js"
|
|
665
|
-
},
|
|
666
|
-
"./validation/validate-schema": {
|
|
667
|
-
"types": "./dist/validation/validate-schema.d.ts",
|
|
668
|
-
"default": "./dist/validation/validate-schema.js"
|
|
669
|
-
},
|
|
670
670
|
"./versions": {
|
|
671
671
|
"types": "./dist/versions.d.ts",
|
|
672
672
|
"default": "./dist/versions.js"
|
|
@@ -724,7 +724,7 @@
|
|
|
724
724
|
"@socketregistry/is-unicode-supported": "1.0.5",
|
|
725
725
|
"@socketregistry/packageurl-js": "1.4.2",
|
|
726
726
|
"@socketregistry/yocto-spinner": "1.0.25",
|
|
727
|
-
"@socketsecurity/lib-stable": "npm:@socketsecurity/lib@5.
|
|
727
|
+
"@socketsecurity/lib-stable": "npm:@socketsecurity/lib@5.21.0",
|
|
728
728
|
"@types/node": "24.9.2",
|
|
729
729
|
"@typescript/native-preview": "7.0.0-dev.20260415.1",
|
|
730
730
|
"@vitest/coverage-v8": "4.0.3",
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Safe JSON parsing with validation and security controls.
|
|
3
|
-
* Provides protection against prototype pollution, size limits, and schema
|
|
4
|
-
* validation.
|
|
5
|
-
*
|
|
6
|
-
* Key Features:
|
|
7
|
-
* - Prototype pollution protection: Blocks `__proto__`, `constructor`, and
|
|
8
|
-
* `prototype` keys via JSON.parse reviver at any depth.
|
|
9
|
-
* - Size limits: Configurable maximum JSON string size (default 10MB).
|
|
10
|
-
* - Schema validation: Optional Zod-compatible schema validation.
|
|
11
|
-
* - Memory safety: Prevents memory exhaustion attacks.
|
|
12
|
-
*/
|
|
13
|
-
import type { SafeJsonParseOptions, Schema } from './types';
|
|
14
|
-
/**
|
|
15
|
-
* Safely parse JSON with optional schema validation and security controls.
|
|
16
|
-
* Throws errors on parse failures, validation failures, or security violations.
|
|
17
|
-
*
|
|
18
|
-
* This is the recommended method for parsing untrusted JSON input as it
|
|
19
|
-
* provides multiple layers of security including prototype pollution
|
|
20
|
-
* protection and size limits.
|
|
21
|
-
*
|
|
22
|
-
* @template T - The expected type of the parsed data
|
|
23
|
-
* @param jsonString - The JSON string to parse
|
|
24
|
-
* @param schema - Optional Zod-compatible schema for validation
|
|
25
|
-
* @param options - Parsing options for security and behavior control
|
|
26
|
-
* @returns The parsed and validated data
|
|
27
|
-
*
|
|
28
|
-
* @throws {Error} When JSON string exceeds `maxSize`.
|
|
29
|
-
* @throws {Error} When JSON parsing fails.
|
|
30
|
-
* @throws {Error} When prototype pollution keys are detected (unless
|
|
31
|
-
* `allowPrototype` is `true`).
|
|
32
|
-
* @throws {Error} When schema validation fails.
|
|
33
|
-
*
|
|
34
|
-
* @example
|
|
35
|
-
* ```ts
|
|
36
|
-
* // Basic parsing with type inference
|
|
37
|
-
* const data = safeJsonParse<User>('{"name":"Alice","age":30}')
|
|
38
|
-
*
|
|
39
|
-
* // With schema validation
|
|
40
|
-
* import { z } from 'zod'
|
|
41
|
-
* const userSchema = z.object({
|
|
42
|
-
* name: z.string(),
|
|
43
|
-
* age: z.number()
|
|
44
|
-
* })
|
|
45
|
-
* const user = safeJsonParse('{"name":"Alice","age":30}', userSchema)
|
|
46
|
-
*
|
|
47
|
-
* // With size limit
|
|
48
|
-
* const data = safeJsonParse(jsonString, undefined, {
|
|
49
|
-
* maxSize: 1024 * 1024 // 1MB
|
|
50
|
-
* })
|
|
51
|
-
*
|
|
52
|
-
* // Allow prototype keys (DANGEROUS — only for trusted sources)
|
|
53
|
-
* const data = safeJsonParse('{"__proto__": {}}', undefined, {
|
|
54
|
-
* allowPrototype: true
|
|
55
|
-
* })
|
|
56
|
-
* ```
|
|
57
|
-
*/
|
|
58
|
-
export declare function safeJsonParse<T = unknown>(jsonString: string, schema?: Schema<T> | undefined, options?: SafeJsonParseOptions): T;
|