#!/usr/bin/env node import { cpSync, existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync } from 'node:fs'; import { createRequire } from 'node:module'; import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { spawnSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; const require = createRequire(import.meta.url); const root = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const expectedVersion = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).dependencies?.npm; const npmPackagePath = require.resolve('npm/package.json'); const npmPackage = JSON.parse(readFileSync(npmPackagePath, 'utf8')); const npmCli = join(dirname(npmPackagePath), 'bin', 'npm-cli.js'); const destination = join(root, 'build', 'publish-runtime'); if (npmPackage.version !== expectedVersion) { throw new Error(`Publish npm version mismatch: expected ${expectedVersion}, got ${npmPackage.version}`); } if (!npmPackage.bundleDependencies?.includes('proc-log')) { throw new Error('Publish npm package does not declare its runtime dependencies as bundled dependencies'); } const temporaryRoot = mkdtempSync(join(tmpdir(), 'makelore-publish-runtime-')); try { const packResult = spawnSync(process.execPath, [ npmCli, 'pack', dirname(npmPackagePath), '--ignore-scripts', '--json', '--pack-destination', temporaryRoot, ], { cwd: root, encoding: 'utf8', shell: false }); if (packResult.status !== 0) { throw new Error(`Unable to pack publish npm runtime: ${packResult.stderr || packResult.stdout}`); } const packMetadata = JSON.parse(packResult.stdout); if (!Array.isArray(packMetadata) || packMetadata.length !== 1) { throw new Error('npm pack returned unexpected metadata'); } const filename = packMetadata[0]?.filename; if (typeof filename !== 'string' || !/^[^/\\]+\.tgz$/.test(filename) || resolve(temporaryRoot, filename) !== join(temporaryRoot, filename)) { throw new Error(`npm pack returned an unsafe filename: ${JSON.stringify(filename)}`); } mkdirSync(join(temporaryRoot, 'runtime'), { recursive: true }); await import('tar').then(({ x }) => x({ file: join(temporaryRoot, filename), cwd: join(temporaryRoot, 'runtime'), strip: 1, })); const stagedRuntime = join(temporaryRoot, 'runtime'); for (const dependency of npmPackage.bundleDependencies) { if (!existsSync(join(stagedRuntime, 'node_modules', ...dependency.split('/'), 'package.json'))) { throw new Error(`Packed npm runtime is missing bundled dependency ${dependency}`); } } rmSync(destination, { recursive: true, force: true }); mkdirSync(dirname(destination), { recursive: true }); cpSync(stagedRuntime, destination, { recursive: true }); } finally { rmSync(temporaryRoot, { recursive: true, force: true }); } console.log(`Prepared self-contained npm ${npmPackage.version} runtime at ${destination}`);