#!/usr/bin/env node import { execSync } from 'child_process'; import { copyFileSync, mkdirSync, existsSync, readFileSync, writeFileSync, rmSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const rootDir = join(__dirname, '..'); // 辅助函数:执行命令 function exec(command, options = {}) { console.log(`\n📦 执行: ${command}`); try { execSync(command, { stdio: 'inherit', cwd: rootDir, ...options }); } catch (error) { console.error(`❌ 命令失败: ${command}`); process.exit(1); } } // 辅助函数:确保目录存在 function ensureDir(dir) { if (!existsSync(dir)) { mkdirSync(dir, { recursive: true }); } } // 辅助函数:读取和写入 JSON function readJSON(path) { return JSON.parse(readFileSync(path, 'utf-8')); } function writeJSON(path, data) { writeFileSync(path, JSON.stringify(data, null, 2)); } // 获取命令行参数 const args = process.argv.slice(2); const command = args[0]; // 构建任务 const tasks = { // 清理所有构建产物 clean() { console.log('🧹 清理构建产物...'); const dirs = [ 'packages/web/build', 'packages/web/dist', 'packages/core/dist', 'packages/core/web-build', 'packages/electron/dist', 'packages/electron/web-build' ]; dirs.forEach(dir => { const path = join(rootDir, dir); if (existsSync(path)) { rmSync(path, { recursive: true, force: true }); console.log(` ✅ 已删除: ${dir}`); } }); }, // 构建 Web 前端 async buildWeb() { console.log('\n🌐 构建 Web 前端...'); exec('npm run build', { cwd: join(rootDir, 'packages/web') }); }, // 构建 Shared 包 async buildShared() { console.log('\n📦 构建 Shared 包...'); exec('npm run build', { cwd: join(rootDir, 'packages/shared') }); }, // 构建 Shared 包 (用于发布) async buildSharedForPublish() { console.log('\n📦 构建 Shared 包 (发布版)...'); const sharedDir = join(rootDir, 'packages/shared'); // 先构建 await tasks.buildShared(); // 处理 package.json(用于发布) const pkgPath = join(sharedDir, 'package.json'); let pkg = readJSON(pkgPath); // 更新版本号 const rootPkg = readJSON(join(rootDir, 'package.json')); pkg.version = rootPkg.version; writeJSON(pkgPath, pkg); console.log(' ✅ 已处理 Shared 包发布配置'); }, // 构建 Core(Node.js 核心) async buildCore() { console.log('\n🎯 构建 Core 包...'); const coreDir = join(rootDir, 'packages/core'); const distDir = join(coreDir, 'dist'); // 创建输出目录 ensureDir(distDir); // 先确保 Web 已构建 if (!existsSync(join(rootDir, 'packages/web/build'))) { await tasks.buildWeb(); } // 使用完整构建流程(包含web构建) exec('npm run build:full', { cwd: coreDir }); // 复制必要文件 const filesToCopy = ['README.md']; filesToCopy.forEach(file => { const src = join(rootDir, file); const dest = join(distDir, file); if (existsSync(src)) { copyFileSync(src, dest); console.log(` ✅ 复制: ${file}`); } }); // 处理 package.json(用于发布) if (args.includes('--publish')) { const corePkgPath = join(coreDir, 'package.json'); let pkg = readJSON(corePkgPath); // 更新版本号 const rootPkg = readJSON(join(rootDir, 'package.json')); pkg.version = rootPkg.version; // 替换 file: 依赖为实际的包版本 if (pkg.dependencies && pkg.dependencies['@dadigua/hyperchat-shared']) { pkg.dependencies['@dadigua/hyperchat-shared'] = `^${rootPkg.version}`; console.log(` ✅ 更新 @dadigua/hyperchat-shared 依赖版本: ^${rootPkg.version}`); } writeJSON(corePkgPath, pkg); console.log(' ✅ 已处理 Core 包发布配置'); } }, // 构建 Electron async buildElectron() { console.log('\n💻 构建 Electron 应用...'); const electronDir = join(rootDir, 'packages/electron'); // 先确保 Web 已构建 if (!existsSync(join(rootDir, 'packages/web/build'))) { await tasks.buildWeb(); } // 使用 Electron 包的完整构建流程 exec('npm run build:electron', { cwd: electronDir }); }, // 构建所有 async buildAll() { console.log('🚀 开始完整构建...\n'); // 清理 tasks.clean(); // 构建各包 (不再需要shared,使用路径别名替换) await tasks.buildCore(); // Core 构建现在包含web构建 await tasks.buildElectron(); console.log('\n✨ 所有构建已完成!'); }, // 发布准备:构建并配置发布用的包 async buildForPublish() { console.log('📦 准备发布构建...\n'); // 清理 tasks.clean(); // 构建 core 包 (发布版) args.push('--publish'); // 确保传递 --publish 参数 await tasks.buildCore(); console.log('\n✨ 发布构建已完成!'); console.log('\n📝 下一步:'); console.log('1. 运行: npm run publish:core'); }, // 发布 core 包 async publishCore() { console.log('📤 发布 Core 包...'); const coreDir = join(rootDir, 'packages/core'); // 检查是否已经构建 if (!existsSync(join(coreDir, 'dist'))) { console.log('⚠️ 检测到 Core 包未构建,先进行构建...'); if (!args.includes('--publish')) { args.push('--publish'); // 确保传递 --publish 参数 } await tasks.buildCore(); } const publishTag = process.env.NPM_PUBLISH_TAG || 'latest'; const tagFlag = publishTag === 'latest' ? '' : ` --tag ${publishTag}`; console.log(`📦 发布标签: ${publishTag}`); exec(`npm publish --access public${tagFlag}`, { cwd: coreDir }); console.log('✅ Core 包发布完成!'); }, // 完整发布流程 async publishAll() { console.log('🚀 开始完整发布流程...\n'); // 1. 构建发布版本 await tasks.buildForPublish(); // 2. 发布 core 包 await tasks.publishCore(); console.log('\n🎉 Core 包发布完成!'); }, // 开发模式 dev() { const target = args[1] || 'web'; console.log(`🔧 启动开发模式: ${target}`); switch (target) { case 'shared': exec('npm run dev', { cwd: join(rootDir, 'packages/shared') }); break; case 'web': exec('npm run start', { cwd: join(rootDir, 'packages/web') }); break; case 'core': exec('npm run start', { cwd: join(rootDir, 'packages/core') }); break; case 'cli': exec('npm run start', { cwd: join(rootDir, 'packages/cli') }); break; case 'electron': exec('npm run start', { cwd: join(rootDir, 'packages/electron') }); break; case 'all': // 使用 concurrently 同时运行多个开发服务器 exec('npx concurrently "npm run start --prefix packages/web" "npm run start --prefix packages/core"'); break; default: console.error(`❌ 未知的开发目标: ${target}`); console.log('可用选项: shared, web, core, cli, electron, all'); process.exit(1); } }, // 帮助信息 help() { console.log(` HyperChat 构建脚本 使用方法: node scripts/build.mjs [options] 构建命令: clean 清理所有构建产物 buildWeb 构建 Web 前端 buildCore 构建 Core 包 (包含Web前端) buildElectron 构建 Electron 应用 buildAll 构建所有包 buildForPublish 构建Core包 (发布版) 发布命令: publishCore 发布 Core 包到 npm publishAll 完整发布流程 (推荐) 开发命令: dev [target] 启动开发模式 (shared/web/core/cli/electron/all) help 显示此帮助信息 选项: --publish 为发布准备 Core 包(处理 package.json) 示例: node scripts/build.mjs buildAll node scripts/build.mjs dev web node scripts/build.mjs buildForPublish node scripts/build.mjs publishCore 发布流程: 1. node scripts/build.mjs publishAll # 推荐:一键发布 或者分步执行: 2a. node scripts/build.mjs buildForPublish 2b. node scripts/build.mjs publishCore `); } }; // 执行命令 const taskName = command || 'help'; const task = tasks[taskName]; if (task) { try { const result = task(); if (result && typeof result.catch === 'function') { result.catch(error => { console.error('❌ 构建失败:', error); process.exit(1); }); } } catch (error) { console.error('❌ 构建失败:', error); process.exit(1); } } else { console.error(`❌ 未知命令: ${taskName}`); tasks.help(); process.exit(1); }