verify-no-workspace-protocol.mjs 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. /**
  2. * prepublishOnly guard — aborts publish if package.json still contains workspace: protocol.
  3. *
  4. * This runs AFTER prepack (which replaces workspace:* with real versions)
  5. * but BEFORE the actual upload. If prepack was skipped or failed silently,
  6. * this script catches it and prevents a broken publish.
  7. *
  8. * Usage in each publishable package:
  9. * "prepublishOnly": "node ../../scripts/verify-no-workspace-protocol.mjs"
  10. */
  11. import { readFile } from "node:fs/promises";
  12. import { join } from "node:path";
  13. const packageJsonPath = join(process.cwd(), "package.json");
  14. const raw = await readFile(packageJsonPath, "utf-8");
  15. const pkg = JSON.parse(raw);
  16. const violations = [];
  17. for (const field of ["dependencies", "optionalDependencies", "peerDependencies"]) {
  18. const deps = pkg[field];
  19. if (!deps) continue;
  20. for (const [name, specifier] of Object.entries(deps)) {
  21. if (typeof specifier === "string" && specifier.startsWith("workspace:")) {
  22. violations.push(` ${field}.${name}: ${specifier}`);
  23. }
  24. }
  25. }
  26. if (violations.length > 0) {
  27. process.stderr.write(
  28. `\n[ERROR] Cannot publish: package.json still contains workspace: protocol references.\n` +
  29. `This means the prepack script did not run or failed silently.\n\n` +
  30. `Violations:\n${violations.join("\n")}\n\n` +
  31. `Fix: run "node ../../scripts/prepare-package-for-publish.mjs" manually,\n` +
  32. `or check that "prepack" is configured in package.json scripts.\n\n`,
  33. );
  34. process.exit(1);
  35. }