diff --git a/cli/src/android/run.ts b/cli/src/android/run.ts index f93040ec3..ed688f22d 100644 --- a/cli/src/android/run.ts +++ b/cli/src/android/run.ts @@ -12,9 +12,20 @@ const debug = Debug('capacitor:android:run'); export async function runAndroid( config: Config, - { target: selectedTarget, flavor: selectedFlavor, forwardPorts: selectedPorts }: RunCommandOptions, + { + target: selectedTarget, + targetName: selectedTargetName, + targetNameSdkVersion: selectedTargetSdkVersion, + flavor: selectedFlavor, + forwardPorts: selectedPorts, + }: RunCommandOptions, ): Promise { - const target = await promptForPlatformTarget(await getPlatformTargets('android'), selectedTarget); + const target = await promptForPlatformTarget( + await getPlatformTargets('android'), + selectedTarget ?? selectedTargetName, + selectedTargetSdkVersion, + selectedTargetName !== undefined, + ); const runFlavor = selectedFlavor || config.android?.flavor || ''; diff --git a/cli/src/common.ts b/cli/src/common.ts index 0040789b4..dbd4d629d 100644 --- a/cli/src/common.ts +++ b/cli/src/common.ts @@ -378,6 +378,8 @@ export interface PlatformTarget { export async function promptForPlatformTarget( targets: PlatformTarget[], selectedTarget?: string, + selectedTargetSdkVersion?: string, + selectByName?: boolean, ): Promise { const { prompt } = await import('prompts'); const validTargets = targets.filter((t) => t.id !== undefined); @@ -405,10 +407,37 @@ export async function promptForPlatformTarget( } const targetID = selectedTarget.trim(); - const target = targets.find((t) => t.id === targetID); + const target = targets.find((t) => { + if (selectByName === true) { + let name = t.name ?? t.model; + if (name) { + // Apple device names may have "smart quotes" in the name, + // strip them and replace them with the "straight" versions + name = name.replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"'); + } + + if (selectedTargetSdkVersion) { + return name === targetID && t.sdkVersion === selectedTargetSdkVersion; + } + + return name === targetID; + } + + return t.id === targetID; + }); if (!target) { - fatal(`Invalid target ID: ${c.input(targetID)}.\n` + `Valid targets are: ${targets.map((t) => t.id).join(', ')}`); + if (selectByName) { + let invalidTargetName = targetID; + if (selectedTargetSdkVersion) { + invalidTargetName += ` [${selectedTargetSdkVersion}]`; + } + fatal( + `Invalid target name: ${c.input(invalidTargetName)}.\n` + + `Valid targets are:\n ${targets.map((t) => `${t.name ?? t.model} [${t.sdkVersion}]`).join('\n')}`, + ); + } + fatal(`Invalid target ID: ${c.input(targetID)}.\n` + `Valid targets are:\n ${targets.map((t) => t.id).join('\n')}`); } return target; diff --git a/cli/src/index.ts b/cli/src/index.ts index 1877d143b..999fb0c1a 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -234,6 +234,11 @@ export function runProgram(config: Config): void { .option('--list', 'list targets, then quit') .addOption(new Option('--json').hideHelp()) .option('--target ', 'use a specific target') + .option('--target-name ', 'use a specific target by name') + .option( + '--target-name-sdk-version ', + 'use a specific sdk version when using --target-name, ex: 26.0 (for iOS 26) or 35 (for Android API 35)', + ) .option('--no-sync', `do not run ${c.input('sync')}`) .option('--forwardPorts ', 'Automatically run "adb reverse" for better live-reloading support') .option('-l, --live-reload', 'Enable Live Reload') @@ -246,7 +251,21 @@ export function runProgram(config: Config): void { config, async ( platform, - { scheme, flavor, list, json, target, sync, forwardPorts, liveReload, host, port, configuration }, + { + scheme, + flavor, + list, + json, + target, + targetName, + targetNameSdkVersion, + sync, + forwardPorts, + liveReload, + host, + port, + configuration, + }, ) => { const { runCommand } = await import('./tasks/run'); await runCommand(config, platform, { @@ -255,6 +274,8 @@ export function runProgram(config: Config): void { list, json, target, + targetName, + targetNameSdkVersion, sync, forwardPorts, liveReload, diff --git a/cli/src/ios/run.ts b/cli/src/ios/run.ts index 0c414494a..13a031f39 100644 --- a/cli/src/ios/run.ts +++ b/cli/src/ios/run.ts @@ -13,9 +13,20 @@ const debug = Debug('capacitor:ios:run'); export async function runIOS( config: Config, - { target: selectedTarget, scheme: selectedScheme, configuration: selectedConfiguration }: RunCommandOptions, + { + target: selectedTarget, + targetName: selectedTargetName, + targetNameSdkVersion: selectedTargetSdkVersion, + scheme: selectedScheme, + configuration: selectedConfiguration, + }: RunCommandOptions, ): Promise { - const target = await promptForPlatformTarget(await getPlatformTargets('ios'), selectedTarget); + const target = await promptForPlatformTarget( + await getPlatformTargets('ios'), + selectedTarget ?? selectedTargetName, + selectedTargetSdkVersion, + selectedTargetName !== undefined, + ); const runScheme = selectedScheme || config.ios.scheme; const configuration = selectedConfiguration || 'Debug'; diff --git a/cli/src/tasks/run.ts b/cli/src/tasks/run.ts index 7217d6123..97413cb09 100644 --- a/cli/src/tasks/run.ts +++ b/cli/src/tasks/run.ts @@ -26,6 +26,8 @@ export interface RunCommandOptions { list?: boolean; json?: boolean; target?: string; + targetName?: string; + targetNameSdkVersion?: string; sync?: boolean; forwardPorts?: string; liveReload?: boolean;