element-web/scripts/design/workspace-utils.mjs
2026-03-25 12:07:57 +00:00

94 lines
2.8 KiB
JavaScript

import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const currentDir = path.dirname(fileURLToPath(import.meta.url));
export const repoRoot = path.resolve(currentDir, "../..");
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}
function parseWorkspacePatterns() {
const workspaceFile = path.join(repoRoot, "pnpm-workspace.yaml");
const contents = fs.readFileSync(workspaceFile, "utf8");
const patterns = [];
for (const line of contents.split(/\r?\n/u)) {
const match = line.match(/^\s*-\s*"([^"]+)"\s*$/u);
if (match) {
patterns.push(match[1]);
}
}
return patterns;
}
function expandWorkspacePattern(pattern) {
if (!pattern.endsWith("/*")) {
throw new Error(`Unsupported workspace pattern: ${pattern}`);
}
const baseDir = pattern.slice(0, -2);
const absoluteBaseDir = path.join(repoRoot, baseDir);
if (!fs.existsSync(absoluteBaseDir)) {
return [];
}
return fs
.readdirSync(absoluteBaseDir, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => path.join(absoluteBaseDir, entry.name));
}
function getWorkspacePackages() {
const packages = [];
const rootPackagePath = path.join(repoRoot, "package.json");
const rootPackage = readJson(rootPackagePath);
packages.push({
name: rootPackage.name,
dir: repoRoot,
relativeDir: ".",
packageJsonPath: rootPackagePath,
packageJson: rootPackage,
});
for (const pattern of parseWorkspacePatterns()) {
for (const packageDir of expandWorkspacePattern(pattern)) {
const packageJsonPath = path.join(packageDir, "package.json");
if (!fs.existsSync(packageJsonPath)) {
continue;
}
packages.push({
name: readJson(packageJsonPath).name,
dir: packageDir,
relativeDir: path.relative(repoRoot, packageDir),
packageJsonPath,
packageJson: readJson(packageJsonPath),
});
}
}
return packages;
}
function findPackagesByScript(scriptName) {
return getWorkspacePackages().filter((pkg) => pkg.packageJson.scripts?.[scriptName]);
}
export function findSinglePackageByScript(scriptName) {
const matches = findPackagesByScript(scriptName);
if (matches.length === 0) {
throw new Error(`No workspace package exposes a ${scriptName} script.`);
}
if (matches.length > 1) {
const packageList = matches.map((pkg) => `${pkg.name} (${pkg.relativeDir})`).join(", ");
throw new Error(`Multiple workspace packages expose a ${scriptName} script: ${packageList}`);
}
return matches[0];
}