UNPKG

@manypkg/cli

Version:

Manypkg is a linter for `package.json` files in Yarn, npm, Lerna, pnpm or Rush monorepos.

84 lines (80 loc) 3.18 kB
import { makeCheck, getMostCommonRangeMap } from "./utils.ts"; import type { Package } from "@manypkg/get-packages"; import { upperBoundOfRangeAWithinBoundsOfB } from "sembear"; import semver from "semver"; type ErrorType = { type: "INVALID_DEV_AND_PEER_DEPENDENCY_RELATIONSHIP"; workspace: Package; peerVersion: string; dependencyName: string; devVersion: string | null; idealDevVersion: string; }; export default makeCheck<ErrorType>({ type: "all", validate: (workspace, allWorkspaces) => { let errors: ErrorType[] = []; let peerDeps = workspace.packageJson.peerDependencies; let devDeps = workspace.packageJson.devDependencies || {}; if (peerDeps) { for (let depName in peerDeps) { if (!devDeps[depName]) { let highestRanges = getMostCommonRangeMap(allWorkspaces); let idealDevVersion = highestRanges.get(depName); let isInternalDependency = allWorkspaces.has(depName); if (isInternalDependency) { idealDevVersion = "*"; } else if (idealDevVersion === undefined) { idealDevVersion = peerDeps[depName]; } errors.push({ type: "INVALID_DEV_AND_PEER_DEPENDENCY_RELATIONSHIP", workspace, peerVersion: peerDeps[depName], dependencyName: depName, devVersion: null, idealDevVersion, }); } else if ( semver.validRange(devDeps[depName]) && // TODO: we should probably error when a peer dep has an invalid range (in a seperate rule) // (also would be good to do a bit more validation instead of just ignoring invalid ranges for normal dep types) semver.validRange(peerDeps[depName]) && !upperBoundOfRangeAWithinBoundsOfB( devDeps[depName], peerDeps[depName] ) ) { let highestRanges = getMostCommonRangeMap(allWorkspaces); let idealDevVersion = highestRanges.get(depName); if (idealDevVersion === undefined) { idealDevVersion = peerDeps[depName]; } errors.push({ type: "INVALID_DEV_AND_PEER_DEPENDENCY_RELATIONSHIP", workspace, dependencyName: depName, peerVersion: peerDeps[depName], devVersion: devDeps[depName], idealDevVersion, }); } } } return errors; }, fix: (error) => { if (!error.workspace.packageJson.devDependencies) { error.workspace.packageJson.devDependencies = {}; } error.workspace.packageJson.devDependencies[error.dependencyName] = error.idealDevVersion; return { requiresInstall: true }; }, print: (error) => { if (error.devVersion === null) { return `${error.workspace.packageJson.name} has a peerDependency on ${error.dependencyName} but it is not also specified in devDependencies, please add it there.`; } return `${error.workspace.packageJson.name} has a peerDependency on ${error.dependencyName} but the range specified in devDependency is not greater than or equal to the range specified in peerDependencies`; }, });