"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_primordials_error = require('../primordials/error.js');
const require_primordials_number = require('../primordials/number.js');
const require_node_fs = require('../node/fs.js');
const require_fs_read_json_cache = require('./read-json-cache.js');
const require_json_parse = require('../json/parse.js');

//#region src/fs/read-json.ts
/**
* @file Read-and-parse helpers for JSON files. Wraps fs reads in actionable
*   error messages keyed off `ENOENT` / `EACCES` / `EPERM` so callers see "JSON
*   file not found" / "Permission denied" rather than the bare errno. Both
*   variants honor `throws: false` to fall back to `undefined` on parse or read
*   failure. Both variants cache parse results by default — keyed on `path +
*   ino + size \+ mtimeMs`, with a defensive `structuredClone` on every hit so
*   callers can mutate the returned object freely. See `_read-json-cache.ts`
*   for the safety rationale + opt-out controls.
*/
/**
* Read and parse a JSON file asynchronously. Reads the file as UTF-8 text and
* parses it as JSON. Optionally accepts a reviver function to transform parsed
* values.
*
* @example
*   ;```ts
*   // Read and parse package.json
*   const pkg = await readJson('./package.json')
*
*   // Read JSON with custom reviver
*   const data = await readJson('./data.json', {
*     reviver: (key, value) => {
*       if (key === 'date') return new Date(value)
*       return value
*     },
*   })
*
*   // Don't throw on parse errors
*   const config = await readJson('./config.json', { throws: false })
*   if (config === undefined) {
*     console.log('Failed to parse config')
*   }
*   ```
*
* @param filepath - Path to JSON file.
* @param options - Read and parse options.
*
* @returns Promise resolving to parsed JSON value, or undefined if throws is
*   false and an error occurs.
*/
/*@__NO_SIDE_EFFECTS__*/
async function readJson(filepath, options) {
	const { cache, reviver, throws, ...fsOptions } = {
		__proto__: null,
		...typeof options === "string" ? { encoding: options } : options
	};
	const shouldThrow = throws === void 0 || !!throws;
	const cacheEnabled = cache !== false && reviver === void 0;
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	const pathStr = String(filepath);
	if (cacheEnabled) try {
		const stat = await fs.promises.stat(filepath);
		const cached = require_fs_read_json_cache.getCachedJson(pathStr, require_primordials_number.NumberCtor(stat.ino), require_primordials_number.NumberCtor(stat.size), require_primordials_number.NumberCtor(stat.mtimeMs));
		if (cached !== void 0) return cached;
	} catch {}
	let content = "";
	try {
		content = await fs.promises.readFile(filepath, {
			__proto__: null,
			...fsOptions,
			encoding: "utf8"
		});
	} catch (e) {
		if (shouldThrow) {
			const code = e.code;
			if (code === "ENOENT") throw new require_primordials_error.ErrorCtor(`JSON file not found: ${filepath}\nEnsure the file exists or create it with the expected structure.`, { cause: e });
			/* c8 ignore start */
			if (code === "EACCES" || code === "EPERM") throw new require_primordials_error.ErrorCtor(`Permission denied reading JSON file: ${filepath}\nCheck file permissions or run with appropriate access.`, { cause: e });
			/* c8 ignore stop */
			throw e;
		}
		return;
	}
	const parsed = /* @__PURE__ */ require_json_parse.parseJson(content, {
		filepath: pathStr,
		reviver,
		throws: shouldThrow
	});
	if (cacheEnabled && parsed !== void 0) try {
		const stat = await fs.promises.stat(filepath);
		require_fs_read_json_cache.setCachedJson(pathStr, require_primordials_number.NumberCtor(stat.ino), require_primordials_number.NumberCtor(stat.size), require_primordials_number.NumberCtor(stat.mtimeMs), parsed);
	} catch {}
	return parsed;
}
/**
* Read and parse a JSON file synchronously. Reads the file as UTF-8 text and
* parses it as JSON. Optionally accepts a reviver function to transform parsed
* values.
*
* @example
*   ;```ts
*   // Read and parse tsconfig.json
*   const tsconfig = readJsonSync('./tsconfig.json')
*
*   // Read JSON with custom reviver
*   const data = readJsonSync('./data.json', {
*     reviver: (key, value) => {
*       if (typeof value === 'string' && /^\d{4}-\d{2}-\d{2}/.test(value)) {
*         return new Date(value)
*       }
*       return value
*     },
*   })
*
*   // Don't throw on parse errors
*   const config = readJsonSync('./config.json', { throws: false })
*   ```
*
* @param filepath - Path to JSON file.
* @param options - Read and parse options.
*
* @returns Parsed JSON value, or undefined if throws is false and an error
*   occurs.
*/
/*@__NO_SIDE_EFFECTS__*/
function readJsonSync(filepath, options) {
	const { cache, reviver, throws, ...fsOptions } = {
		__proto__: null,
		...typeof options === "string" ? { encoding: options } : options
	};
	const shouldThrow = throws === void 0 || !!throws;
	const cacheEnabled = cache !== false && reviver === void 0;
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	const pathStr = String(filepath);
	if (cacheEnabled) try {
		const stat = fs.statSync(filepath);
		const cached = require_fs_read_json_cache.getCachedJson(pathStr, require_primordials_number.NumberCtor(stat.ino), require_primordials_number.NumberCtor(stat.size), require_primordials_number.NumberCtor(stat.mtimeMs));
		if (cached !== void 0) return cached;
	} catch {}
	let content = "";
	try {
		content = fs.readFileSync(filepath, {
			__proto__: null,
			...fsOptions,
			encoding: "utf8"
		});
	} catch (e) {
		if (shouldThrow) {
			const code = e.code;
			if (code === "ENOENT") throw new require_primordials_error.ErrorCtor(`JSON file not found: ${filepath}\nEnsure the file exists or create it with the expected structure.`, { cause: e });
			/* c8 ignore start */
			if (code === "EACCES" || code === "EPERM") throw new require_primordials_error.ErrorCtor(`Permission denied reading JSON file: ${filepath}\nCheck file permissions or run with appropriate access.`, { cause: e });
			/* c8 ignore stop */
			throw e;
		}
		return;
	}
	const parsed = /* @__PURE__ */ require_json_parse.parseJson(content, {
		filepath: pathStr,
		reviver,
		throws: shouldThrow
	});
	if (cacheEnabled && parsed !== void 0) try {
		const stat = fs.statSync(filepath);
		require_fs_read_json_cache.setCachedJson(pathStr, require_primordials_number.NumberCtor(stat.ino), require_primordials_number.NumberCtor(stat.size), require_primordials_number.NumberCtor(stat.mtimeMs), parsed);
	} catch {}
	return parsed;
}

//#endregion
exports.clearReadJsonCache = require_fs_read_json_cache.clearReadJsonCache;
exports.getReadJsonCacheStats = require_fs_read_json_cache.getReadJsonCacheStats;
exports.readJson = readJson;
exports.readJsonSync = readJsonSync;
exports.setReadJsonCacheMax = require_fs_read_json_cache.setReadJsonCacheMax;
exports.setReadJsonCacheTtlMs = require_fs_read_json_cache.setReadJsonCacheTtlMs;