| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- /**
- * Standalone verification for publish-time package manifests.
- *
- * Usage:
- * node scripts/verify-no-workspace-protocol.mjs packages/cli packages/core
- * node ../../scripts/verify-no-workspace-protocol.mjs .
- *
- * Run this only after publish versions have been rewritten.
- *
- * Checks two invariants before publish:
- * 1. publishable dependency fields must not contain workspace: specifiers
- * 2. internal workspace dependencies must match the current workspace package version exactly
- */
- import { access, readdir, readFile } from "node:fs/promises";
- import { join, resolve } from "node:path";
- const dirs = process.argv.slice(2);
- if (dirs.length === 0) {
- process.stderr.write("Usage: node verify-no-workspace-protocol.mjs <pkg-dir> [<pkg-dir>...]\n");
- process.exit(1);
- }
- async function exists(path) {
- try {
- await access(path);
- return true;
- } catch {
- return false;
- }
- }
- async function findWorkspaceRoot(startDir) {
- let dir = resolve(startDir);
- for (let i = 0; i < 10; i++) {
- if (await exists(join(dir, "packages"))) {
- return dir;
- }
- const parent = resolve(dir, "..");
- if (parent === dir) break;
- dir = parent;
- }
- throw new Error(`Could not find workspace root from ${startDir}`);
- }
- async function loadWorkspaceVersions(workspaceRoot) {
- const packagesDir = join(workspaceRoot, "packages");
- const entries = await readdir(packagesDir);
- const versions = new Map();
- for (const entry of entries) {
- try {
- const raw = await readFile(join(packagesDir, entry, "package.json"), "utf-8");
- const pkg = JSON.parse(raw);
- versions.set(pkg.name, pkg.version);
- } catch {
- // ignore directories that are not publishable packages
- }
- }
- return versions;
- }
- let failed = false;
- const workspaceRoot = await findWorkspaceRoot(process.cwd());
- const workspaceVersions = await loadWorkspaceVersions(workspaceRoot);
- for (const dirArg of dirs) {
- const dir = resolve(process.cwd(), dirArg);
- const packageJsonPath = join(dir, "package.json");
- const raw = await readFile(packageJsonPath, "utf-8");
- const pkg = JSON.parse(raw);
- let dirFailed = false;
- for (const field of ["dependencies", "optionalDependencies", "peerDependencies"]) {
- const deps = pkg[field];
- if (!deps) continue;
- for (const [name, specifier] of Object.entries(deps)) {
- if (typeof specifier === "string" && specifier.startsWith("workspace:")) {
- process.stderr.write(`FAIL: ${dir} — ${field}.${name}: ${specifier}\n`);
- dirFailed = true;
- failed = true;
- continue;
- }
- const workspaceVersion = workspaceVersions.get(name);
- if (workspaceVersion && specifier !== workspaceVersion) {
- process.stderr.write(
- `FAIL: ${dir} — ${field}.${name}: expected ${workspaceVersion}, got ${specifier}\n`,
- );
- dirFailed = true;
- failed = true;
- }
- }
- }
- if (!dirFailed) {
- process.stderr.write(`OK: ${dir}\n`);
- }
- }
- if (failed) {
- process.exit(1);
- }
|