1/** 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 * @format 8 */ 9 10'use strict'; 11 12const yargs = require('yargs'); 13const fs = require('fs'); 14 15const CONFIG_FILE_NAME = 'react-native.config.js'; 16const PROJECT_FIELD = 'project'; 17const IOS_FIELD = 'ios'; 18const LEGACY_COMPONENTS_FIELD = 'unstable_reactLegacyComponentNames'; 19const OUTPUT_FILE_NAME = 'RCTLegacyInteropComponents.mm'; 20 21const argv = yargs 22 .option('p', { 23 alias: 'path', 24 description: 'Path to React Native application', 25 }) 26 .option('o', { 27 alias: 'outputPath', 28 description: 'Path where generated artifacts will be output to', 29 }) 30 .usage('Usage: $0 -p [path to app]') 31 .demandOption(['p']).argv; 32 33const appRoot = argv.path; 34const outputPath = argv.outputPath; 35 36function fileBody(components) { 37 // eslint-disable duplicate-license-header 38 return ` 39/* 40 * Copyright (c) Meta Platforms, Inc. and affiliates. 41 * 42 * This source code is licensed under the MIT license found in the 43 * LICENSE file in the root directory of this source tree. 44 */ 45 46#import "RCTLegacyInteropComponents.h" 47 48@implementation RCTLegacyInteropComponents 49 50+ (NSArray<NSString *> *)legacyInteropComponents 51{ 52 return @[ 53${components} 54 ]; 55} 56 57@end 58`; 59 // eslint-enable duplicate-license-header 60} 61 62function extractComponentsNames(reactNativeConfig) { 63 if (!reactNativeConfig) { 64 console.log('No reactNativeConfig in the react-native.config.js file'); 65 return null; 66 } 67 68 const project = reactNativeConfig[PROJECT_FIELD]; 69 70 if (!project) { 71 console.log(`No ${PROJECT_FIELD} in the react-native config`); 72 return null; 73 } 74 75 const ios = project[IOS_FIELD]; 76 77 if (!ios) { 78 console.log( 79 `No ${IOS_FIELD} in the ${PROJECT_FIELD} object of the config file`, 80 ); 81 return null; 82 } 83 84 const componentNames = ios[LEGACY_COMPONENTS_FIELD]; 85 86 if (!componentNames) { 87 console.log( 88 `No '${LEGACY_COMPONENTS_FIELD}' field in the ${PROJECT_FIELD}.${IOS_FIELD} object`, 89 ); 90 return null; 91 } 92 return componentNames; 93} 94 95function generateRCTLegacyInteropComponents() { 96 const configFilePath = `${appRoot}/${CONFIG_FILE_NAME}`; 97 let reactNativeConfig = null; 98 try { 99 reactNativeConfig = require(configFilePath); 100 } catch (error) { 101 console.log(`No ${configFilePath}. Skip LegacyInterop generation`); 102 return; 103 } 104 105 const componentNames = extractComponentsNames(reactNativeConfig); 106 if (!componentNames) { 107 console.log('Skip LegacyInterop generation'); 108 return; 109 } 110 111 let componentsArray = componentNames.map(name => `\t\t\t@"${name}",`); 112 // Remove the last comma 113 if (componentsArray.length > 0) { 114 componentsArray[componentsArray.length - 1] = componentsArray[ 115 componentsArray.length - 1 116 ].slice(0, -1); 117 } 118 119 const filePath = `${outputPath}/${OUTPUT_FILE_NAME}`; 120 fs.writeFileSync(filePath, fileBody(componentsArray.join('\n'))); 121} 122 123generateRCTLegacyInteropComponents(); 124