@socketsecurity/lib 6.0.0 → 6.0.2

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 (135) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +26 -17
  3. package/dist/ai/discover.js +2 -2
  4. package/dist/ai/spawn.js +3 -3
  5. package/dist/ai/worktree.js +3 -3
  6. package/dist/argv/parse-args-string.d.ts +30 -0
  7. package/dist/argv/parse-args-string.js +42 -0
  8. package/dist/bin/check-primordials.js +15 -10
  9. package/dist/bin/check.js +2 -2
  10. package/dist/bin/exec.d.ts +1 -1
  11. package/dist/bin/exec.js +2 -2
  12. package/dist/bin/socket-lib.js +2 -2
  13. package/dist/{ttl-cache/cache.js → cache/ttl/store.js} +15 -15
  14. package/dist/{ttl-cache → cache/ttl}/types.d.ts +1 -1
  15. package/dist/checks/primordials-defaults.d.ts +20 -0
  16. package/dist/checks/primordials-defaults.js +92 -0
  17. package/dist/colors/socket-palette.d.ts +69 -0
  18. package/dist/colors/socket-palette.js +91 -0
  19. package/dist/constants/socket.js +1 -1
  20. package/dist/cover/code.js +2 -2
  21. package/dist/cover/type.js +2 -2
  22. package/dist/debug/_internal.d.ts +1 -1
  23. package/dist/debug/_internal.js +2 -2
  24. package/dist/debug/output.js +5 -5
  25. package/dist/dlx/binary-types.d.ts +2 -2
  26. package/dist/dlx/binary.d.ts +2 -2
  27. package/dist/dlx/binary.js +3 -3
  28. package/dist/dlx/firewall.js +2 -2
  29. package/dist/dlx/manifest.js +2 -2
  30. package/dist/dlx/package.d.ts +2 -2
  31. package/dist/dlx/package.js +2 -2
  32. package/dist/dlx/types.d.ts +2 -2
  33. package/dist/eco/npm/npm/exec.d.ts +2 -2
  34. package/dist/eco/npm/npm/exec.js +2 -2
  35. package/dist/eco/npm/pnpm/exec.d.ts +1 -1
  36. package/dist/eco/npm/script.d.ts +1 -1
  37. package/dist/eco/npm/script.js +3 -3
  38. package/dist/eco/npm/yarnpkg/yarn/exec.d.ts +1 -1
  39. package/dist/{signal-exit → events/exit}/_internal.d.ts +1 -1
  40. package/dist/{signal-exit/register.js → events/exit/handler.js} +4 -4
  41. package/dist/{signal-exit → events/exit}/intercept.js +2 -2
  42. package/dist/{signal-exit → events/exit}/types.d.ts +1 -1
  43. package/dist/{warnings/event-target.d.ts → events/warning/handler.d.ts} +1 -1
  44. package/dist/{warnings/event-target.js → events/warning/handler.js} +4 -4
  45. package/dist/{warnings → events/warning}/suppress.d.ts +3 -3
  46. package/dist/{warnings → events/warning}/suppress.js +2 -2
  47. package/dist/external-tools/janus/asset-names.d.ts +7 -0
  48. package/dist/external-tools/janus/asset-names.js +5 -0
  49. package/dist/external-tools/janus/from-download.d.ts +1 -1
  50. package/dist/external-tools/janus/from-download.js +12 -4
  51. package/dist/fs/read-json-cache.d.ts +83 -0
  52. package/dist/fs/read-json-cache.js +156 -0
  53. package/dist/fs/read-json.d.ts +6 -1
  54. package/dist/fs/read-json.js +80 -8
  55. package/dist/fs/types.d.ts +14 -0
  56. package/dist/git/_internal.js +3 -3
  57. package/dist/github/refs-cache.d.ts +1 -1
  58. package/dist/github/refs-cache.js +2 -2
  59. package/dist/github/token.d.ts +1 -1
  60. package/dist/github/token.js +2 -2
  61. package/dist/globs/{glob.js → match.js} +3 -3
  62. package/dist/http-request/browser-fetch.d.ts +10 -0
  63. package/dist/http-request/browser-fetch.js +32 -0
  64. package/dist/http-request/browser.d.ts +190 -0
  65. package/dist/http-request/browser.js +224 -0
  66. package/dist/http-request/download-types.d.ts +2 -2
  67. package/dist/http-request/http-request.d.ts +12 -0
  68. package/dist/http-request/http-request.js +36 -0
  69. package/dist/http-request/node.d.ts +29 -0
  70. package/dist/http-request/{convenience.js → node.js} +9 -3
  71. package/dist/http-request/request-attempt.js +4 -0
  72. package/dist/http-request/request-types.d.ts +15 -0
  73. package/dist/http-request/request.js +5 -0
  74. package/dist/links/{link.d.ts → create.d.ts} +2 -2
  75. package/dist/links/{link.js → create.js} +3 -3
  76. package/dist/logger/_internal.d.ts +1 -1
  77. package/dist/logger/browser.d.ts +18 -0
  78. package/dist/logger/browser.js +58 -0
  79. package/dist/logger/console.js +3 -3
  80. package/dist/logger/default.d.ts +11 -0
  81. package/dist/logger/default.js +37 -0
  82. package/dist/logger/logger.d.ts +8 -403
  83. package/dist/logger/logger.js +3 -827
  84. package/dist/logger/node.d.ts +400 -0
  85. package/dist/logger/node.js +856 -0
  86. package/dist/logger/symbols-builder.d.ts +1 -1
  87. package/dist/logger/types.d.ts +1 -1
  88. package/dist/packages/isolation.js +3 -3
  89. package/dist/packages/provenance.d.ts +42 -0
  90. package/dist/packages/provenance.js +71 -0
  91. package/dist/packages/types.d.ts +2 -0
  92. package/dist/primordials/globals.d.ts +6 -3
  93. package/dist/primordials/globals.js +15 -9
  94. package/dist/primordials/map-set.d.ts +35 -0
  95. package/dist/primordials/map-set.js +43 -0
  96. package/dist/primordials/url.d.ts +1 -1
  97. package/dist/process/lock-manager.js +4 -4
  98. package/dist/{spawn → process/spawn}/_internal.js +3 -3
  99. package/dist/{spawn/spawn.js → process/spawn/child.js} +13 -13
  100. package/dist/{spawn → process/spawn}/errors.js +5 -5
  101. package/dist/{spawn → process/spawn}/stdio.js +1 -1
  102. package/dist/{spawn → process/spawn}/types.d.ts +3 -3
  103. package/dist/promises/types.d.ts +15 -2
  104. package/dist/releases/github-archives.js +2 -2
  105. package/dist/releases/github-downloads.js +4 -4
  106. package/dist/spinner/{registry.d.ts → default.d.ts} +1 -1
  107. package/dist/spinner/{registry.js → default.js} +3 -3
  108. package/dist/spinner/spinner.js +4 -4
  109. package/dist/spinner/with.d.ts +1 -1
  110. package/dist/stdio/divider.js +2 -2
  111. package/dist/stdio/footer.js +2 -2
  112. package/dist/stdio/header.js +2 -2
  113. package/dist/stdio/prompts.js +2 -2
  114. package/package.json +410 -132
  115. package/dist/http-request/convenience.d.ts +0 -104
  116. package/dist/promise-queue/types.d.ts +0 -10
  117. package/dist/ttl-cache/types.js +0 -18
  118. /package/dist/{ttl-cache/cache.d.ts → cache/ttl/store.d.ts} +0 -0
  119. /package/dist/{promise-queue → cache/ttl}/types.js +0 -0
  120. /package/dist/{signal-exit → events/exit}/_internal.js +0 -0
  121. /package/dist/{signal-exit/register.d.ts → events/exit/handler.d.ts} +0 -0
  122. /package/dist/{signal-exit → events/exit}/intercept.d.ts +0 -0
  123. /package/dist/{signal-exit → events/exit}/lifecycle.d.ts +0 -0
  124. /package/dist/{signal-exit → events/exit}/lifecycle.js +0 -0
  125. /package/dist/{signal-exit → events/exit}/signals.d.ts +0 -0
  126. /package/dist/{signal-exit → events/exit}/signals.js +0 -0
  127. /package/dist/{signal-exit → events/exit}/types.js +0 -0
  128. /package/dist/globs/{glob.d.ts → match.d.ts} +0 -0
  129. /package/dist/{spawn → process/spawn}/_internal.d.ts +0 -0
  130. /package/dist/{spawn/spawn.d.ts → process/spawn/child.d.ts} +0 -0
  131. /package/dist/{spawn → process/spawn}/errors.d.ts +0 -0
  132. /package/dist/{spawn → process/spawn}/stdio.d.ts +0 -0
  133. /package/dist/{spawn → process/spawn}/types.js +0 -0
  134. /package/dist/{promise-queue → promises}/queue.d.ts +0 -0
  135. /package/dist/{promise-queue → promises}/queue.js +0 -0
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var asset_names_exports = {};
22
22
  __export(asset_names_exports, {
23
23
  JANUS_ASSET_MAP: () => JANUS_ASSET_MAP,
24
+ JANUS_SUPPORTED_PLATFORM_ARCHES: () => JANUS_SUPPORTED_PLATFORM_ARCHES,
24
25
  getJanusAssetEntry: () => getJanusAssetEntry,
25
26
  getJanusDownloadUrl: () => getJanusDownloadUrl
26
27
  });
