From 98a7211fc1bfcbfb6c96fef2bdaef37ef669b365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Thu, 26 Mar 2026 14:29:27 -0400 Subject: [PATCH] fix: rewrite workspace deps before npm publish --- .github/workflows/publish.yml | 1 + package.json | 1 + scripts/prepare-publish-manifests.ts | 87 ++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 scripts/prepare-publish-manifests.ts diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4e22ea1b4c..1f54b29497 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,6 +23,7 @@ jobs: registry-url: "https://registry.npmjs.org" - run: bun install --frozen-lockfile - run: bun run build + - run: bun run prepare:publish-manifests - name: Publish @hyperframes/core continue-on-error: true diff --git a/package.json b/package.json index 9657921fe0..185cb5609b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "studio": "bun run --filter @hyperframes/studio dev", "build:hyperframes-runtime": "bun run --filter @hyperframes/core build:hyperframes-runtime", "build:hyperframes-runtime:modular": "bun run --filter @hyperframes/core build:hyperframes-runtime:modular", + "prepare:publish-manifests": "tsx scripts/prepare-publish-manifests.ts", "set-version": "tsx scripts/set-version.ts", "lint": "oxlint .", "lint:fix": "oxlint --fix .", diff --git a/scripts/prepare-publish-manifests.ts b/scripts/prepare-publish-manifests.ts new file mode 100644 index 0000000000..5db90af852 --- /dev/null +++ b/scripts/prepare-publish-manifests.ts @@ -0,0 +1,87 @@ +#!/usr/bin/env tsx + +import { readdirSync, readFileSync, writeFileSync } from "fs"; +import { join } from "path"; + +const ROOT = join(import.meta.dirname, ".."); +const PACKAGES_DIR = join(ROOT, "packages"); +const DEP_FIELDS = [ + "dependencies", + "devDependencies", + "peerDependencies", + "optionalDependencies", +] as const; + +type DepField = (typeof DEP_FIELDS)[number]; +type PackageJson = { + name: string; + version: string; + [key: string]: unknown; +} & Partial>>; + +function listPackageJsonPaths() { + return readdirSync(PACKAGES_DIR).map((dir) => join(PACKAGES_DIR, dir, "package.json")); +} + +function loadPackageJson(path: string): PackageJson { + return JSON.parse(readFileSync(path, "utf8")) as PackageJson; +} + +function resolveWorkspaceSpec(spec: string, version: string) { + const workspaceSpec = spec.slice("workspace:".length); + + if (workspaceSpec === "" || workspaceSpec === "*") return version; + if (workspaceSpec === "^") return `^${version}`; + if (workspaceSpec === "~") return `~${version}`; + if (workspaceSpec.startsWith("^")) return `^${version}`; + if (workspaceSpec.startsWith("~")) return `~${version}`; + + return workspaceSpec; +} + +function main() { + const packageJsonPaths = listPackageJsonPaths(); + const packageVersions = new Map( + packageJsonPaths.map((path) => { + const pkg = loadPackageJson(path); + return [pkg.name, pkg.version] as const; + }), + ); + + let rewrites = 0; + + for (const path of packageJsonPaths) { + const pkg = loadPackageJson(path); + let changed = false; + + for (const field of DEP_FIELDS) { + const deps = pkg[field]; + if (!deps) continue; + + for (const [depName, spec] of Object.entries(deps)) { + if (!spec.startsWith("workspace:")) continue; + + const depVersion = packageVersions.get(depName); + if (!depVersion) { + throw new Error(`Cannot resolve workspace dependency ${depName} in ${path}`); + } + + const resolvedSpec = resolveWorkspaceSpec(spec, depVersion); + if (resolvedSpec === spec) continue; + + deps[depName] = resolvedSpec; + rewrites += 1; + changed = true; + console.log(`${pkg.name} ${field} ${depName}: ${spec} -> ${resolvedSpec}`); + } + } + + if (changed) { + writeFileSync(path, `${JSON.stringify(pkg, null, 2)}\n`); + } + } + + console.log(`Rewrote ${rewrites} workspace dependency reference(s) for publish.`); +} + +main();