"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_string = require('../../../primordials/string.js');
const require_primordials_array = require('../../../primordials/array.js');
const require_primordials_map_set = require('../../../primordials/map-set.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_smol_manifest = require('../../../smol/manifest.js');
const require_eco_manifest_manifest_error = require('../../manifest/manifest-error.js');
const require_eco_npm_npm_extract_package_name_from_path = require('./extract-package-name-from-path.js');
const require_eco_npm_npm_parse_git_url = require('./parse-git-url.js');

//#region src/eco/npm/npm/parse-lockfile.ts
/**
* @file `parsePackageLock(content)` — parses an npm `package-lock.json` /
*   `npm-shrinkwrap.json` (v1/v2/v3) into a `ParsedLockfile`. On socket-btm's
*   smol Node binary this routes to `node:smol-manifest`'s native
*   `parseLockfile(content, 'npm', 'npm')`; on stock Node it runs the JS impl
*   below. Throws:
*
*   - `ManifestError(ERR_INVALID_JSON)` — JSON.parse failure
*   - `RangeError` — v1 nested-deps exceed `MAX_LOCKFILE_DEPTH = 64`, surfaces
*     malformed input rather than blowing the JS stack v2/v3 uses the flat
*     `packages` key; v1 uses recursive `dependencies`. The two paths converge
*     on the same `ParsedLockfile` shape so downstream consumers don't branch
*     on `lockVersion`. Source material (in lock-step order, newest → oldest):
*
*   1. **C++ native parser** in socket-btm/node-smol-builder:
*      additions/source-patched/src/socketsecurity/manifest/parser_npm.cc Same
*      algorithm, same fixes — keep the two in lock-step.
*   2. **socket-sdxgen** — algorithm oracle, broader production exposure:
*      socket-sdxgen/src/parsers/npm/package-lock-v1.mts
*      socket-sdxgen/src/parsers/npm/package-lock-v2.mts
*      socket-sdxgen/src/parsers/npm/npm-shrinkwrap.mts
*   3. **cdxgen** (pinned v11.11.0) — sdxgen's upstream baseline:
*      https://github.com/CycloneDX/cdxgen/blob/v11.11.0/lib/parsers/js.js
*      (parseLockFile / parsePkgLock)
*   4. **npm lockfile specs**: v1 (legacy):
*      https://docs.npmjs.com/cli/v6/configuring-npm/package-lock-json v2/v3:
*      https://docs.npmjs.com/cli/v10/configuring-npm/package-lock-json
*      arborist (canonical reader/writer):
*      https://github.com/npm/cli/tree/latest/workspaces/arborist Bug fixes
*      implemented here (and in the native parser):
*
*   - Fix 1 v1 alias extraction. `version: "npm:<real>@<ver>"` surfaces the real
*     registry identity on the PackageRef; `_index` keeps the original alias
*     key for lookups.
*   - Fix 2a v2/v3 workspace path entries prefer `pkg.name` over path-derived
*     fallback (workspace paths like `packages/ui` lack the `node_modules/`
*     prefix).
*   - Fix 2b v2/v3 aliased installs (`node_modules/<alias>` with `name: "<real>"`
*     field) prefer `pkg.name`. Same code path as Fix 2a. Regression fixtures
*     live under socket-btm's test/fixtures/ sdxgen-bug-regressions/ — every
*     shipped fix has a matching fixture directory there.
*/
const MAX_LOCKFILE_DEPTH = 64;
function addToIndex(packageIndex, name, idx) {
	const existing = packageIndex[name];
	if (existing === void 0) packageIndex[name] = idx;
	else if (typeof existing === "number") packageIndex[name] = [existing, idx];
	else require_primordials_array.ArrayPrototypePush(existing, idx);
}
function buildPackageRef(name, pkg) {
	let vcsUrl;
	let vcsCommit;
	if (typeof pkg.resolved === "string") {
		const gitMatch = require_eco_npm_npm_parse_git_url.parseGitUrl(pkg.resolved);
		if (gitMatch) {
			vcsUrl = gitMatch.url;
			vcsCommit = gitMatch.commit;
		}
	}
	const depsKey = pkg.dependencies ?? pkg.requires;
	const dependencies = depsKey && typeof depsKey === "object" ? require_primordials_object.ObjectKeys(depsKey) : [];
	let effectiveName = name;
	let version = typeof pkg.version === "string" ? pkg.version : "0.0.0";
	if (require_primordials_string.StringPrototypeStartsWith(version, "npm:")) {
		const rest = require_primordials_string.StringPrototypeSlice(version, 4);
		const atIdx = require_primordials_string.StringPrototypeLastIndexOf(rest, "@");
		if (atIdx > 0) {
			effectiveName = require_primordials_string.StringPrototypeSlice(rest, 0, atIdx);
			version = require_primordials_string.StringPrototypeSlice(rest, atIdx + 1);
		}
	}
	return require_primordials_object.ObjectFreeze({
		__proto__: null,
		name: effectiveName,
		version,
		resolved: typeof pkg.resolved === "string" ? pkg.resolved : void 0,
		integrity: typeof pkg.integrity === "string" ? pkg.integrity : void 0,
		ecosystem: "npm",
		depType: resolveDepType(pkg),
		isDev: !!pkg.dev,
		isOptional: !!pkg.optional,
		isPeer: !!pkg.peer,
		isBundled: !!pkg.inBundle,
		license: typeof pkg.license === "string" ? pkg.license : void 0,
		vcsUrl,
		vcsCommit,
		dependencies
	});
}
function jsParsePackageLock(content) {
	let data;
	try {
		data = require_primordials_json.JSONParse(content);
	} catch (e) {
		throw new require_eco_manifest_manifest_error.ManifestError(`Invalid JSON: ${require_errors_message.errorMessage(e)}`, "ERR_INVALID_JSON");
	}
	if (data.packages) return parseV2V3(data, data.packages);
	if (data.dependencies) return parseV1(data, data.dependencies);
	return require_primordials_object.ObjectFreeze({
		__proto__: null,
		type: "lockfile",
		lockVersion: String(data.lockfileVersion ?? 1),
		ecosystem: "npm",
		packages: require_primordials_object.ObjectFreeze([]),
		_index: { __proto__: null }
	});
}
function parseV1(data, rootDeps) {
	const packageIndex = { __proto__: null };
	const packages = [];
	const visited = new require_primordials_map_set.SetCtor();
	const flatten = (deps, parentPath, depth) => {
		if (depth > MAX_LOCKFILE_DEPTH) throw new require_primordials_error.RangeErrorCtor(`Lockfile dependency nesting exceeds ${MAX_LOCKFILE_DEPTH} levels at ${parentPath}`);
		const depKeys = require_primordials_object.ObjectKeys(deps);
		for (let di = 0, { length } = depKeys; di < length; di++) {
			const name = depKeys[di];
			const pkg = deps[name];
			const key = `${name}@${typeof pkg.version === "string" ? pkg.version : "0.0.0"}`;
			if (visited.has(key)) continue;
			if (packageIndex[name] === void 0) {
				require_primordials_array.ArrayPrototypePush(packages, buildPackageRef(name, pkg));
				packageIndex[name] = packages.length - 1;
			}
			if (pkg.dependencies && typeof pkg.dependencies === "object") {
				visited.add(key);
				flatten(pkg.dependencies, `${parentPath}/${name}`, depth + 1);
				visited.delete(key);
			}
		}
	};
	flatten(rootDeps, "", 0);
	return require_primordials_object.ObjectFreeze({
		__proto__: null,
		type: "lockfile",
		lockVersion: String(data.lockfileVersion ?? 1),
		ecosystem: "npm",
		packages: require_primordials_object.ObjectFreeze(packages),
		_index: packageIndex
	});
}
function parseV2V3(data, rawPackages) {
	const packageIndex = { __proto__: null };
	const pkgKeys = require_primordials_object.ObjectKeys(rawPackages);
	const packages = require_primordials_array.ArrayFrom({ length: rawPackages[""] !== void 0 ? pkgKeys.length - 1 : pkgKeys.length });
	let pkgCount = 0;
	for (let ki = 0, { length } = pkgKeys; ki < length; ki++) {
		const pkgPath = pkgKeys[ki];
		if (pkgPath === "") continue;
		const pkg = rawPackages[pkgPath];
		const nameFromPath = require_eco_npm_npm_extract_package_name_from_path.extractPackageNameFromPath(pkgPath);
		const name = typeof pkg.name === "string" && pkg.name.length > 0 ? pkg.name : nameFromPath;
		packages[pkgCount] = buildPackageRef(name, pkg);
		addToIndex(packageIndex, name, pkgCount);
		pkgCount++;
	}
	packages.length = pkgCount;
	return require_primordials_object.ObjectFreeze({
		__proto__: null,
		type: "lockfile",
		lockVersion: String(data.lockfileVersion ?? 1),
		ecosystem: "npm",
		packages: require_primordials_object.ObjectFreeze(packages),
		_index: packageIndex
	});
}
function resolveDepType(pkg) {
	if (pkg.dev) return "dev";
	if (pkg.optional) return "optional";
	if (pkg.peer) return "peer";
	return "prod";
}
const _smol = /* @__PURE__ */ require_smol_manifest.getSmolManifest();
const parsePackageLock = _smol ? (content) => _smol.parseLockfile(content, "npm", "npm") : jsParsePackageLock;

//#endregion
exports.addToIndex = addToIndex;
exports.buildPackageRef = buildPackageRef;
exports.jsParsePackageLock = jsParsePackageLock;
exports.parsePackageLock = parsePackageLock;
exports.parseV1 = parseV1;
exports.parseV2V3 = parseV2V3;
exports.resolveDepType = resolveDepType;