UNPKG

cadb

Version:

安卓/鸿蒙系统截图/录屏工具

450 lines (420 loc) 13.7 kB
/** * Created by Niki on 2025/2/13 16:52. * Email: m13296644326@163.com */ const program = require('commander'); const { listenAnyKeyInput, processFile, loadOrCollectProjectPathBatch, } = require('../common/utils'); const {logRed, ctripHarmony, ztripHarmony} = require('../common/constants'); const { doTextFetchHttps, doTextPostFetchHttps, } = require('../common/utils/doTextFetchHttps'); const _ = require('lodash'); const fs = require('fs'); const JSON5 = require('json5'); const moment = require('moment'); const {table: TableConsole} = require('table'); const path = require('path'); let ctripHarmonyPath = ''; let ztripHarmonyPath = ''; // 请求bundle info的url, 等待拼接projectId const bundleUrl = 'https://mcd.release.ctripcorp.com/publish/project/'; const fetchVersionListUrl = 'https://mcd.release.ctripcorp.com/service/mcdConfig/get?appId=99999999'; const fetchVersionProjectUrl = 'https://mcd.release.ctripcorp.com/publish/projects'; program .option('-c --noCache', 'drop local project path cache') .action(args => { run(args); }) .parse(process.argv); async function run(args) { await loadLocalProjectPath(args); const versionList = await fetchVersionList(); const targetVersionItem = await selectVersion(versionList); const projectId = await fetchProjectId(targetVersionItem); const bundleInfoList = await fetchBundleInfo(projectId); const ztripPackageJsonPath = getPackageJsonPath(); const localPackageJsonInfo = readLocalHarmonyLibrary(ztripPackageJsonPath); const {matchedLibraryList: upgradeVersionList, unmatchedLibraryList} = createUpgradeVersionList(bundleInfoList, localPackageJsonInfo); printVersionTable(upgradeVersionList); await confirmGoOn(); await modifyPackageJson(upgradeVersionList); await wait(); // 阅读携程项目, 获取新版本 const upgradeVersionListCtrip = createUpgradeVersionListFromCtripProject(unmatchedLibraryList); printCtripVersionTable(upgradeVersionListCtrip); await modifyPackageJson(upgradeVersionListCtrip); syncRnOhVersion(); printFinalHint(); setTimeout(() => { process.exit(); }, 100); } async function loadLocalProjectPath(args) { const {noCache} = args; const pathList = await loadOrCollectProjectPathBatch( [ctripHarmony, ztripHarmony], noCache, ); ctripHarmonyPath = pathList[0]; ztripHarmonyPath = pathList[1]; } async function fetchVersionList() { console.log('starting version info fetch'); console.log('version info fetch url: ', fetchVersionListUrl); try { const versionInfoRes = await doTextFetchHttps(fetchVersionListUrl); const {success, message, clientVersions} = versionInfoRes; if (!success) { logRed('version info fetch failed: ' + message); process.exit(); } console.log('bundle info fetch success'); // console.log('res: ', JSON.stringify(clientVersions.slice(0, 4), null, 2)) return clientVersions.slice(0, 4); } catch (err) { console.log('version info fetch failed: ', err); process.exit(); } process.exit(); } async function selectVersion(versionList) { // 选择一个版本 console.log('\r\n请选择一个版本: '); const tableHead = ['Index', 'Version']; const list = [tableHead]; versionList.forEach((item, index) => { list.push([index, item.version]); }); const output = TableConsole(list); console.log(output); // 监听输入 const {controlCPress, key} = await listenAnyKeyInput(); if (controlCPress) { console.log('quit task'); process.exit(); } else { const index = parseInt(key, 10); if (isNaN(index) || index < 0 || index >= versionList.length) { logRed('请输入正确的序号'); process.exit(); } console.log('选择的版本: ', versionList[index].version); return versionList[index]; } return null; } async function fetchProjectId(targetVersionItem) { const {version, formalCode} = targetVersionItem; console.log('starting project info fetch'); const body = { appId: '99999999', platform: 'Harmony', version: {code: formalCode, name: version}, }; console.log('url: ', fetchVersionProjectUrl, 'body: ', body); const info = await doTextPostFetchHttps(fetchVersionProjectUrl, body); let {data: projectList = [], message, resultCode} = JSON.parse(info); if (resultCode !== 200) { logRed('project info fetch failed: ' + message); process.exit(); } console.log('project info fetch success'); projectList = projectList.map(item => { const {id, baseInfo} = item; const { planName, platform, branch, creator: {name: creatorName}, } = baseInfo; return { projectId: id, planName, creatorName, platform, branch, }; }); // 打印版本表格 const tableHead = [ 'Version Name', 'Platform', 'Id', 'Type', 'Creator', 'Branch', ]; const list = [tableHead]; projectList.forEach(item => { const {projectId, planName, creatorName, platform, branch} = item; list.push([version, platform, projectId, planName, creatorName, branch]); }); const output = TableConsole(list); console.log(output); const find = _.find(projectList, item => { // const {planName, platform, branch} = item; const {planName, platform} = item; // const isRelBranch = branch === `rel/${version}`; return platform === 'Harmony' && planName === '集成版'; }); if (!find) { logRed('未找到集成版的项目'); process.exit(); } return find.projectId; } async function fetchBundleInfo(projectId) { const fetchUrl = `${bundleUrl}${projectId}`; console.log('starting bundle info fetch'); console.log('bundle info fetch url: ', fetchUrl); try { const bundleInfo = await doTextFetchHttps(fetchUrl); console.log('bundle info fetch success'); if (_.isEmpty(bundleInfo?.data?.bundleList)) { logRed('bundle info list is empty'); process.exit(); } return bundleInfo.data.bundleList; } catch (err) { console.log('bundle info fetch failed: ', err); process.exit(); } process.exit(); } function getPackageJsonPath() { return path.join(ztripHarmonyPath, 'oh-package.json5'); } function readLocalHarmonyLibrary(packageJsonPath) { const json5Str = fs.readFileSync(packageJsonPath, 'utf8'); try { const json5Data = JSON5.parse(json5Str); console.log('项目: ', json5Data.name); return json5Data; } catch (err) { console.log(err); process.exit(); } return null; } function createUpgradeVersionList(bundleInfoList, localPackageJsonInfo) { const {overrides} = localPackageJsonInfo; const matchedLibraryList = []; const unmatchedLibraryList = []; for (const lbName in overrides) { const find = _.find(bundleInfoList, item => { let lastName = lbName; if (lbName.includes('/')) { lastName = lbName.split('/')[1]; } return lastName.toLowerCase() === item.bundleCode.toLowerCase(); }); const originVersion = overrides[lbName]; if (!find) { if (/^\d/.test(originVersion)) { logRed('匹配失败: ' + lbName); unmatchedLibraryList.push({ name: lbName, originVersion: originVersion, }); } } else { const {latestVersion} = find; const {bundleVersionName, markTime} = latestVersion; const compareResult = compareVersions(originVersion, bundleVersionName); if (compareResult >= 0) { console.log('无需更新: ', lbName); } else { matchedLibraryList.push({ name: lbName, originVersion: originVersion, newVersion: bundleVersionName, createTime: markTime, }); } } } return {matchedLibraryList, unmatchedLibraryList}; } function compareVersions(versionA, versionB) { const parseVersion = v => { const parts = v.split(/[-+]/); // 根据 "-" 和 "+" 分隔版本号和预发布/构建标识 const versionNumbers = parts[0].split('.').map(Number); // 将版本号分解为数字数组 const prerelease = parts[1] || ''; // 预发布部分 return {versionNumbers, prerelease}; }; const vA = parseVersion(versionA); const vB = parseVersion(versionB); for ( let i = 0; i < Math.max(vA.versionNumbers.length, vB.versionNumbers.length); i++ ) { const numA = vA.versionNumbers[i] || 0; // 默认为0,如果缺失部分 const numB = vB.versionNumbers[i] || 0; // 默认为0,如果缺失部分 if (numA > numB) { return 1; } // versionA 大 if (numA < numB) { return -1; } // versionB 大 } // 如果版本号部分相同,比较预发布部分 if (vA.prerelease && !vB.prerelease) { return -1; } // versionA 是预发布版,versionB 是正式的版本 if (!vA.prerelease && vB.prerelease) { return 1; } // versionB 是预发布版,versionA 是正式的版本 if (vA.prerelease && vB.prerelease) { return vA.prerelease.localeCompare(vB.prerelease); // 预发布字符串进行比较 } return 0; // 两个版本相同 } function printVersionTable(upgradeVersionList) { console.log('\r\n对比mcd最新版本依赖: '); const tableHead = [ 'Library Name', 'New Version', 'Compile Time', 'Local Old Version', ]; const list = [tableHead]; upgradeVersionList.forEach(item => { const {newVersion, name, originVersion, createTime} = item; list.push([ name, newVersion, `${moment(createTime, null, 'zh-cn').fromNow()}`, originVersion, ]); }); const output = TableConsole(list); console.log(output); } async function confirmGoOn() { console.log( '\r\nstep3: 以上是将要自动更新的依赖情况, 请确认是否进入下一步(Press Any key to go on):', ); const {controlCPress} = await listenAnyKeyInput(); if (controlCPress) { console.log('quit task'); process.exit(); } } async function modifyPackageJson(upgradeVersionList) { // '@ctbusiness/ctdevtools': '8.75.0-beta.20241015142902', // const {newVersion, name, originVersion, createTime} = item; const packageJsonPath = getPackageJsonPath(); console.log('\r\n开始写入新版本: \r\n'); await processFile(packageJsonPath, line => { const trimLine = line.trim(); if (/(^(['"])(@[^'"/]+\/[^'"/]+))/.test(trimLine)) { const lbName = RegExp.$1.replace('"', '').replace("'", ''); // console.log('lbName', lbName); const find = _.find(upgradeVersionList, {name: lbName}); if (find) { const left = line.split(trimLine)[0]; const {newVersion, originVersion} = find; console.log(`${lbName}: ${originVersion} -> ${newVersion}`); return `${left}"${lbName}": "${newVersion}",`; } } return line; }); } function createUpgradeVersionListFromCtripProject(unmatchedLibraryList) { const ctripPath = path.join(ctripHarmonyPath, 'oh-package.json5'); const ctripLibraryMap = readLocalHarmonyLibrary(ctripPath).overrides; const upgradeVersionListCtrip = []; for (const item of unmatchedLibraryList) { const {name, originVersion} = item; const ctripVersion = ctripLibraryMap[name]; if (!ctripVersion) { logRed('匹配失败: ' + name); continue; } const compareResult = compareVersions(originVersion, ctripVersion); if (compareResult >= 0) { console.log('无需更新: ', name); continue; } upgradeVersionListCtrip.push({ name, originVersion, newVersion: ctripVersion, }); } return upgradeVersionListCtrip; } function printCtripVersionTable(upgradeVersionListCtrip) { console.log('\r\n落后Ctrip_Harmony项目的依赖: '); const tableHead = ['Library Name', 'Ctrip New Version', 'Ztrip Old Version']; const list = [tableHead]; upgradeVersionListCtrip.forEach(item => { const {newVersion, name, originVersion} = item; list.push([name, newVersion, originVersion]); }); const output = TableConsole(list); console.log(output); } function syncRnOhVersion() { const ctripModulePath = path.join( ctripHarmonyPath, 'entry/Phone/src/main/module.json5', ); const ztripModulePath1 = path.join( ztripHarmonyPath, 'app_config/default/config.json5', ); const ztripModulePath2 = path.join( ztripHarmonyPath, 'app_config/travel/config.json5', ); const json5Str = fs.readFileSync(ctripModulePath, 'utf8'); const ctripConfig = JSON5.parse(json5Str); const ctripMeta = _.get(ctripConfig, 'module.metadata', []); const find = _.find(ctripMeta, {name: 'rnoh_version'}); if (!find) { console.log(`${ctripModulePath}下未找到 rnoh_version`); return; } const rnohVersion = find.value; modifyZtripModuleRnOhVersion(ztripModulePath1, rnohVersion); console.log( `\r\n已更新 ${ztripModulePath1} 下的 rnoh_version: ${rnohVersion}`, ); modifyZtripModuleRnOhVersion(ztripModulePath2, rnohVersion); console.log(`已更新 ${ztripModulePath2} 下的 rnoh_version: ${rnohVersion}`); } function modifyZtripModuleRnOhVersion(modulePath, rnohVersion) { const json5Str = fs.readFileSync(modulePath, 'utf8'); const zConfig1 = JSON5.parse(json5Str); zConfig1.metadata = zConfig1.metadata.map(t => { if (t.name === 'rnoh_version') { t.value = rnohVersion; } return t; }); fs.writeFileSync(modulePath, JSON.stringify(zConfig1, null, 2)); } function printFinalHint() { console.log( '\r\n!!! 后续请逐个分析 ctrip_harmony 项目的commit, 以同步其他改动', ); } function wait(duration) { return new Promise((res, rej) => { setTimeout(() => { res(); }, duration); }); }