| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- #!/usr/bin/env node
- /**
- * Pack every published package into release tarballs, in publish order
- * (platform packages first, then the entries that optionally depend on
- * them), and write `publish-order.txt` next to them. `pnpm pack` produces
- * the EXACT bytes `pnpm publish` would upload and runs each package's
- * `prepack` gate, so a missing binary or unbuilt `lib/` refuses here.
- *
- * Usage: `node scripts/pack-release.mjs [dest] [--current-platform-only]`.
- * The flag packs only THIS host's platform package plus the entries — for
- * per-architecture CI legs, where the other architecture's binary does not
- * exist (the exact refusal its prepack gate exists for).
- */
- import fs from 'node:fs';
- import path from 'node:path';
- import { spawnSync } from 'node:child_process';
- import { entryDirs, platformDirs, readJson, root } from './repo.mjs';
- const args = process.argv.slice(2);
- const currentPlatformOnly = args.includes('--current-platform-only');
- const destination = path.resolve(args.find((arg) => !arg.startsWith('--')) || path.join(root, 'dist', 'npm'));
- function hostPlatformDirs() {
- const hostPlatform = `${process.platform}-${process.arch}`;
- return platformDirs().filter((dir) => readJson(path.join(root, dir, 'prebuilds.json')).platform === hostPlatform);
- }
- function run(command, args) {
- const result = spawnSync(command, args, {
- cwd: root,
- stdio: 'inherit',
- });
- if (result.error) throw result.error;
- if (result.status !== 0) {
- process.exit(result.status ?? 1);
- }
- }
- function tarballName(manifest) {
- if (manifest.name.startsWith('@')) {
- return `${manifest.name.slice(1).replace('/', '-')}-${manifest.version}.tgz`;
- }
- return `${manifest.name}-${manifest.version}.tgz`;
- }
- fs.rmSync(destination, { recursive: true, force: true });
- fs.mkdirSync(destination, { recursive: true });
- const dirs = [...(currentPlatformOnly ? hostPlatformDirs() : platformDirs()), ...entryDirs()];
- const platformSet = new Set(platformDirs());
- const publishOrder = [];
- for (const dir of dirs) {
- const manifest = readJson(path.join(root, dir, 'package.json'));
- // Platform packages are packed with npm: pnpm pack (observed on 11.7.0)
- // normalizes file modes and STRIPS the executable bit, which ships a
- // launcher no consumer can spawn; npm pack preserves it. Platform packages
- // have no dependencies by construction, so they need none of pnpm's
- // workspace-protocol conversion — the entry packages do, and carry no
- // executables, so they keep pnpm pack.
- if (platformSet.has(dir)) {
- run('npm', ['pack', `./${dir}`, '--pack-destination', destination]);
- } else {
- run('pnpm', ['--dir', dir, 'pack', '--pack-destination', destination]);
- }
- const tarball = tarballName(manifest);
- const tarballPath = path.join(destination, tarball);
- if (!fs.existsSync(tarballPath)) {
- throw new Error(`expected pack output not found: ${tarballPath}`);
- }
- publishOrder.push(tarball);
- }
- fs.writeFileSync(path.join(destination, 'publish-order.txt'), `${publishOrder.join('\n')}\n`);
- console.log(`Packed ${publishOrder.length} packages into ${path.relative(root, destination)}`);
|