From 83bf40fa53d822ed5e08f8783b8806cd05a04038 Mon Sep 17 00:00:00 2001 From: weishu Date: Sat, 3 Jan 2026 22:22:45 +0800 Subject: [PATCH] Fix npm release wrapper package --- cli/.gitignore | 4 +- cli/scripts/prepare-npm-packages.ts | 86 ++++++++++++++++++++++++++--- cli/scripts/release-all.ts | 11 ++-- 3 files changed, 87 insertions(+), 14 deletions(-) diff --git a/cli/.gitignore b/cli/.gitignore index 25292f19..e1176cae 100644 --- a/cli/.gitignore +++ b/cli/.gitignore @@ -18,6 +18,8 @@ oclif.manifest.json /npm/*/package.json /npm/*/bin/hapi /npm/*/bin/hapi.exe +/npm/*/bin/hapi.cjs +/npm/*/NOTICE @@ -34,4 +36,4 @@ pnpm-lock.yaml .happy/ **/*.log -.release-notes-temp.md \ No newline at end of file +.release-notes-temp.md diff --git a/cli/scripts/prepare-npm-packages.ts b/cli/scripts/prepare-npm-packages.ts index 6505448a..68262ffd 100644 --- a/cli/scripts/prepare-npm-packages.ts +++ b/cli/scripts/prepare-npm-packages.ts @@ -1,16 +1,17 @@ /** - * Prepare npm platform packages for publishing. + * Prepare npm packages for publishing. * * This script: * 1. Reads the version from cli/package.json - * 2. Generates package.json for each platform package - * 3. Copies binaries from dist-exe to npm package directories - * 4. Updates optionalDependencies versions in main package.json + * 2. Generates the main npm package (wrapper) + * 3. Generates package.json for each platform package + * 4. Copies binaries from dist-exe to npm package directories + * 5. Updates optionalDependencies versions in main package.json * * Run after `bun run build:exe:all` */ -import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { chmodSync, copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -58,12 +59,20 @@ const PLATFORMS = [ ] as const; interface MainPackageJson { + name: string; version: string; + description?: string; + author?: string | { name: string; email?: string; url?: string }; license?: string; + type?: string; + homepage?: string; + bugs?: string | { url?: string; email?: string }; repository?: { type: string; url: string; + directory?: string; }; + bin?: Record; } async function readMainPackageJson(): Promise { @@ -91,6 +100,62 @@ function generatePlatformPackageJson( }; } +function buildOptionalDependencies(version: string): Record { + const optionalDependencies: Record = {}; + + for (const platform of PLATFORMS) { + optionalDependencies[`@twsxtd/hapi-${platform.name}`] = version; + } + + return optionalDependencies; +} + +function generateMainPackageJson( + mainPkg: MainPackageJson, + optionalDependencies: Record +): object { + return { + name: mainPkg.name, + version: mainPkg.version, + description: mainPkg.description, + author: mainPkg.author, + license: mainPkg.license ?? 'MIT', + type: mainPkg.type, + homepage: mainPkg.homepage, + bugs: mainPkg.bugs, + repository: mainPkg.repository, + bin: mainPkg.bin ?? { hapi: 'bin/hapi.cjs' }, + files: ['bin/hapi.cjs', 'NOTICE'], + optionalDependencies + }; +} + +function prepareMainPackage( + mainPkg: MainPackageJson, + projectRoot: string, + npmDir: string +): void { + const mainDir = join(npmDir, 'main'); + const binDir = join(mainDir, 'bin'); + const optionalDependencies = buildOptionalDependencies(mainPkg.version); + + mkdirSync(binDir, { recursive: true }); + + const srcBin = join(projectRoot, 'bin', 'hapi.cjs'); + const destBin = join(binDir, 'hapi.cjs'); + copyFileSync(srcBin, destBin); + chmodSync(destBin, 0o755); + + const srcNotice = join(projectRoot, 'NOTICE'); + const destNotice = join(mainDir, 'NOTICE'); + copyFileSync(srcNotice, destNotice); + + const pkgJson = generateMainPackageJson(mainPkg, optionalDependencies); + const pkgJsonPath = join(mainDir, 'package.json'); + writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4) + '\n'); + console.log(`Generated: ${pkgJsonPath}`); +} + async function preparePlatform( platform: typeof PLATFORMS[number], mainPkg: MainPackageJson, @@ -133,9 +198,7 @@ function updateMainPackageOptionalDeps(version: string): void { pkg.optionalDependencies = {}; } - for (const platform of PLATFORMS) { - pkg.optionalDependencies[`@twsxtd/hapi-${platform.name}`] = version; - } + pkg.optionalDependencies = buildOptionalDependencies(version); writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); console.log(`Updated optionalDependencies in package.json to version ${version}`); @@ -155,6 +218,13 @@ async function main(): Promise { let hasErrors = false; + try { + prepareMainPackage(mainPkg, projectRoot, npmDir); + } catch (error) { + console.error('Error preparing main package:', error); + hasErrors = true; + } + for (const platform of PLATFORMS) { try { await preparePlatform(platform, mainPkg, distExeDir, npmDir); diff --git a/cli/scripts/release-all.ts b/cli/scripts/release-all.ts index 2a87dfe0..fda7e502 100644 --- a/cli/scripts/release-all.ts +++ b/cli/scripts/release-all.ts @@ -4,8 +4,8 @@ * 1. Bump version * 2. Build binaries (with embedded web assets) * 3. Publish platform packages first (so lockfile can resolve them) - * 4. bun install (to get complete lockfile with published packages) - * 5. Publish main package + * 4. Publish main package + * 5. bun install (to get complete lockfile with published packages) * 6. Git commit + tag + push */ @@ -113,8 +113,9 @@ async function main(): Promise { } // Step 4: Publish main package - console.log('\n📤 Step 5: Publishing main package...'); - run(`npm publish --access public${dryRun ? ' --dry-run' : ''}`); + console.log('\n📤 Step 4: Publishing main package...'); + const mainNpmDir = join(projectRoot, 'npm', 'main'); + run(`npm publish --access public${dryRun ? ' --dry-run' : ''}`, mainNpmDir); // --publish-npm 模式到此结束 if (publishNpm) { @@ -123,7 +124,7 @@ async function main(): Promise { } // Step 5: bun install to get complete lockfile - console.log('\n📥 Step 4: Updating lockfile...'); + console.log('\n📥 Step 5: Updating lockfile...'); await runWithTimeoutRetry('bun install', repoRoot); // Step 6: Git commit + tag + push