@rnx-kit/tools-react-native
Advanced tools
Comparing version 2.0.2 to 2.0.3
export { | ||
loadContext, | ||
loadContextAsync, | ||
readReactNativeConfig, | ||
resolveCommunityCLI, | ||
} from "./lib/context"; |
import type { Config } from "@react-native-community/cli-types"; | ||
import * as nodefs from "fs"; | ||
import * as nodefs from "node:fs"; | ||
export declare function getCurrentState(projectRoot: string): string; | ||
@@ -4,0 +4,0 @@ export declare function getSavedState(projectRoot: string, |
@@ -32,5 +32,6 @@ "use strict"; | ||
const path_1 = require("@rnx-kit/tools-node/path"); | ||
const crypto = __importStar(require("crypto")); | ||
const nodefs = __importStar(require("fs")); | ||
const path = __importStar(require("path")); | ||
const crypto = __importStar(require("node:crypto")); | ||
const nodefs = __importStar(require("node:fs")); | ||
const path = __importStar(require("node:path")); | ||
const context_1 = require("./context"); | ||
const HASH_ALGO = "sha256"; | ||
@@ -65,3 +66,3 @@ const UTF8 = { encoding: "utf-8" }; | ||
const sha2 = crypto.createHash(HASH_ALGO); | ||
const configFiles = ["package.json", "react-native.config.js"]; | ||
const configFiles = ["package.json", ...context_1.REACT_NATIVE_CONFIG_FILES]; | ||
updateHash(sha2, configFiles, projectRoot, "all"); | ||
@@ -68,0 +69,0 @@ const lockfiles = [ |
import type { Config } from "@react-native-community/cli-types"; | ||
export declare const REACT_NATIVE_CONFIG_FILES: string[]; | ||
/** | ||
@@ -21,2 +22,3 @@ * Finds path to `@react-native-community/cli`. | ||
export declare function loadContextAsync(projectRoot?: string): Promise<Config>; | ||
export declare function readReactNativeConfig(packageDir: string, cwd?: string): Record<string, unknown> | undefined; | ||
//# sourceMappingURL=context.d.ts.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.REACT_NATIVE_CONFIG_FILES = void 0; | ||
exports.resolveCommunityCLI = resolveCommunityCLI; | ||
exports.loadContext = loadContext; | ||
exports.loadContextAsync = loadContextAsync; | ||
exports.readReactNativeConfig = readReactNativeConfig; | ||
const package_1 = require("@rnx-kit/tools-node/package"); | ||
const node_child_process_1 = require("node:child_process"); | ||
const fs = __importStar(require("node:fs")); | ||
const path = __importStar(require("node:path")); | ||
const cache_1 = require("./cache"); | ||
@@ -11,2 +39,8 @@ // As of 0.76, `@react-native-community/cli` is no longer a dependency of | ||
const RN_CLI_DECOUPLED = 76; | ||
exports.REACT_NATIVE_CONFIG_FILES = [ | ||
"react-native.config.ts", | ||
"react-native.config.mjs", | ||
"react-native.config.cjs", | ||
"react-native.config.js", | ||
]; | ||
function toNumber(version) { | ||
@@ -92,2 +126,25 @@ const [major, minor = 0] = version.split("."); | ||
} | ||
function readReactNativeConfig(packageDir, cwd = process.cwd()) { | ||
for (const configFile of exports.REACT_NATIVE_CONFIG_FILES) { | ||
const configPath = path.join(packageDir, configFile); | ||
if (fs.existsSync(configPath)) { | ||
const url = process.platform === "win32" | ||
? `file://${configPath.replaceAll("\\", "/")}` | ||
: configPath; | ||
const args = [ | ||
"--no-warnings", | ||
"--eval", | ||
`import("${url}").then((config) => console.log(JSON.stringify(config.default ?? config)));`, | ||
]; | ||
const { stderr, stdout } = (0, node_child_process_1.spawnSync)(process.argv0, args, { cwd }); | ||
const errors = stderr?.toString().trim(); | ||
if (errors) { | ||
console.error(`${configPath}: ${errors}`); | ||
} | ||
const json = stdout?.toString().trim(); | ||
return json ? JSON.parse(json) : undefined; | ||
} | ||
} | ||
return undefined; | ||
} | ||
//# sourceMappingURL=context.js.map |
@@ -1,2 +0,2 @@ | ||
export { loadContext, loadContextAsync, resolveCommunityCLI } from "./context"; | ||
export { loadContext, loadContextAsync, readReactNativeConfig, resolveCommunityCLI, } from "./context"; | ||
export { findMetroPath, getMetroVersion, requireModuleFromMetro, } from "./metro"; | ||
@@ -3,0 +3,0 @@ export { expandPlatformExtensions, getAvailablePlatforms, getAvailablePlatformsUncached, parsePlatform, platformExtensions, } from "./platform"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.platformExtensions = exports.parsePlatform = exports.getAvailablePlatformsUncached = exports.getAvailablePlatforms = exports.expandPlatformExtensions = exports.requireModuleFromMetro = exports.getMetroVersion = exports.findMetroPath = exports.resolveCommunityCLI = exports.loadContextAsync = exports.loadContext = void 0; | ||
exports.platformExtensions = exports.parsePlatform = exports.getAvailablePlatformsUncached = exports.getAvailablePlatforms = exports.expandPlatformExtensions = exports.requireModuleFromMetro = exports.getMetroVersion = exports.findMetroPath = exports.resolveCommunityCLI = exports.readReactNativeConfig = exports.loadContextAsync = exports.loadContext = void 0; | ||
var context_1 = require("./context"); | ||
Object.defineProperty(exports, "loadContext", { enumerable: true, get: function () { return context_1.loadContext; } }); | ||
Object.defineProperty(exports, "loadContextAsync", { enumerable: true, get: function () { return context_1.loadContextAsync; } }); | ||
Object.defineProperty(exports, "readReactNativeConfig", { enumerable: true, get: function () { return context_1.readReactNativeConfig; } }); | ||
Object.defineProperty(exports, "resolveCommunityCLI", { enumerable: true, get: function () { return context_1.resolveCommunityCLI; } }); | ||
@@ -8,0 +9,0 @@ var metro_1 = require("./metro"); |
@@ -14,14 +14,14 @@ /** | ||
/** | ||
* Returns a map of available React Native platforms. The result is cached. | ||
* Returns a map of available React Native platforms. The result is NOT cached. | ||
* @param startDir The directory to look for react-native platforms from | ||
* @param platformMap A platform-to-npm-package map of known packages | ||
* @returns A platform-to-npm-package map, excluding "core" platforms. | ||
*/ | ||
export declare const getAvailablePlatforms: (startDir?: string) => Record<string, string>; | ||
export declare function getAvailablePlatformsUncached(startDir?: string, platformMap?: Record<string, string>): typeof platformMap; | ||
/** | ||
* Returns a map of available React Native platforms. The result is NOT cached. | ||
* Returns a map of available React Native platforms. The result is cached. | ||
* @param startDir The directory to look for react-native platforms from | ||
* @param platformMap A platform-to-npm-package map of known packages | ||
* @returns A platform-to-npm-package map, excluding "core" platforms. | ||
*/ | ||
export declare function getAvailablePlatformsUncached(startDir?: string, platformMap?: Record<string, string>): Record<string, string>; | ||
export declare const getAvailablePlatforms: (startDir?: string) => Record<string, string>; | ||
/** | ||
@@ -28,0 +28,0 @@ * Returns file extensions that can be mapped to the target platform. |
@@ -32,4 +32,4 @@ "use strict"; | ||
const package_1 = require("@rnx-kit/tools-node/package"); | ||
const fs = __importStar(require("fs")); | ||
const path = __importStar(require("path")); | ||
const fs = __importStar(require("node:fs")); | ||
const path = __importStar(require("node:path")); | ||
const context_1 = require("./context"); | ||
@@ -53,7 +53,3 @@ /** | ||
/** | ||
* Returns a map of available React Native platforms. | ||
* | ||
* Note: This is used only when `@react-native-community/cli-config` is not | ||
* available. This function will be dropped when 0.68 is no longer supported. | ||
* | ||
* Returns a map of available React Native platforms. The result is NOT cached. | ||
* @param startDir The directory to look for react-native platforms from | ||
@@ -63,3 +59,3 @@ * @param platformMap A platform-to-npm-package map of known packages | ||
*/ | ||
function getAvailablePlatformsCompat(startDir = process.cwd(), platformMap = { android: "", ios: "" }) { | ||
function getAvailablePlatformsUncached(startDir = process.cwd(), platformMap = { android: "", ios: "" }) { | ||
const packageJson = path.join(startDir, "package.json"); | ||
@@ -72,35 +68,39 @@ if (!fs.existsSync(packageJson)) { | ||
} | ||
const options = { startDir }; | ||
const { dependencies, peerDependencies, devDependencies } = JSON.parse(fs.readFileSync(packageJson, { encoding: "utf-8" })); | ||
const packages = new Set(dependencies ? Object.keys(dependencies) : []); | ||
if (peerDependencies) { | ||
Object.keys(peerDependencies).forEach((pkg) => packages.add(pkg)); | ||
for (const deps of [peerDependencies, devDependencies]) { | ||
if (deps) { | ||
for (const pkg of Object.keys(deps)) { | ||
packages.add(pkg); | ||
} | ||
} | ||
} | ||
if (devDependencies) { | ||
Object.keys(devDependencies).forEach((pkg) => packages.add(pkg)); | ||
} | ||
packages.forEach((pkgName) => { | ||
const pkgPath = (0, package_1.findPackageDependencyDir)(pkgName, options); | ||
const recordPlatformPackage = (pkgPath) => { | ||
if (!pkgPath) { | ||
return; | ||
} | ||
const configPath = path.join(pkgPath, "react-native.config.js"); | ||
if (fs.existsSync(configPath)) { | ||
try { | ||
const { platforms } = require(configPath); | ||
if (platforms) { | ||
Object.keys(platforms).forEach((platform) => { | ||
if (typeof platformMap[platform] === "undefined") { | ||
const { npmPackageName } = platforms[platform]; | ||
if (npmPackageName) { | ||
platformMap[platform] = npmPackageName; | ||
} | ||
} | ||
}); | ||
const manifest = (0, context_1.readReactNativeConfig)(pkgPath, startDir); | ||
if (!manifest) { | ||
return; | ||
} | ||
const { platforms } = manifest; | ||
if (!platforms || typeof platforms !== "object") { | ||
return; | ||
} | ||
for (const [platform, info] of Object.entries(platforms)) { | ||
if (typeof platformMap[platform] === "undefined") { | ||
const { npmPackageName } = info; | ||
if (npmPackageName) { | ||
platformMap[platform] = npmPackageName; | ||
} | ||
} | ||
catch (_) { | ||
// ignore | ||
} | ||
} | ||
}; | ||
recordPlatformPackage(startDir); | ||
const options = { startDir }; | ||
packages.forEach((pkgName) => { | ||
const pkgPath = (0, package_1.findPackageDependencyDir)(pkgName, options); | ||
if (pkgPath) { | ||
recordPlatformPackage(pkgPath); | ||
} | ||
}); | ||
@@ -115,14 +115,7 @@ return platformMap; | ||
exports.getAvailablePlatforms = (() => { | ||
const isTesting = Boolean(process.env.NODE_TEST_CONTEXT) || process.env.NODE_ENV === "test"; | ||
let platformMap = undefined; | ||
return (startDir = process.cwd()) => { | ||
if (!platformMap) { | ||
try { | ||
platformMap = getAvailablePlatformsUncached(startDir); | ||
} | ||
catch (_) { | ||
// This only happens when `@react-native-community/cli-config` is not | ||
// available. This path may be dropped when 0.68 is no longer | ||
// supported. | ||
platformMap = getAvailablePlatformsCompat(startDir); | ||
} | ||
if (!platformMap || isTesting) { | ||
platformMap = getAvailablePlatformsUncached(startDir); | ||
} | ||
@@ -133,20 +126,2 @@ return platformMap; | ||
/** | ||
* Returns a map of available React Native platforms. The result is NOT cached. | ||
* @param startDir The directory to look for react-native platforms from | ||
* @param platformMap A platform-to-npm-package map of known packages | ||
* @returns A platform-to-npm-package map, excluding "core" platforms. | ||
*/ | ||
function getAvailablePlatformsUncached(startDir = process.cwd(), platformMap = { android: "", ios: "" }) { | ||
const { platforms } = (0, context_1.loadContext)(startDir); | ||
if (typeof platforms === "object" && platforms) { | ||
for (const [name, info] of Object.entries(platforms)) { | ||
const { npmPackageName } = info; | ||
if (npmPackageName) { | ||
platformMap[name] = npmPackageName; | ||
} | ||
} | ||
} | ||
return platformMap; | ||
} | ||
/** | ||
* Returns file extensions that can be mapped to the target platform. | ||
@@ -153,0 +128,0 @@ * @param platform The platform to retrieve extensions for |
{ | ||
"name": "@rnx-kit/tools-react-native", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"description": "A collection of supplemental react-native functions and types", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/microsoft/rnx-kit/tree/main/packages/tools-react-native#readme", |
import type { Config } from "@react-native-community/cli-types"; | ||
import { findUp } from "@rnx-kit/tools-node/path"; | ||
import * as crypto from "crypto"; | ||
import * as nodefs from "fs"; | ||
import * as path from "path"; | ||
import * as crypto from "node:crypto"; | ||
import * as nodefs from "node:fs"; | ||
import * as path from "node:path"; | ||
import { REACT_NATIVE_CONFIG_FILES } from "./context"; | ||
@@ -48,3 +49,3 @@ const HASH_ALGO = "sha256"; | ||
const configFiles = ["package.json", "react-native.config.js"]; | ||
const configFiles = ["package.json", ...REACT_NATIVE_CONFIG_FILES]; | ||
updateHash(sha2, configFiles, projectRoot, "all"); | ||
@@ -51,0 +52,0 @@ |
@@ -7,2 +7,5 @@ import type { loadConfig } from "@react-native-community/cli"; | ||
} from "@rnx-kit/tools-node/package"; | ||
import { spawnSync } from "node:child_process"; | ||
import * as fs from "node:fs"; | ||
import * as path from "node:path"; | ||
import { | ||
@@ -19,2 +22,9 @@ getCurrentState, | ||
export const REACT_NATIVE_CONFIG_FILES = [ | ||
"react-native.config.ts", | ||
"react-native.config.mjs", | ||
"react-native.config.cjs", | ||
"react-native.config.js", | ||
]; | ||
function toNumber(version: string): number { | ||
@@ -120,1 +130,33 @@ const [major, minor = 0] = version.split("."); | ||
} | ||
export function readReactNativeConfig( | ||
packageDir: string, | ||
cwd = process.cwd() | ||
): Record<string, unknown> | undefined { | ||
for (const configFile of REACT_NATIVE_CONFIG_FILES) { | ||
const configPath = path.join(packageDir, configFile); | ||
if (fs.existsSync(configPath)) { | ||
const url = | ||
process.platform === "win32" | ||
? `file://${configPath.replaceAll("\\", "/")}` | ||
: configPath; | ||
const args = [ | ||
"--no-warnings", | ||
"--eval", | ||
`import("${url}").then((config) => console.log(JSON.stringify(config.default ?? config)));`, | ||
]; | ||
const { stderr, stdout } = spawnSync(process.argv0, args, { cwd }); | ||
const errors = stderr?.toString().trim(); | ||
if (errors) { | ||
console.error(`${configPath}: ${errors}`); | ||
} | ||
const json = stdout?.toString().trim(); | ||
return json ? JSON.parse(json) : undefined; | ||
} | ||
} | ||
return undefined; | ||
} |
@@ -1,3 +0,8 @@ | ||
export { loadContext, loadContextAsync, resolveCommunityCLI } from "./context"; | ||
export { | ||
loadContext, | ||
loadContextAsync, | ||
readReactNativeConfig, | ||
resolveCommunityCLI, | ||
} from "./context"; | ||
export { | ||
findMetroPath, | ||
@@ -4,0 +9,0 @@ getMetroVersion, |
import { findPackageDependencyDir } from "@rnx-kit/tools-node/package"; | ||
import * as fs from "fs"; | ||
import * as path from "path"; | ||
import { loadContext } from "./context"; | ||
import * as fs from "node:fs"; | ||
import * as path from "node:path"; | ||
import { readReactNativeConfig } from "./context"; | ||
@@ -34,7 +34,3 @@ /** | ||
/** | ||
* Returns a map of available React Native platforms. | ||
* | ||
* Note: This is used only when `@react-native-community/cli-config` is not | ||
* available. This function will be dropped when 0.68 is no longer supported. | ||
* | ||
* Returns a map of available React Native platforms. The result is NOT cached. | ||
* @param startDir The directory to look for react-native platforms from | ||
@@ -44,6 +40,6 @@ * @param platformMap A platform-to-npm-package map of known packages | ||
*/ | ||
function getAvailablePlatformsCompat( | ||
export function getAvailablePlatformsUncached( | ||
startDir = process.cwd(), | ||
platformMap: Record<string, string> = { android: "", ios: "" } | ||
) { | ||
): typeof platformMap { | ||
const packageJson = path.join(startDir, "package.json"); | ||
@@ -57,3 +53,2 @@ if (!fs.existsSync(packageJson)) { | ||
const options = { startDir }; | ||
const { dependencies, peerDependencies, devDependencies } = JSON.parse( | ||
@@ -66,11 +61,11 @@ fs.readFileSync(packageJson, { encoding: "utf-8" }) | ||
); | ||
if (peerDependencies) { | ||
Object.keys(peerDependencies).forEach((pkg) => packages.add(pkg)); | ||
for (const deps of [peerDependencies, devDependencies]) { | ||
if (deps) { | ||
for (const pkg of Object.keys(deps)) { | ||
packages.add(pkg); | ||
} | ||
} | ||
} | ||
if (devDependencies) { | ||
Object.keys(devDependencies).forEach((pkg) => packages.add(pkg)); | ||
} | ||
packages.forEach((pkgName) => { | ||
const pkgPath = findPackageDependencyDir(pkgName, options); | ||
const recordPlatformPackage = (pkgPath: string | undefined) => { | ||
if (!pkgPath) { | ||
@@ -80,20 +75,30 @@ return; | ||
const configPath = path.join(pkgPath, "react-native.config.js"); | ||
if (fs.existsSync(configPath)) { | ||
try { | ||
const { platforms } = require(configPath); | ||
if (platforms) { | ||
Object.keys(platforms).forEach((platform) => { | ||
if (typeof platformMap[platform] === "undefined") { | ||
const { npmPackageName } = platforms[platform]; | ||
if (npmPackageName) { | ||
platformMap[platform] = npmPackageName; | ||
} | ||
} | ||
}); | ||
const manifest = readReactNativeConfig(pkgPath, startDir); | ||
if (!manifest) { | ||
return; | ||
} | ||
const { platforms } = manifest; | ||
if (!platforms || typeof platforms !== "object") { | ||
return; | ||
} | ||
for (const [platform, info] of Object.entries(platforms)) { | ||
if (typeof platformMap[platform] === "undefined") { | ||
const { npmPackageName } = info; | ||
if (npmPackageName) { | ||
platformMap[platform] = npmPackageName; | ||
} | ||
} catch (_) { | ||
// ignore | ||
} | ||
} | ||
}; | ||
recordPlatformPackage(startDir); | ||
const options = { startDir }; | ||
packages.forEach((pkgName) => { | ||
const pkgPath = findPackageDependencyDir(pkgName, options); | ||
if (pkgPath) { | ||
recordPlatformPackage(pkgPath); | ||
} | ||
}); | ||
@@ -110,13 +115,9 @@ | ||
export const getAvailablePlatforms = (() => { | ||
const isTesting = | ||
Boolean(process.env.NODE_TEST_CONTEXT) || process.env.NODE_ENV === "test"; | ||
let platformMap: Record<string, string> | undefined = undefined; | ||
return (startDir = process.cwd()) => { | ||
if (!platformMap) { | ||
try { | ||
platformMap = getAvailablePlatformsUncached(startDir); | ||
} catch (_) { | ||
// This only happens when `@react-native-community/cli-config` is not | ||
// available. This path may be dropped when 0.68 is no longer | ||
// supported. | ||
platformMap = getAvailablePlatformsCompat(startDir); | ||
} | ||
if (!platformMap || isTesting) { | ||
platformMap = getAvailablePlatformsUncached(startDir); | ||
} | ||
@@ -128,24 +129,2 @@ return platformMap; | ||
/** | ||
* Returns a map of available React Native platforms. The result is NOT cached. | ||
* @param startDir The directory to look for react-native platforms from | ||
* @param platformMap A platform-to-npm-package map of known packages | ||
* @returns A platform-to-npm-package map, excluding "core" platforms. | ||
*/ | ||
export function getAvailablePlatformsUncached( | ||
startDir = process.cwd(), | ||
platformMap: Record<string, string> = { android: "", ios: "" } | ||
) { | ||
const { platforms } = loadContext(startDir); | ||
if (typeof platforms === "object" && platforms) { | ||
for (const [name, info] of Object.entries(platforms)) { | ||
const { npmPackageName } = info; | ||
if (npmPackageName) { | ||
platformMap[name] = npmPackageName; | ||
} | ||
} | ||
} | ||
return platformMap; | ||
} | ||
/** | ||
* Returns file extensions that can be mapped to the target platform. | ||
@@ -152,0 +131,0 @@ * @param platform The platform to retrieve extensions for |
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
51828
1157
6