mirror of
https://gitcode.com/github-mirrors/react-native-update-cli.git
synced 2025-11-07 01:43:39 +08:00
semver range
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
18
src/app.ts
18
src/app.ts
@@ -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;
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
type ZipFile as YauzlZipFile,
|
||||
} from 'yauzl';
|
||||
import { question, checkPlugins } from './utils';
|
||||
import { checkPlatform } from './app';
|
||||
import { checkPlatform, getPlatform } from './app';
|
||||
import { spawn, spawnSync } from 'child_process';
|
||||
import semverSatisfies from 'semver/functions/satisfies';
|
||||
const g2js = require('gradle-to-js/lib/parser');
|
||||
@@ -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,
|
||||
|
||||
@@ -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)',
|
||||
};
|
||||
|
||||
@@ -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: '(未命名)',
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
12
src/types.ts
12
src/types.ts
@@ -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[];
|
||||
}
|
||||
|
||||
279
src/versions.ts
279
src/versions.ts
@@ -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 semverSatisfies from 'semver/functions/satisfies';
|
||||
|
||||
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,18 @@ 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 +179,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 +197,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 +222,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) =>
|
||||
semverSatisfies(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) =>
|
||||
semverSatisfies(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) =>
|
||||
semverSatisfies(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 +303,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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user