diff --git a/packages/react-native-builder-bob/src/targets/codegen.ts b/packages/react-native-builder-bob/src/targets/codegen.ts index ecb1c04b2..e55ce2169 100644 --- a/packages/react-native-builder-bob/src/targets/codegen.ts +++ b/packages/react-native-builder-bob/src/targets/codegen.ts @@ -1,10 +1,10 @@ import kleur from 'kleur'; import type { Input } from '../types'; import { patchCodegen } from '../utils/patchCodegen'; -import { spawn } from '../utils/spawn'; import fs from 'fs-extra'; import path from 'path'; import del from 'del'; +import { runRNCCli } from '../utils/runRNCCli'; type Options = Input; @@ -33,11 +33,9 @@ export default async function build({ root, report }: Options) { } try { - await spawn('npx', ['@react-native-community/cli', 'codegen'], { - stdio: 'ignore', - }); + await runRNCCli(['codegen']); - patchCodegen(root, packageJson, report); + await patchCodegen(root, packageJson, report); report.success('Generated native code with codegen'); } catch (e: unknown) { diff --git a/packages/react-native-builder-bob/src/utils/runRNCCli.ts b/packages/react-native-builder-bob/src/utils/runRNCCli.ts new file mode 100644 index 000000000..744bf1cc8 --- /dev/null +++ b/packages/react-native-builder-bob/src/utils/runRNCCli.ts @@ -0,0 +1,54 @@ +import { type SpawnOptions } from 'node:child_process'; +import { spawn } from './spawn'; +import path from 'node:path'; +import fs from 'fs-extra'; +import assert from 'node:assert'; + +// This is a special case for calling bob from the XCode scripts +// XCode scripts don't have the node binary properly set +// We expose an env value for node instead. +const NODE_BINARY = process.env['NODE_BINARY'] || 'node'; + +/** + * Runs the React Native Community CLI with the specified arguments + */ +export async function runRNCCli( + args: string[], + options: SpawnOptions = { + stdio: 'ignore', + } +) { + const rncCliBinaryName = await getCliBinaryName(); + + const RNC_CLI_BINARY_PATH = path.resolve( + process.cwd(), // We are always expected to run in the library + 'node_modules', + '.bin', + rncCliBinaryName + ); + + return await spawn(NODE_BINARY, [RNC_CLI_BINARY_PATH, ...args], options); +} + +async function getCliBinaryName(): Promise { + const rncCliPackagePath = await spawn(NODE_BINARY, [ + '-e', + `console.log(require.resolve('@react-native-community/cli/package.json'))`, + ]); + + const rncCliPackage = await fs.readJson(rncCliPackagePath); + const binProperty = rncCliPackage.bin as Record; + assert( + typeof binProperty === 'object', + "React Native CLI doesn't specify proper binaries" + ); + + const binaries = Object.keys(binProperty); + const rncCliBinaryName = binaries[0] as string; + assert( + typeof rncCliBinaryName === 'string', + "React Native Community CLI doesn't have any binaries to run" + ); + + return rncCliBinaryName; +}