diff --git a/packages/rn-tester/BUCK b/packages/rn-tester/BUCK index f9b0023a2522..6a1137be3e29 100644 --- a/packages/rn-tester/BUCK +++ b/packages/rn-tester/BUCK @@ -65,7 +65,7 @@ rn_library( "pfh:ReactNative_CommonInfrastructurePlaceholder", "supermodule:xplat/default/public.react_native.playground", ], - native_component_spec_name = "MyNativeViewSpec", + native_component_spec_name = "AppSpecs", skip_processors = True, visibility = ["PUBLIC"], deps = [ @@ -317,7 +317,7 @@ rn_xplat_cxx_library2( reexport_all_header_dependencies = False, visibility = ["PUBLIC"], deps = [ - ":generated_components-MyNativeViewSpec", + ":generated_components-AppSpecs", "//xplat/js/react-native-github:RCTFabricComponentViewsBase", ], ) diff --git a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm index 7c5d0ac794c5..7fe66d4050d7 100644 --- a/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm +++ b/packages/rn-tester/NativeComponentExample/ios/RNTMyNativeViewComponentView.mm @@ -7,10 +7,10 @@ #import "RNTMyNativeViewComponentView.h" -#import -#import -#import -#import +#import +#import +#import +#import #import "RCTFabricComponentsPlugins.h" diff --git a/packages/rn-tester/package.json b/packages/rn-tester/package.json index d3de2629d0f6..4a34e4655626 100644 --- a/packages/rn-tester/package.json +++ b/packages/rn-tester/package.json @@ -31,21 +31,8 @@ "ws": "^6.1.4" }, "codegenConfig": { - "libraries": [ - { - "name": "ScreenshotManagerSpec", - "type": "modules", - "ios": {}, - "android": {}, - "jsSrcsDir": "NativeModuleExample" - }, - { - "name": "MyNativeViewSpec", - "type": "components", - "ios": {}, - "android": {}, - "jsSrcsDir": "NativeComponentExample/js" - } - ] + "name": "AppSpecs", + "type": "all", + "jsSrcsDir": "." } } diff --git a/scripts/codegen/__test_fixtures__/fixtures.js b/scripts/codegen/__test_fixtures__/fixtures.js index ec6e6188440e..86adfa0cd594 100644 --- a/scripts/codegen/__test_fixtures__/fixtures.js +++ b/scripts/codegen/__test_fixtures__/fixtures.js @@ -10,6 +10,48 @@ 'use-strict'; +const SINGLE_LIBRARY_CODEGEN_CONFIG = { + codegenConfig: { + libraries: [ + { + name: 'react-native', + type: 'all', + jsSrcsDir: '.', + }, + ], + }, +}; + +const MULTIPLE_LIBRARIES_CODEGEN_CONFIG = { + codegenConfig: { + libraries: [ + { + name: 'react-native', + type: 'all', + jsSrcsDir: '.', + }, + { + name: 'my-component', + type: 'components', + jsSrcsDir: 'component/js', + }, + { + name: 'my-module', + type: 'module', + jsSrcsDir: 'module/js', + }, + ], + }, +}; + +const NO_LIBRARIES_CONFIG_FILE = { + codegenConfig: { + name: 'AppModules', + type: 'all', + jsSrcsDir: '.', + }, +}; + const SCHEMA_TEXT = ` { "modules": { @@ -84,4 +126,7 @@ const SCHEMA = JSON.parse(SCHEMA_TEXT); module.exports = { schemaText: SCHEMA_TEXT, schema: SCHEMA, + noLibrariesConfigFile: NO_LIBRARIES_CONFIG_FILE, + singleLibraryCodegenConfig: SINGLE_LIBRARY_CODEGEN_CONFIG, + multipleLibrariesCodegenConfig: MULTIPLE_LIBRARIES_CODEGEN_CONFIG, }; diff --git a/scripts/codegen/__tests__/generate-artifacts-executor-test.js b/scripts/codegen/__tests__/generate-artifacts-executor-test.js index ed106ec820ef..b53806d26f77 100644 --- a/scripts/codegen/__tests__/generate-artifacts-executor-test.js +++ b/scripts/codegen/__tests__/generate-artifacts-executor-test.js @@ -11,8 +11,13 @@ 'use strict'; const underTest = require('../generate-artifacts-executor'); +const fixtures = require('../__test_fixtures__/fixtures'); const path = require('path'); +const codegenConfigKey = 'codegenConfig'; +const reactNativeDependencyName = 'react-native'; +const rootPath = path.join(__dirname, '../../..'); + describe('generateCode', () => { it('executeNodes with the right arguents', () => { // Define variables and expected values @@ -69,3 +74,130 @@ describe('generateCode', () => { expect(mkdirSyncInvocationCount).toBe(2); }); }); + +describe('extractLibrariesFromJSON', () => { + it('throws if in react-native and no dependencies found', () => { + let libraries = []; + let configFile = {}; + expect(() => { + underTest._extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + ); + }).toThrow(); + }); + + it('it skips if not into react-native and no dependencies found', () => { + let libraries = []; + let configFile = {}; + + underTest._extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + 'some-node-module', + 'node_modules/some', + ); + expect(libraries.length).toBe(0); + }); + + it('extracts a single dependency when config has no libraries', () => { + let libraries = []; + let configFile = fixtures.noLibrariesConfigFile; + underTest._extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + 'my-app', + '.', + ); + expect(libraries.length).toBe(1); + expect(libraries[0]).toEqual({ + library: 'my-app', + config: { + name: 'AppModules', + type: 'all', + jsSrcsDir: '.', + }, + libraryPath: '.', + }); + }); + + it("extract codegenConfig when it's empty", () => { + const configFile = {codegenConfig: {libraries: []}}; + let libraries = []; + underTest._extractLibrariesFromJSON( + configFile, + codegenConfigKey, + libraries, + reactNativeDependencyName, + rootPath, + ); + expect(libraries.length).toBe(0); + }); + + it('extract codegenConfig when dependency is one', () => { + const configFile = fixtures.singleLibraryCodegenConfig; + let libraries = []; + underTest._extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + reactNativeDependencyName, + rootPath, + ); + expect(libraries.length).toBe(1); + expect(libraries[0]).toEqual({ + library: reactNativeDependencyName, + config: { + name: 'react-native', + type: 'all', + jsSrcsDir: '.', + }, + libraryPath: rootPath, + }); + }); + + it('extract codegenConfig with multiple dependencies', () => { + const configFile = fixtures.multipleLibrariesCodegenConfig; + const myDependency = 'my-dependency'; + const myDependencyPath = path.join(__dirname, myDependency); + let libraries = []; + underTest._extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + myDependency, + myDependencyPath, + ); + expect(libraries.length).toBe(3); + expect(libraries[0]).toEqual({ + library: myDependency, + config: { + name: 'react-native', + type: 'all', + jsSrcsDir: '.', + }, + libraryPath: myDependencyPath, + }); + expect(libraries[1]).toEqual({ + library: myDependency, + config: { + name: 'my-component', + type: 'components', + jsSrcsDir: 'component/js', + }, + libraryPath: myDependencyPath, + }); + expect(libraries[2]).toEqual({ + library: myDependency, + config: { + name: 'my-module', + type: 'module', + jsSrcsDir: 'module/js', + }, + libraryPath: myDependencyPath, + }); + }); +}); diff --git a/scripts/codegen/generate-artifacts-executor.js b/scripts/codegen/generate-artifacts-executor.js index 94278756326e..784f44a2631a 100644 --- a/scripts/codegen/generate-artifacts-executor.js +++ b/scripts/codegen/generate-artifacts-executor.js @@ -52,6 +52,97 @@ function readPackageJSON(appRootDir) { } // Reading Libraries +function extractLibrariesFromConfigurationArray( + configFile, + codegenConfigKey, + libraries, + dependency, + dependencyPath, +) { + console.log(`[Codegen] Found ${dependency}`); + configFile[codegenConfigKey].libraries.forEach(config => { + const libraryConfig = { + library: dependency, + config, + libraryPath: dependencyPath, + }; + libraries.push(libraryConfig); + }); +} + +function extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + dependency, + dependencyPath, +) { + var isBlocking = false; + if (dependency == null) { + dependency = REACT_NATIVE_DEPENDENCY_NAME; + dependencyPath = RN_ROOT; + // If we are exploring the ReactNative libraries, we want to raise an error + // if the codegen is not properly configured. + isBlocking = true; + } + + if (configFile[codegenConfigKey] == null) { + if (isBlocking) { + throw `[Codegen] Error: Could not find codegen config for ${dependency} .`; + } + return; + } + + if (configFile[codegenConfigKey].libraries == null) { + console.log(`[Codegen] Found ${dependency}`); + var config = configFile[codegenConfigKey]; + libraries.push({ + library: dependency, + config, + libraryPath: dependencyPath, + }); + } else { + console.log(`[Codegen] CodegenConfig Deprecated Setup for ${dependency}. + The configuration file still contains the codegen in the libraries array. + If possible, replace it with a single object. + `); + console.debug(`BEFORE: + { + // ... + "codegenConfig": { + "libraries": [ + { + "name": "libName1", + "type": "all|components|modules", + "jsSrcsRoot": "libName1/js" + }, + { + "name": "libName2", + "type": "all|components|modules", + "jsSrcsRoot": "libName2/src" + } + ] + } + } + + AFTER: + { + "codegenConfig": { + "name": "libraries", + "type": "all", + "jsSrcsRoot": "." + } + } + `); + extractLibrariesFromConfigurationArray( + configFile, + codegenConfigKey, + libraries, + dependency, + dependencyPath, + ); + } +} function handleReactNativeCodeLibraries( libraries, @@ -66,21 +157,7 @@ function handleReactNativeCodeLibraries( throw '[Codegen] Error: Could not find config file for react-native.'; } const reactNativeConfigFile = JSON.parse(fs.readFileSync(reactNativePkgJson)); - if ( - reactNativeConfigFile[codegenConfigKey] == null || - reactNativeConfigFile[codegenConfigKey].libraries == null - ) { - throw '[Codegen] Error: Could not find codegen config for react-native.'; - } - console.log('[Codegen] Found react-native'); - reactNativeConfigFile[codegenConfigKey].libraries.forEach(config => { - const libraryConfig = { - library: REACT_NATIVE_DEPENDENCY_NAME, - config, - libraryPath: RN_ROOT, - }; - libraries.push(libraryConfig); - }); + extractLibrariesFromJSON(reactNativeConfigFile, libraries, codegenConfigKey); } function handleThirdPartyLibraries( @@ -109,20 +186,13 @@ function handleThirdPartyLibraries( ); if (fs.existsSync(configFilePath)) { const configFile = JSON.parse(fs.readFileSync(configFilePath)); - if ( - configFile[codegenConfigKey] != null && - configFile[codegenConfigKey].libraries != null - ) { - console.log(`[Codegen] Found ${dependency}`); - configFile[codegenConfigKey].libraries.forEach(config => { - const libraryConfig = { - library: dependency, - config, - libraryPath: codegenConfigFileDir, - }; - libraries.push(libraryConfig); - }); - } + extractLibrariesFromJSON( + configFile, + libraries, + codegenConfigKey, + dependency, + codegenConfigFileDir, + ); } }); } @@ -137,21 +207,13 @@ function handleInAppLibraries( '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app', ); - // Handle in-app libraries - if ( - pkgJson[codegenConfigKey] != null && - pkgJson[codegenConfigKey].libraries != null - ) { - console.log(`[Codegen] Found ${pkgJson.name}`); - pkgJson[codegenConfigKey].libraries.forEach(config => { - const libraryConfig = { - library: pkgJson.name, - config, - libraryPath: appRootDir, - }; - libraries.push(libraryConfig); - }); - } + extractLibrariesFromJSON( + pkgJson, + libraries, + codegenConfigKey, + pkgJson.name, + appRootDir, + ); } // CodeGen @@ -377,6 +439,8 @@ function execute( module.exports = { execute: execute, - _executeNodeScript: executeNodeScript, // exported for testing purposes only - _generateCode: generateCode, // exported for testing purposes only + // exported for testing purposes only: + _extractLibrariesFromJSON: extractLibrariesFromJSON, + _executeNodeScript: executeNodeScript, + _generateCode: generateCode, }; diff --git a/scripts/react_native_pods.rb b/scripts/react_native_pods.rb index d17d089df14b..52a18c6a3e2a 100644 --- a/scripts/react_native_pods.rb +++ b/scripts/react_native_pods.rb @@ -356,10 +356,20 @@ def get_react_codegen_script_phases(options={}) app_package_path = File.join(app_path, 'package.json') app_codegen_config = get_codegen_config_from_file(app_package_path, config_key) file_list = [] - app_codegen_config['libraries'].each do |library| - library_dir = File.join(app_path, library['jsSrcsDir']) - file_list.concat (`find #{library_dir} -type f \\( -name "Native*.js" -or -name "*NativeComponent.js" \\)`.split("\n").sort) + if app_codegen_config['libraries'] then + Pod::UI.warn '[Deprecated] You are using the old `libraries` array to list all your codegen.\nThis method will be removed in the future.\nUpdate your `package.json` with a single object.' + app_codegen_config['libraries'].each do |library| + library_dir = File.join(app_path, library['jsSrcsDir']) + file_list.concat (`find #{library_dir} -type f \\( -name "Native*.js" -or -name "*NativeComponent.js" \\)`.split("\n").sort) + end + elsif app_codegen_config['jsSrcsDir'] then + codegen_dir = File.join(app_path, app_codegen_config['jsSrcsDir']) + file_list.concat (`find #{codegen_dir} -type f \\( -name "Native*.js" -or -name "*NativeComponent.js" \\)`.split("\n").sort) + else + Pod::UI.warn '[Error] Codegen not properly configured. Please add the `codegenConf` entry to your `package.json`' + exit 1 end + input_files = file_list.map { |filename| "${PODS_ROOT}/../#{Pathname.new(filename).realpath().relative_path_from(Pod::Config.instance.installation_root)}" } # Add a script phase to trigger generate artifact.