import { logger } from "../../../../logger/index.js";
import { findLocalSiblingOrParent, getSiblingFileName, readLocalFile } from "../../../../util/fs/index.js";
import { NpmDatasource } from "../../../datasource/npm/index.js";
import { resolveNpmrc } from "../npmrc.js";
import { getExtractedConstraints } from "./common/dependency.js";
import { extractPackageJson, hasPackageManager } from "./common/package-file.js";
import { extractPnpmWorkspaceFile, tryParsePnpmWorkspaceYaml } from "./pnpm.js";
import { extractYarnCatalogs, isZeroInstall } from "./yarn.js";
import { postExtract } from "./post/index.js";
import { loadConfigFromLegacyYarnrc, loadConfigFromYarnrcYml, resolveRegistryUrl } from "./yarnrc.js";
import { isArray, isNonEmptyObject, isNonEmptyStringAndNotWhitespace, isString } from "@sindresorhus/is";
import upath from "upath";
//#region lib/modules/manager/npm/extract/index.ts
function hasMultipleLockFiles(lockFiles) {
	return Object.values(lockFiles).filter(isString).length > 1;
}
async function extractPackageFile(content, packageFile, config) {
	logger.trace(`npm.extractPackageFile(${packageFile})`);
	logger.trace({ content });
	let packageJson;
	try {
		packageJson = JSON.parse(content);
	} catch {
		logger.debug({ packageFile }, `Invalid JSON`);
		return null;
	}
	const res = extractPackageJson(packageJson, packageFile);
	if (!res) return null;
	let workspacesPackages;
	if (isArray(packageJson.workspaces)) workspacesPackages = packageJson.workspaces;
	else workspacesPackages = packageJson.workspaces?.packages;
	const lockFiles = {
		yarnLock: "yarn.lock",
		packageLock: "package-lock.json",
		shrinkwrapJson: "npm-shrinkwrap.json",
		pnpmShrinkwrap: "pnpm-lock.yaml"
	};
	for (const [key, val] of Object.entries(lockFiles)) {
		const filePath = getSiblingFileName(packageFile, val);
		if (await readLocalFile(filePath, "utf8")) lockFiles[key] = filePath;
		else lockFiles[key] = void 0;
	}
	lockFiles.npmLock = lockFiles.packageLock ?? lockFiles.shrinkwrapJson;
	delete lockFiles.packageLock;
	delete lockFiles.shrinkwrapJson;
	if (hasMultipleLockFiles(lockFiles)) logger.warn("Updating multiple npm lock files is deprecated and support will be removed in future versions.");
	const { npmrc, npmrcFileName } = await resolveNpmrc(packageFile, config);
	const yarnrcYmlFileName = await findLocalSiblingOrParent(packageFile, ".yarnrc.yml");
	const yarnZeroInstall = yarnrcYmlFileName ? await isZeroInstall(yarnrcYmlFileName) : false;
	let yarnrcConfig = null;
	const repoYarnrcYml = yarnrcYmlFileName ? await readLocalFile(yarnrcYmlFileName, "utf8") : null;
	if (isString(repoYarnrcYml) && repoYarnrcYml.trim().length > 0) yarnrcConfig = loadConfigFromYarnrcYml(repoYarnrcYml);
	const legacyYarnrcFileName = await findLocalSiblingOrParent(packageFile, ".yarnrc");
	const repoLegacyYarnrc = legacyYarnrcFileName ? await readLocalFile(legacyYarnrcFileName, "utf8") : null;
	if (isString(repoLegacyYarnrc) && repoLegacyYarnrc.trim().length > 0) yarnrcConfig = loadConfigFromLegacyYarnrc(repoLegacyYarnrc);
	if (res.deps.length === 0) {
		logger.debug("Package file has no deps");
		if (!(!!res.managerData?.packageJsonName || !!res.packageFileVersion || !!npmrc || workspacesPackages)) {
			logger.debug("Skipping file");
			return null;
		}
	}
	let skipInstalls = config.skipInstalls;
	if (skipInstalls === null) if (!!res.deps.some((dep) => !!dep.currentValue?.startsWith("file:") || !!dep.currentValue?.startsWith("npm:")) && !!lockFiles.npmLock || yarnZeroInstall) {
		logger.debug("Automatically setting skipInstalls to false");
		skipInstalls = false;
	} else skipInstalls = true;
	const extractedConstraints = getExtractedConstraints(res.deps);
	if (yarnrcConfig) {
		for (const dep of res.deps) if (dep.depName) {
			const registryUrlFromYarnrcConfig = resolveRegistryUrl(dep.packageName ?? dep.depName, yarnrcConfig);
			if (registryUrlFromYarnrcConfig && dep.datasource === NpmDatasource.id) dep.registryUrls = [registryUrlFromYarnrcConfig];
		}
	}
	return {
		...res,
		npmrc,
		managerData: {
			...res.managerData,
			...lockFiles,
			yarnZeroInstall,
			hasPackageManager: isNonEmptyStringAndNotWhitespace(packageJson.packageManager) || isNonEmptyObject(packageJson.devEngines?.packageManager),
			workspacesPackages,
			npmrcFileName
		},
		skipInstalls,
		extractedConstraints
	};
}
async function extractAllPackageFiles(config, packageFiles) {
	const npmFiles = [];
	for (const packageFile of packageFiles) {
		const content = await readLocalFile(packageFile, "utf8");
		if (content) {
			const parsedPnpmWorkspaceYaml = tryParsePnpmWorkspaceYaml(content);
			if (parsedPnpmWorkspaceYaml.success) {
				logger.trace({ packageFile }, `Extracting file as a pnpm workspace YAML file`);
				const deps = await extractPnpmWorkspaceFile(parsedPnpmWorkspaceYaml.data, packageFile);
				if (deps) npmFiles.push({
					...deps,
					packageFile
				});
			} else if (packageFile.endsWith("json")) {
				logger.trace({ packageFile }, `Extracting as a package.json file`);
				const deps = await extractPackageFile(content, packageFile, config);
				if (deps) npmFiles.push({
					...deps,
					packageFile
				});
			} else {
				logger.trace({ packageFile }, `Extracting as a .yarnrc.yml file`);
				const yarnConfig = loadConfigFromYarnrcYml(content);
				if (yarnConfig?.catalogs || yarnConfig?.catalog) {
					const hasPackageManagerResult = await hasPackageManager(upath.dirname(packageFile));
					const catalogsDeps = await extractYarnCatalogs({
						catalog: yarnConfig.catalog,
						catalogs: yarnConfig.catalogs
					}, packageFile, hasPackageManagerResult);
					if (catalogsDeps) npmFiles.push({
						...catalogsDeps,
						packageFile
					});
				}
			}
		} else logger.debug({ packageFile }, `No content found`);
	}
	await postExtract(npmFiles);
	return npmFiles;
}
//#endregion
export { extractAllPackageFiles };

//# sourceMappingURL=index.js.map