"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_array = require('../primordials/array.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_paths_socket = require('../paths/socket.js');
let src_external__npmcli_arborist = require("../external/@npmcli/arborist");
src_external__npmcli_arborist = require_runtime.__toESM(src_external__npmcli_arborist);

//#region src/dlx/arborist.ts
/**
* @file Safe Arborist wrapper for dlx installs and lockfile-only resolution.
*   Every Arborist invocation in this module is configured with a fixed set of
*   security-hardening options mirroring socket-cli v1.1.79 SafeArborist:
*
*   - audit: false — no network call to the npm audit endpoint
*   - fund: false — no collection/display of funding URLs
*   - ignoreScripts: true — no preinstall/install/postinstall scripts
*   - progress: false — no progress bar on stdout
*   - saveBundle: false — never update bundledDependencies
*   - silent: true — suppress Arborist's default log output `save` varies by
*     operation: {@link safeIdealTree} uses `save: true` so Arborist writes
*     `package-lock.json`; {@link safeReify} uses `save: false` so the caller's
*     `package.json` is never rewritten. A `.npmrc` with the equivalent
*     settings is also written into the install directory as a
*     belt-and-suspenders defense for any downstream tool that reads it.
*/
/**
* Fixed Arborist options that must not be overridden by callers. Mirrors
* socket-cli v1.1.79's SafeArborist overrides: audit: false, fund: false,
* ignoreScripts: true, save: false, saveBundle: false, silent: true, progress:
* false.
*/
function getBaseArboristOptions(installPath, options) {
	return {
		__proto__: null,
		path: installPath,
		cache: require_paths_socket.getSocketCacacheDir(),
		audit: false,
		fund: false,
		ignoreScripts: true,
		progress: false,
		save: false,
		saveBundle: false,
		silent: options.quiet
	};
}
/**
* Read the single declared dependency from a package.json. We only support one
* top-level dep per snapshot, which keeps the result unambiguous (no "which of
* N deps did we pin?").
*/
function readSingleDependency(packageJsonPath) {
	const names = require_primordials_object.ObjectKeys(require_primordials_json.JSONParse((/* @__PURE__ */ require_node_fs.getNodeFs()).readFileSync(packageJsonPath, "utf8")).dependencies ?? {});
	if (names.length !== 1) throw new require_primordials_error.ErrorCtor(`safeIdealTree expects exactly one top-level dependency in ${packageJsonPath}, found ${names.length}`);
	return names[0];
}
/**
* Read the top-level package from an Arborist idealTree's inventory. Arborist's
* `Inventory` extends `Map`, so iteration yields `[key, node]` pairs — use
* `.values()` to get nodes directly.
*/
function readTopLevelFromIdealTree(tree, targetName) {
	const inventory = tree?.inventory;
	if (!inventory || typeof inventory.values !== "function") throw new require_primordials_error.ErrorCtor("Arborist idealTree missing inventory");
	for (const node of inventory.values()) {
		if (node.isProjectRoot) continue;
		if (node.name === targetName && node.depth === 1) {
			if (!node.version || !node.integrity) throw new require_primordials_error.ErrorCtor(`Arborist idealTree node for ${targetName} missing version/integrity`);
			return {
				name: node.name,
				version: node.version,
				integrity: node.integrity
			};
		}
	}
	throw new require_primordials_error.ErrorCtor(`Arborist idealTree inventory has no top-level node for ${targetName}`);
}
/**
* Run Arborist in `packageLockOnly` mode against a directory that already
* contains a `package.json` with a single dependency. Resolves the graph
* against the registry and writes `package-lock.json` into `path`, but does NOT
* install into `node_modules`.
*
* Used by snapshot/bootstrap flows to obtain a lockfile + top-level integrity
* without paying for a full install.
*
* Uses `save: true` (rather than our usual `save: false`) so Arborist actually
* writes the lockfile — without that flag, `reify()` in `packageLockOnly` mode
* with no `add` list skips the write.
*/
async function safeIdealTree(options) {
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	const path = /* @__PURE__ */ require_node_path.getNodePath();
	const { before, path: installPath, quiet = true } = options;
	const targetName = readSingleDependency(path.join(installPath, "package.json"));
	const arb = new src_external__npmcli_arborist.default({
		...getBaseArboristOptions(installPath, { quiet }),
		...before !== void 0 ? { before } : {},
		packageLockOnly: true,
		save: true
	});
	/* c8 ignore next - External Arborist call */
	const tree = await arb.buildIdealTree();
	/* c8 ignore next - External Arborist call */
	await arb.reify();
	const top = readTopLevelFromIdealTree(tree, targetName);
	const lockfile = await fs.promises.readFile(path.join(installPath, "package-lock.json"), "utf8");
	return {
		...top,
		lockfile
	};
}
/**
* Install into `node_modules` using Arborist's reify operation. Honors the
* committed `package-lock.json` in `path` when `packageLock: true`.
*
* Does not fetch registry metadata for versions already pinned by the lockfile
* — arborist uses the lockfile's `integrity` strings to fetch tarballs by ssri.
* This is the strongest form of pinning pnpm/npm offer.
*/
async function safeReify(options) {
	const { packageLock = true, path: installPath, quiet = true } = options;
	/* c8 ignore next - External Arborist call */
	await new src_external__npmcli_arborist.default({
		...getBaseArboristOptions(installPath, { quiet }),
		packageLock
	}).reify();
}
/**
* Write a hardened `.npmrc` into `path`. Used by both preview and pin flows as
* a second layer of protection alongside the Arborist options.
*
* Content written (always): ignore-scripts=true audit=false fund=false
* save=false save-bundle=false progress=false.
*
* When {@link WriteSafeNpmrcOptions.minReleaseDays} is set, also writes:
* min-release-age=<days>
*
* When {@link WriteSafeNpmrcOptions.minReleaseMins} is set, also writes the
* pnpm-style equivalent: minimum-release-age=<minutes>
*/
async function writeSafeNpmrc(installPath, options) {
	const fs = /* @__PURE__ */ require_node_fs.getNodeFs();
	const path = /* @__PURE__ */ require_node_path.getNodePath();
	const { minReleaseDays, minReleaseMins } = {
		__proto__: null,
		...options
	};
	if (minReleaseDays !== void 0 && minReleaseMins !== void 0) throw new require_primordials_error.ErrorCtor("writeSafeNpmrc: minReleaseDays and minReleaseMins are mutually exclusive");
	const lines = [
		"ignore-scripts=true",
		"audit=false",
		"fund=false",
		"save=false",
		"save-bundle=false",
		"progress=false"
	];
	if (minReleaseDays !== void 0) require_primordials_array.ArrayPrototypePush(lines, `min-release-age=${minReleaseDays}`);
	if (minReleaseMins !== void 0) require_primordials_array.ArrayPrototypePush(lines, `minimum-release-age=${minReleaseMins}`);
	await fs.promises.writeFile(path.join(installPath, ".npmrc"), lines.join("\n") + "\n", "utf8");
}

//#endregion
exports.getBaseArboristOptions = getBaseArboristOptions;
exports.readSingleDependency = readSingleDependency;
exports.readTopLevelFromIdealTree = readTopLevelFromIdealTree;
exports.safeIdealTree = safeIdealTree;
exports.safeReify = safeReify;
exports.writeSafeNpmrc = writeSafeNpmrc;