From d53596d92c237ed487700d0471185d2ecd7d1cd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Thu, 26 Mar 2026 15:32:04 -0400 Subject: [PATCH] fix: use pnpm publish for workspace packages --- .github/workflows/publish.yml | 12 +-- packages/cli/package.json | 4 +- packages/engine/package.json | 4 +- packages/producer/package.json | 2 - packages/studio/package.json | 4 +- .../prepare-package-manifest-for-publish.mjs | 87 ------------------- .../restore-package-manifest-after-pack.mjs | 32 ------- scripts/verify-packed-manifests.mjs | 28 +++--- 8 files changed, 27 insertions(+), 146 deletions(-) delete mode 100644 scripts/prepare-package-manifest-for-publish.mjs delete mode 100644 scripts/restore-package-manifest-after-pack.mjs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 57ac5a941d..d5ec28d892 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -21,37 +21,39 @@ jobs: with: node-version: 24 registry-url: "https://registry.npmjs.org" + - run: corepack enable + - run: corepack prepare pnpm@10.17.1 --activate - run: bun install --frozen-lockfile - run: bun run build - run: bun run verify:packed-manifests - name: Publish @hyperframes/core continue-on-error: true - run: npm --workspace packages/core publish --access public --no-git-checks + run: pnpm --filter @hyperframes/core publish --access public --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish @hyperframes/engine continue-on-error: true - run: npm --workspace packages/engine publish --access public --no-git-checks + run: pnpm --filter @hyperframes/engine publish --access public --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish @hyperframes/producer continue-on-error: true - run: npm --workspace packages/producer publish --access public --no-git-checks + run: pnpm --filter @hyperframes/producer publish --access public --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish @hyperframes/studio continue-on-error: true - run: npm --workspace packages/studio publish --access public --no-git-checks + run: pnpm --filter @hyperframes/studio publish --access public --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Publish hyperframes (CLI) continue-on-error: true - run: npm --workspace packages/cli publish --access public --no-git-checks + run: pnpm --filter @hyperframes/cli publish --access public --no-git-checks env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/packages/cli/package.json b/packages/cli/package.json index 56e1819361..2917f13a2b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -15,9 +15,7 @@ "build:studio": "cd ../studio && bun run build", "build:runtime": "tsx scripts/build-runtime.ts", "build:copy": "mkdir -p dist/studio dist/docs dist/templates && cp -r ../studio/dist/* dist/studio/ && cp -r src/templates/blank src/templates/warm-grain src/templates/play-mode src/templates/swiss-grid src/templates/vignelli dist/templates/ && (cp src/docs/*.md dist/docs/ 2>/dev/null || true)", - "typecheck": "tsc --noEmit", - "prepack": "node ../../scripts/prepare-package-manifest-for-publish.mjs", - "postpack": "node ../../scripts/restore-package-manifest-after-pack.mjs" + "typecheck": "tsc --noEmit" }, "dependencies": { "@hono/node-server": "^1.8.0", diff --git a/packages/engine/package.json b/packages/engine/package.json index 112383fc8c..bc12f60549 100644 --- a/packages/engine/package.json +++ b/packages/engine/package.json @@ -11,9 +11,7 @@ "scripts": { "build": "tsc", "test": "vitest run", - "typecheck": "tsc --noEmit", - "prepack": "node ../../scripts/prepare-package-manifest-for-publish.mjs", - "postpack": "node ../../scripts/restore-package-manifest-after-pack.mjs" + "typecheck": "tsc --noEmit" }, "dependencies": { "@hono/node-server": "^1.13.0", diff --git a/packages/producer/package.json b/packages/producer/package.json index 0326d3ad0a..4d58612631 100644 --- a/packages/producer/package.json +++ b/packages/producer/package.json @@ -36,8 +36,6 @@ "docker:build:test": "docker build -f ../../Dockerfile.test -t hyperframes-producer:test ../..", "docker:test": "docker run --rm --security-opt seccomp=unconfined --shm-size=2g -v ./tests:/app/packages/producer/tests hyperframes-producer:test", "docker:test:update": "docker run --rm --security-opt seccomp=unconfined --shm-size=2g -v ./tests:/app/packages/producer/tests hyperframes-producer:test --update", - "prepack": "node ../../scripts/prepare-package-manifest-for-publish.mjs", - "postpack": "node ../../scripts/restore-package-manifest-after-pack.mjs", "prepublishOnly": "echo skip" }, "dependencies": { diff --git a/packages/studio/package.json b/packages/studio/package.json index 06425c2256..74a21a230a 100644 --- a/packages/studio/package.json +++ b/packages/studio/package.json @@ -15,9 +15,7 @@ "scripts": { "dev": "vite", "build": "vite build", - "typecheck": "tsc --noEmit", - "prepack": "node ../../scripts/prepare-package-manifest-for-publish.mjs", - "postpack": "node ../../scripts/restore-package-manifest-after-pack.mjs" + "typecheck": "tsc --noEmit" }, "dependencies": { "@codemirror/autocomplete": "^6.20.1", diff --git a/scripts/prepare-package-manifest-for-publish.mjs b/scripts/prepare-package-manifest-for-publish.mjs deleted file mode 100644 index 87bdccf6c5..0000000000 --- a/scripts/prepare-package-manifest-for-publish.mjs +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env node - -import { createHash } from "node:crypto"; -import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; -import { tmpdir } from "node:os"; - -const ROOT = join(import.meta.dirname, ".."); -const PACKAGES_DIR = join(ROOT, "packages"); -const BACKUP_DIR = join(tmpdir(), "hyperframes-publish-manifest-backups"); -const DEP_FIELDS = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"]; - -function loadPackageJson(path) { - return JSON.parse(readFileSync(path, "utf8")); -} - -function listWorkspacePackages() { - return readdirSync(PACKAGES_DIR) - .map((dir) => join(PACKAGES_DIR, dir, "package.json")) - .filter((path) => existsSync(path)); -} - -function getBackupPath(packageJsonPath) { - const digest = createHash("sha256").update(packageJsonPath).digest("hex"); - return join(BACKUP_DIR, `${digest}.json`); -} - -function resolveWorkspaceSpec(spec, version, packageJsonPath, depName) { - const workspaceSpec = spec.slice("workspace:".length); - - if (workspaceSpec === "" || workspaceSpec === "*") return version; - if (workspaceSpec === "^") return `^${version}`; - if (workspaceSpec === "~") return `~${version}`; - - throw new Error( - `Unsupported workspace spec "${spec}" for ${depName} in ${packageJsonPath}. ` + - "Update the publish rewrite script before publishing this package.", - ); -} - -function main() { - const packageJsonPath = join(process.cwd(), "package.json"); - const pkg = loadPackageJson(packageJsonPath); - const workspacePackages = new Map( - listWorkspacePackages().map((path) => { - const workspacePkg = loadPackageJson(path); - return [workspacePkg.name, workspacePkg.version]; - }), - ); - - mkdirSync(BACKUP_DIR, { recursive: true }); - const backupPath = getBackupPath(packageJsonPath); - try { - readFileSync(backupPath, "utf8"); - } catch { - writeFileSync(backupPath, `${JSON.stringify(pkg, null, 2)}\n`); - } - - let rewrites = 0; - - for (const field of DEP_FIELDS) { - const deps = pkg[field]; - if (!deps) continue; - - for (const [depName, spec] of Object.entries(deps)) { - if (!String(spec).startsWith("workspace:")) continue; - - const depVersion = workspacePackages.get(depName); - if (!depVersion) { - throw new Error(`Cannot resolve workspace dependency ${depName} in ${packageJsonPath}`); - } - - const resolvedSpec = resolveWorkspaceSpec(spec, depVersion, packageJsonPath, depName); - deps[depName] = resolvedSpec; - rewrites += 1; - console.log(`${pkg.name} ${field} ${depName}: ${spec} -> ${resolvedSpec}`); - } - } - - if (rewrites > 0) { - writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\n`); - } - - console.log(`Prepared ${pkg.name} for packing by rewriting ${rewrites} workspace reference(s).`); -} - -main(); diff --git a/scripts/restore-package-manifest-after-pack.mjs b/scripts/restore-package-manifest-after-pack.mjs deleted file mode 100644 index c2a2cbf34e..0000000000 --- a/scripts/restore-package-manifest-after-pack.mjs +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env node - -import { createHash } from "node:crypto"; -import { readFileSync, rmSync, writeFileSync } from "node:fs"; -import { join } from "node:path"; -import { tmpdir } from "node:os"; - -const BACKUP_DIR = join(tmpdir(), "hyperframes-publish-manifest-backups"); - -function getBackupPath(packageJsonPath) { - const digest = createHash("sha256").update(packageJsonPath).digest("hex"); - return join(BACKUP_DIR, `${digest}.json`); -} - -function main() { - const packageJsonPath = join(process.cwd(), "package.json"); - const backupPath = getBackupPath(packageJsonPath); - - let backup; - try { - backup = readFileSync(backupPath, "utf8"); - } catch { - console.log(`No publish-manifest backup found for ${packageJsonPath}; nothing to restore.`); - return; - } - - writeFileSync(packageJsonPath, backup); - rmSync(backupPath, { force: true }); - console.log(`Restored ${packageJsonPath} after packing.`); -} - -main(); diff --git a/scripts/verify-packed-manifests.mjs b/scripts/verify-packed-manifests.mjs index 057196d351..b2b7fdd2ce 100644 --- a/scripts/verify-packed-manifests.mjs +++ b/scripts/verify-packed-manifests.mjs @@ -1,8 +1,9 @@ #!/usr/bin/env node import { execFileSync } from "node:child_process"; -import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs"; +import { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; +import { tmpdir } from "node:os"; const ROOT = join(import.meta.dirname, ".."); const PACKAGES_DIR = join(ROOT, "packages"); @@ -29,12 +30,12 @@ function listWorkspaceRefs(pkg) { } function parsePackJson(output, workspace) { - const match = output.match(/(\[\s*{[\s\S]*}\s*])\s*$/); - if (!match) { - throw new Error(`Could not parse npm pack JSON output for ${workspace}`); + try { + const parsed = JSON.parse(output); + return Array.isArray(parsed) ? parsed : [parsed]; + } catch { + throw new Error(`Could not parse pnpm pack JSON output for ${workspace}`); } - - return JSON.parse(match[1]); } function main() { @@ -44,10 +45,15 @@ function main() { ); if (listWorkspaceRefs(sourcePackageJson).length === 0) continue; - const packOutput = execFileSync("npm", ["pack", "--json", "--workspace", workspace], { - cwd: ROOT, - encoding: "utf8", - }); + const packDir = mkdtempSync(join(tmpdir(), "hyperframes-pack-")); + const packOutput = execFileSync( + "pnpm", + ["pack", "--json", "--pack-destination", packDir], + { + cwd: join(ROOT, workspace), + encoding: "utf8", + }, + ); const [{ filename }] = parsePackJson(packOutput, workspace); try { @@ -65,7 +71,7 @@ function main() { console.log(`Verified ${workspace}: packed manifest is publish-safe.`); } finally { - rmSync(join(ROOT, filename), { force: true }); + rmSync(packDir, { force: true, recursive: true }); } } }