From e4ec71bb07128bcaff6853d79c13afc13f738483 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 26 Jun 2026 18:25:00 +0100 Subject: [PATCH] breaking: Bundle iOS and Android as core platforms --- packages/cli-config/src/loadConfig.ts | 34 +++++++++++++++++++++++++-- packages/cli/package.json | 2 ++ packages/cli/src/commands/index.ts | 4 ++++ packages/cli/src/index.ts | 28 ++++++++++++++++++++++ packages/cli/tsconfig.json | 2 ++ 5 files changed, 68 insertions(+), 2 deletions(-) diff --git a/packages/cli-config/src/loadConfig.ts b/packages/cli-config/src/loadConfig.ts index b01c2d03b..c951905e0 100644 --- a/packages/cli-config/src/loadConfig.ts +++ b/packages/cli-config/src/loadConfig.ts @@ -84,15 +84,37 @@ const removeDuplicateCommands = (commands: Command[]) => { return Array.from(uniqueCommandsMap.values()); }; +/** + * Returns the built-in platforms to seed the config with, honoring the + * `selectedPlatform` filter the same way dependency platforms are filtered. The + * project's own and dependencies' platforms are layered on top of these. + */ +const getBasePlatforms = ( + platforms: Config['platforms'] | undefined, + selectedPlatform: string | undefined, +): {[platform: string]: Config['platforms'][string]} => { + if (!platforms) { + return {}; + } + if (selectedPlatform != null) { + return platforms[selectedPlatform] + ? {[selectedPlatform]: platforms[selectedPlatform]} + : {}; + } + return platforms; +}; + /** * Loads CLI configuration */ export default function loadConfig({ projectRoot = findProjectRoot(), selectedPlatform, + platforms, }: { projectRoot?: string; selectedPlatform?: string; + platforms?: Config['platforms']; }): Config { let lazyProject: ProjectConfig; const userConfig = readConfigFromDisk(projectRoot); @@ -110,7 +132,10 @@ export default function loadConfig({ dependencies: userConfig.dependencies, commands: userConfig.commands, healthChecks: userConfig.healthChecks || [], - platforms: userConfig.platforms, + platforms: { + ...getBasePlatforms(platforms, selectedPlatform), + ...userConfig.platforms, + }, assets: userConfig.assets, get project() { if (lazyProject) { @@ -188,9 +213,11 @@ export default function loadConfig({ export async function loadConfigAsync({ projectRoot = findProjectRoot(), selectedPlatform, + platforms, }: { projectRoot?: string; selectedPlatform?: string; + platforms?: Config['platforms']; }): Promise { let lazyProject: ProjectConfig; const userConfig = await readConfigFromDiskAsync(projectRoot); @@ -208,7 +235,10 @@ export async function loadConfigAsync({ dependencies: userConfig.dependencies, commands: userConfig.commands, healthChecks: userConfig.healthChecks || [], - platforms: userConfig.platforms, + platforms: { + ...getBasePlatforms(platforms, selectedPlatform), + ...userConfig.platforms, + }, assets: userConfig.assets, get project() { if (lazyProject) { diff --git a/packages/cli/package.json b/packages/cli/package.json index 1e849da07..a5aed9848 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -27,6 +27,8 @@ "@react-native-community/cli-clean": "20.2.0", "@react-native-community/cli-config": "20.2.0", "@react-native-community/cli-doctor": "20.2.0", + "@react-native-community/cli-platform-android": "20.2.0", + "@react-native-community/cli-platform-ios": "20.2.0", "@react-native-community/cli-server-api": "20.2.0", "@react-native-community/cli-tools": "20.2.0", "@react-native-community/cli-types": "20.2.0", diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 306fd5449..b609cc5e0 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -2,12 +2,16 @@ import {Command, DetachedCommand} from '@react-native-community/cli-types'; import {commands as cleanCommands} from '@react-native-community/cli-clean'; import {commands as doctorCommands} from '@react-native-community/cli-doctor'; import {commands as configCommands} from '@react-native-community/cli-config'; +import {commands as androidCommands} from '@react-native-community/cli-platform-android'; +import {commands as iosCommands} from '@react-native-community/cli-platform-ios'; import init from './init'; export const projectCommands = [ ...configCommands, cleanCommands.clean, doctorCommands.info, + ...iosCommands, + ...androidCommands, ] as Command[]; export const detachedCommands = [ diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index dd8fd2223..c56a5a478 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -5,6 +5,14 @@ import type { Config, DetachedCommand, } from '@react-native-community/cli-types'; +import { + projectConfig as androidProjectConfig, + dependencyConfig as androidDependencyConfig, +} from '@react-native-community/cli-platform-android'; +import { + projectConfig as iosProjectConfig, + dependencyConfig as iosDependencyConfig, +} from '@react-native-community/cli-platform-ios'; import childProcess from 'child_process'; import {Command as CommanderCommand} from 'commander'; import path from 'path'; @@ -197,6 +205,26 @@ async function setupAndRun(platformName?: string) { config = await loadConfigAsync({ selectedPlatform, + // iOS and Android are core platforms bundled with the CLI, so they are + // always registered. The project's own and dependencies' configs can + // still override them. + // + // The cast is needed because the platform packages' `projectConfig`/ + // `dependencyConfig` return `null` and take required params, whereas the + // `PlatformConfig` interface models these as `void`. These functions are + // the canonical implementations the CLI already calls via the config scan. + platforms: { + ios: { + npmPackageName: '@react-native-community/cli-platform-ios', + projectConfig: iosProjectConfig, + dependencyConfig: iosDependencyConfig, + }, + android: { + npmPackageName: '@react-native-community/cli-platform-android', + projectConfig: androidProjectConfig, + dependencyConfig: androidDependencyConfig, + }, + } as Config['platforms'], }); logger.enable(); diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json index 3848b08e3..e6d066349 100644 --- a/packages/cli/tsconfig.json +++ b/packages/cli/tsconfig.json @@ -9,6 +9,8 @@ {"path": "../cli-config"}, {"path": "../cli-doctor"}, {"path": "../cli-link-assets"}, + {"path": "../cli-platform-android"}, + {"path": "../cli-platform-ios"}, {"path": "../cli-server-api"}, {"path": "../cli-types"}, {"path": "../cli-tools"}