react-native
Version:
A framework for building native apps using React
121 lines (107 loc) • 3.28 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
;
const {TEMPLATES_FOLDER_PATH} = require('./constants');
const {
codegenLog,
isReactNativeCoreLibrary,
parseiOSAnnotations,
} = require('./utils');
const fs = require('fs');
const path = require('path');
const MODULE_PROVIDERS_H_TEMPLATE_PATH = path.join(
TEMPLATES_FOLDER_PATH,
'RCTModuleProvidersH.template',
);
const MODULE_PROVIDERS_MM_TEMPLATE_PATH = path.join(
TEMPLATES_FOLDER_PATH,
'RCTModuleProvidersMM.template',
);
function generateRCTModuleProviders(
projectRoot,
pkgJson,
libraries,
outputDir,
) {
fs.mkdirSync(outputDir, {recursive: true});
// Generate Header File
codegenLog('Generating RCTModulesProvider.h');
const templateH = fs.readFileSync(MODULE_PROVIDERS_H_TEMPLATE_PATH, 'utf8');
const finalPathH = path.join(outputDir, 'RCTModuleProviders.h');
fs.writeFileSync(finalPathH, templateH);
codegenLog(`Generated artifact: ${finalPathH}`);
codegenLog('Generating RCTModuleProviders.mm');
let modulesInLibraries = {};
let app = pkgJson.codegenConfig
? {config: pkgJson.codegenConfig, libraryPath: projectRoot}
: null;
const moduleLibraries = libraries
.concat(app)
.filter(Boolean)
.filter(({config, libraryPath}) => {
if (
isReactNativeCoreLibrary(config.name) ||
config.type === 'components'
) {
return false;
}
return true;
});
// Old API
moduleLibraries.forEach(({config, libraryPath}) => {
const libraryName = JSON.parse(
fs.readFileSync(path.join(libraryPath, 'package.json')),
).name;
if (config.ios?.modulesProvider) {
modulesInLibraries[libraryName] = Object.keys(
config.ios?.modulesProvider,
).map(moduleName => {
return {
moduleName,
className: config.ios?.modulesProvider[moduleName],
};
});
}
});
// New API
const iosAnnotations = parseiOSAnnotations(moduleLibraries);
for (const [libraryName, {modules: moduleAnnotationMap}] of Object.entries(
iosAnnotations,
)) {
for (const [moduleName, annotation] of Object.entries(
moduleAnnotationMap,
)) {
if (annotation.className) {
modulesInLibraries[libraryName] = modulesInLibraries[libraryName] || [];
modulesInLibraries[libraryName].push({
moduleName,
className: annotation.className,
});
}
}
}
const modulesMapping = Object.keys(modulesInLibraries)
.flatMap(library => {
const modules = modulesInLibraries[library];
return modules.map(({moduleName, className}) => {
return `\t\t@"${moduleName}": @"${className}", // ${library}`;
});
})
.join('\n');
// Generate implementation file
const templateMM = fs
.readFileSync(MODULE_PROVIDERS_MM_TEMPLATE_PATH, 'utf8')
.replace(/{moduleMapping}/, modulesMapping);
const finalPathMM = path.join(outputDir, 'RCTModuleProviders.mm');
fs.writeFileSync(finalPathMM, templateMM);
codegenLog(`Generated artifact: ${finalPathMM}`);
}
module.exports = {
generateRCTModuleProviders,
};