@socketsecurity/lib 5.19.1 → 5.20.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 +30 -0
- package/dist/cache-with-ttl.d.ts +7 -0
- package/dist/cache-with-ttl.js +26 -7
- package/dist/constants/socket.js +1 -1
- package/dist/dlx/lockfile.js +4 -1
- package/dist/dlx/manifest.d.ts +10 -4
- package/dist/dlx/package.d.ts +1 -1
- package/dist/dlx/package.js +5 -2
- package/dist/external/@npmcli/package-json/lib/read-package.js +40 -32
- package/dist/external/@npmcli/package-json/lib/sort.js +104 -92
- package/dist/external/@npmcli/package-json.js +9 -3968
- package/dist/external/@sinclair/typebox/value.js +9007 -0
- package/dist/external/@sinclair/typebox.js +7891 -0
- package/dist/external/debug.js +162 -328
- package/dist/external/npm-pack.js +13935 -33342
- package/dist/http-request.d.ts +0 -25
- package/dist/http-request.js +6 -5
- package/dist/ipc.js +43 -10
- package/dist/json/edit.d.ts +1 -1
- package/dist/memoization.js +6 -0
- package/dist/paths/packages.js +6 -2
- package/dist/promise-queue.js +1 -1
- package/dist/stdio/progress.js +1 -1
- package/dist/tables.js +2 -3
- package/dist/validation/validate-schema.d.ts +124 -0
- package/dist/validation/validate-schema.js +108 -0
- package/package.json +7 -6
- package/dist/external/zod.js +0 -15223
- package/dist/zod.d.ts +0 -5
- package/dist/zod.js +0 -30
package/dist/http-request.d.ts
CHANGED
|
@@ -890,31 +890,6 @@ export declare function httpRequest(url: string, options?: HttpRequestOptions |
|
|
|
890
890
|
* ```
|
|
891
891
|
*/
|
|
892
892
|
export declare function httpText(url: string, options?: HttpRequestOptions | undefined): Promise<string>;
|
|
893
|
-
/**
|
|
894
|
-
* Parse a checksums file text into a filename-to-hash map.
|
|
895
|
-
*
|
|
896
|
-
* Supports standard checksums file formats:
|
|
897
|
-
* - BSD style: "SHA256 (filename) = hash"
|
|
898
|
-
* - GNU style: "hash filename" (two spaces)
|
|
899
|
-
* - Simple style: "hash filename" (single space)
|
|
900
|
-
*
|
|
901
|
-
* Lines starting with '#' are treated as comments and ignored.
|
|
902
|
-
* Empty lines are ignored.
|
|
903
|
-
*
|
|
904
|
-
* @param text - Raw text content of a checksums file
|
|
905
|
-
* @returns Map of filenames to lowercase SHA256 hashes
|
|
906
|
-
*
|
|
907
|
-
* @example
|
|
908
|
-
* ```ts
|
|
909
|
-
* const text = `
|
|
910
|
-
* # SHA256 checksums
|
|
911
|
-
* e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 file.zip
|
|
912
|
-
* abc123def456... other.tar.gz
|
|
913
|
-
* `
|
|
914
|
-
* const checksums = parseChecksums(text)
|
|
915
|
-
* console.log(checksums['file.zip']) // 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
|
|
916
|
-
* ```
|
|
917
|
-
*/
|
|
918
893
|
export declare function parseChecksums(text: string): Checksums;
|
|
919
894
|
/**
|
|
920
895
|
* Parse a `Retry-After` HTTP header value into milliseconds.
|
package/dist/http-request.js
CHANGED
|
@@ -644,6 +644,9 @@ async function httpText(url, options) {
|
|
|
644
644
|
}
|
|
645
645
|
return response.text();
|
|
646
646
|
}
|
|
647
|
+
const CHECKSUM_BSD_RE = /^SHA256\s+\((.+)\)\s+=\s+([a-fA-F0-9]{64})$/;
|
|
648
|
+
const CHECKSUM_GNU_RE = /^([a-fA-F0-9]{64})\s+(.+)$/;
|
|
649
|
+
const RETRY_AFTER_INT_RE = /^\d+$/;
|
|
647
650
|
function parseChecksums(text) {
|
|
648
651
|
const checksums = { __proto__: null };
|
|
649
652
|
for (const line of text.split("\n")) {
|
|
@@ -651,14 +654,12 @@ function parseChecksums(text) {
|
|
|
651
654
|
if (!trimmed || trimmed.startsWith("#")) {
|
|
652
655
|
continue;
|
|
653
656
|
}
|
|
654
|
-
const bsdMatch =
|
|
655
|
-
/^SHA256\s+\((.+)\)\s+=\s+([a-fA-F0-9]{64})$/
|
|
656
|
-
);
|
|
657
|
+
const bsdMatch = CHECKSUM_BSD_RE.exec(trimmed);
|
|
657
658
|
if (bsdMatch) {
|
|
658
659
|
checksums[bsdMatch[1]] = bsdMatch[2].toLowerCase();
|
|
659
660
|
continue;
|
|
660
661
|
}
|
|
661
|
-
const gnuMatch =
|
|
662
|
+
const gnuMatch = CHECKSUM_GNU_RE.exec(trimmed);
|
|
662
663
|
if (gnuMatch) {
|
|
663
664
|
checksums[gnuMatch[2]] = gnuMatch[1].toLowerCase();
|
|
664
665
|
}
|
|
@@ -674,7 +675,7 @@ function parseRetryAfterHeader(value) {
|
|
|
674
675
|
return void 0;
|
|
675
676
|
}
|
|
676
677
|
const trimmed = raw.trim();
|
|
677
|
-
if (
|
|
678
|
+
if (RETRY_AFTER_INT_RE.test(trimmed)) {
|
|
678
679
|
const seconds = Number(trimmed);
|
|
679
680
|
return seconds * 1e3;
|
|
680
681
|
}
|
package/dist/ipc.js
CHANGED
|
@@ -35,15 +35,16 @@ __export(ipc_exports, {
|
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(ipc_exports);
|
|
37
37
|
var import_node_process = __toESM(require("node:process"));
|
|
38
|
+
var import_typebox = require("./external/@sinclair/typebox");
|
|
38
39
|
var import_socket = require("./paths/socket");
|
|
39
|
-
var
|
|
40
|
-
const IpcStubSchema =
|
|
40
|
+
var import_validate_schema = require("./validation/validate-schema");
|
|
41
|
+
const IpcStubSchema = import_typebox.Type.Object({
|
|
41
42
|
/** Process ID that created the stub. */
|
|
42
|
-
pid:
|
|
43
|
+
pid: import_typebox.Type.Integer({ minimum: 1 }),
|
|
43
44
|
/** Creation timestamp for age validation. */
|
|
44
|
-
timestamp:
|
|
45
|
+
timestamp: import_typebox.Type.Number({ exclusiveMinimum: 0 }),
|
|
45
46
|
/** The actual data payload. */
|
|
46
|
-
data:
|
|
47
|
+
data: import_typebox.Type.Unknown()
|
|
47
48
|
});
|
|
48
49
|
let _fs;
|
|
49
50
|
let _path;
|
|
@@ -52,6 +53,24 @@ async function ensureIpcDirectory(filePath) {
|
|
|
52
53
|
const path = /* @__PURE__ */ getPath();
|
|
53
54
|
const dir = path.dirname(filePath);
|
|
54
55
|
await fs.promises.mkdir(dir, { recursive: true, mode: 448 });
|
|
56
|
+
if (import_node_process.default.platform === "win32") {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const stats = await fs.promises.lstat(dir);
|
|
60
|
+
if (!stats.isDirectory()) {
|
|
61
|
+
throw new Error(`IPC path is not a directory: ${dir}`);
|
|
62
|
+
}
|
|
63
|
+
const getuid = import_node_process.default.getuid;
|
|
64
|
+
const ownUid = typeof getuid === "function" ? getuid.call(import_node_process.default) : -1;
|
|
65
|
+
if (ownUid !== -1 && stats.uid !== ownUid) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
`IPC directory ${dir} is owned by another user (uid ${stats.uid}); refusing to use it.`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const mode = stats.mode & 511;
|
|
71
|
+
if ((mode & 63) !== 0) {
|
|
72
|
+
await fs.promises.chmod(dir, 448);
|
|
73
|
+
}
|
|
55
74
|
}
|
|
56
75
|
// @__NO_SIDE_EFFECTS__
|
|
57
76
|
function getFs() {
|
|
@@ -81,12 +100,26 @@ async function writeIpcStub(appName, data) {
|
|
|
81
100
|
pid: import_node_process.default.pid,
|
|
82
101
|
timestamp: Date.now()
|
|
83
102
|
};
|
|
84
|
-
const validated =
|
|
103
|
+
const validated = (0, import_validate_schema.parseSchema)(IpcStubSchema, ipcData);
|
|
85
104
|
const fs = /* @__PURE__ */ getFs();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
105
|
+
const flags = fs.constants.O_CREAT | fs.constants.O_WRONLY | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW;
|
|
106
|
+
let handle;
|
|
107
|
+
try {
|
|
108
|
+
handle = await fs.promises.open(stubPath, flags, 384);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
const err = e;
|
|
111
|
+
if (err.code === "EEXIST") {
|
|
112
|
+
await fs.promises.unlink(stubPath);
|
|
113
|
+
handle = await fs.promises.open(stubPath, flags, 384);
|
|
114
|
+
} else {
|
|
115
|
+
throw err;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await handle.writeFile(JSON.stringify(validated, null, 2), "utf8");
|
|
120
|
+
} finally {
|
|
121
|
+
await handle.close();
|
|
122
|
+
}
|
|
90
123
|
return stubPath;
|
|
91
124
|
}
|
|
92
125
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/json/edit.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { EditableJsonConstructor } from './types';
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```ts
|
|
10
|
-
* import { getEditableJsonClass } from '@socketsecurity/lib/json'
|
|
10
|
+
* import { getEditableJsonClass } from '@socketsecurity/lib/json/edit'
|
|
11
11
|
*
|
|
12
12
|
* const EditableJson = getEditableJsonClass<MyConfigType>()
|
|
13
13
|
* const config = await EditableJson.load('./config.json')
|
package/dist/memoization.js
CHANGED
|
@@ -183,6 +183,11 @@ function memoizeAsync(fn, options = {}) {
|
|
|
183
183
|
const inflight = refreshing.get(key);
|
|
184
184
|
if (inflight) {
|
|
185
185
|
(0, import_debug.debugLog)(`[memoizeAsync:${name}] stale-dedup`, { key });
|
|
186
|
+
const inflightIndex = accessOrder.indexOf(key);
|
|
187
|
+
if (inflightIndex !== -1) {
|
|
188
|
+
accessOrder.splice(inflightIndex, 1);
|
|
189
|
+
}
|
|
190
|
+
accessOrder.push(key);
|
|
186
191
|
return await inflight;
|
|
187
192
|
}
|
|
188
193
|
cache.delete(key);
|
|
@@ -198,6 +203,7 @@ function memoizeAsync(fn, options = {}) {
|
|
|
198
203
|
const entry = cache.get(key);
|
|
199
204
|
if (entry) {
|
|
200
205
|
entry.value = Promise.resolve(result);
|
|
206
|
+
entry.timestamp = Date.now();
|
|
201
207
|
}
|
|
202
208
|
return result;
|
|
203
209
|
},
|
package/dist/paths/packages.js
CHANGED
|
@@ -34,8 +34,12 @@ function getPath() {
|
|
|
34
34
|
return _path;
|
|
35
35
|
}
|
|
36
36
|
// @__NO_SIDE_EFFECTS__
|
|
37
|
+
function isPackageJsonFile(filepath) {
|
|
38
|
+
return filepath === "package.json" || filepath.endsWith("/package.json") || filepath.endsWith("\\package.json");
|
|
39
|
+
}
|
|
40
|
+
// @__NO_SIDE_EFFECTS__
|
|
37
41
|
function resolvePackageJsonDirname(filepath) {
|
|
38
|
-
if (filepath
|
|
42
|
+
if (/* @__PURE__ */ isPackageJsonFile(filepath)) {
|
|
39
43
|
const path = /* @__PURE__ */ getPath();
|
|
40
44
|
return (0, import_normalize.normalizePath)(path.dirname(filepath));
|
|
41
45
|
}
|
|
@@ -43,7 +47,7 @@ function resolvePackageJsonDirname(filepath) {
|
|
|
43
47
|
}
|
|
44
48
|
// @__NO_SIDE_EFFECTS__
|
|
45
49
|
function resolvePackageJsonPath(filepath) {
|
|
46
|
-
if (filepath
|
|
50
|
+
if (/* @__PURE__ */ isPackageJsonFile(filepath)) {
|
|
47
51
|
return (0, import_normalize.normalizePath)(filepath);
|
|
48
52
|
}
|
|
49
53
|
const path = /* @__PURE__ */ getPath();
|
package/dist/promise-queue.js
CHANGED
|
@@ -69,7 +69,7 @@ class PromiseQueue {
|
|
|
69
69
|
return;
|
|
70
70
|
}
|
|
71
71
|
this.running++;
|
|
72
|
-
task.fn().then(task.resolve).catch(task.reject).finally(() => {
|
|
72
|
+
Promise.resolve().then(() => task.fn()).then(task.resolve).catch(task.reject).finally(() => {
|
|
73
73
|
this.running--;
|
|
74
74
|
this.runNext();
|
|
75
75
|
});
|
package/dist/stdio/progress.js
CHANGED
package/dist/tables.js
CHANGED
|
@@ -37,11 +37,10 @@ module.exports = __toCommonJS(tables_exports);
|
|
|
37
37
|
var import_yoctocolors_cjs = __toESM(require("./external/yoctocolors-cjs"));
|
|
38
38
|
var import_strings = require("./strings");
|
|
39
39
|
function displayWidth(text) {
|
|
40
|
-
return (0, import_strings.
|
|
40
|
+
return (0, import_strings.stringWidth)(text);
|
|
41
41
|
}
|
|
42
42
|
function padText(text, width, align = "left") {
|
|
43
|
-
const
|
|
44
|
-
const textWidth = stripped.length;
|
|
43
|
+
const textWidth = displayWidth(text);
|
|
45
44
|
const padding = Math.max(0, width - textWidth);
|
|
46
45
|
switch (align) {
|
|
47
46
|
case "right":
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Universal schema validation for Zod-style schemas (Zod v3,
|
|
3
|
+
* v4, and any `safeParse`-shaped duck type).
|
|
4
|
+
*
|
|
5
|
+
* Accepts a schema and returns a tagged result.
|
|
6
|
+
* - `{ ok: true, value }` — validation passed, `value` is typed as the
|
|
7
|
+
* schema's inferred output (`z.infer<typeof S>`).
|
|
8
|
+
* - `{ ok: false, errors }` — validation failed, `errors` is a normalized
|
|
9
|
+
* list of `{ path, message }`.
|
|
10
|
+
*
|
|
11
|
+
* Zod is detected purely structurally via `.safeParse` — no runtime import of
|
|
12
|
+
* the `zod` package is required by socket-lib.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
* Socket-lib additionally recognizes TypeBox schemas for its own internal
|
|
16
|
+
* use (e.g. `src/ipc.ts`'s stub-file validation). That path is not a
|
|
17
|
+
* supported consumer API — callers should use Zod.
|
|
18
|
+
*/
|
|
19
|
+
import type { Schema } from './types';
|
|
20
|
+
/**
|
|
21
|
+
* TypeBox's `Kind` symbol. We reference it structurally for schema detection
|
|
22
|
+
* rather than importing it from `@sinclair/typebox` — detection scans the
|
|
23
|
+
* schema's own-symbol keys for one whose description is `'TypeBox.Kind'`.
|
|
24
|
+
* The `Value` runtime is only loaded lazily when a TypeBox schema is seen.
|
|
25
|
+
*/
|
|
26
|
+
type TypeBoxKindSymbol = symbol & {
|
|
27
|
+
__typeBoxKindBrand?: never;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Structural minimum of a TypeBox `TSchema`. The phantom `static` field is
|
|
31
|
+
* the type TypeBox uses for inference (`Static<T> = T['static']`).
|
|
32
|
+
*/
|
|
33
|
+
interface TypeBoxLikeSchema {
|
|
34
|
+
[k: TypeBoxKindSymbol]: string;
|
|
35
|
+
static: unknown;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Structural shape of a Zod v4 schema — carries output type on `_zod.output`.
|
|
39
|
+
*/
|
|
40
|
+
interface ZodV4LikeSchema<O = unknown> {
|
|
41
|
+
_zod: {
|
|
42
|
+
output: O;
|
|
43
|
+
};
|
|
44
|
+
safeParse(data: unknown): unknown;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Structural shape of a Zod v3 schema — carries output type on `_output`.
|
|
48
|
+
*/
|
|
49
|
+
interface ZodV3LikeSchema<O = unknown> {
|
|
50
|
+
_output: O;
|
|
51
|
+
safeParse(data: unknown): unknown;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Any schema kind this helper accepts.
|
|
55
|
+
*/
|
|
56
|
+
export type AnySchema = TypeBoxLikeSchema | ZodV4LikeSchema<unknown> | ZodV3LikeSchema<unknown> | Schema<unknown>;
|
|
57
|
+
/**
|
|
58
|
+
* Infer the validated output type from any supported schema kind.
|
|
59
|
+
*
|
|
60
|
+
* Order matters: TypeBox schemas also carry a phantom `static` field, so we
|
|
61
|
+
* check for TypeBox before falling through to Zod and the duck-type.
|
|
62
|
+
*/
|
|
63
|
+
export type Infer<S> = S extends {
|
|
64
|
+
static: infer Static;
|
|
65
|
+
} ? Static : S extends {
|
|
66
|
+
_zod: {
|
|
67
|
+
output: infer O;
|
|
68
|
+
};
|
|
69
|
+
} ? O : S extends {
|
|
70
|
+
_output: infer O;
|
|
71
|
+
} ? O : S extends Schema<infer T> ? T : unknown;
|
|
72
|
+
/**
|
|
73
|
+
* A single normalized validation error.
|
|
74
|
+
* - `path` is a dotted or slash-separated identifier locating the bad value.
|
|
75
|
+
* - `message` is human-readable.
|
|
76
|
+
*/
|
|
77
|
+
export interface ValidationIssue {
|
|
78
|
+
/** Array path into the value (e.g. `['user', 'age']`). */
|
|
79
|
+
path: Array<string | number>;
|
|
80
|
+
/** Human-readable description of the failure. */
|
|
81
|
+
message: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Tagged-union result of {@link validateSchema}. Callers narrow on `ok`.
|
|
85
|
+
*/
|
|
86
|
+
export type ValidateResult<T> = {
|
|
87
|
+
ok: true;
|
|
88
|
+
value: T;
|
|
89
|
+
} | {
|
|
90
|
+
ok: false;
|
|
91
|
+
errors: ValidationIssue[];
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Validate `data` against a Zod-style `schema`. Non-throwing.
|
|
95
|
+
*
|
|
96
|
+
* Accepted schemas:
|
|
97
|
+
* - `zod` schemas, v3 and v4 (detected via `.safeParse` on the schema)
|
|
98
|
+
* - Any object conforming to {@link Schema} (the socket-lib duck type)
|
|
99
|
+
*
|
|
100
|
+
* The return type narrows `value` to {@link Infer | `Infer<S>`}, so callers
|
|
101
|
+
* get `z.infer<typeof S>` with no casts.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { z } from 'zod'
|
|
106
|
+
* const U = z.object({ name: z.string() })
|
|
107
|
+
* const r = validateSchema(U, data)
|
|
108
|
+
* if (r.ok) r.value.name // string
|
|
109
|
+
* ```
|
|
110
|
+
*
|
|
111
|
+
* Errors are normalized to {@link ValidationIssue}: `{ path, message }`.
|
|
112
|
+
*/
|
|
113
|
+
export declare function validateSchema<S>(schema: S, data: unknown): ValidateResult<Infer<S>>;
|
|
114
|
+
/**
|
|
115
|
+
* Parse `data` against `schema` and return the validated value. Throws if
|
|
116
|
+
* validation fails. This is the throwing twin of {@link validateSchema}.
|
|
117
|
+
*
|
|
118
|
+
* Use when you want fail-fast semantics at a trust boundary. For recoverable
|
|
119
|
+
* validation (form input, external configs), prefer {@link validateSchema}.
|
|
120
|
+
*
|
|
121
|
+
* @throws {Error} When validation fails. The message lists all issues.
|
|
122
|
+
*/
|
|
123
|
+
export declare function parseSchema<S>(schema: S, data: unknown): Infer<S>;
|
|
124
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
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 validate_schema_exports = {};
|
|
22
|
+
__export(validate_schema_exports, {
|
|
23
|
+
parseSchema: () => parseSchema,
|
|
24
|
+
validateSchema: () => validateSchema
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(validate_schema_exports);
|
|
27
|
+
function isTypeBoxSchema(schema) {
|
|
28
|
+
if (schema === null || typeof schema !== "object") {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
for (const sym of Object.getOwnPropertySymbols(schema)) {
|
|
32
|
+
if (sym.description === "TypeBox.Kind") {
|
|
33
|
+
return typeof schema[sym] === "string";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
function normalizeTypeBoxErrors(errors) {
|
|
39
|
+
const out = [];
|
|
40
|
+
for (const err of errors) {
|
|
41
|
+
const segs = err.path.split("/").filter(Boolean);
|
|
42
|
+
out.push({
|
|
43
|
+
path: segs.map((s) => {
|
|
44
|
+
const n = Number(s);
|
|
45
|
+
return Number.isInteger(n) && String(n) === s ? n : s;
|
|
46
|
+
}),
|
|
47
|
+
message: err.message
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
function normalizeZodError(err) {
|
|
53
|
+
if (err === null || typeof err !== "object") {
|
|
54
|
+
return [{ path: [], message: String(err) }];
|
|
55
|
+
}
|
|
56
|
+
const issues = err.issues;
|
|
57
|
+
if (!Array.isArray(issues)) {
|
|
58
|
+
return [{ path: [], message: "Unknown validation error" }];
|
|
59
|
+
}
|
|
60
|
+
return issues.map((issue) => {
|
|
61
|
+
const i = issue;
|
|
62
|
+
return {
|
|
63
|
+
path: Array.isArray(i.path) ? i.path : [],
|
|
64
|
+
message: typeof i.message === "string" ? i.message : "Invalid value"
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function validateSchema(schema, data) {
|
|
69
|
+
if (isTypeBoxSchema(schema)) {
|
|
70
|
+
const { Value } = require("../external/@sinclair/typebox/value");
|
|
71
|
+
if (Value.Check(schema, data)) {
|
|
72
|
+
return { ok: true, value: data };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
errors: normalizeTypeBoxErrors(Value.Errors(schema, data))
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (schema !== null && typeof schema === "object" && typeof schema.safeParse === "function") {
|
|
80
|
+
const result = schema.safeParse(data);
|
|
81
|
+
if (result.success === true) {
|
|
82
|
+
return {
|
|
83
|
+
ok: true,
|
|
84
|
+
value: result.data
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
errors: normalizeZodError(result.error)
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
throw new TypeError(
|
|
93
|
+
"validateSchema: unsupported schema kind. Expected a TypeBox schema, a Zod schema, or an object with a safeParse method."
|
|
94
|
+
);
|
|
95
|
+
}
|
|
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
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
105
|
+
0 && (module.exports = {
|
|
106
|
+
parseSchema,
|
|
107
|
+
validateSchema
|
|
108
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@socketsecurity/lib",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.20.1",
|
|
4
4
|
"packageManager": "pnpm@11.0.0-rc.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Core utilities and infrastructure for Socket.dev security tools",
|
|
@@ -663,6 +663,10 @@
|
|
|
663
663
|
"types": "./dist/validation/types.d.ts",
|
|
664
664
|
"default": "./dist/validation/types.js"
|
|
665
665
|
},
|
|
666
|
+
"./validation/validate-schema": {
|
|
667
|
+
"types": "./dist/validation/validate-schema.d.ts",
|
|
668
|
+
"default": "./dist/validation/validate-schema.js"
|
|
669
|
+
},
|
|
666
670
|
"./versions": {
|
|
667
671
|
"types": "./dist/versions.d.ts",
|
|
668
672
|
"default": "./dist/versions.js"
|
|
@@ -671,10 +675,6 @@
|
|
|
671
675
|
"types": "./dist/words.d.ts",
|
|
672
676
|
"default": "./dist/words.js"
|
|
673
677
|
},
|
|
674
|
-
"./zod": {
|
|
675
|
-
"types": "./dist/zod.d.ts",
|
|
676
|
-
"default": "./dist/zod.js"
|
|
677
|
-
},
|
|
678
678
|
"./data/extensions.json": "./data/extensions.json",
|
|
679
679
|
"./package.json": "./package.json",
|
|
680
680
|
"./tsconfig.dts.json": "./tsconfig.dts.json",
|
|
@@ -720,10 +720,11 @@
|
|
|
720
720
|
"@npmcli/arborist": "9.1.4",
|
|
721
721
|
"@npmcli/package-json": "7.0.0",
|
|
722
722
|
"@npmcli/promise-spawn": "8.0.3",
|
|
723
|
+
"@sinclair/typebox": "0.34.49",
|
|
723
724
|
"@socketregistry/is-unicode-supported": "1.0.5",
|
|
724
725
|
"@socketregistry/packageurl-js": "1.4.2",
|
|
725
726
|
"@socketregistry/yocto-spinner": "1.0.25",
|
|
726
|
-
"@socketsecurity/lib-stable": "npm:@socketsecurity/lib@5.19.
|
|
727
|
+
"@socketsecurity/lib-stable": "npm:@socketsecurity/lib@5.19.1",
|
|
727
728
|
"@types/node": "24.9.2",
|
|
728
729
|
"@typescript/native-preview": "7.0.0-dev.20260415.1",
|
|
729
730
|
"@vitest/coverage-v8": "4.0.3",
|