Skip to content
Merged
6 changes: 6 additions & 0 deletions .changeset/short-singers-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rnx-kit/tools-react-native": patch
---

Add additional platform helpers for react-native related to platform names and
suffixes
29 changes: 16 additions & 13 deletions packages/tools-react-native/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,21 @@ import * as platformTools from "@rnx-kit/tools-react-native/platform";
| -------- | ------------ | ----------------------------------------- |
| platform | AllPlatforms | List of supported react-native platforms. |

| Category | Function | Description |
| -------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| context | `loadContext(projectRoot)` | Equivalent to calling `loadConfig()` from `@react-native-community/cli`, but the result is cached for faster subsequent accesses. |
| context | `loadContextAsync(projectRoot)` | Equivalent to calling `loadConfigAsync()` (with fallback to `loadConfig()`) from `@react-native-community/cli`, but the result is cached for faster subsequent accesses. |
| context | `resolveCommunityCLI(root, reactNativePath)` | Finds path to `@react-native-community/cli`. |
| metro | `findMetroPath(projectRoot)` | Finds the installation path of Metro. |
| metro | `getMetroVersion(projectRoot)` | Returns Metro version number. |
| metro | `requireModuleFromMetro(moduleName, fromDir)` | Imports specified module starting from the installation directory of the currently used `metro` version. |
| platform | `expandPlatformExtensions(platform, extensions)` | Returns a list of extensions that should be tried for the target platform in prioritized order. |
| platform | `getAvailablePlatforms(startDir)` | Returns a map of available React Native platforms. The result is cached. |
| platform | `getAvailablePlatformsUncached(startDir, platformMap)` | Returns a map of available React Native platforms. The result is NOT cached. |
| platform | `parsePlatform(val)` | Parse a string to ensure it maps to a valid react-native platform. |
| platform | `platformExtensions(platform)` | Returns file extensions that can be mapped to the target platform. |
| Category | Function | Description |
| -------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| context | `loadContext(projectRoot)` | Equivalent to calling `loadConfig()` from `@react-native-community/cli`, but the result is cached for faster subsequent accesses. |
| context | `loadContextAsync(projectRoot)` | Equivalent to calling `loadConfigAsync()` (with fallback to `loadConfig()`) from `@react-native-community/cli`, but the result is cached for faster subsequent accesses. |
| context | `resolveCommunityCLI(root, reactNativePath)` | Finds path to `@react-native-community/cli`. |
| metro | `findMetroPath(projectRoot)` | Finds the installation path of Metro. |
| metro | `getMetroVersion(projectRoot)` | Returns Metro version number. |
| metro | `requireModuleFromMetro(moduleName, fromDir)` | Imports specified module starting from the installation directory of the currently used `metro` version. |
| platform | `expandPlatformExtensions(platform, extensions)` | Returns a list of extensions that should be tried for the target platform in prioritized order. |
| platform | `getAvailablePlatforms(startDir)` | Returns a map of available React Native platforms. The result is cached. |
| platform | `getAvailablePlatformsUncached(startDir, platformMap)` | Returns a map of available React Native platforms. The result is NOT cached. |
| platform | `getModuleSuffixes(platform, appendEmpty)` | Get the module suffixes array for a given platform, suitable for use with TypeScript's moduleSuffixes setting in the form of ['.ios', '.native', ''] or ['.windows', '.win', '.native', ''] or similar |
| platform | `parsePlatform(val)` | Parse a string to ensure it maps to a valid react-native platform. |
| platform | `platformExtensions(platform)` | Returns file extensions that can be mapped to the target platform. |
| platform | `platformValues()` | |
| platform | `tryParsePlatform(val)` | |

<!-- @rnx-kit/api end -->
3 changes: 3 additions & 0 deletions packages/tools-react-native/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export {
expandPlatformExtensions,
getAvailablePlatforms,
getAvailablePlatformsUncached,
getModuleSuffixes,
parsePlatform,
platformExtensions,
platformValues,
tryParsePlatform,
} from "./platform";
export type { AllPlatforms } from "./platform";
67 changes: 56 additions & 11 deletions packages/tools-react-native/src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,23 @@ import { readReactNativeConfig } from "./context";
/**
* List of supported react-native platforms.
*/
export type AllPlatforms = "android" | "ios" | "macos" | "win32" | "windows";
export type AllPlatforms =
| "android"
| "ios"
| "macos"
| "win32"
| "windows"
| "visionos";

// Possible values for AllPlatforms
const allValues: AllPlatforms[] = [
"android",
"ios",
"macos",
"win32",
"windows",
"visionos",
];

/**
* Returns a list of extensions that should be tried for the target platform in
Expand All @@ -30,6 +46,25 @@ export function expandPlatformExtensions(
return expanded;
}

/**
* Get the module suffixes array for a given platform, suitable for use with TypeScript's moduleSuffixes setting
* in the form of ['.ios', '.native', ''] or ['.windows', '.win', '.native', ''] or similar
*
* @param platform platform to get module suffixes for
* @param appendEmpty finish the suffixes with an empty entry, required for typescript usage
* @returns an array of suffixes to try to match a module to in order of priority
*/
export function getModuleSuffixes(
platform: AllPlatforms,
appendEmpty = true
): string[] {
const extensions = platformExtensions(platform).map((ext) => `.${ext}`);
if (appendEmpty) {
extensions.push("");
}
return extensions;
}

/**
* Returns a map of available React Native platforms. The result is NOT cached.
* @param startDir The directory to look for react-native platforms from
Expand Down Expand Up @@ -134,22 +169,32 @@ export function platformExtensions(platform: string): string[] {
}
}

/**
* @returns the given string as a platform value or undefined if it is not a valid platform.
*/
export function tryParsePlatform(val: string): AllPlatforms | undefined {
return allValues.includes(val as AllPlatforms)
? (val as AllPlatforms)
: undefined;
}

/**
* Parse a string to ensure it maps to a valid react-native platform.
*
* @param val Input string
* @returns React-native platform name. Throws `Error` on failure.
*/
export function parsePlatform(val: string): AllPlatforms {
switch (val) {
case "android":
case "ios":
case "macos":
case "win32":
case "windows":
return val;

default:
throw new Error("Invalid platform '" + val + "'");
const platform = tryParsePlatform(val);
if (!platform) {
throw new Error(`Unknown platform '${val}'`);
}
return platform;
}

/**
* @returns List of all supported react-native platforms.
*/
export function platformValues(): readonly AllPlatforms[] {
return allValues;
}
Loading