renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
145 lines (144 loc) • 6.41 kB
JavaScript
import { logger } from "../../../../logger/index.js";
import { findLocalSiblingOrParent, getSiblingFileName, readLocalFile } from "../../../../util/fs/index.js";
import { NpmDatasource } from "../../../datasource/npm/index.js";
import { PnpmWorkspaceFile } from "../schema.js";
import { resolveNpmrc } from "../npmrc.js";
import { getExtractedConstraints } from "./common/dependency.js";
import { extractPackageJson, hasPackageManager } from "./common/package-file.js";
import { extractPnpmWorkspaceFile } 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)
// v8 ignore else -- TODO: add tests #40625
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) if (packageFile.endsWith("pnpm-workspace.yaml")) {
logger.trace({ packageFile }, `Extracting as a pnpm-workspace.yaml file`);
const parsedPnpmWorkspaceYaml = await PnpmWorkspaceFile.safeParseAsync(content);
if (parsedPnpmWorkspaceYaml.success) {
logger.trace({ packageFile }, `Extracting file as a pnpm workspace YAML file`);
const deps = await extractPnpmWorkspaceFile(parsedPnpmWorkspaceYaml.data, packageFile);
// v8 ignore else -- TODO: add test #40625
if (deps) npmFiles.push({
...deps,
packageFile
});
} else logger.warn({
packageFile,
err: parsedPnpmWorkspaceYaml.error
}, `Failed to parse pnpm-workspace.yaml file`);
} else if (packageFile.endsWith("json")) {
logger.trace({ packageFile }, `Extracting as a package.json file`);
const deps = await extractPackageFile(content, packageFile, config);
// v8 ignore else -- TODO: add tests #40625
if (deps) npmFiles.push({
...deps,
packageFile
});
} else {
logger.trace({ packageFile }, `Extracting as a .yarnrc.yml file`);
const yarnConfig = loadConfigFromYarnrcYml(content);
// v8 ignore else -- TODO: add tests #40625
if (yarnConfig?.catalogs || yarnConfig?.catalog) {
const hasPackageManagerResult = await hasPackageManager(upath.dirname(packageFile));
const catalogsDeps = await extractYarnCatalogs({
catalog: yarnConfig.catalog,
catalogs: yarnConfig.catalogs
}, packageFile, hasPackageManagerResult);
// v8 ignore else -- TODO: add tests #40625
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