diff --git a/packages/react-native-builder-bob/src/build.ts b/packages/react-native-builder-bob/src/build.ts index db3766ea..093fbb32 100644 --- a/packages/react-native-builder-bob/src/build.ts +++ b/packages/react-native-builder-bob/src/build.ts @@ -1,15 +1,11 @@ -import path from 'path'; +import fs from 'fs-extra'; import kleur from 'kleur'; -import * as logger from './utils/logger'; -import buildCommonJS from './targets/commonjs'; -import buildModule from './targets/module'; -import buildTypescript from './targets/typescript'; -import buildCodegen from './targets/codegen'; -import customTarget from './targets/custom'; +import path from 'path'; +import yargs from 'yargs'; import { type Options, type Target } from './types'; -import fs from 'fs-extra'; import { loadConfig } from './utils/loadConfig'; -import yargs from 'yargs'; +import * as logger from './utils/logger'; +import { run } from './utils/workerize'; export const args = { target: { @@ -147,21 +143,11 @@ async function buildTarget({ switch (targetName) { case 'commonjs': - await buildCommonJS({ - root, - source: path.resolve(root, source), - output: path.resolve(root, output, 'commonjs'), - exclude, - options: targetOptions, - variants, - report, - }); - break; case 'module': - await buildModule({ + await run(targetName, { root, source: path.resolve(root, source), - output: path.resolve(root, output, 'module'), + output: path.resolve(root, output, targetName), exclude, options: targetOptions, variants, @@ -183,7 +169,7 @@ async function buildTarget({ return false; }) ?? false; - await buildTypescript({ + await run('typescript', { root, source: path.resolve(root, source), output: path.resolve(root, output, 'typescript'), @@ -195,7 +181,7 @@ async function buildTarget({ } break; case 'codegen': - await buildCodegen({ + await run('codegen', { root, source: path.resolve(root, source), output: path.resolve(root, output, 'typescript'), @@ -203,7 +189,7 @@ async function buildTarget({ }); break; case 'custom': - await customTarget({ + await run('custom', { options: targetOptions, source: path.resolve(root, source), report, diff --git a/packages/react-native-builder-bob/src/targets/codegen/patches/patchCodegenAndroidPackage.ts b/packages/react-native-builder-bob/src/targets/codegen/patches/patchCodegenAndroidPackage.ts index 5b0fbd97..f157bbe5 100644 --- a/packages/react-native-builder-bob/src/targets/codegen/patches/patchCodegenAndroidPackage.ts +++ b/packages/react-native-builder-bob/src/targets/codegen/patches/patchCodegenAndroidPackage.ts @@ -1,6 +1,7 @@ import fs from 'fs-extra'; import path from 'path'; import type { Report } from '../../../types'; +import kleur from 'kleur'; export const CODEGEN_DOCS = 'https://reactnative.dev/docs/the-new-architecture/using-codegen#configuring-codegen'; @@ -50,7 +51,9 @@ export async function patchCodegenAndroidPackage( // If this issue is ever fixed in react-native, this check will prevent the patching from running. if (!(await fs.pathExists(codegenJavaPath))) { report.info( - `Could not find ${codegenJavaPath}. Skipping patching codegen java files.` + `Could not find ${kleur.blue( + path.relative(projectPath, codegenJavaPath) + )}. Skipping patching codegen java files.` ); return; } diff --git a/packages/react-native-builder-bob/src/utils/workerize.ts b/packages/react-native-builder-bob/src/utils/workerize.ts new file mode 100644 index 00000000..642b21ea --- /dev/null +++ b/packages/react-native-builder-bob/src/utils/workerize.ts @@ -0,0 +1,94 @@ +import kleur from 'kleur'; +import { + Worker, + isMainThread, + parentPort, + workerData, +} from 'node:worker_threads'; +import codegen from '../targets/codegen'; +import commonjs from '../targets/commonjs'; +import custom from '../targets/custom'; +import module from '../targets/module'; +import typescript from '../targets/typescript'; +import type { Report, Target } from '../types'; + +type WorkerData = { + target: T; + data: Omit[0], 'report'>; +}; + +const targets = { + commonjs, + module, + typescript, + codegen, + custom, +} as const; + +export const run = async ( + target: T, + { report, ...data }: Parameters<(typeof targets)[T]>[0] +) => { + if (!isMainThread) { + throw new Error('Worker can only be run from the main thread'); + } + + const worker = new Worker(__filename, { + workerData: { + target, + data, + } satisfies WorkerData, + env: { + ...process.env, + FORCE_COLOR: process.stdout.isTTY ? '1' : '0', + }, + }); + + worker.on('message', (message) => { + switch (message.type) { + case 'info': + report.info(message.message); + break; + case 'warn': + report.warn(message.message); + break; + case 'error': + report.error(message.message); + break; + case 'success': + report.success(message.message); + break; + } + }); + + worker.on('error', (error) => { + report.error(error.message); + }); + + worker.on('exit', (code) => { + if (code !== 0) { + report.error(`exited with code ${kleur.red(code)}`); + } + }); +}; + +if (!isMainThread) { + const { target, data } = workerData as WorkerData; + + const report: Report = { + info: (message) => parentPort?.postMessage({ type: 'info', message }), + warn: (message) => parentPort?.postMessage({ type: 'warn', message }), + error: (message) => parentPort?.postMessage({ type: 'error', message }), + success: (message) => parentPort?.postMessage({ type: 'success', message }), + }; + + if (target in targets) { + // @ts-expect-error - typescript doesn't support correlated union types https://github.com/microsoft/TypeScript/issues/30581 + targets[target]({ ...data, report }).catch((error) => { + console.log(error); + process.exit(1); + }); + } else { + throw new Error(`Unknown target: ${target}`); + } +}