1
0
mirror of https://gitcode.com/github-mirrors/react-native-update-cli.git synced 2025-09-17 18:06:10 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

Compare commits

..

3 Commits

Author SHA1 Message Date
sunnylqm
18d772b1bc fix version compare 2025-05-15 22:45:08 +08:00
sunnylqm
bf0cea66b9 Update version to 1.45.1 and add semverRange property in cli.json 2025-05-15 22:29:57 +08:00
sunnylqm
8c31ee5762 semver range 2025-05-15 22:13:42 +08:00
12 changed files with 192 additions and 206 deletions

View File

@@ -25,7 +25,7 @@
"properties": "^1.2.1",
"read": "^4.1.0",
"registry-auth-token": "^5.1.0",
"semver": "^7.7.1",
"semver": "^7.7.2",
"tcp-ping": "^0.1.1",
"tty-table": "4.2",
"yauzl": "^3.2.0",
@@ -33,11 +33,11 @@
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@swc/cli": "0.7.3",
"@swc/cli": "0.7.7",
"@swc/core": "^1.11.24",
"@types/filesize-parser": "^1.5.3",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.14.1",
"@types/node": "^22.15.18",
"@types/node-fetch": "^2.6.12",
"@types/progress": "^2.0.7",
"@types/semver": "^7.7.0",
@@ -125,7 +125,7 @@
"@sindresorhus/is": ["@sindresorhus/is@5.6.0", "", {}, "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g=="],
"@swc/cli": ["@swc/cli@0.7.3", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-rnVXNnlURjdOuPaBIwZ3TmBA44BF/eP0j154LanlgPEYfau74ige7cpKlKkZr1IBqMOG99lAnYNxQipDWA3hdg=="],
"@swc/cli": ["@swc/cli@0.7.7", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-j4yYm9bx3pxWofaJKX1BFwj/3ngUDynN4UIQ2Xd2h0h/7Gt7zkReBTpDN7g5S13mgAYxacaTHTOUsz18097E8w=="],
"@swc/core": ["@swc/core@1.11.24", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.21" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.24", "@swc/core-darwin-x64": "1.11.24", "@swc/core-linux-arm-gnueabihf": "1.11.24", "@swc/core-linux-arm64-gnu": "1.11.24", "@swc/core-linux-arm64-musl": "1.11.24", "@swc/core-linux-x64-gnu": "1.11.24", "@swc/core-linux-x64-musl": "1.11.24", "@swc/core-win32-arm64-msvc": "1.11.24", "@swc/core-win32-ia32-msvc": "1.11.24", "@swc/core-win32-x64-msvc": "1.11.24" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg=="],
@@ -165,7 +165,7 @@
"@types/jsonfile": ["@types/jsonfile@6.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ=="],
"@types/node": ["@types/node@22.14.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw=="],
"@types/node": ["@types/node@22.15.18", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg=="],
"@types/node-fetch": ["@types/node-fetch@2.6.12", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.0" } }, "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA=="],
@@ -625,7 +625,7 @@
"seek-bzip": ["seek-bzip@2.0.0", "", { "dependencies": { "commander": "^6.0.0" }, "bin": { "seek-bunzip": "bin/seek-bunzip", "seek-table": "bin/seek-bzip-table" } }, "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg=="],
"semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"semver-regex": ["semver-regex@4.0.5", "", {}, "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw=="],

View File

@@ -87,6 +87,9 @@
"maxPackageVersion": {
"hasValue": true
},
"semverRange": {
"hasValue": true
},
"rollout": {
"hasValue": true
}

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-update-cli",
"version": "1.44.7",
"version": "1.45.2",
"description": "command line tool for react-native-update (remote updates for react native)",
"main": "index.js",
"bin": {
@@ -57,7 +57,7 @@
"properties": "^1.2.1",
"read": "^4.1.0",
"registry-auth-token": "^5.1.0",
"semver": "^7.7.1",
"semver": "^7.7.2",
"tcp-ping": "^0.1.1",
"tty-table": "4.2",
"yauzl": "^3.2.0",
@@ -68,11 +68,11 @@
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@swc/cli": "0.7.3",
"@swc/cli": "0.7.7",
"@swc/core": "^1.11.24",
"@types/filesize-parser": "^1.5.3",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.14.1",
"@types/node": "^22.15.18",
"@types/node-fetch": "^2.6.12",
"@types/progress": "^2.0.7",
"@types/semver": "^7.7.0",

View File

@@ -11,7 +11,7 @@ import {
credentialFile,
defaultEndpoint,
} from './utils/constants';
import type { Session } from 'types';
import type { Session, Package } from 'types';
import FormData from 'form-data';
import { t } from './utils/i18n';
@@ -177,3 +177,8 @@ export async function uploadFile(fn: string, key?: string) {
// const body = await response.json();
return { hash: key || formData.key };
}
export const getAllPackages = async (appId: string) => {
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
return data as Package[] | undefined | null;
};

View File

@@ -8,7 +8,13 @@ import { t } from './utils/i18n';
const validPlatforms = ['ios', 'android', 'harmony'];
export function checkPlatform(platform: Platform) {
export async function getPlatform(platform?: string) {
return assertPlatform(
platform || (await question(t('platformQuestion'))),
) as Platform;
}
export function assertPlatform(platform: string) {
if (!validPlatforms.includes(platform)) {
throw new Error(t('unsupportedPlatform', { platform }));
}
@@ -16,7 +22,7 @@ export function checkPlatform(platform: Platform) {
}
export function getSelectedApp(platform: Platform) {
checkPlatform(platform);
assertPlatform(platform);
if (!fs.existsSync('update.json')) {
throw new Error(t('appNotSelected', { platform }));
@@ -68,9 +74,7 @@ export const commands = {
}) {
const name = options.name || (await question(t('appNameQuestion')));
const { downloadUrl } = options;
const platform = checkPlatform(
options.platform || (await question(t('platformQuestion'))),
);
const platform = await getPlatform(options.platform);
const { id } = await post('/app/create', { name, platform, downloadUrl });
console.log(t('createAppSuccess', { id }));
await this.selectApp({
@@ -104,9 +108,7 @@ export const commands = {
args: string[];
options: { platform: Platform };
}) => {
const platform = checkPlatform(
options.platform || (await question(t('platformQuestion'))),
);
const platform = await getPlatform(options.platform);
const id = args[0]
? Number.parseInt(args[0])
: (await chooseApp(platform)).id;

View File

@@ -8,9 +8,9 @@ import {
type ZipFile as YauzlZipFile,
} from 'yauzl';
import { question, checkPlugins } from './utils';
import { checkPlatform } from './app';
import { getPlatform } from './app';
import { spawn, spawnSync } from 'child_process';
import semverSatisfies from 'semver/functions/satisfies';
import { satisfies } from 'compare-versions';
const g2js = require('gradle-to-js/lib/parser');
import os from 'os';
const properties = require('properties');
@@ -101,7 +101,7 @@ async function runReactNativeBundleCommand({
.toString(),
).version;
// expo cli 0.10.17 (expo 49) 开始支持 bundle:embed
if (semverSatisfies(expoCliVersion, '>= 0.10.17')) {
if (satisfies(expoCliVersion, '>= 0.10.17')) {
usingExpo = true;
} else {
cliPath = undefined;
@@ -902,9 +902,7 @@ function diffArgsCheck(args: string[], options: any, diffFn: string) {
export const commands = {
bundle: async ({ options }) => {
const platform = checkPlatform(
options.platform || (await question(t('platformPrompt'))),
);
const platform = await getPlatform(options.platform);
const {
bundleName,

View File

@@ -73,9 +73,11 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
'Multiple lock files detected ({{- lockFiles}}), which may cause inconsistent dependencies and hot-updating issues.',
nativePackageId: 'Native Package ID',
nativeVersion: 'Native Version',
nativeVersionNotFound: 'No native version found >= {{version}}',
nativeVersionNotFoundLess: 'No native version found <= {{version}}',
nativeVersionNotFoundGte: 'No native version found >= {{version}}',
nativeVersionNotFoundLte: 'No native version found <= {{version}}',
nativeVersionNotFoundMatch: 'No matching native version found: {{version}}',
nativePackageIdNotFound: 'No native package id found: {{id}}',
noPackagesFound: 'No packages found. (appId: {{appId}})',
offset: 'Offset {{offset}}',
operationComplete: 'Operation complete, bound to {{count}} native versions',
operationSuccess: 'Operation successful',
@@ -122,4 +124,9 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
versionBind:
'Bound version {{version}} to native version {{nativeVersion}} (id: {{id}})',
welcomeMessage: 'Welcome to Cresc hot update service, {{name}}.',
versionNameQuestion: 'Enter version name:',
versionDescriptionQuestion: 'Enter version description:',
versionMetaInfoQuestion: 'Enter custom meta info:',
updateNativePackageQuestion: 'Bind to native package now?(Y/N)',
unnamed: '(Unnamed)',
};

View File

@@ -69,9 +69,11 @@ export default {
'检测到多种不同格式的锁文件({{- lockFiles}}),这可能导致依赖关系不一致而使热更异常。',
nativePackageId: '原生包 Id',
nativeVersion: '原生版本',
nativeVersionNotFound: '未查询到 >= {{version}} 的原生版本',
nativeVersionNotFoundLess: '未查询到 <= {{version}} 的原生版本',
nativeVersionNotFoundGte: '未查询到 >= {{version}} 的原生版本',
nativeVersionNotFoundLte: '未查询到 <= {{version}} 的原生版本',
nativeVersionNotFoundMatch: '未查询到匹配原生版本:{{version}}',
nativePackageIdNotFound: '未查询到原生包 id: {{id}}',
noPackagesFound: '未查询到任何原生包appId: {{appId}}',
offset: '偏移量 {{offset}}',
operationComplete: '操作完成,共已绑定 {{count}} 个原生版本',
operationSuccess: '操作成功',
@@ -115,4 +117,9 @@ export default {
versionBind:
'已将热更版本 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。',
versionNameQuestion: '输入版本名称:',
versionDescriptionQuestion: '输入版本描述:',
versionMetaInfoQuestion: '输入自定义的 meta info:',
updateNativePackageQuestion: '是否现在将此热更应用到原生包上?(Y/N)',
unnamed: '(未命名)',
};

View File

@@ -1,8 +1,8 @@
import { get, post, uploadFile } from './api';
import { get, getAllPackages, post, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { t } from './utils/i18n';
import { checkPlatform, getSelectedApp } from './app';
import { checkPlatform, getPlatform, getSelectedApp } from './app';
import { getApkInfo, getIpaInfo, getAppInfo } from './utils';
import Table from 'tty-table';
@@ -11,14 +11,14 @@ import { getCommitInfo } from './utils/git';
import type { Platform } from 'types';
export async function listPackage(appId: string) {
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const allPkgs = await getAllPackages(appId);
const header = [
{ value: t('nativePackageId') },
{ value: t('nativeVersion') },
];
const rows = [];
for (const pkg of data) {
for (const pkg of allPkgs) {
const { version } = pkg;
let versionInfo = '';
if (version) {
@@ -36,8 +36,8 @@ export async function listPackage(appId: string) {
}
console.log(Table(header, rows).render());
console.log(t('totalPackages', { count: data.length }));
return data;
console.log(t('totalPackages', { count: allPkgs.length }));
return allPkgs;
}
export async function choosePackage(appId: string) {
@@ -174,9 +174,7 @@ export const commands = {
console.log(await getApkInfo(fn));
},
packages: async ({ options }: { options: { platform: Platform } }) => {
const platform = checkPlatform(
options.platform || (await question(t('platformPrompt'))),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
await listPackage(appId);
},

View File

@@ -8,3 +8,15 @@ export interface Session {
}
export type Platform = 'ios' | 'android' | 'harmony';
export interface Package {
id: string;
name: string;
}
export interface Version {
id: string;
hash: string;
name: string;
packages?: Package[];
}

View File

@@ -3,7 +3,7 @@ import os from 'os';
import path from 'path';
import pkg from '../../package.json';
import AppInfoParser from './app-info-parser';
import semverSatisfies from 'semver/functions/satisfies';
import { satisfies } from 'compare-versions';
import chalk from 'chalk';
import latestVersion from '../utils/latest-version';
import { checkPlugins } from './check-plugin';
@@ -189,24 +189,24 @@ export async function printVersionCommand() {
: '';
console.log(`react-native-update: ${rnuVersion}${latestRnuVersion}`);
if (IS_CRESC) {
if (semverSatisfies(rnuVersion, '<10.27.0')) {
if (satisfies(rnuVersion, '<10.27.0')) {
console.error(
'Unsupported version, please update to the latest version: npm i react-native-update@latest',
);
process.exit(1);
}
} else {
if (semverSatisfies(rnuVersion, '<8.5.2')) {
if (satisfies(rnuVersion, '<8.5.2')) {
console.warn(
`当前版本已不再支持,请至少升级到 v8 的最新小版本后重新打包(代码无需改动): npm i react-native-update@8 .
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`,
);
} else if (semverSatisfies(rnuVersion, '9.0.0 - 9.2.1')) {
} else if (satisfies(rnuVersion, '9.0.0 - 9.2.1')) {
console.warn(
`当前版本已不再支持,请至少升级到 v9 的最新小版本后重新打包(代码无需改动,可直接热更): npm i react-native-update@9 .
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`,
);
} else if (semverSatisfies(rnuVersion, '10.0.0 - 10.17.0')) {
} else if (satisfies(rnuVersion, '10.0.0 - 10.17.0')) {
console.warn(
'当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10',
);

View File

@@ -1,25 +1,13 @@
import { get, post, put, uploadFile } from './api';
import { get, getAllPackages, post, put, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { t } from './utils/i18n';
import { checkPlatform, getSelectedApp } from './app';
import { getPlatform, getSelectedApp } from './app';
import { choosePackage } from './package';
import { compare } from 'compare-versions';
import { depVersions } from './utils/dep-versions';
import { getCommitInfo } from './utils/git';
import type { Platform } from 'types';
interface Package {
id: string;
name: string;
}
interface Version {
id: string;
hash: string;
name: string;
packages?: Package[];
}
import type { Package, Platform, Version } from 'types';
import { satisfies } from 'compare-versions';
interface CommandOptions {
name?: string;
@@ -31,6 +19,7 @@ interface CommandOptions {
packageVersion?: string;
minPackageVersion?: string;
maxPackageVersion?: string;
semverRange?: string;
rollout?: string;
}
@@ -113,6 +102,49 @@ async function chooseVersion(appId: string) {
}
}
export const bindVersionToPackages = async ({
appId,
versionId,
pkgs,
rollout,
}: {
appId: string;
versionId: string;
pkgs: Package[];
rollout?: number;
}) => {
if (rollout !== undefined) {
const rolloutConfig: Record<string, number> = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
rollout: rollout,
})}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkg.name,
id: pkg.id,
})}`,
);
}
console.log(t('operationComplete', { count: pkgs.length }));
};
export const commands = {
publish: async function ({
args,
@@ -128,21 +160,19 @@ export const commands = {
throw new Error(t('publishUsage'));
}
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
const { hash } = await uploadFile(fn);
const versionName =
name || (await question('输入版本名称: ')) || '(未命名)';
name || (await question(t('versionNameQuestion'))) || t('unnamed');
const { id } = await post(`/app/${appId}/version/create`, {
name: versionName,
hash,
description: description || (await question('输入版本描述:')),
metaInfo: metaInfo || (await question('输入自定义的 meta info:')),
description:
description || (await question(t('versionDescriptionQuestion'))),
metaInfo: metaInfo || (await question(t('versionMetaInfoQuestion'))),
deps: depVersions,
commit: await getCommitInfo(),
});
@@ -150,17 +180,14 @@ export const commands = {
saveToLocal(fn, `${appId}/ppk/${id}.ppk`);
console.log(t('packageUploadSuccess', { id }));
const v = await question('是否现在将此热更应用到原生包上?(Y/N)');
const v = await question(t('updateNativePackageQuestion'));
if (v.toLowerCase() === 'y') {
await this.update({ args: [], options: { versionId: id, platform } });
}
return versionName;
},
versions: async ({ options }: { options: CommandOptions }) => {
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
await listVersions(appId);
},
@@ -171,20 +198,18 @@ export const commands = {
args: string[];
options: CommandOptions;
}) => {
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
let versionId = options.versionId || (await chooseVersion(appId)).id;
if (versionId === 'null') {
versionId = undefined;
}
let pkgId: string | undefined;
let pkgId = options.packageId;
let pkgVersion = options.packageVersion;
let minPkgVersion = options.minPackageVersion;
let maxPkgVersion = options.maxPackageVersion;
let semverRange = options.semverRange;
let rollout: number | undefined = undefined;
if (options.rollout !== undefined) {
@@ -198,146 +223,78 @@ export const commands = {
}
}
if (minPkgVersion) {
minPkgVersion = String(minPkgVersion).trim();
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const pkgs = data.filter((pkg: Package) =>
compare(pkg.name, minPkgVersion!, '>='),
);
if (pkgs.length === 0) {
throw new Error(t('nativeVersionNotFound', { version: minPkgVersion }));
}
if (rollout !== undefined) {
const rolloutConfig: Record<string, number> = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
rollout: rollout,
})}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkg.name,
id: pkg.id,
})}`,
);
}
console.log(t('operationComplete', { count: pkgs.length }));
return;
}
if (maxPkgVersion) {
maxPkgVersion = String(maxPkgVersion).trim();
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const pkgs = data.filter((pkg: Package) =>
compare(pkg.name, maxPkgVersion!, '<='),
);
if (pkgs.length === 0) {
throw new Error(
t('nativeVersionNotFoundLess', { version: maxPkgVersion }),
);
}
if (rollout !== undefined) {
const rolloutConfig: Record<string, number> = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
rollout: rollout,
})}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkg.name,
id: pkg.id,
})}`,
);
}
console.log(t('operationComplete', { count: pkgs.length }));
return;
const allPkgs = await getAllPackages(appId);
if (!allPkgs) {
throw new Error(t('noPackagesFound', { appId }));
}
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
if (pkgVersion) {
let pkgsToBind: Package[] = [];
if (minPkgVersion) {
minPkgVersion = String(minPkgVersion).trim();
pkgsToBind = allPkgs.filter((pkg: Package) =>
satisfies(pkg.name, `>=${minPkgVersion}`),
);
if (pkgsToBind.length === 0) {
throw new Error(
t('nativeVersionNotFoundGte', { version: minPkgVersion }),
);
}
} else if (maxPkgVersion) {
maxPkgVersion = String(maxPkgVersion).trim();
pkgsToBind = allPkgs.filter((pkg: Package) =>
satisfies(pkg.name, `<=${maxPkgVersion}`),
);
if (pkgsToBind.length === 0) {
throw new Error(
t('nativeVersionNotFoundLte', { version: maxPkgVersion }),
);
}
} else if (pkgVersion) {
pkgVersion = pkgVersion.trim();
const pkg = data.find((pkg: Package) => pkg.name === pkgVersion);
const pkg = allPkgs.find((pkg: Package) => pkg.name === pkgVersion);
if (pkg) {
pkgId = pkg.id;
pkgsToBind = [pkg];
} else {
throw new Error(
t('nativeVersionNotFoundMatch', { version: pkgVersion }),
);
}
}
if (!pkgId) {
pkgId = options.packageId || (await choosePackage(appId)).id;
}
} else if (semverRange) {
semverRange = semverRange.trim();
pkgsToBind = allPkgs.filter((pkg: Package) =>
satisfies(pkg.name, semverRange!),
);
if (pkgsToBind.length === 0) {
throw new Error(
t('nativeVersionNotFoundMatch', { version: semverRange }),
);
}
} else {
if (!pkgId) {
pkgId = (await choosePackage(appId)).id;
}
if (!pkgId) {
throw new Error(t('packageIdRequired'));
}
if (!pkgVersion) {
const pkg = data.find((pkg: Package) => String(pkg.id) === String(pkgId));
if (!pkgId) {
throw new Error(t('packageIdRequired'));
}
const pkg = allPkgs.find(
(pkg: Package) => String(pkg.id) === String(pkgId),
);
if (pkg) {
pkgVersion = pkg.name;
pkgsToBind = [pkg];
} else {
throw new Error(t('nativePackageIdNotFound', { id: pkgId }));
}
}
if (rollout !== undefined && pkgVersion) {
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: {
[pkgVersion]: rollout,
},
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgVersion,
rollout: rollout,
})}`,
);
}
if (versionId !== undefined) {
await put(`/app/${appId}/package/${pkgId}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkgVersion,
id: pkgId,
})}`,
);
}
await bindVersionToPackages({
appId,
versionId,
pkgs: pkgsToBind,
rollout,
});
console.log(t('operationSuccess'));
},
updateVersionInfo: async ({
@@ -347,10 +304,7 @@ export const commands = {
args: string[];
options: CommandOptions;
}) => {
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
const versionId = options.versionId || (await chooseVersion(appId)).id;