UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

218 lines • 8.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractPnpmFilters = extractPnpmFilters; exports.findPnpmWorkspace = findPnpmWorkspace; exports.detectPnpmWorkspaces = detectPnpmWorkspaces; exports.getPnpmLock = getPnpmLock; exports.tryParsePnpmWorkspaceYaml = tryParsePnpmWorkspaceYaml; exports.extractPnpmWorkspaceFile = extractPnpmWorkspaceFile; const tslib_1 = require("tslib"); const is_1 = tslib_1.__importDefault(require("@sindresorhus/is")); const find_packages_1 = require("find-packages"); const upath_1 = tslib_1.__importDefault(require("upath")); const global_1 = require("../../../../config/global"); const logger_1 = require("../../../../logger"); const fs_1 = require("../../../../util/fs"); const yaml_1 = require("../../../../util/yaml"); const schema_1 = require("../schema"); const catalogs_1 = require("./common/catalogs"); function isPnpmLockfile(obj) { return is_1.default.plainObject(obj) && 'lockfileVersion' in obj; } async function extractPnpmFilters(fileName) { try { // TODO: use schema (#9610,#22198) const contents = (0, yaml_1.parseSingleYaml)((await (0, fs_1.readLocalFile)(fileName, 'utf8'))); if (!Array.isArray(contents.packages) || !contents.packages.every((item) => is_1.default.string(item))) { logger_1.logger.trace({ fileName }, 'Failed to find required "packages" array in pnpm-workspace.yaml'); return undefined; } return contents.packages; } catch (err) { logger_1.logger.trace({ fileName, err }, 'Failed to parse pnpm-workspace.yaml'); return undefined; } } async function findPnpmWorkspace(packageFile) { // search for pnpm-workspace.yaml const workspaceYamlPath = await (0, fs_1.findLocalSiblingOrParent)(packageFile, 'pnpm-workspace.yaml'); if (!workspaceYamlPath) { logger_1.logger.trace({ packageFile }, 'Failed to locate pnpm-workspace.yaml in a parent directory.'); return null; } // search for pnpm-lock.yaml next to pnpm-workspace.yaml const pnpmLockfilePath = (0, fs_1.getSiblingFileName)(workspaceYamlPath, 'pnpm-lock.yaml'); if (!(await (0, fs_1.localPathExists)(pnpmLockfilePath))) { logger_1.logger.trace({ workspaceYamlPath, packageFile }, 'Failed to find a pnpm-lock.yaml sibling for the workspace.'); return null; } return { lockFilePath: pnpmLockfilePath, workspaceYamlPath, }; } async function detectPnpmWorkspaces(packageFiles) { logger_1.logger.debug(`Detecting pnpm Workspaces`); const packagePathCache = new Map(); for (const p of packageFiles) { const { packageFile, managerData } = p; const pnpmShrinkwrap = managerData?.pnpmShrinkwrap; // check if pnpmShrinkwrap-file has already been provided if (pnpmShrinkwrap) { logger_1.logger.trace({ packageFile, pnpmShrinkwrap }, 'Found an existing pnpm shrinkwrap file; skipping pnpm monorepo check.'); continue; } // search for corresponding pnpm workspace // TODO #22198 const pnpmWorkspace = await findPnpmWorkspace(packageFile); if (pnpmWorkspace === null) { continue; } const { workspaceYamlPath, lockFilePath } = pnpmWorkspace; // check if package matches workspace filter if (!packagePathCache.has(workspaceYamlPath)) { const filters = await extractPnpmFilters(workspaceYamlPath); const localDir = global_1.GlobalConfig.get('localDir'); const packages = await (0, find_packages_1.findPackages)(upath_1.default.dirname(upath_1.default.join(localDir, workspaceYamlPath)), { patterns: filters, // Match the ignores used in @pnpm/find-workspace-packages ignore: ['**/node_modules/**', '**/bower_components/**'], }); const packagePaths = packages.map((pkg) => upath_1.default.join(pkg.dir, 'package.json')); packagePathCache.set(workspaceYamlPath, packagePaths); } const packagePaths = packagePathCache.get(workspaceYamlPath); const isPackageInWorkspace = packagePaths?.some((p) => p.endsWith(packageFile)); if (isPackageInWorkspace) { p.managerData ??= {}; p.managerData.pnpmShrinkwrap = lockFilePath; } else { logger_1.logger.trace({ packageFile, workspaceYamlPath }, `Didn't find the package in the pnpm workspace`); } } } async function getPnpmLock(filePath) { try { const pnpmLockRaw = await (0, fs_1.readLocalFile)(filePath, 'utf8'); if (!pnpmLockRaw) { throw new Error('Unable to read pnpm-lock.yaml'); } const lockParsed = (0, yaml_1.parseSingleYaml)(pnpmLockRaw); if (!isPnpmLockfile(lockParsed)) { throw new Error('Invalid or empty lockfile'); } logger_1.logger.trace({ lockParsed }, 'pnpm lockfile parsed'); // field lockfileVersion is type string in lockfileVersion = 6 and type number in < 6 const lockfileVersion = is_1.default.number(lockParsed.lockfileVersion) ? lockParsed.lockfileVersion : parseFloat(lockParsed.lockfileVersion); const lockedVersions = getLockedVersions(lockParsed); const lockedCatalogVersions = getLockedCatalogVersions(lockParsed); return { lockedVersionsWithPath: lockedVersions, lockedVersionsWithCatalog: lockedCatalogVersions, lockfileVersion, }; } catch (err) { logger_1.logger.debug({ filePath, err }, 'Warning: Exception parsing pnpm lockfile'); return { lockedVersions: {} }; } } function getLockedCatalogVersions(lockParsed) { const lockedVersions = {}; if (is_1.default.nonEmptyObject(lockParsed.catalogs)) { for (const [catalog, dependencies] of Object.entries(lockParsed.catalogs)) { const versions = {}; for (const [dep, versionCarrier] of Object.entries(dependencies)) { versions[dep] = versionCarrier.version; } lockedVersions[catalog] = versions; } } return lockedVersions; } function getLockedVersions(lockParsed) { const lockedVersions = {}; // monorepo if (is_1.default.nonEmptyObject(lockParsed.importers)) { for (const [importer, imports] of Object.entries(lockParsed.importers)) { lockedVersions[importer] = getLockedDependencyVersions(imports); } } // normal repo else { lockedVersions['.'] = getLockedDependencyVersions(lockParsed); } return lockedVersions; } function getLockedDependencyVersions(obj) { const dependencyTypes = [ 'dependencies', 'devDependencies', 'optionalDependencies', ]; const res = {}; for (const depType of dependencyTypes) { res[depType] = {}; for (const [pkgName, versionCarrier] of Object.entries(obj[depType] ?? {})) { let version; if (is_1.default.object(versionCarrier)) { version = versionCarrier.version; } else { version = versionCarrier; } const pkgVersion = version.split('(')[0].trim(); res[depType][pkgName] = pkgVersion; } } return res; } function tryParsePnpmWorkspaceYaml(content) { try { const data = (0, yaml_1.parseSingleYaml)(content, { customSchema: schema_1.PnpmWorkspaceFile, }); return { success: true, data }; } catch { return { success: false }; } } async function extractPnpmWorkspaceFile(catalogs, packageFile) { logger_1.logger.trace(`pnpm.extractPnpmWorkspaceFile(${packageFile})`); const pnpmCatalogs = pnpmCatalogsToArray(catalogs); const deps = (0, catalogs_1.extractCatalogDeps)(pnpmCatalogs); let pnpmShrinkwrap; const filePath = (0, fs_1.getSiblingFileName)(packageFile, 'pnpm-lock.yaml'); if (await (0, fs_1.readLocalFile)(filePath, 'utf8')) { pnpmShrinkwrap = filePath; } return { deps, managerData: { pnpmShrinkwrap, }, }; } function pnpmCatalogsToArray({ catalog: defaultCatalogDeps, catalogs: namedCatalogs, }) { const result = []; if (defaultCatalogDeps !== undefined) { result.push({ name: 'default', dependencies: defaultCatalogDeps }); } if (!namedCatalogs) { return result; } for (const [name, dependencies] of Object.entries(namedCatalogs)) { result.push({ name, dependencies, }); } return result; } //# sourceMappingURL=pnpm.js.map