feat: support custom library paths in react-native.config.js for codegen on iOS (#34580)

Summary:
Currently for codegen to work for a library on iOS, it needs to be located
inside `node_modules`. This patch adds support for libraries defined in
`react-native.config.js`.

This is useful when developing libraries as well as monorepos where the library
may exist outside of the `node_modules`.

Example:

```js
// react-native.config.js
const path = require('path');

module.exports = {
  dependencies: {
    'react-native-library-name': {
      root: path.join(__dirname, '..'),
    },
  },
};
```

## Changelog

[Internal] [Added] - Support custom library paths in `react-native.config.js` for codegen on iOS

Pull Request resolved: https://github.com/facebook/react-native/pull/34580

Test Plan:
Tested on a test application and ensured that codegen finds the library specified in `react-native.config.js`

https://user-images.githubusercontent.com/1174278/188141056-bce03730-2a13-4648-8889-9727aaf2c3c4.mp4

I have also added a basic test case for this scenario.

Reviewed By: jacdebug, cortinico

Differential Revision: D39257919

Pulled By: cipolleschi

fbshipit-source-id: 131189f1941128a59b9b1e28af61a9038eb4536b
This commit is contained in:
Satyajit Sahoo
2022-09-08 03:09:16 -07:00
committed by Dmitry Rykun
parent ad582f5e8a
commit f0ffd2291c
4 changed files with 202 additions and 52 deletions
+85 -13
View File
@@ -204,6 +204,55 @@ function handleThirdPartyLibraries(
});
}
function handleLibrariesFromReactNativeConfig(
libraries,
codegenConfigKey,
codegenConfigFilename,
appRootDir,
) {
const rnConfigFileName = 'react-native.config.js';
console.log(
`\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${rnConfigFileName}`,
);
const rnConfigFilePath = path.join(appRootDir, rnConfigFileName);
if (fs.existsSync(rnConfigFilePath)) {
const rnConfig = require(rnConfigFilePath);
if (rnConfig.dependencies != null) {
Object.keys(rnConfig.dependencies).forEach(name => {
const dependencyConfig = rnConfig.dependencies[name];
if (dependencyConfig.root) {
const codegenConfigFileDir = path.resolve(
appRootDir,
dependencyConfig.root,
);
const configFilePath = path.join(
codegenConfigFileDir,
codegenConfigFilename,
);
const pkgJsonPath = path.join(codegenConfigFileDir, 'package.json');
if (fs.existsSync(configFilePath)) {
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath));
const configFile = JSON.parse(fs.readFileSync(configFilePath));
extractLibrariesFromJSON(
configFile,
libraries,
codegenConfigKey,
pkgJson.name,
codegenConfigFileDir,
);
}
}
});
}
}
}
function handleInAppLibraries(
libraries,
pkgJson,
@@ -362,6 +411,39 @@ function createComponentProvider(
}
}
function findCodegenEnabledLibraries(
appRootDir,
baseCodegenConfigFileDir,
codegenConfigFilename,
codegenConfigKey,
) {
const pkgJson = readPackageJSON(appRootDir);
const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies};
const libraries = [];
handleReactNativeCodeLibraries(
libraries,
codegenConfigFilename,
codegenConfigKey,
);
handleThirdPartyLibraries(
libraries,
baseCodegenConfigFileDir,
dependencies,
codegenConfigFilename,
codegenConfigKey,
);
handleLibrariesFromReactNativeConfig(
libraries,
codegenConfigKey,
codegenConfigFilename,
appRootDir,
);
handleInAppLibraries(libraries, pkgJson, codegenConfigKey, appRootDir);
return libraries;
}
// It removes all the empty files and empty folders
// it finds, starting from `filepath`, recursively.
//
@@ -429,23 +511,12 @@ function execute(
}
try {
const pkgJson = readPackageJSON(appRootDir);
const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies};
const libraries = [];
handleReactNativeCodeLibraries(
libraries,
codegenConfigFilename,
codegenConfigKey,
);
handleThirdPartyLibraries(
libraries,
const libraries = findCodegenEnabledLibraries(
appRootDir,
baseCodegenConfigFileDir,
dependencies,
codegenConfigFilename,
codegenConfigKey,
);
handleInAppLibraries(libraries, pkgJson, codegenConfigKey, appRootDir);
if (libraries.length === 0) {
console.log('[Codegen] No codegen-enabled libraries found.');
@@ -482,6 +553,7 @@ module.exports = {
execute: execute,
// exported for testing purposes only:
_extractLibrariesFromJSON: extractLibrariesFromJSON,
_findCodegenEnabledLibraries: findCodegenEnabledLibraries,
_executeNodeScript: executeNodeScript,
_generateCode: generateCode,
_cleanupEmptyFilesAndFolders: cleanupEmptyFilesAndFolders,