"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_runtime = require('../_virtual/_rolldown/runtime.js');
const require_primordials_error = require('../primordials/error.js');
const require_primordials_number = require('../primordials/number.js');
const require_primordials_map_set = require('../primordials/map-set.js');
const require_primordials_date = require('../primordials/date.js');
let node_process = require("node:process");
node_process = require_runtime.__toESM(node_process);

//#region src/fs/read-json-cache.ts
/**
* @file Process-scoped LRU cache for `readJson` / `readJsonSync` results, keyed
*   by absolute path + stat (`ino + size + mtimeMs`). Why default-on caching is
*   safe:
*
*   - Stat-validated keys: a `stat()` call before serving a cache hit ensures the
*     file hasn't changed (mtime + size mismatch ⇒ cache miss, re-read).
*   - Defensive clone on hit: every hit returns `structuredClone(parsed)` so
*     callers can mutate the returned object without poisoning the cache for
*     the next reader. The clone cost is far less than re-read + re-parse for
*     anything bigger than a trivial JSON document.
*   - Reviver opt-out: when the caller passes a `reviver` function, we skip the
*     cache. Function identity isn't safely hashable across boundaries, and the
*     reviver can produce a different shape from the same bytes.
*   - Per-call escape hatch: `cache: false` in the options bypasses the cache for
*     cases where staleness must be observed (file-watcher tooling, etc.).
*   - Bounded growth: an LRU cap (default 256 entries) protects long-running
*     daemons. Tunable via `SOCKET_LIB_READ_JSON_CACHE_MAX` env or
*     `setReadJsonCacheMax()`.
*   - Test escape hatch: `clearReadJsonCache()` resets the whole cache between
*     test cases that rely on fresh reads. Not cached:
*   - Read failures (ENOENT under `throws: false` returns `undefined`). Caching
*     undefined would silently miss a file that gets created later.
*   - Reads with a `reviver` (see above).
*   - Reads with explicit `cache: false`.
*   - Relative paths whose `resolvePath` would change CWD-sensitively. We key on
*     the literal input path, so callers passing relative paths from different
*     CWDs would get separate cache entries — correct but pessimistic.
*/
const DEFAULT_MAX_ENTRIES = 256;
const DEFAULT_TTL_MS = 300 * 1e3;
const cache = new require_primordials_map_set.MapCtor();
let cacheMax = readMaxFromEnv();
let cacheTtlMs = readTtlFromEnv();
let hits = 0;
let misses = 0;
/**
* Drop all cached entries. Tests call this between cases that depend on a fresh
* read; long-running daemons can call it on file-watcher invalidation events
* for paths the daemon knows are about to change in bulk.
*/
function clearReadJsonCache() {
	cache.clear();
	hits = 0;
	misses = 0;
}
/**
* Look up a cached parse result. Returns a fresh structured clone on hit (so
* callers can mutate freely), or `undefined` on miss.
*
* @param key Cache key — absolute file path. Caller resolves any relative
*   inputs to absolute so two different CWDs don't share an entry.
* @param ino Inode (or `0` on platforms without one — Windows reports 0 from
*   the Node `fs.Stats` shim, in which case size + mtimeMs carry the
*   invalidation signal).
* @param size File size in bytes.
* @param mtimeMs Modification time in milliseconds.
*/
function getCachedJson(key, ino, size, mtimeMs) {
	const entry = cache.get(key);
	if (!entry) {
		misses += 1;
		return;
	}
	if (cacheTtlMs > 0 && require_primordials_date.DateNow() - entry.insertedAt > cacheTtlMs) {
		cache.delete(key);
		misses += 1;
		return;
	}
	if (entry.ino !== ino || entry.size !== size || entry.mtimeMs !== mtimeMs) {
		cache.delete(key);
		misses += 1;
		return;
	}
	hits += 1;
	return structuredClone(entry.parsed);
}
/**
* Snapshot diagnostics. Useful for tests and for tooling that wants to log
* cache effectiveness at end of run.
*/
function getReadJsonCacheStats() {
	return {
		size: cache.size,
		max: cacheMax,
		ttlMs: cacheTtlMs,
		hits,
		misses
	};
}
function readMaxFromEnv() {
	const env = node_process.default.env["SOCKET_LIB_READ_JSON_CACHE_MAX"];
	if (env) {
		const n = require_primordials_number.NumberParseInt(env, 10);
		if (n > 0 && require_primordials_number.NumberIsFinite(n)) return n;
	}
	return DEFAULT_MAX_ENTRIES;
}
function readTtlFromEnv() {
	const env = node_process.default.env["SOCKET_LIB_READ_JSON_CACHE_TTL_MS"];
	if (env) {
		const n = require_primordials_number.NumberParseInt(env, 10);
		if (n >= 0 && require_primordials_number.NumberIsFinite(n)) return n;
	}
	return DEFAULT_TTL_MS;
}
/**
* Store a parsed value. Evicts the oldest entry when the cache is full.
*
* Never stores `undefined` — callers must guard for the "file not found,
* throws: false" case before invoking this.
*/
function setCachedJson(key, ino, size, mtimeMs, parsed) {
	if (cache.size >= cacheMax) {
		const oldest = cache.keys().next().value;
		if (oldest !== void 0) cache.delete(oldest);
	}
	cache.set(key, {
		ino,
		size,
		mtimeMs,
		parsed: structuredClone(parsed),
		insertedAt: require_primordials_date.DateNow()
	});
}
/**
* Adjust the cache size cap at runtime. Useful for tooling that knows it'll
* walk many manifests in one pass and wants a larger cap, or for tests that
* want to bound the cap small so eviction is observable.
*
* Trims excess entries on shrink.
*/
function setReadJsonCacheMax(max) {
	if (max <= 0 || !require_primordials_number.NumberIsFinite(max)) throw new require_primordials_error.ErrorCtor(`setReadJsonCacheMax: max must be a positive finite number, got ${max}`);
	cacheMax = max;
	while (cache.size > cacheMax) {
		const oldest = cache.keys().next().value;
		if (oldest === void 0) break;
		cache.delete(oldest);
	}
}
/**
* Adjust the time-based ejection window at runtime. Default is 5 minutes; pass
* `0` to disable time-based ejection entirely (entries then live until LRU
* eviction or `clearReadJsonCache`).
*/
function setReadJsonCacheTtlMs(ttlMs) {
	if (ttlMs < 0 || !require_primordials_number.NumberIsFinite(ttlMs)) throw new require_primordials_error.ErrorCtor(`setReadJsonCacheTtlMs: ttlMs must be a non-negative finite number, got ${ttlMs}`);
	cacheTtlMs = ttlMs;
}

//#endregion
exports.clearReadJsonCache = clearReadJsonCache;
exports.getCachedJson = getCachedJson;
exports.getReadJsonCacheStats = getReadJsonCacheStats;
exports.readMaxFromEnv = readMaxFromEnv;
exports.readTtlFromEnv = readTtlFromEnv;
exports.setCachedJson = setCachedJson;
exports.setReadJsonCacheMax = setReadJsonCacheMax;
exports.setReadJsonCacheTtlMs = setReadJsonCacheTtlMs;