import { readdir, readFile } from "node:fs/promises"; import path from "node:path"; const rootDir = process.cwd(); const requiredScripts = ["lint", "typecheck", "test", "build", "dev:smoke"]; // 只支持当前仓库声明的一层通配符,例如 apps/* 和 packages/*。 function parseWorkspacePatterns(source) { return source .split("\n") .map((line) => line.trim()) .filter((line) => line.startsWith("- ")) .map((line) => line.slice(2).trim().replace(/^["']|["']$/g, "")); } async function pathExists(filePath) { try { await readFile(filePath, "utf8"); return true; } catch (error) { if (error && error.code === "ENOENT") { return false; } throw error; } } async function findWorkspaceManifests(patterns) { const manifests = []; for (const pattern of patterns) { if (!pattern.endsWith("/*")) { throw new Error(`不支持的 workspace pattern: ${pattern}`); } const baseDir = path.join(rootDir, pattern.slice(0, -2)); try { const entries = await readdir(baseDir, { withFileTypes: true }); for (const entry of entries) { if (!entry.isDirectory()) { continue; } const manifestPath = path.join(baseDir, entry.name, "package.json"); if (await pathExists(manifestPath)) { manifests.push(manifestPath); } } } catch (error) { if (error && error.code === "ENOENT") { continue; } throw error; } } return manifests; } async function readManifest(manifestPath) { const raw = await readFile(manifestPath, "utf8"); try { return JSON.parse(raw); } catch (error) { throw new Error(`${path.relative(rootDir, manifestPath)} 不是有效 JSON: ${error.message}`); } } const workspaceConfigPath = path.join(rootDir, "pnpm-workspace.yaml"); const workspaceConfig = await readFile(workspaceConfigPath, "utf8"); const manifests = await findWorkspaceManifests(parseWorkspacePatterns(workspaceConfig)); const failures = []; for (const manifestPath of manifests) { const manifest = await readManifest(manifestPath); const missingScripts = requiredScripts.filter((scriptName) => !manifest.scripts?.[scriptName]); if (missingScripts.length > 0) { failures.push({ packageName: manifest.name || path.relative(rootDir, path.dirname(manifestPath)), manifestPath, missingScripts }); } } if (failures.length > 0) { console.error("以下 workspace package 缺少必需脚本:"); for (const failure of failures) { console.error( `- ${failure.packageName} (${path.relative(rootDir, failure.manifestPath)}): ${failure.missingScripts.join(", ")}` ); } process.exitCode = 1; }