check-dependency-version-consistency
Version:
Ensures dependencies are on consistent versions across a monorepo.
81 lines (80 loc) • 3.15 kB
JavaScript
import { existsSync, readFileSync } from 'node:fs';
import { join, relative } from 'node:path';
import { load } from 'js-yaml';
/*
* Class to represent all of the information we need to know about a package in a workspace.
*/
export class Package {
/** Absolute path to package */
path;
/** Absolute path to workspace.*/
pathWorkspace;
/** Absolute path to package.json. */
pathPackageJson;
packageJson;
packageJsonEndsInNewline;
pnpmWorkspacePackages;
constructor(path, pathWorkspace) {
this.path = path;
this.pathWorkspace = pathWorkspace;
// package.json
this.pathPackageJson = join(path, 'package.json');
const packageJsonContents = readFileSync(this.pathPackageJson, 'utf8');
this.packageJsonEndsInNewline = packageJsonContents.endsWith('\n');
this.packageJson = JSON.parse(packageJsonContents);
// pnpm-workspace.yaml
const pnpmWorkspacePath = join(path, 'pnpm-workspace.yaml');
if (existsSync(pnpmWorkspacePath)) {
const pnpmWorkspaceContents = readFileSync(pnpmWorkspacePath, 'utf8');
const pnpmWorkspaceYaml = load(pnpmWorkspaceContents);
this.pnpmWorkspacePackages = pnpmWorkspaceYaml.packages;
}
}
get name() {
if (this.workspacePatterns.length > 0 && !this.packageJson.name) {
return '(Root)';
}
if (!this.packageJson.name) {
throw new Error(`${this.pathPackageJson} missing \`name\``);
}
return this.packageJson.name;
}
/** Relative to workspace root. */
get pathRelative() {
return relative(this.pathWorkspace, this.path);
}
get workspacePatterns() {
if (this.packageJson.workspaces) {
if (Array.isArray(this.packageJson.workspaces)) {
return this.packageJson.workspaces;
}
else if (this.packageJson.workspaces.packages) {
if (!Array.isArray(this.packageJson.workspaces.packages)) {
throw new TypeError('package.json `workspaces.packages` is not a string array.');
}
return this.packageJson.workspaces.packages;
}
else {
throw new TypeError('package.json `workspaces` is not a string array.');
}
}
if (this.pnpmWorkspacePackages) {
// eslint-disable-next-line unicorn/no-instanceof-array -- using Array.isArray() loses type information about the array.
if (!(this.pnpmWorkspacePackages instanceof Array)) {
throw new TypeError('pnpm-workspace.yaml `packages` is not a string array.');
}
return this.pnpmWorkspacePackages;
}
return [];
}
static exists(path) {
const packageJsonPath = join(path, 'package.json');
return existsSync(packageJsonPath);
}
static some(packages, callback) {
return packages.some((package_) => callback(package_));
}
static comparator(package1, package2) {
return package1.name.localeCompare(package2.name);
}
}