@socketsecurity/lib 5.26.1 → 5.28.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +1 -1
  3. package/dist/bin/check-primordials.d.ts +18 -0
  4. package/dist/bin/check-primordials.js +229 -0
  5. package/dist/bin/check.d.ts +15 -0
  6. package/dist/bin/check.js +73 -0
  7. package/dist/bin/socket-lib.d.ts +17 -0
  8. package/dist/bin/socket-lib.js +64 -0
  9. package/dist/checks/primordials.d.ts +110 -0
  10. package/dist/checks/primordials.js +244 -0
  11. package/dist/compression.d.ts +218 -0
  12. package/dist/compression.js +275 -0
  13. package/dist/constants/socket.js +1 -1
  14. package/dist/crypto.js +3 -10
  15. package/dist/dlx/package.d.ts +30 -0
  16. package/dist/dlx/package.js +5 -3
  17. package/dist/external/adm-zip.js +2 -2
  18. package/dist/external/tar-fs.js +2 -2
  19. package/dist/fs.js +31 -45
  20. package/dist/node/async-hooks.d.ts +6 -0
  21. package/dist/node/async-hooks.js +34 -0
  22. package/dist/node/child-process.d.ts +11 -0
  23. package/dist/node/child-process.js +34 -0
  24. package/dist/node/crypto.d.ts +6 -0
  25. package/dist/node/crypto.js +34 -0
  26. package/dist/node/events.d.ts +6 -0
  27. package/dist/node/events.js +34 -0
  28. package/dist/node/fs-promises.d.ts +6 -0
  29. package/dist/node/fs-promises.js +34 -0
  30. package/dist/node/fs.d.ts +14 -0
  31. package/dist/node/fs.js +34 -0
  32. package/dist/node/http.d.ts +6 -0
  33. package/dist/node/http.js +34 -0
  34. package/dist/node/https.d.ts +6 -0
  35. package/dist/node/https.js +34 -0
  36. package/dist/node/os.d.ts +6 -0
  37. package/dist/node/os.js +34 -0
  38. package/dist/node/path.d.ts +6 -0
  39. package/dist/node/path.js +34 -0
  40. package/dist/node/timers-promises.d.ts +6 -0
  41. package/dist/node/timers-promises.js +34 -0
  42. package/dist/node/url.d.ts +6 -0
  43. package/dist/node/url.js +34 -0
  44. package/dist/node/util.d.ts +6 -0
  45. package/dist/node/util.js +34 -0
  46. package/dist/primordials.d.ts +76 -2
  47. package/dist/primordials.js +294 -23
  48. package/dist/sea/util.d.ts +43 -0
  49. package/dist/{sea.js → sea/util.js} +7 -7
  50. package/dist/smol/primordial.d.ts +80 -0
  51. package/dist/smol/primordial.js +46 -0
  52. package/dist/smol/util.d.ts +87 -0
  53. package/dist/smol/util.js +59 -0
  54. package/dist/smol/versions.d.ts +46 -0
  55. package/dist/smol/versions.js +46 -0
  56. package/dist/spawn.js +13 -28
  57. package/dist/versions.js +27 -22
  58. package/package.json +102 -9
  59. package/dist/sea.d.ts +0 -30
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ /* Socket Lib - Built with esbuild */
3
+ "use strict";
4
+ var __create = Object.create;
5
+ var __defProp = Object.defineProperty;
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __getOwnPropNames = Object.getOwnPropertyNames;
8
+ var __getProtoOf = Object.getPrototypeOf;
9
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
23
+ // If the importer is in node compatibility mode or this is not an ESM
24
+ // file that has been converted to a CommonJS file using a Babel-
25
+ // compatible transform (i.e. "__esModule" has not been set), then set
26
+ // "default" to the CommonJS "module.exports" for node compatibility.
27
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
28
+ mod
29
+ ));
30
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+ var primordials_exports = {};
32
+ __export(primordials_exports, {
33
+ checkPrimordials: () => checkPrimordials,
34
+ extractPrimordialsNames: () => extractPrimordialsNames,
35
+ extractTsExports: () => extractTsExports,
36
+ resolveSocketLibPrimordials: () => resolveSocketLibPrimordials
37
+ });
38
+ module.exports = __toCommonJS(primordials_exports);
39
+ var import_node_fs = require("node:fs");
40
+ var import_node_path = __toESM(require("node:path"));
41
+ var import_arrays = require("../arrays");
42
+ const NAME_HEAD_RE = /^([A-Za-z_$][A-Za-z0-9_$]*)/;
43
+ function stripComments(src) {
44
+ let out = src.replace(/\/\*[\s\S]*?\*\//g, "");
45
+ out = out.replace(/^[\t ]*\/\/.*$/gm, "");
46
+ out = out.replace(/[\t ]+\/\/.*$/gm, "");
47
+ return out;
48
+ }
49
+ function collectJsFiles(dir) {
50
+ const out = [];
51
+ if (!(0, import_node_fs.existsSync)(dir)) {
52
+ return out;
53
+ }
54
+ const stack = [dir];
55
+ while (stack.length > 0) {
56
+ const cur = stack.pop();
57
+ let entries;
58
+ try {
59
+ entries = (0, import_node_fs.readdirSync)(cur);
60
+ } catch {
61
+ continue;
62
+ }
63
+ for (const name of entries) {
64
+ const full = import_node_path.default.join(cur, name);
65
+ let stat;
66
+ try {
67
+ stat = (0, import_node_fs.statSync)(full);
68
+ } catch {
69
+ continue;
70
+ }
71
+ if (stat.isDirectory()) {
72
+ stack.push(full);
73
+ } else if (stat.isFile() && full.endsWith(".js")) {
74
+ out.push(full);
75
+ }
76
+ }
77
+ }
78
+ return out;
79
+ }
80
+ function extractPrimordialsNames(src) {
81
+ const cleaned = stripComments(src);
82
+ const re = /const\s*\{\s*([^}]*?)\}\s*=\s*primordials\b/g;
83
+ const out = [];
84
+ let m;
85
+ while ((m = re.exec(cleaned)) !== null) {
86
+ for (const raw of m[1].split(",")) {
87
+ const trimmed = raw.trim();
88
+ if (!trimmed) {
89
+ continue;
90
+ }
91
+ const nameMatch = NAME_HEAD_RE.exec(trimmed);
92
+ if (nameMatch) {
93
+ out.push(nameMatch[1]);
94
+ }
95
+ }
96
+ }
97
+ return out;
98
+ }
99
+ function extractTsExports(src) {
100
+ const out = /* @__PURE__ */ new Set();
101
+ for (const m of src.matchAll(
102
+ /^export\s+(?:declare\s+)?const\s+([A-Za-z_$][A-Za-z0-9_$]*)/gm
103
+ )) {
104
+ out.add(m[1]);
105
+ }
106
+ for (const m of src.matchAll(
107
+ /^export\s+(?:declare\s+)?function\s+([A-Za-z_$][A-Za-z0-9_$]*)/gm
108
+ )) {
109
+ out.add(m[1]);
110
+ }
111
+ for (const m of src.matchAll(/^export\s*\{\s*([^}]+)\}/gm)) {
112
+ for (const raw of m[1].split(",")) {
113
+ const trimmed = raw.trim();
114
+ if (!trimmed) {
115
+ continue;
116
+ }
117
+ const nameMatch = NAME_HEAD_RE.exec(trimmed);
118
+ if (nameMatch) {
119
+ out.add(nameMatch[1]);
120
+ }
121
+ }
122
+ }
123
+ return [...out];
124
+ }
125
+ function resolveSocketLibPrimordials(config) {
126
+ if (config.socketLibPrimordialsPath) {
127
+ if (!(0, import_node_fs.existsSync)(config.socketLibPrimordialsPath)) {
128
+ throw new Error(
129
+ `socketLibPrimordialsPath does not exist: ${config.socketLibPrimordialsPath}`
130
+ );
131
+ }
132
+ return config.socketLibPrimordialsPath;
133
+ }
134
+ const repoRoot = config.repoRoot ?? process.cwd();
135
+ const sibling = import_node_path.default.resolve(
136
+ repoRoot,
137
+ "..",
138
+ "socket-lib",
139
+ "src",
140
+ "primordials.ts"
141
+ );
142
+ if ((0, import_node_fs.existsSync)(sibling)) {
143
+ return sibling;
144
+ }
145
+ const installed = import_node_path.default.resolve(
146
+ repoRoot,
147
+ "node_modules",
148
+ "@socketsecurity",
149
+ "lib",
150
+ "dist",
151
+ "primordials.d.ts"
152
+ );
153
+ if ((0, import_node_fs.existsSync)(installed)) {
154
+ return installed;
155
+ }
156
+ throw new Error(
157
+ `Cannot locate socket-lib primordials source. Looked at:
158
+ ${sibling}
159
+ ${installed}
160
+ Either clone socket-lib at ../socket-lib or run \`pnpm install\`.`
161
+ );
162
+ }
163
+ function checkPrimordials(config) {
164
+ const repoRoot = config.repoRoot ?? process.cwd();
165
+ const used = /* @__PURE__ */ new Set();
166
+ const usedToFiles = /* @__PURE__ */ new Map();
167
+ for (const dir of config.scanDirs) {
168
+ const fullDir = import_node_path.default.resolve(repoRoot, dir);
169
+ const jsFiles = collectJsFiles(fullDir);
170
+ for (const file of jsFiles) {
171
+ let src;
172
+ try {
173
+ src = (0, import_node_fs.readFileSync)(file, "utf8");
174
+ } catch {
175
+ continue;
176
+ }
177
+ if (!src.includes("primordials")) {
178
+ continue;
179
+ }
180
+ const names = extractPrimordialsNames(src);
181
+ if (names.length === 0) {
182
+ continue;
183
+ }
184
+ const rel = import_node_path.default.relative(repoRoot, file);
185
+ for (const name of names) {
186
+ used.add(name);
187
+ const arr = usedToFiles.get(name) ?? [];
188
+ if (!arr.includes(rel)) {
189
+ arr.push(rel);
190
+ }
191
+ usedToFiles.set(name, arr);
192
+ }
193
+ }
194
+ }
195
+ const socketLibPath = resolveSocketLibPrimordials(config);
196
+ const socketLibNames = new Set(
197
+ extractTsExports((0, import_node_fs.readFileSync)(socketLibPath, "utf8"))
198
+ );
199
+ const findings = [];
200
+ for (const name of [...used].sort()) {
201
+ if (config.nodeInternalOnly.has(name)) {
202
+ continue;
203
+ }
204
+ if (socketLibNames.has(name)) {
205
+ continue;
206
+ }
207
+ const aliased = config.aliasMap.get(name);
208
+ if (aliased) {
209
+ if (socketLibNames.has(aliased)) {
210
+ continue;
211
+ }
212
+ findings.push({
213
+ kind: "missing-from-socket-lib",
214
+ name,
215
+ files: usedToFiles.get(name) ?? [],
216
+ hint: `\`${name}\` is mapped to socket-lib's \`${aliased}\`, but \`${aliased}\` is not exported. Add \`export const ${aliased} = ${name}\` to socket-lib/src/primordials.ts.`
217
+ });
218
+ continue;
219
+ }
220
+ findings.push({
221
+ kind: "unmapped",
222
+ name,
223
+ files: usedToFiles.get(name) ?? [],
224
+ hint: `\`${name}\` is destructured from \`primordials\` but no socket-lib mapping exists. Pick one: ` + (0, import_arrays.joinOr)([
225
+ `add \`${name}\` to socket-lib/src/primordials.ts`,
226
+ `add a \`${name}\` \u2192 \`<libName>\` entry to the alias map`,
227
+ `add \`${name}\` to nodeInternalOnly (if Node-internal only)`
228
+ ]) + "."
229
+ });
230
+ }
231
+ return {
232
+ used,
233
+ usedToFiles,
234
+ socketLibNames,
235
+ findings
236
+ };
237
+ }
238
+ // Annotate the CommonJS export names for ESM import in node:
239
+ 0 && (module.exports = {
240
+ checkPrimordials,
241
+ extractPrimordialsNames,
242
+ extractTsExports,
243
+ resolveSocketLibPrimordials
244
+ });
@@ -0,0 +1,218 @@
1
+ /**
2
+ * @fileoverview Async compression / decompression helpers (brotli + gzip).
3
+ *
4
+ * Three calling shapes cover most use cases:
5
+ *
6
+ * 1. In-memory — compress/decompress a Buffer or string, get a Buffer
7
+ * back. For payloads small enough to fit in memory.
8
+ *
9
+ * const compressed = await compressBrotli(JSON.stringify(payload))
10
+ * const original = await decompressBrotli(compressed)
11
+ *
12
+ * 2. File-to-file — stream pipeline through zlib, no memory hit.
13
+ * For arbitrary-sized files (build artifacts, scan output, logs).
14
+ *
15
+ * await compressBrotliFile('input.json', 'input.json.br')
16
+ * await decompressBrotliFile('input.json.br', 'input.json')
17
+ *
18
+ * 3. Raw streams — use directly in your own pipeline. The factory
19
+ * returns the underlying zlib transform so you can compose it
20
+ * with anything (e.g. tar pipelines, HTTP body streams).
21
+ *
22
+ * readable.pipe(createBrotliCompressor()).pipe(writable)
23
+ *
24
+ * Detection:
25
+ *
26
+ * - `isBrotliCompressed(buf)` — peek the first byte for the brotli
27
+ * magic-byte signature (no full parse).
28
+ * - `hasBrotliExtension(path)` — `.br` / `.brotli` filename suffix.
29
+ *
30
+ * Compression-level defaults are tuned for one-shot CLI use: brotli at
31
+ * quality 11 (max compression, slow but it's a one-shot upload), gzip
32
+ * at level 6 (the zlib default). Override via the `level` option if
33
+ * the call is hot or the input is large.
34
+ */
35
+ import { Buffer } from 'node:buffer';
36
+ import { type BrotliOptions, type ZlibOptions } from 'node:zlib';
37
+ export interface CompressOptions {
38
+ /**
39
+ * Compression level. Brotli accepts 0–11 (11 = max, slowest). Gzip
40
+ * accepts 0–9 (9 = max). Defaults: brotli 11, gzip 6.
41
+ */
42
+ level?: number | undefined;
43
+ /**
44
+ * Hint for the input size in bytes. Lets brotli pick a better
45
+ * window/blocking strategy. Pass when known; ignored for gzip.
46
+ */
47
+ size?: number | undefined;
48
+ }
49
+ /**
50
+ * Options for the file-to-file helpers. Pass `{ inPlace: true }` to
51
+ * skip the explicit destPath argument: the helper picks the
52
+ * canonical destination (`.br` / `.gz` suffix on compress; suffix
53
+ * stripped on decompress) and removes the source file on success.
54
+ *
55
+ * await compressBrotliFile('input.json', { inPlace: true })
56
+ * // => writes input.json.br, deletes input.json
57
+ *
58
+ * await decompressBrotliFile('input.json.br', { inPlace: true })
59
+ * // => writes input.json, deletes input.json.br
60
+ */
61
+ export interface CompressFileOptions extends CompressOptions {
62
+ /**
63
+ * Replace the source file: derive destPath from srcPath, then
64
+ * `safeDelete(srcPath)` after the write succeeds. When set, the
65
+ * `destPath` positional argument must be omitted.
66
+ */
67
+ inPlace?: boolean | undefined;
68
+ }
69
+ interface ResolvedBrotliOptions extends BrotliOptions {
70
+ params: NonNullable<BrotliOptions['params']>;
71
+ }
72
+ /**
73
+ * Translate `CompressOptions` into the `BrotliOptions` zlib expects.
74
+ * Defaults `quality` to 11 (max) when not provided, and forwards a
75
+ * positive `size` hint. Exposed for callers building their own zlib
76
+ * pipelines and for unit-test coverage.
77
+ */
78
+ export declare function resolveBrotliOptions(options: CompressOptions | undefined): ResolvedBrotliOptions;
79
+ /**
80
+ * Translate `CompressOptions` into the `ZlibOptions` zlib expects.
81
+ * Returns an empty options object when no `level` is given (zlib uses
82
+ * its default, level 6). Exposed for parity with
83
+ * `resolveBrotliOptions` and for unit-test coverage.
84
+ */
85
+ export declare function resolveGzipOptions(options: CompressOptions | undefined): ZlibOptions;
86
+ /**
87
+ * Compress a string or Buffer with brotli. Strings are encoded as UTF-8
88
+ * before compression — pass an explicit Buffer if you have non-UTF-8
89
+ * input.
90
+ */
91
+ export declare function compressBrotli(input: string | Buffer, options?: CompressOptions | undefined): Promise<Buffer>;
92
+ /**
93
+ * Decompress a brotli-compressed Buffer.
94
+ */
95
+ export declare function decompressBrotli(input: Buffer): Promise<Buffer>;
96
+ /**
97
+ * Stream-compress a file with brotli. Two call shapes:
98
+ *
99
+ * compressBrotliFile(src, dest, options?)
100
+ * Writes compressed output to `dest`. Source is left intact.
101
+ *
102
+ * compressBrotliFile(src, { inPlace: true, ...options })
103
+ * Writes to `<src>.br` and deletes `src` after the write
104
+ * succeeds. Returns the new path.
105
+ *
106
+ * Returns the destination path in both shapes — same string the
107
+ * caller passed in or the computed `.br` path for inPlace.
108
+ */
109
+ export declare function compressBrotliFile(srcPath: string, destPath: string, options?: CompressOptions | undefined): Promise<string>;
110
+ export declare function compressBrotliFile(srcPath: string, options: CompressFileOptions): Promise<string>;
111
+ /**
112
+ * Stream-decompress a brotli file. Two call shapes:
113
+ *
114
+ * decompressBrotliFile(src, dest)
115
+ * Writes decompressed output to `dest`. Source is left intact.
116
+ *
117
+ * decompressBrotliFile(src, { inPlace: true })
118
+ * Strips the `.br`/`.brotli` suffix to derive the destination,
119
+ * then deletes the compressed source after the write succeeds.
120
+ * Throws if `src` has no recognizable extension.
121
+ *
122
+ * Returns the destination path in both shapes.
123
+ */
124
+ export declare function decompressBrotliFile(srcPath: string, destPath: string): Promise<string>;
125
+ export declare function decompressBrotliFile(srcPath: string, options: CompressFileOptions): Promise<string>;
126
+ /**
127
+ * Create a brotli compress transform stream. Compose into your own
128
+ * pipeline. The `pipeline` from `node:stream/promises` is the safe
129
+ * way to wire it up — it handles error propagation across all stages.
130
+ */
131
+ export declare function createBrotliCompressor(options?: CompressOptions | undefined): import("zlib").BrotliCompress;
132
+ /**
133
+ * Create a brotli decompress transform stream.
134
+ */
135
+ export declare function createBrotliDecompressor(): import("zlib").BrotliDecompress;
136
+ /**
137
+ * Compress a string or Buffer with gzip. Strings are encoded as UTF-8
138
+ * before compression. Default level is 6 (zlib default).
139
+ */
140
+ export declare function compressGzip(input: string | Buffer, options?: CompressOptions | undefined): Promise<Buffer>;
141
+ /**
142
+ * Decompress a gzip-compressed Buffer.
143
+ */
144
+ export declare function decompressGzip(input: Buffer): Promise<Buffer>;
145
+ /**
146
+ * Stream-compress a file with gzip. Two call shapes:
147
+ *
148
+ * compressGzipFile(src, dest, options?)
149
+ * Writes compressed output to `dest`. Source is left intact.
150
+ *
151
+ * compressGzipFile(src, { inPlace: true, ...options })
152
+ * Writes to `<src>.gz` and deletes `src` after the write
153
+ * succeeds. Returns the new path.
154
+ */
155
+ export declare function compressGzipFile(srcPath: string, destPath: string, options?: CompressOptions | undefined): Promise<string>;
156
+ export declare function compressGzipFile(srcPath: string, options: CompressFileOptions): Promise<string>;
157
+ /**
158
+ * Stream-decompress a gzip file. Two call shapes:
159
+ *
160
+ * decompressGzipFile(src, dest)
161
+ * Writes decompressed output to `dest`. Source is left intact.
162
+ *
163
+ * decompressGzipFile(src, { inPlace: true })
164
+ * Strips the `.gz`/`.gzip`/`.tgz` suffix to derive the
165
+ * destination, then deletes the compressed source after the
166
+ * write succeeds. Throws if `src` has no recognizable extension.
167
+ */
168
+ export declare function decompressGzipFile(srcPath: string, destPath: string): Promise<string>;
169
+ export declare function decompressGzipFile(srcPath: string, options: CompressFileOptions): Promise<string>;
170
+ /**
171
+ * Create a gzip compress transform stream.
172
+ */
173
+ export declare function createGzipCompressor(options?: CompressOptions | undefined): import("zlib").Gzip;
174
+ /**
175
+ * Create a gzip decompress transform stream.
176
+ */
177
+ export declare function createGzipDecompressor(): import("zlib").Gunzip;
178
+ /**
179
+ * Cheap pre-flight check: does the buffer look like it could be
180
+ * brotli? Returns false for inputs too short to be valid. Brotli has
181
+ * no fixed magic bytes, so this is intentionally permissive — the
182
+ * authoritative test is `decompressBrotli(buf)` succeeding. Use for
183
+ * UI hints, not correctness.
184
+ */
185
+ export declare function isBrotliCompressed(input: Buffer): boolean;
186
+ /**
187
+ * Magic-byte check for gzip. Reads the first two bytes and matches
188
+ * the gzip spec's 0x1f 0x8b signature. Authoritative.
189
+ */
190
+ export declare function isGzipCompressed(input: Buffer): boolean;
191
+ export declare const BROTLI_EXTS: ReadonlySet<string>;
192
+ export declare const GZIP_EXTS: ReadonlySet<string>;
193
+ /**
194
+ * Extension check for brotli paths — matches `.br` / `.brotli`
195
+ * (case-insensitive). Naming follows node:path's `extname`.
196
+ */
197
+ export declare function hasBrotliExt(filePath: string): boolean;
198
+ /**
199
+ * Extension check for gzip paths — matches `.gz` / `.gzip` / `.tgz`
200
+ * (case-insensitive). Naming follows node:path's `extname`.
201
+ */
202
+ export declare function hasGzipExt(filePath: string): boolean;
203
+ /**
204
+ * Strip the trailing extension from a filename when it matches one of
205
+ * `exts`. Returns the input unchanged when the trailing extname isn't
206
+ * in the set. Case-insensitive on the extension — preserves the rest
207
+ * of the path's casing.
208
+ *
209
+ * The `exts` set decides what counts. Pass `BROTLI_EXTS` / `GZIP_EXTS`
210
+ * (re-exported from this module) for the canonical compression sets,
211
+ * or your own set for custom classifiers.
212
+ *
213
+ * This helper is generic — it does NOT know that `.tgz` is short for
214
+ * `.tar.gz`. Callers that need that convention compose this with their
215
+ * own follow-up (see `decompressGzipFile` for the canonical example).
216
+ */
217
+ export declare function stripExt(filePath: string, exts: ReadonlySet<string>): string;
218
+ export {};