"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_string = require('../primordials/string.js');
const require_constants_platform = require('../constants/platform.js');
const require_paths_conversion = require('../paths/conversion.js');
const require_paths_predicates = require('../paths/predicates.js');
const require_node_fs = require('../node/fs.js');
const require_node_path = require('../node/path.js');
const require_primordials_object = require('../primordials/object.js');
const require_primordials_json = require('../primordials/json.js');
const require_errors_message = require('../errors/message.js');
const require_process_spawn_child = require('../process/spawn/child.js');
const require_paths_socket = require('../paths/socket.js');
const require_packages_operations = require('./operations.js');
let src_external_npm_package_arg = require("../external/npm-package-arg");
src_external_npm_package_arg = require_runtime.__toESM(src_external_npm_package_arg);

//#region src/packages/isolation.ts
/**
* @file Package isolation utilities for testing. Provides tools to set up
*   isolated test environments for packages.
*/
/**
* Copy options for fs.cp with cross-platform retry support.
*/
const FS_CP_OPTIONS = {
	dereference: true,
	errorOnExist: false,
	filter: (src) => !src.includes("node_modules") && !require_primordials_string.StringPrototypeEndsWith(src, ".DS_Store"),
	force: true,
	recursive: true,
	...require_constants_platform.WIN32 ? {
		maxRetries: 3,
		retryDelay: 100
	} : {}
};
/**
* Isolates a package in a temporary test environment.
*
* Supports multiple input types: 1. File system path (absolute or relative) 2.
* Package name with optional version spec 3. npm package spec (parsed via
* npm-package-arg)
*
* @throws {Error} When package installation or setup fails.
*/
async function isolatePackage(packageSpec, options) {
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	const path = /* @__PURE__ */ require_node_path.getNodePath();
	const { imports, install, onPackageJson, sourcePath: optSourcePath } = {
		__proto__: null,
		...options
	};
	let sourcePath = optSourcePath;
	let packageName;
	let spec;
	if (/* @__PURE__ */ require_paths_predicates.isPath(packageSpec)) {
		const trimmedPath = /* @__PURE__ */ require_paths_conversion.trimLeadingDotSlash(packageSpec);
		const pathToResolve = /* @__PURE__ */ require_paths_predicates.isAbsolute(trimmedPath) ? trimmedPath : packageSpec;
		sourcePath = path.resolve(pathToResolve);
		if (!fs.existsSync(sourcePath)) throw new require_primordials_error.ErrorCtor(`Source path does not exist: ${sourcePath}`);
		const pkgJson = await /* @__PURE__ */ require_packages_operations.readPackageJson(sourcePath, { normalize: true });
		if (!pkgJson) throw new require_primordials_error.ErrorCtor(`Could not read package.json from: ${sourcePath}`);
		packageName = pkgJson.name;
	} else {
		const parsed = (0, src_external_npm_package_arg.default)(packageSpec);
		packageName = parsed.name;
		if (parsed.type === "directory" || parsed.type === "file") {
			sourcePath = parsed.fetchSpec;
			if (!sourcePath || !fs.existsSync(sourcePath)) throw new require_primordials_error.ErrorCtor(`Source path does not exist: ${sourcePath}`);
			if (!packageName) {
				const pkgJson = await /* @__PURE__ */ require_packages_operations.readPackageJson(sourcePath, { normalize: true });
				if (!pkgJson) throw new require_primordials_error.ErrorCtor(`Could not read package.json from: ${sourcePath}`);
				packageName = pkgJson.name;
			}
		} else spec = parsed.fetchSpec || parsed.rawSpec;
	}
	if (!packageName) throw new require_primordials_error.ErrorCtor(`Could not determine package name from: ${packageSpec}`);
	const sanitizedName = packageName.replace(/[@/]/g, "-");
	const tempDir = await fs.promises.mkdtemp(path.join(require_paths_socket.getOsTmpDir(), `socket-test-${sanitizedName}-`));
	const packageTempDir = path.join(tempDir, sanitizedName);
	await fs.promises.mkdir(packageTempDir, { recursive: true });
	let installedPath;
	let originalPackageJson;
	if (spec) {
		await fs.promises.writeFile(path.join(packageTempDir, "package.json"), require_primordials_json.JSONStringify({
			name: "test-temp",
			private: true,
			version: "1.0.0"
		}, null, 2));
		if (install) await install(packageTempDir);
		else await require_process_spawn_child.spawn("pnpm", ["add", require_primordials_string.StringPrototypeStartsWith(spec, "https://") ? spec : `${packageName}@${spec}`], {
			cwd: packageTempDir,
			shell: require_constants_platform.WIN32,
			stdio: "pipe"
		});
		installedPath = path.join(packageTempDir, "node_modules", packageName);
		originalPackageJson = await /* @__PURE__ */ require_packages_operations.readPackageJson(installedPath, { normalize: true });
		if (sourcePath) {
			const realInstalledPath = await resolveRealPath(installedPath);
			if (await resolveRealPath(sourcePath) !== realInstalledPath) await fs.promises.cp(sourcePath, installedPath, FS_CP_OPTIONS);
		}
	} else {
		if (!sourcePath) throw new require_primordials_error.ErrorCtor("sourcePath is required when no version spec provided");
		const scopedPath = require_primordials_string.StringPrototypeStartsWith(packageName, "@") ? path.join(packageTempDir, "node_modules", packageName.split("/")[0] ?? "") : path.join(packageTempDir, "node_modules");
		await fs.promises.mkdir(scopedPath, { recursive: true });
		installedPath = path.join(packageTempDir, "node_modules", packageName);
		await fs.promises.cp(sourcePath, installedPath, FS_CP_OPTIONS);
	}
	if (onPackageJson || originalPackageJson) {
		const pkgJsonPath = path.join(installedPath, "package.json");
		const mergedPkgJson = await mergePackageJson(pkgJsonPath, originalPackageJson);
		const finalPkgJson = onPackageJson ? await onPackageJson(mergedPkgJson) : mergedPkgJson;
		await fs.promises.writeFile(pkgJsonPath, require_primordials_json.JSONStringify(finalPkgJson, null, 2));
	}
	if (install) await install(installedPath);
	else await require_process_spawn_child.spawn("pnpm", ["install"], {
		cwd: installedPath,
		shell: require_constants_platform.WIN32,
		stdio: "pipe"
	});
	const exports = imports ? { __proto__: null } : void 0;
	if (imports) for (const { 0: key, 1: specifier } of require_primordials_object.ObjectEntries(imports)) {
		const fullPath = path.join(installedPath, specifier);
		exports[key] = require(fullPath);
	}
	return {
		exports,
		tmpdir: installedPath
	};
}
/**
* Merge and write package.json with original and new values.
*/
async function mergePackageJson(pkgJsonPath, originalPkgJson) {
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	let pkgJson;
	try {
		pkgJson = require_primordials_json.JSONParse(await fs.promises.readFile(pkgJsonPath, "utf8"));
	} catch (e) {
		throw new require_primordials_error.ErrorCtor(`Failed to parse ${pkgJsonPath}: ${require_errors_message.errorMessage(e)}`, { cause: e });
	}
	return originalPkgJson ? {
		...originalPkgJson,
		...pkgJson
	} : pkgJson;
}
/**
* Resolve a path to its real location, handling symlinks. Falls back to a
* non-realpath resolution if the OS rejects the lookup (ENOENT, EACCES, etc.) —
* caller still gets a usable absolute path either way.
*/
async function resolveRealPath(pathStr) {
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	const path = /* @__PURE__ */ require_node_path.getNodePath();
	try {
		return await fs.promises.realpath(pathStr);
	} catch {
		return path.resolve(pathStr);
	}
}

//#endregion
exports.isolatePackage = isolatePackage;
exports.mergePackageJson = mergePackageJson;
exports.resolveRealPath = resolveRealPath;