UNPKG

@plasosdk/client-sdk

Version:

Plaso教育平台的客户端SDK

312 lines (273 loc) 9.76 kB
#!/usr/bin/env node /** * Plaso SDK 发布脚本 * * 功能: * - 自动升级版本号(major/minor/patch) * - 检查登录状态 * - 发布包 * * 使用方法: * - 基本用法: npm run release * (无参数时会进入交互模式,询问是否跳过版本升级) * - 跳过版本升级(推荐): npm run release-skip * - 跳过版本升级(手动传参): npm run release -- --skip-version-upgrade * - 跳过版本升级(简写): npm run release -- -s * * 注意: * - 使用跳过版本选项时,会检查当前版本是否已发布,如已发布会提示确认 * - 如果您手动修改了版本号,建议使用跳过版本升级选项 * - 此脚本假设您已经手动设置了正确的npm源,不会自动切换源 */ const { execSync } = require('child_process'); const readline = require('readline'); const fs = require('fs'); const path = require('path'); // 创建readline接口 const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); // 添加跨平台休眠函数 function sleep(seconds) { // 根据操作系统选择合适的休眠方法 const isWindows = process.platform === 'win32'; try { if (isWindows) { // Windows 使用 timeout 命令 execSync(`timeout /t ${seconds}`, { stdio: 'ignore' }); } else { // Unix 系统使用 sleep 命令 execSync(`sleep ${seconds}`, { stdio: 'ignore' }); } } catch (error) { // 如果命令执行失败,使用JavaScript的setTimeout作为备选 console.log(`系统休眠命令失败,使用JavaScript休眠 ${seconds} 秒`); const start = Date.now(); while (Date.now() - start < seconds * 1000) { // 空循环等待 } } } // 执行命令的函数 function executeCommand(command) { try { execSync(command, { stdio: 'inherit' }); return true; } catch (error) { // 检查是否是版本已存在的错误 if (error.message.includes('You cannot publish over the previously published versions')) { console.log('\n该版本已经发布过了,无需重复发布'); return true; } console.error(`执行命令失败: ${command}`); console.error(error.message); return false; } } // 检查npm登录状态 function checkNpmLoginStatus() { try { // 直接使用npm命令而不是npx const output = execSync('npm whoami', { encoding: 'utf8' }); const username = output.trim(); if (username.length > 0) { console.log(`当前登录用户: ${username}`); return true; } return false; } catch (error) { console.log('npm登录状态检查失败,您可能尚未登录'); return false; } } // 确保npm登录 async function ensureNpmLogin() { console.log('\n检查npm登录状态...'); // 检查登录状态 const isLoggedIn = checkNpmLoginStatus(); if (!isLoggedIn) { console.log('未登录,开始登录流程...'); // 登录命令 const loginCmd = 'npm login'; if (!executeCommand(loginCmd)) { throw new Error('npm登录失败'); } // 再次检查登录状态 if (!checkNpmLoginStatus()) { throw new Error('登录失败,请重试'); } console.log('登录成功!'); return true; } else { console.log('已经登录,跳过登录步骤'); return true; } } // 提示用户输入 function prompt(question) { return new Promise((resolve) => { rl.question(question, (answer) => { resolve(answer); }); }); } // 读取package.json文件 function readPackageJson() { const packagePath = path.join(process.cwd(), 'package.json'); const packageContent = fs.readFileSync(packagePath, 'utf8'); return JSON.parse(packageContent); } // 写入package.json文件 function writePackageJson(packageJson) { const packagePath = path.join(process.cwd(), 'package.json'); fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + '\n'); } // 升级版本号 function upgradeVersion(currentVersion, type) { const [major, minor, patch] = currentVersion.split('.').map(Number); switch (type) { case 'major': return `${major + 1}.0.0`; case 'minor': return `${major}.${minor + 1}.0`; case 'patch': default: return `${major}.${minor}.${patch + 1}`; } } // 检查版本是否已发布 async function checkVersionExists(packageName, version) { try { console.log(`检查版本 ${packageName}@${version} 是否已发布...`); const cmd = `npx npm view ${packageName}@${version} version --json`; try { execSync(cmd, { stdio: 'ignore' }); console.log(`版本 ${version} 已存在于npm仓库`); return true; } catch (e) { // 如果命令执行失败,通常意味着版本不存在 console.log(`版本 ${version} 不存在于npm仓库,可以发布`); return false; } } catch (error) { console.error('检查版本失败:', error.message); // 发生错误时,默认允许继续(让npm publish时再判断) return false; } } // 解析命令行参数 function parseArgs() { const args = process.argv.slice(2); const options = { skipVersionUpgrade: false, interactive: args.length === 0 // 如果没有传入参数,则启用交互模式 }; for (let i = 0; i < args.length; i++) { const arg = args[i]; if (arg === '--skip-version-upgrade' || arg === '-s') { options.skipVersionUpgrade = true; } } return options; } async function main() { // 解析命令行参数 const options = parseArgs(); try { console.log('开始发布SDK...'); // 交互模式:如果没有传入命令行参数,则询问是否要跳过版本升级 if (options.interactive) { const skipVersionAnswer = await prompt('是否跳过版本升级? (y/n): '); if (skipVersionAnswer.toLowerCase() === 'y') { options.skipVersionUpgrade = true; console.log('已选择跳过版本升级'); } } // 0. 升级版本号 console.log('\n0. 升级版本号...'); const packageJson = readPackageJson(); const currentVersion = packageJson.version; let newVersion; // 如果命令行参数指定跳过版本升级 if (options.skipVersionUpgrade) { console.log('检测到--skip-version-upgrade参数,跳过版本升级'); newVersion = currentVersion; } else { console.log(`当前版本: ${currentVersion}`); console.log('请选择版本升级类型:'); console.log('1. major - 主版本号升级 (不兼容的API变更)'); console.log('2. minor - 次版本号升级 (向后兼容的功能性新增)'); console.log('3. patch - 修订号升级 (向后兼容的问题修正)'); console.log('4. skip - 跳过版本升级,保持当前版本'); const versionType = await prompt('请输入选项 (1/2/3/4,默认为3): '); let type; switch (versionType.trim()) { case '1': type = 'major'; newVersion = upgradeVersion(currentVersion, type); break; case '2': type = 'minor'; newVersion = upgradeVersion(currentVersion, type); break; case '4': console.log('已选择跳过版本升级'); newVersion = currentVersion; break; case '3': default: type = 'patch'; newVersion = upgradeVersion(currentVersion, type); break; } } console.log(`版本: ${newVersion}`); // 如果版本没有变化,直接询问是否确认发布 const confirmMessage = newVersion === currentVersion ? `确认发布当前版本 ${currentVersion}? (y/n): ` : `确认将版本从 ${currentVersion} 升级到 ${newVersion}? (y/n): `; const confirm = await prompt(confirmMessage); if (confirm.toLowerCase() !== 'y') { console.log('已取消发布'); return; } // 只有当版本变化时才写入package.json if (newVersion !== currentVersion) { packageJson.version = newVersion; writePackageJson(packageJson); console.log(`版本已更新为 ${newVersion}`); } else { console.log(`继续使用当前版本 ${currentVersion}`); // 当用户选择继续使用当前版本时,检查该版本是否已发布 const versionExists = await checkVersionExists(packageJson.name, currentVersion); if (versionExists) { console.log(`\n警告: 版本 ${currentVersion} 已经发布,继续操作会失败。`); const forceContinue = await prompt('是否仍要继续? (y/n): '); if (forceContinue.toLowerCase() !== 'y') { console.log('已取消发布'); return; } console.log('用户选择强制继续,可能会在发布时报错'); } } // 1. 确保登录 console.log('\n1. 检查登录状态...'); if (!await ensureNpmLogin()) { throw new Error('登录失败'); } // 2. 发布包 console.log('\n2. 开始发布包...'); const publishCmd = 'npm publish --ignore-scripts'; if (!executeCommand(publishCmd)) { throw new Error('发布包失败'); } console.log(`\n恭喜!${packageJson.name}@${newVersion} 已成功发布到npm!`); } catch (error) { console.error('\n发布失败:', error.message); process.exit(1); } finally { rl.close(); } } main();