@@ -33,6 +34,9 @@ const JANUS_ASSET_MAP = (0, import_object.ObjectFreeze)({
33
34
  asset: "janus-aarch64-apple-darwin.tar.gz"
34
35
  })
35
36
  });
37
+ const JANUS_SUPPORTED_PLATFORM_ARCHES = (0, import_object.ObjectFreeze)(
38
+ Object.keys(JANUS_ASSET_MAP)
39
+ );
36
40
  function getJanusAssetEntry(platformArch) {
37
41
  return JANUS_ASSET_MAP[platformArch];
38
42
  }
@@ -47,6 +51,7 @@ function getJanusDownloadUrl(opts) {
47
51
  // Annotate the CommonJS export names for ESM import in node:
48
52
  0 && (module.exports = {
49
53
  JANUS_ASSET_MAP,
54
+ JANUS_SUPPORTED_PLATFORM_ARCHES,
50
55
  getJanusAssetEntry,
51
56
  getJanusDownloadUrl
52
57
  });
@@ -23,4 +23,4 @@ export interface JanusFromDownloadOptions {
23
23
  cacheDir?: string | undefined;
24
24
  downloader?: BinaryDownloader | undefined;
25
25
  }
26
- export declare function janusFromDownload(opts: JanusFromDownloadOptions): Promise<ResolvedJanus | undefined>;
26
+ export declare function janusFromDownload(opts: JanusFromDownloadOptions): Promise<ResolvedJanus>;
@@ -34,15 +34,24 @@ __export(from_download_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(from_download_exports);
36
36
  var import_node_path = __toESM(require("node:path"));
37
- var import_node_process = __toESM(require("node:process"));
38
37
  var import_socket = require("../../paths/socket");
39
38
  var import_from_download = require("../from-download");
40
39
  var import_asset_names = require("./asset-names");
41
40
  async function janusFromDownload(opts) {
42
41
  const { cacheDir, downloader, integrity, platformArch, version } = opts;
42
+ if (!import_asset_names.JANUS_SUPPORTED_PLATFORM_ARCHES.includes(platformArch)) {
43
+ const supported = import_asset_names.JANUS_SUPPORTED_PLATFORM_ARCHES.map((p) => `\`${p}\``).join(
44
+ ", "
45
+ );
46
+ throw new Error(
47
+ `janusFromDownload: platformArch must be one of [${supported}], got \`${platformArch}\`. Upstream janus only publishes the macOS arm64 build (see https://github.com/divmain/janus/releases); request \`darwin-arm64\` or use a different tool for other platforms.`
48
+ );
49
+ }
43
50
  const url = (0, import_asset_names.getJanusDownloadUrl)({ version, platformArch });
44
51
  if (!url) {
45
- return void 0;
52
+ throw new Error(
53
+ `janusFromDownload: no upstream asset for janus@${version} on \`${platformArch}\`. The platform is in the supported set but the version may be missing; check https://github.com/divmain/janus/releases/tag/v${version}.`
54
+ );
46
55
  }
47
56
  const extractedDir = cacheDir ?? import_node_path.default.join((0, import_socket.getSocketWheelhouseDir)(), "janus", version, platformArch);
48
57
  const archive = await (0, import_from_download.downloadAndExtractTool)({
@@ -52,9 +61,8 @@ async function janusFromDownload(opts) {
52
61
  extractedDir,
53
62
  downloader
54
63
  });
55
- const binary = import_node_process.default.platform === "win32" ? "janus.exe" : "janus";
56
64
  return {
57
- path: import_node_path.default.join(extractedDir, binary),
65
+ path: import_node_path.default.join(extractedDir, "janus"),
58
66
  source: "download",
59
67
  integrity: archive.integrity
60
68
  };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @file Process-scoped LRU cache for `readJson` / `readJsonSync` results, keyed
3
+ * by absolute path + stat (`ino + size + mtimeMs`). Why default-on caching is
4
+ * safe:
5
+ *
6
+ * - Stat-validated keys: a `stat()` call before serving a cache hit ensures the
7
+ * file hasn't changed (mtime + size mismatch ⇒ cache miss, re-read).
8
+ * - Defensive clone on hit: every hit returns `structuredClone(parsed)` so
9
+ * callers can mutate the returned object without poisoning the cache for
10
+ * the next reader. The clone cost is far less than re-read + re-parse for
11
+ * anything bigger than a trivial JSON document.
12
+ * - Reviver opt-out: when the caller passes a `reviver` function, we skip the
13
+ * cache. Function identity isn't safely hashable across boundaries, and the
14
+ * reviver can produce a different shape from the same bytes.
15
+ * - Per-call escape hatch: `cache: false` in the options bypasses the cache for
16
+ * cases where staleness must be observed (file-watcher tooling, etc.).
17
+ * - Bounded growth: an LRU cap (default 256 entries) protects long-running
18
+ * daemons. Tunable via `SOCKET_LIB_READ_JSON_CACHE_MAX` env or
19
+ * `setReadJsonCacheMax()`.
20
+ * - Test escape hatch: `clearReadJsonCache()` resets the whole cache between
21
+ * test cases that rely on fresh reads. Not cached:
22
+ * - Read failures (ENOENT under `throws: false` returns `undefined`). Caching
23
+ * undefined would silently miss a file that gets created later.
24
+ * - Reads with a `reviver` (see above).
25
+ * - Reads with explicit `cache: false`.
26
+ * - Relative paths whose `resolvePath` would change CWD-sensitively. We key on
27
+ * the literal input path, so callers passing relative paths from different
28
+ * CWDs would get separate cache entries — correct but pessimistic.
29
+ */
30
+ import type { JsonValue } from '../json/types';
31
+ /**
32
+ * Drop all cached entries. Tests call this between cases that depend on a fresh
33
+ * read; long-running daemons can call it on file-watcher invalidation events
34
+ * for paths the daemon knows are about to change in bulk.
35
+ */
36
+ export declare function clearReadJsonCache(): void;
37
+ /**
38
+ * Look up a cached parse result. Returns a fresh structured clone on hit (so
39
+ * callers can mutate freely), or `undefined` on miss.
40
+ *
41
+ * @param key Cache key — absolute file path. Caller resolves any relative
42
+ * inputs to absolute so two different CWDs don't share an entry.
43
+ * @param ino Inode (or `0` on platforms without one — Windows reports 0 from
44
+ * the Node `fs.Stats` shim, in which case size + mtimeMs carry the
45
+ * invalidation signal).
46
+ * @param size File size in bytes.
47
+ * @param mtimeMs Modification time in milliseconds.
48
+ */
49
+ export declare function getCachedJson(key: string, ino: number, size: number, mtimeMs: number): JsonValue | undefined;
50
+ /**
51
+ * Snapshot diagnostics. Useful for tests and for tooling that wants to log
52
+ * cache effectiveness at end of run.
53
+ */
54
+ export declare function getReadJsonCacheStats(): {
55
+ size: number;
56
+ max: number;
57
+ ttlMs: number;
58
+ hits: number;
59
+ misses: number;
60
+ };
61
+ export declare function readMaxFromEnv(): number;
62
+ export declare function readTtlFromEnv(): number;
63
+ /**
64
+ * Store a parsed value. Evicts the oldest entry when the cache is full.
65
+ *
66
+ * Never stores `undefined` — callers must guard for the "file not found,
67
+ * throws: false" case before invoking this.
68
+ */
69
+ export declare function setCachedJson(key: string, ino: number, size: number, mtimeMs: number, parsed: JsonValue): void;
70
+ /**
71
+ * Adjust the cache size cap at runtime. Useful for tooling that knows it'll
72
+ * walk many manifests in one pass and wants a larger cap, or for tests that
73
+ * want to bound the cap small so eviction is observable.
74
+ *
75
+ * Trims excess entries on shrink.
76
+ */
77
+ export declare function setReadJsonCacheMax(max: number): void;
78
+ /**
79
+ * Adjust the time-based ejection window at runtime. Default is 5 minutes; pass
80
+ * `0` to disable time-based ejection entirely (entries then live until LRU
81
+ * eviction or `clearReadJsonCache`).
82
+ */
83
+ export declare function setReadJsonCacheTtlMs(ttlMs: number): void;
@@ -0,0 +1,156 @@
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 read_json_cache_exports = {};
32
+ __export(read_json_cache_exports, {
33
+ clearReadJsonCache: () => clearReadJsonCache,
34
+ getCachedJson: () => getCachedJson,
35
+ getReadJsonCacheStats: () => getReadJsonCacheStats,
36
+ readMaxFromEnv: () => readMaxFromEnv,
37
+ readTtlFromEnv: () => readTtlFromEnv,
38
+ setCachedJson: () => setCachedJson,
39
+ setReadJsonCacheMax: () => setReadJsonCacheMax,
40
+ setReadJsonCacheTtlMs: () => setReadJsonCacheTtlMs
41
+ });
42
+ module.exports = __toCommonJS(read_json_cache_exports);
43
+ var import_node_process = __toESM(require("node:process"));
44
+ var import_date = require("../primordials/date");
45
+ var import_error = require("../primordials/error");
46
+ var import_map_set = require("../primordials/map-set");
47
+ var import_number = require("../primordials/number");
48
+ const DEFAULT_MAX_ENTRIES = 256;
49
+ const DEFAULT_TTL_MS = 5 * 60 * 1e3;
50
+ const cache = new import_map_set.MapCtor();
51
+ let cacheMax = readMaxFromEnv();
52
+ let cacheTtlMs = readTtlFromEnv();
53
+ let hits = 0;
54
+ let misses = 0;
55
+ function clearReadJsonCache() {
56
+ cache.clear();
57
+ hits = 0;
58
+ misses = 0;
59
+ }
60
+ function getCachedJson(key, ino, size, mtimeMs) {
61
+ const entry = cache.get(key);
62
+ if (!entry) {
63
+ misses += 1;
64
+ return void 0;
65
+ }
66
+ if (cacheTtlMs > 0 && (0, import_date.DateNow)() - entry.insertedAt > cacheTtlMs) {
67
+ cache.delete(key);
68
+ misses += 1;
69
+ return void 0;
70
+ }
71
+ if (entry.ino !== ino || entry.size !== size || entry.mtimeMs !== mtimeMs) {
72
+ cache.delete(key);
73
+ misses += 1;
74
+ return void 0;
75
+ }
76
+ hits += 1;
77
+ return structuredClone(entry.parsed);
78
+ }
79
+ function getReadJsonCacheStats() {
80
+ return {
81
+ size: cache.size,
82
+ max: cacheMax,
83
+ ttlMs: cacheTtlMs,
84
+ hits,
85
+ misses
86
+ };
87
+ }
88
+ function readMaxFromEnv() {
89
+ const env = import_node_process.default.env["SOCKET_LIB_READ_JSON_CACHE_MAX"];
90
+ if (env) {
91
+ const n = (0, import_number.NumberParseInt)(env, 10);
92
+ if (n > 0 && (0, import_number.NumberIsFinite)(n)) {
93
+ return n;
94
+ }
95
+ }
96
+ return DEFAULT_MAX_ENTRIES;
97
+ }
98
+ function readTtlFromEnv() {
99
+ const env = import_node_process.default.env["SOCKET_LIB_READ_JSON_CACHE_TTL_MS"];
100
+ if (env) {
101
+ const n = (0, import_number.NumberParseInt)(env, 10);
102
+ if (n >= 0 && (0, import_number.NumberIsFinite)(n)) {
103
+ return n;
104
+ }
105
+ }
106
+ return DEFAULT_TTL_MS;
107
+ }
108
+ function setCachedJson(key, ino, size, mtimeMs, parsed) {
109
+ if (cache.size >= cacheMax) {
110
+ const oldest = cache.keys().next().value;
111
+ if (oldest !== void 0) {
112
+ cache.delete(oldest);
113
+ }
114
+ }
115
+ cache.set(key, {
116
+ ino,
117
+ size,
118
+ mtimeMs,
119
+ parsed: structuredClone(parsed),
120
+ insertedAt: (0, import_date.DateNow)()
121
+ });
122
+ }
123
+ function setReadJsonCacheMax(max) {
124
+ if (max <= 0 || !(0, import_number.NumberIsFinite)(max)) {
125
+ throw new import_error.ErrorCtor(
126
+ `setReadJsonCacheMax: max must be a positive finite number, got ${max}`
127
+ );
128
+ }
129
+ cacheMax = max;
130
+ while (cache.size > cacheMax) {
131
+ const oldest = cache.keys().next().value;
132
+ if (oldest === void 0) {
133
+ break;
134
+ }
135
+ cache.delete(oldest);
136
+ }
137
+ }
138
+ function setReadJsonCacheTtlMs(ttlMs) {
139
+ if (ttlMs < 0 || !(0, import_number.NumberIsFinite)(ttlMs)) {
140
+ throw new import_error.ErrorCtor(
141
+ `setReadJsonCacheTtlMs: ttlMs must be a non-negative finite number, got ${ttlMs}`
142
+ );
143
+ }
144
+ cacheTtlMs = ttlMs;
145
+ }
146
+ // Annotate the CommonJS export names for ESM import in node:
147
+ 0 && (module.exports = {
148
+ clearReadJsonCache,
149
+ getCachedJson,
150
+ getReadJsonCacheStats,
151
+ readMaxFromEnv,
152
+ readTtlFromEnv,
153
+ setCachedJson,
154
+ setReadJsonCacheMax,
155
+ setReadJsonCacheTtlMs
156
+ });
@@ -3,8 +3,13 @@
3
3
  * error messages keyed off `ENOENT` / `EACCES` / `EPERM` so callers see "JSON
4
4
  * file not found" / "Permission denied" rather than the bare errno. Both
5
5
  * variants honor `throws: false` to fall back to `undefined` on parse or read
6
- * failure.
6
+ * failure. Both variants cache parse results by default — keyed on `path +
7
+ * ino + size \+ mtimeMs`, with a defensive `structuredClone` on every hit so
8
+ * callers can mutate the returned object freely. See `_read-json-cache.ts`
9
+ * for the safety rationale + opt-out controls.
7
10
  */
11
+ import { clearReadJsonCache, getReadJsonCacheStats, setReadJsonCacheMax, setReadJsonCacheTtlMs } from './read-json-cache';
12
+ export { clearReadJsonCache, getReadJsonCacheStats, setReadJsonCacheMax, setReadJsonCacheTtlMs, };
8
13
  import type { PathLike } from 'node:fs';
9
14
  import type { ReadJsonOptions } from './types';
10
15
  /**
@@ -20,22 +20,45 @@ var __copyProps = (to, from, except, desc) => {
20
20
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
21
  var read_json_exports = {};
22
22
  __export(read_json_exports, {
23
+ clearReadJsonCache: () => import_read_json_cache.clearReadJsonCache,
24
+ getReadJsonCacheStats: () => import_read_json_cache.getReadJsonCacheStats,
23
25
  readJson: () => readJson,
24
- readJsonSync: () => readJsonSync
26
+ readJsonSync: () => readJsonSync,
27
+ setReadJsonCacheMax: () => import_read_json_cache.setReadJsonCacheMax,
28
+ setReadJsonCacheTtlMs: () => import_read_json_cache.setReadJsonCacheTtlMs
25
29
  });
26
30
  module.exports = __toCommonJS(read_json_exports);
31
+ var import_read_json_cache = require("./read-json-cache");
27
32
  var import_parse = require("../json/parse");
28
33
  var import_fs = require("../node/fs");
29
34
  var import_error = require("../primordials/error");
35
+ var import_number = require("../primordials/number");
30
36
  // @__NO_SIDE_EFFECTS__
31
37
  async function readJson(filepath, options) {
32
38
  const opts = typeof options === "string" ? { encoding: options } : options;
33
- const { reviver, throws, ...fsOptions } = {
39
+ const { cache, reviver, throws, ...fsOptions } = {
34
40
  __proto__: null,
35
41
  ...opts
36
42
  };
37
43
  const shouldThrow = throws === void 0 || !!throws;
44
+ const cacheEnabled = cache !== false && reviver === void 0;
38
45
  const fs = (0, import_fs.getNodeFs)();
46
+ const pathStr = String(filepath);
47
+ if (cacheEnabled) {
48
+ try {
49
+ const stat = await fs.promises.stat(filepath);
50
+ const cached = (0, import_read_json_cache.getCachedJson)(
51
+ pathStr,
52
+ (0, import_number.NumberCtor)(stat.ino),
53
+ (0, import_number.NumberCtor)(stat.size),
54
+ (0, import_number.NumberCtor)(stat.mtimeMs)
55
+ );
56
+ if (cached !== void 0) {
57
+ return cached;
58
+ }
59
+ } catch {
60
+ }
61
+ }
39
62
  let content = "";
40
63
  try {
41
64
  content = await fs.promises.readFile(filepath, {
@@ -64,21 +87,52 @@ Check file permissions or run with appropriate access.`,
64
87
  }
65
88
  return void 0;
66
89
  }
67
- return (0, import_parse.parseJson)(content, {
68
- filepath: String(filepath),
90
+ const parsed = (0, import_parse.parseJson)(content, {
91
+ filepath: pathStr,
69
92
  reviver,
70
93
  throws: shouldThrow
71
94
  });
95
+ if (cacheEnabled && parsed !== void 0) {
96
+ try {
97
+ const stat = await fs.promises.stat(filepath);
98
+ (0, import_read_json_cache.setCachedJson)(
99
+ pathStr,
100
+ (0, import_number.NumberCtor)(stat.ino),
101
+ (0, import_number.NumberCtor)(stat.size),
102
+ (0, import_number.NumberCtor)(stat.mtimeMs),
103
+ parsed
104
+ );
105
+ } catch {
106
+ }
107
+ }
108
+ return parsed;
72
109
  }
73
110
  // @__NO_SIDE_EFFECTS__
74
111
  function readJsonSync(filepath, options) {
75
112
  const opts = typeof options === "string" ? { encoding: options } : options;
76
- const { reviver, throws, ...fsOptions } = {
113
+ const { cache, reviver, throws, ...fsOptions } = {
77
114
  __proto__: null,
78
115
  ...opts
79
116
  };
80
117
  const shouldThrow = throws === void 0 || !!throws;
118
+ const cacheEnabled = cache !== false && reviver === void 0;
81
119
  const fs = (0, import_fs.getNodeFs)();
120
+ const pathStr = String(filepath);
121
+ if (cacheEnabled) {
122
+ try {
123
+ const stat = fs.statSync(filepath);
124
+ const cached = (0, import_read_json_cache.getCachedJson)(
125
+ pathStr,
126
+ (0, import_number.NumberCtor)(stat.ino),
127
+ (0, import_number.NumberCtor)(stat.size),
128
+ (0, import_number.NumberCtor)(stat.mtimeMs)
129
+ );
130
+ if (cached !== void 0) {
131
+ return cached;
132
+ }
133
+ } catch {
134
+ }
135
+ }
82
136
  let content = "";
83
137
  try {
84
138
  content = fs.readFileSync(filepath, {
@@ -107,14 +161,32 @@ Check file permissions or run with appropriate access.`,
107
161
  }
108
162
  return void 0;
109
163
  }
110
- return (0, import_parse.parseJson)(content, {
111
- filepath: String(filepath),
164
+ const parsed = (0, import_parse.parseJson)(content, {
165
+ filepath: pathStr,
112
166
  reviver,
113
167
  throws: shouldThrow
114
168
  });
169
+ if (cacheEnabled && parsed !== void 0) {
170
+ try {
171
+ const stat = fs.statSync(filepath);
172
+ (0, import_read_json_cache.setCachedJson)(
173
+ pathStr,
174
+ (0, import_number.NumberCtor)(stat.ino),
175
+ (0, import_number.NumberCtor)(stat.size),
176
+ (0, import_number.NumberCtor)(stat.mtimeMs),
177
+ parsed
178
+ );
179
+ } catch {
180
+ }
181
+ }
182
+ return parsed;
115
183
  }
116
184
  // Annotate the CommonJS export names for ESM import in node:
117
185
  0 && (module.exports = {
186
+ clearReadJsonCache,
187
+ getReadJsonCacheStats,
118
188
  readJson,
119
- readJsonSync
189
+ readJsonSync,
190
+ setReadJsonCacheMax,
191
+ setReadJsonCacheTtlMs
120
192
  });
@@ -128,8 +128,22 @@ export type ReadJsonOptions = Remap<ReadFileOptions & {
128
128
  /**
129
129
  * JSON reviver function to transform parsed values. Same as the second
130
130
  * parameter to `JSON.parse()`.
131
+ *
132
+ * Note: when a `reviver` is passed, the read-result cache is bypassed —
133
+ * function identity isn't safely hashable and the reviver can transform the
134
+ * same bytes into a different shape.
131
135
  */
132
136
  reviver?: Parameters<typeof JSON.parse>[1] | undefined;
137
+ /**
138
+ * Opt out of the process-scoped read-result cache. Default `true` (cache
139
+ * ON). Set to `false` when staleness must be observed — e.g. file-watcher
140
+ * tooling that wants to see live disk state on every call. The cache
141
+ * validates entries with a `stat()` (inode + size + mtime) on every hit, so
142
+ * the default-on path is safe for everyday use.
143
+ *
144
+ * @default true
145
+ */
146
+ cache?: boolean | undefined;
133
147
  }>;
134
148
  /**
135
149
  * Options for read operations with abort support.
@@ -43,7 +43,7 @@ var import_json = require("../primordials/json");
43
43
  var import_map_set = require("../primordials/map-set");
44
44
  var import_object = require("../primordials/object");
45
45
  var import_string = require("../primordials/string");
46
- var import_spawn = require("../spawn/spawn");
46
+ var import_child = require("../process/spawn/child");
47
47
  var import_strip = require("../ansi/strip");
48
48
  var import_repo = require("./repo");
49
49
  const gitDiffCache = new import_map_set.MapCtor();
@@ -107,7 +107,7 @@ async function innerDiff(args, options) {
107
107
  }
108
108
  let result;
109
109
  try {
110
- const spawnResult = await (0, import_spawn.spawn)(args[0], args[1], {
110
+ const spawnResult = await (0, import_child.spawn)(args[0], args[1], {
111
111
  ...args[2],
112
112
  stdioString: false
113
113
  });
@@ -141,7 +141,7 @@ function innerDiffSync(args, options) {
141
141
  }
142
142
  let result;
143
143
  try {
144
- const spawnResult = (0, import_spawn.spawnSync)(args[0], args[1], {
144
+ const spawnResult = (0, import_child.spawnSync)(args[0], args[1], {
145
145
  ...args[2],
146
146
  stdioString: false
147
147
  });
@@ -9,7 +9,7 @@
9
9
  * - Default TTL: 5 minutes
10
10
  * - Disable everything with the `DISABLE_GITHUB_CACHE` env var
11
11
  */
12
- import type { TtlCache } from '../ttl-cache/types';
12
+ import type { TtlCache } from '../cache/ttl/types';
13
13
  /**
14
14
  * Clear the ref resolution cache (in-memory only). Clears the in-memory
15
15
  * memoization cache without affecting the persistent disk cache. Useful for
@@ -24,7 +24,7 @@ __export(refs_cache_exports, {
24
24
  getGithubCache: () => getGithubCache
25
25
  });
26
26
  module.exports = __toCommonJS(refs_cache_exports);
27
- var import_cache = require("../ttl-cache/cache");
27
+ var import_store = require("../cache/ttl/store");
28
28
  var import_constants = require("./constants");
29
29
  let _githubCache;
30
30
  async function clearRefCache() {
@@ -34,7 +34,7 @@ async function clearRefCache() {
34
34
  }
35
35
  function getGithubCache() {
36
36
  if (_githubCache === void 0) {
37
- _githubCache = (0, import_cache.createTtlCache)({
37
+ _githubCache = (0, import_store.createTtlCache)({
38
38
  memoize: true,
39
39
  prefix: "github-refs",
40
40
  ttl: import_constants.DEFAULT_CACHE_TTL_MS
@@ -5,7 +5,7 @@
5
5
  * helpers exist so callers can constrain the search (e.g., env-only contexts
6
6
  * where shelling out to git would be wrong).
7
7
  */
8
- import type { SpawnOptions } from '../spawn/types';
8
+ import type { SpawnOptions } from '../process/spawn/types';
9
9
  /**
10
10
  * Get GitHub authentication token from environment variables. Checks multiple
11
11
  * environment variable names in priority order.
@@ -27,13 +27,13 @@ __export(token_exports, {
27
27
  module.exports = __toCommonJS(token_exports);
28
28
  var import_github = require("../env/github");
29
29
  var import_socket_cli = require("../env/socket-cli");
30
- var import_spawn = require("../spawn/spawn");
30
+ var import_child = require("../process/spawn/child");
31
31
  function getGitHubToken() {
32
32
  return (0, import_github.getGithubToken)() || (0, import_github.getGhToken)() || (0, import_socket_cli.getSocketCliGithubToken)() || void 0;
33
33
  }
34
34
  async function getGitHubTokenFromGitConfig(options) {
35
35
  try {
36
- const result = await (0, import_spawn.spawn)("git", ["config", "github.token"], {
36
+ const result = await (0, import_child.spawn)("git", ["config", "github.token"], {
37
37
  ...options,
38
38
  stdio: "pipe"
39
39
  });
@@ -18,13 +18,13 @@ 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 glob_exports = {};
22
- __export(glob_exports, {
21
+ var match_exports = {};
22
+ __export(match_exports, {
23
23
  canUseNodeFsGlob: () => canUseNodeFsGlob,
24
24
  glob: () => glob,
25
25
  globSync: () => globSync
26
26
  });
27
- module.exports = __toCommonJS(glob_exports);
27
+ module.exports = __toCommonJS(match_exports);
28
28
  var import_resolvers = require("../promises/resolvers");
29
29
  var import_internal = require("./_internal");
30
30
  function canUseNodeFsGlob(options) {
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @file Thin wrapper over the global `fetch()` so tests can mock the network
3
+ * layer via `vi.mock('@socketsecurity/lib/http-request/browser-fetch')`
4
+ * without monkey-patching `globalThis.fetch` (which conflicts with the
5
+ * project's nock-based test setup). The wrapper itself is `c8 ignore`-marked
6
+ * because the body is a single uncoverable fetch call; coverage credit is
7
+ * preserved by the wider test suite that mocks this module and asserts the
8
+ * call shape.
9
+ */
10
+ export declare function doFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
@@ -0,0 +1,32 @@
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 browser_fetch_exports = {};
22
+ __export(browser_fetch_exports, {
23
+ doFetch: () => doFetch
24
+ });
25
+ module.exports = __toCommonJS(browser_fetch_exports);
26
+ function doFetch(input, init) {
27
+ return fetch(input, init);
28
+ }
29
+ // Annotate the CommonJS export names for ESM import in node:
30
+ 0 && (module.exports = {
31
+ doFetch
32
+ });