fix(tools-react-native): support loading ESM config files (#3422)

This commit is contained in:
Tommy Nguyen 2024-11-19 20:00:19 +01:00 коммит произвёл GitHub
Родитель ac1cfa362a
Коммит 1ae018add4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 77 добавлений и 29 удалений

Просмотреть файл

@ -0,0 +1,5 @@
---
"@rnx-kit/tools-react-native": patch
---
Add support for loading ESM config files

Просмотреть файл

@ -24,17 +24,18 @@ import * as platformTools from "@rnx-kit/tools-react-native/platform";
| -------- | ------------ | ----------------------------------------- |
| platform | AllPlatforms | List of supported react-native platforms. |
| Category | Function | Description |
| -------- | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| context | `loadContext(root)` | Equivalent to calling `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 | `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. |
<!-- @rnx-kit/api end -->

Просмотреть файл

@ -1,3 +1,4 @@
import type { loadConfig } from "@react-native-community/cli";
import type { Config } from "@react-native-community/cli-types";
import {
findPackageDependencyDir,
@ -34,6 +35,24 @@ function findStartDir(root: string, reactNativePath = ""): string {
return toNumber(version) < RN_CLI_DECOUPLED ? reactNative : root;
}
function getConfigOrState(projectRoot: string): Config | string {
const state = getCurrentState(projectRoot);
if (state === getSavedState(projectRoot)) {
const config = loadConfigFromCache(projectRoot);
if (config) {
return config;
}
}
return state;
}
function makeLoadConfigOptions(fn: typeof loadConfig, projectRoot: string) {
return fn.length === 1
? { projectRoot }
: (projectRoot as unknown as { projectRoot: string });
}
/**
* Finds path to `@react-native-community/cli`.
* @param root Project root
@ -50,26 +69,49 @@ export function resolveCommunityCLI(
/**
* Equivalent to calling `loadConfig()` from `@react-native-community/cli`, but
* the result is cached for faster subsequent accesses.
* @param root Project root; defaults to current working directory
* @param projectRoot Project root; defaults to current working directory
*/
export function loadContext(root = process.cwd()): Config {
const state = getCurrentState(root);
if (state === getSavedState(root)) {
const config = loadConfigFromCache(root);
if (config) {
return config;
}
export function loadContext(projectRoot = process.cwd()): Config {
const state = getConfigOrState(projectRoot);
if (typeof state !== "string") {
return state;
}
const rncli = resolveCommunityCLI(root);
const rncli = resolveCommunityCLI(projectRoot);
const { loadConfig } = require(rncli);
const config: Config =
loadConfig.length === 1
? loadConfig({ projectRoot: root })
: loadConfig(root);
saveConfigToCache(root, state, config);
const options = makeLoadConfigOptions(loadConfig, projectRoot);
const config = loadConfig(options);
saveConfigToCache(projectRoot, state, config);
return config;
}
/**
* Equivalent to calling `loadConfigAsync()` (with fallback to `loadConfig()`)
* from `@react-native-community/cli`, but the result is cached for faster
* subsequent accesses.
* @param projectRoot Project root; defaults to current working directory
*/
export async function loadContextAsync(
projectRoot = process.cwd()
): Promise<Config> {
const state = getConfigOrState(projectRoot);
if (typeof state !== "string") {
return state;
}
const rncli = resolveCommunityCLI(projectRoot);
const { loadConfig, loadConfigAsync } = require(rncli);
const options = makeLoadConfigOptions(loadConfig, projectRoot);
if (!loadConfigAsync) {
const config = loadConfig(options);
saveConfigToCache(projectRoot, state, config);
return config;
}
const config = await loadConfigAsync(options);
saveConfigToCache(projectRoot, state, config);
return config;
}

Просмотреть файл

@ -1,4 +1,4 @@
export { loadContext, resolveCommunityCLI } from "./context";
export { loadContext, loadContextAsync, resolveCommunityCLI } from "./context";
export {
findMetroPath,
getMetroVersion,