From 2d7e7943e3f972a0a8265e35109b73c6df049e39 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Tue, 8 Apr 2025 23:49:48 +0200 Subject: [PATCH 1/4] fix: improve error handling --- .../src/targets/codegen/index.ts | 12 ++++++------ .../src/targets/typescript.ts | 2 +- .../src/utils/androidAssemble.ts | 1 + .../src/utils/compile.ts | 4 +++- .../src/utils/runRNCCli.ts | 14 -------------- .../src/utils/spawn.ts | 19 ++++++++++++++++++- 6 files changed, 29 insertions(+), 23 deletions(-) delete mode 100644 packages/react-native-builder-bob/src/utils/runRNCCli.ts diff --git a/packages/react-native-builder-bob/src/targets/codegen/index.ts b/packages/react-native-builder-bob/src/targets/codegen/index.ts index 33e6c6e2d..315424733 100644 --- a/packages/react-native-builder-bob/src/targets/codegen/index.ts +++ b/packages/react-native-builder-bob/src/targets/codegen/index.ts @@ -4,8 +4,8 @@ import { patchCodegenAndroidPackage } from './patches/patchCodegenAndroidPackage import fs from 'fs-extra'; import path from 'path'; import del from 'del'; -import { runRNCCli } from '../../utils/runRNCCli'; import { removeCodegenAppLevelCode } from './patches/removeCodegenAppLevelCode'; +import { spawn } from '../../utils/spawn'; type Options = Omit; @@ -42,7 +42,7 @@ export default async function build({ root, report }: Options) { } try { - await runRNCCli(['codegen']); + await spawn('npx', ['@react-native-community/cli', 'codegen']); if (codegenType === 'modules' || codegenType === 'all') { await patchCodegenAndroidPackage(root, packageJson, report); @@ -53,8 +53,8 @@ export default async function build({ root, report }: Options) { } catch (e: unknown) { if (e != null && typeof e === 'object') { if ('stdout' in e && e.stdout != null) { - throw new Error( - `Errors found while generating codegen files:\n${e.stdout.toString()}` + report.error( + `Errors found while running codegen:\n\n${e.stdout.toString()}` ); } else if ('message' in e && typeof e.message === 'string') { if ( @@ -62,13 +62,13 @@ export default async function build({ root, report }: Options) { "Error: Cannot find module '@react-native-community/cli/package.json'" ) ) { - throw new Error( + report.error( "You don't have `@react-native-community/cli` in your root package's dev dependencies. Please install it and make sure it uses the same version as your application." ); } } } - throw e; + throw new Error('Failed to run codegen.', { cause: e }); } } diff --git a/packages/react-native-builder-bob/src/targets/typescript.ts b/packages/react-native-builder-bob/src/targets/typescript.ts index 24aedd48a..3e5dc02bb 100644 --- a/packages/react-native-builder-bob/src/targets/typescript.ts +++ b/packages/react-native-builder-bob/src/targets/typescript.ts @@ -424,6 +424,6 @@ export default async function build({ throw e; } - throw new Error('Failed to build definition files.'); + throw new Error('Failed to build definition files.', { cause: e }); } } diff --git a/packages/react-native-builder-bob/src/utils/androidAssemble.ts b/packages/react-native-builder-bob/src/utils/androidAssemble.ts index 9729c862a..e211e5432 100644 --- a/packages/react-native-builder-bob/src/utils/androidAssemble.ts +++ b/packages/react-native-builder-bob/src/utils/androidAssemble.ts @@ -25,6 +25,7 @@ export default async function androidAssemble({ ); const gradleWrapper = platform() === 'win32' ? 'gradlew.bat' : './gradlew'; + if (await fs.pathExists(path.join(androidPath, gradleWrapper))) { execFileSync(gradleWrapper, ['assemble'], { cwd: androidPath }); } else { diff --git a/packages/react-native-builder-bob/src/utils/compile.ts b/packages/react-native-builder-bob/src/utils/compile.ts index a9b07a42f..f21c8791f 100644 --- a/packages/react-native-builder-bob/src/utils/compile.ts +++ b/packages/react-native-builder-bob/src/utils/compile.ts @@ -307,7 +307,9 @@ export default async function compile({ }` ); - throw new Error(`Found incorrect path in '${name}' field.`); + throw new Error(`Found incorrect path in '${name}' field.`, { + cause: e, + }); } throw e; diff --git a/packages/react-native-builder-bob/src/utils/runRNCCli.ts b/packages/react-native-builder-bob/src/utils/runRNCCli.ts deleted file mode 100644 index 8ad105819..000000000 --- a/packages/react-native-builder-bob/src/utils/runRNCCli.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { type SpawnOptions } from 'node:child_process'; -import { spawn } from './spawn'; - -/** - * Runs the React Native Community CLI with the specified arguments - */ -export async function runRNCCli( - args: string[], - options: SpawnOptions = { - stdio: ['ignore', 'ignore', 'pipe'], - } -) { - return await spawn('npx', ['@react-native-community/cli', ...args], options); -} diff --git a/packages/react-native-builder-bob/src/utils/spawn.ts b/packages/react-native-builder-bob/src/utils/spawn.ts index 775fe7de1..b7954bd84 100644 --- a/packages/react-native-builder-bob/src/utils/spawn.ts +++ b/packages/react-native-builder-bob/src/utils/spawn.ts @@ -22,7 +22,24 @@ export const spawn = async (...args: Parameters) => { if (code === 0) { resolve(stdout.trim()); } else { - reject(new Error(stderr.trim())); + const error = new Error(stderr.trim() || 'Unknown error'); + + Object.defineProperties(error, { + stdout: { + enumerable: false, + value: stdout, + }, + stderr: { + enumerable: false, + value: stderr, + }, + code: { + enumerable: false, + value: code, + }, + }); + + reject(error); } }); }); From 66dcc212473c8ace501115fa2646737e9d752ad5 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 9 Apr 2025 22:10:46 +0200 Subject: [PATCH 2/4] fix: restrict react-native version to 0.78.2 --- packages/create-react-native-library/src/index.ts | 7 +++++-- packages/create-react-native-library/src/inform.ts | 2 +- packages/create-react-native-library/src/input.ts | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/create-react-native-library/src/index.ts b/packages/create-react-native-library/src/index.ts index ca03b407c..322d910a3 100644 --- a/packages/create-react-native-library/src/index.ts +++ b/packages/create-react-native-library/src/index.ts @@ -20,8 +20,9 @@ import { createInitialGitCommit } from './utils/initialCommit'; import { prompt } from './utils/prompt'; import { resolveNpmPackageVersion } from './utils/resolveNpmPackageVersion'; -const FALLBACK_BOB_VERSION = '0.38.3'; +const FALLBACK_BOB_VERSION = '0.40.4'; const FALLBACK_NITRO_MODULES_VERSION = '0.22.1'; +const SUPPORTED_REACT_NATIVE_VERSION = '0.78.2'; // eslint-disable-next-line @typescript-eslint/no-unused-expressions yargs @@ -69,6 +70,8 @@ async function create(_argv: yargs.Arguments) { const promptAnswers = await prompt(questions, argv); const answers: Answers = { ...promptAnswers, + reactNativeVersion: + promptAnswers.reactNativeVersion ?? SUPPORTED_REACT_NATIVE_VERSION, local, }; @@ -94,7 +97,7 @@ async function create(_argv: yargs.Arguments) { await fs.mkdirp(folder); - if (answers.reactNativeVersion != null) { + if (answers.reactNativeVersion !== SUPPORTED_REACT_NATIVE_VERSION) { printUsedRNVersion(answers.reactNativeVersion, config); } diff --git a/packages/create-react-native-library/src/inform.ts b/packages/create-react-native-library/src/inform.ts index e6c18318f..8ded66eac 100644 --- a/packages/create-react-native-library/src/inform.ts +++ b/packages/create-react-native-library/src/inform.ts @@ -129,7 +129,7 @@ export function printUsedRNVersion( ) { if (config.example === 'vanilla') { console.log( - `${kleur.blue('ℹ')} Using ${kleur.cyan( + `${kleur.blue('ℹ')} Using untested ${kleur.cyan( `react-native@${version}` )} for the example` ); diff --git a/packages/create-react-native-library/src/input.ts b/packages/create-react-native-library/src/input.ts index 23620d1a1..162ee17ea 100644 --- a/packages/create-react-native-library/src/input.ts +++ b/packages/create-react-native-library/src/input.ts @@ -181,7 +181,7 @@ export type Answers = { languages: ProjectLanguages; type: ProjectType; example: ExampleApp; - reactNativeVersion?: string; + reactNativeVersion: string; local?: boolean; }; From 462731c540077a8e823e91213336ef58f2fcc266 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 9 Apr 2025 22:24:44 +0200 Subject: [PATCH 3/4] refactor: run tsc asynchronously --- .../src/targets/typescript.ts | 375 +++++++++--------- .../src/utils/spawn.ts | 4 +- 2 files changed, 184 insertions(+), 195 deletions(-) diff --git a/packages/react-native-builder-bob/src/targets/typescript.ts b/packages/react-native-builder-bob/src/targets/typescript.ts index 3e5dc02bb..8a09d36fb 100644 --- a/packages/react-native-builder-bob/src/targets/typescript.ts +++ b/packages/react-native-builder-bob/src/targets/typescript.ts @@ -1,12 +1,12 @@ -import kleur from 'kleur'; -import path from 'path'; -import fs from 'fs-extra'; -import which from 'which'; -import spawn from 'cross-spawn'; import del from 'del'; +import fs from 'fs-extra'; import JSON5 from 'json5'; +import kleur from 'kleur'; import { platform } from 'os'; +import path from 'path'; +import which from 'which'; import type { Input, Variants } from '../types'; +import { spawn } from '../utils/spawn'; type Options = Input & { options?: { @@ -108,13 +108,11 @@ export default async function build({ const cli = execpath?.split('/').pop()?.includes('yarn') ? 'yarn' : 'npm'; if (cli === 'yarn') { - const result = spawn.sync('yarn', ['bin', 'tsc'], { - stdio: 'pipe', - encoding: 'utf-8', + const result = await spawn('yarn', ['bin', 'tsc'], { cwd: root, }); - tsc = result.stdout.trim(); + tsc = result.trim(); } else { tsc = path.resolve(root, 'node_modules', '.bin', 'tsc'); } @@ -190,7 +188,7 @@ export default async function build({ // Ignore } - const result = spawn.sync( + await spawn( tsc, [ '--pretty', @@ -204,210 +202,203 @@ export default async function build({ '--outDir', outDir, ], - { - stdio: 'inherit', - cwd: root, - } + { cwd: root } ); - if (result.status === 0) { - await del([tsbuildinfo]); + await del([tsbuildinfo]); - if (esm) { - if (outputs?.commonjs && outputs?.module) { - // When ESM compatible output is enabled and commonjs build is present, we need to generate 2 builds for commonjs and esm - // In this case we copy the already generated types, and add `package.json` with `type` field - await fs.copy(outputs.commonjs, outputs.module); - await fs.writeJSON(path.join(outputs.commonjs, 'package.json'), { - type: 'commonjs', - }); - await fs.writeJSON(path.join(outputs.module, 'package.json'), { - type: 'module', - }); - } else if (outputs?.commonjs) { - await fs.writeJSON(path.join(outputs.commonjs, 'package.json'), { - type: 'commonjs', - }); - } else if (outputs?.module) { - await fs.writeJSON(path.join(outputs.module, 'package.json'), { - type: 'module', - }); - } + if (esm) { + if (outputs?.commonjs && outputs?.module) { + // When ESM compatible output is enabled and commonjs build is present, we need to generate 2 builds for commonjs and esm + // In this case we copy the already generated types, and add `package.json` with `type` field + await fs.copy(outputs.commonjs, outputs.module); + await fs.writeJSON(path.join(outputs.commonjs, 'package.json'), { + type: 'commonjs', + }); + await fs.writeJSON(path.join(outputs.module, 'package.json'), { + type: 'module', + }); + } else if (outputs?.commonjs) { + await fs.writeJSON(path.join(outputs.commonjs, 'package.json'), { + type: 'commonjs', + }); + } else if (outputs?.module) { + await fs.writeJSON(path.join(outputs.module, 'package.json'), { + type: 'module', + }); } + } - report.success( - `Wrote definition files to ${kleur.blue(path.relative(root, output))}` - ); + report.success( + `Wrote definition files to ${kleur.blue(path.relative(root, output))}` + ); - const pkg = JSON.parse( - await fs.readFile(path.join(root, 'package.json'), 'utf-8') - ); + const pkg = JSON.parse( + await fs.readFile(path.join(root, 'package.json'), 'utf-8') + ); - const fields: Field[] = [ - { - name: 'types', - value: pkg.types, - output: outputs.commonjs, - error: false, - message: undefined, - }, - ...(pkg.exports?.['.']?.types - ? [ - { - name: "exports['.'].types", - value: pkg.exports?.['.']?.types, - output: outDir, - error: Boolean( - pkg.exports?.['.']?.import && pkg.exports?.['.']?.require - ), - message: `using ${kleur.blue( - "exports['.'].import" - )} and ${kleur.blue( - "exports['.'].require" - )}. Specify ${kleur.blue( - "exports['.'].import.types" - )} and ${kleur.blue("exports['.'].require.types")} instead.`, - }, - ] - : []), - { - name: "exports['.'].import.types", - value: pkg.exports?.['.']?.import?.types, - output: outputs.module, - error: !esm, - message: `the ${kleur.blue( - 'esm' - )} option is not enabled for the ${kleur.blue('module')} target`, - }, - { - name: "exports['.'].require.types", - value: pkg.exports?.['.']?.require?.types, - output: outputs.commonjs, - error: false, - message: undefined, - }, - ]; - - const getGeneratedTypesPath = async (field: Field) => { - if (!field.output || field.error) { - return null; - } + const fields: Field[] = [ + { + name: 'types', + value: pkg.types, + output: outputs.commonjs, + error: false, + message: undefined, + }, + ...(pkg.exports?.['.']?.types + ? [ + { + name: "exports['.'].types", + value: pkg.exports?.['.']?.types, + output: outDir, + error: Boolean( + pkg.exports?.['.']?.import && pkg.exports?.['.']?.require + ), + message: `using ${kleur.blue( + "exports['.'].import" + )} and ${kleur.blue( + "exports['.'].require" + )}. Specify ${kleur.blue( + "exports['.'].import.types" + )} and ${kleur.blue("exports['.'].require.types")} instead.`, + }, + ] + : []), + { + name: "exports['.'].import.types", + value: pkg.exports?.['.']?.import?.types, + output: outputs.module, + error: !esm, + message: `the ${kleur.blue( + 'esm' + )} option is not enabled for the ${kleur.blue('module')} target`, + }, + { + name: "exports['.'].require.types", + value: pkg.exports?.['.']?.require?.types, + output: outputs.commonjs, + error: false, + message: undefined, + }, + ]; + + const getGeneratedTypesPath = async (field: Field) => { + if (!field.output || field.error) { + return null; + } - if (pkg.source) { - const indexDTsName = - path.basename(pkg.source).replace(/\.(jsx?|tsx?)$/, '') + '.d.ts'; - - const potentialPaths = [ - path.join(field.output, path.dirname(pkg.source), indexDTsName), - path.join( - field.output, - path.relative(source, path.join(root, path.dirname(pkg.source))), - indexDTsName - ), - ]; - - for (const potentialPath of potentialPaths) { - if (await fs.pathExists(potentialPath)) { - return path.relative(root, potentialPath); - } + if (pkg.source) { + const indexDTsName = + path.basename(pkg.source).replace(/\.(jsx?|tsx?)$/, '') + '.d.ts'; + + const potentialPaths = [ + path.join(field.output, path.dirname(pkg.source), indexDTsName), + path.join( + field.output, + path.relative(source, path.join(root, path.dirname(pkg.source))), + indexDTsName + ), + ]; + + for (const potentialPath of potentialPaths) { + if (await fs.pathExists(potentialPath)) { + return path.relative(root, potentialPath); } } + } - return null; - }; - - const invalidFieldNames = ( - await Promise.all( - fields.map(async (field) => { - if (field.error) { - if (field.value) { - report.warn( - `The ${kleur.blue(field.name)} field in ${kleur.blue( - `package.json` - )} should not be set when ${field.message}.` - ); - } - - return null; - } + return null; + }; - if ( - field.name.startsWith('exports') && - field.value && - !/^\.\//.test(field.value) - ) { - report.error( + const invalidFieldNames = ( + await Promise.all( + fields.map(async (field) => { + if (field.error) { + if (field.value) { + report.warn( `The ${kleur.blue(field.name)} field in ${kleur.blue( `package.json` - )} should be a relative path starting with ${kleur.blue( - './' - )}. Found: ${kleur.blue(field.value)}` + )} should not be set when ${field.message}.` ); - - return field.name; } - if ( - field.value && - !(await fs.pathExists(path.join(root, field.value))) - ) { - const generatedTypesPath = await getGeneratedTypesPath(field); + return null; + } - report.error( - `The ${kleur.blue(field.name)} field in ${kleur.blue( - 'package.json' - )} points to a non-existent file: ${kleur.blue( - field.value - )}.\nVerify the path points to the correct file under ${kleur.blue( - path.relative(root, output) - )}${ - generatedTypesPath - ? ` (found ${kleur.blue(generatedTypesPath)}).` - : '.' - }` - ); + if ( + field.name.startsWith('exports') && + field.value && + !/^\.\//.test(field.value) + ) { + report.error( + `The ${kleur.blue(field.name)} field in ${kleur.blue( + `package.json` + )} should be a relative path starting with ${kleur.blue( + './' + )}. Found: ${kleur.blue(field.value)}` + ); - return field.name; - } + return field.name; + } - return null; - }) - ) - ).filter((name): name is string => name != null); + if ( + field.value && + !(await fs.pathExists(path.join(root, field.value))) + ) { + const generatedTypesPath = await getGeneratedTypesPath(field); + + report.error( + `The ${kleur.blue(field.name)} field in ${kleur.blue( + 'package.json' + )} points to a non-existent file: ${kleur.blue( + field.value + )}.\nVerify the path points to the correct file under ${kleur.blue( + path.relative(root, output) + )}${ + generatedTypesPath + ? ` (found ${kleur.blue(generatedTypesPath)}).` + : '.' + }` + ); - if (invalidFieldNames.length) { - throw new Error( - `Found errors for fields: ${invalidFieldNames.join(', ')}.` - ); - } + return field.name; + } - const validFields = fields.filter((field) => !field.error); + return null; + }) + ) + ).filter((name): name is string => name != null); - if (validFields.every((field) => field.value == null)) { - const suggestedTypesPaths = ( - await Promise.all( - validFields.map((field) => getGeneratedTypesPath(field)) - ) - ) - .filter((path): path is string => path != null) - .filter((path, i, self) => self.indexOf(path) === i); + if (invalidFieldNames.length) { + throw new Error( + `Found errors for fields: ${invalidFieldNames.join(', ')}.` + ); + } - report.warn( - `No ${validFields - .map((field) => kleur.blue(field.name)) - .join(' or ')} field found in ${kleur.blue( - 'package.json' - )}. Consider ${ - suggestedTypesPaths.length - ? `pointing to ${suggestedTypesPaths - .map((path) => kleur.blue(path)) - .join(' or ')}` - : `adding ${validFields.length > 1 ? 'them' : 'it'}` - } so that consumers of your package can use the typescript definitions.` - ); - } - } else { - throw new Error('Failed to build definition files.'); + const validFields = fields.filter((field) => !field.error); + + if (validFields.every((field) => field.value == null)) { + const suggestedTypesPaths = ( + await Promise.all( + validFields.map((field) => getGeneratedTypesPath(field)) + ) + ) + .filter((path): path is string => path != null) + .filter((path, i, self) => self.indexOf(path) === i); + + report.warn( + `No ${validFields + .map((field) => kleur.blue(field.name)) + .join(' or ')} field found in ${kleur.blue( + 'package.json' + )}. Consider ${ + suggestedTypesPaths.length + ? `pointing to ${suggestedTypesPaths + .map((path) => kleur.blue(path)) + .join(' or ')}` + : `adding ${validFields.length > 1 ? 'them' : 'it'}` + } so that consumers of your package can use the typescript definitions.` + ); } } catch (e: unknown) { if (e != null && typeof e === 'object') { @@ -417,11 +408,7 @@ export default async function build({ ); } else if ('message' in e && typeof e.message === 'string') { report.error(e.message); - } else { - throw e; } - } else { - throw e; } throw new Error('Failed to build definition files.', { cause: e }); diff --git a/packages/react-native-builder-bob/src/utils/spawn.ts b/packages/react-native-builder-bob/src/utils/spawn.ts index b7954bd84..12fd7e0b1 100644 --- a/packages/react-native-builder-bob/src/utils/spawn.ts +++ b/packages/react-native-builder-bob/src/utils/spawn.ts @@ -22,7 +22,9 @@ export const spawn = async (...args: Parameters) => { if (code === 0) { resolve(stdout.trim()); } else { - const error = new Error(stderr.trim() || 'Unknown error'); + const error = new Error( + stderr.trim() || `Command exited with code ${code}` + ); Object.defineProperties(error, { stdout: { From 5c07d727b03d3140885c163e9811202c3b4d8233 Mon Sep 17 00:00:00 2001 From: Satyajit Sahoo Date: Wed, 9 Apr 2025 22:27:17 +0200 Subject: [PATCH 4/4] chore: publish - create-react-native-library@0.49.7 - react-native-builder-bob@0.40.5 --- packages/create-react-native-library/CHANGELOG.md | 6 ++++++ packages/create-react-native-library/package.json | 2 +- packages/react-native-builder-bob/CHANGELOG.md | 6 ++++++ packages/react-native-builder-bob/package.json | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/create-react-native-library/CHANGELOG.md b/packages/create-react-native-library/CHANGELOG.md index 4730332ff..0802953b8 100644 --- a/packages/create-react-native-library/CHANGELOG.md +++ b/packages/create-react-native-library/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.49.7](https://github.com/callstack/react-native-builder-bob/compare/create-react-native-library@0.49.6...create-react-native-library@0.49.7) (2025-04-09) + +### Bug Fixes + +- restrict react-native version to 0.78.2 ([66dcc21](https://github.com/callstack/react-native-builder-bob/commit/66dcc212473c8ace501115fa2646737e9d752ad5)) - by @ + ## [0.49.6](https://github.com/callstack/react-native-builder-bob/compare/create-react-native-library@0.49.5...create-react-native-library@0.49.6) (2025-04-08) ### Bug Fixes diff --git a/packages/create-react-native-library/package.json b/packages/create-react-native-library/package.json index 25d7e5260..ca568a9af 100644 --- a/packages/create-react-native-library/package.json +++ b/packages/create-react-native-library/package.json @@ -1,6 +1,6 @@ { "name": "create-react-native-library", - "version": "0.49.6", + "version": "0.49.7", "description": "CLI to scaffold React Native libraries", "keywords": [ "react-native", diff --git a/packages/react-native-builder-bob/CHANGELOG.md b/packages/react-native-builder-bob/CHANGELOG.md index af6cef485..828fa6f7f 100644 --- a/packages/react-native-builder-bob/CHANGELOG.md +++ b/packages/react-native-builder-bob/CHANGELOG.md @@ -3,6 +3,12 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [0.40.5](https://github.com/callstack/react-native-builder-bob/compare/react-native-builder-bob@0.40.4...react-native-builder-bob@0.40.5) (2025-04-09) + +### Bug Fixes + +- improve error handling ([2d7e794](https://github.com/callstack/react-native-builder-bob/commit/2d7e7943e3f972a0a8265e35109b73c6df049e39)) - by @satya164 + ## [0.40.4](https://github.com/callstack/react-native-builder-bob/compare/react-native-builder-bob@0.40.3...react-native-builder-bob@0.40.4) (2025-04-08) ### Bug Fixes diff --git a/packages/react-native-builder-bob/package.json b/packages/react-native-builder-bob/package.json index 8b5b98e05..38b3a2484 100644 --- a/packages/react-native-builder-bob/package.json +++ b/packages/react-native-builder-bob/package.json @@ -1,6 +1,6 @@ { "name": "react-native-builder-bob", - "version": "0.40.4", + "version": "0.40.5", "description": "CLI to build JavaScript files for React Native libraries", "keywords": [ "react-native",