function main()

in scripts/generate-artifacts.js [74:304]


function main(appRootDir, outputPath) {
  if (appRootDir == null) {
    console.error('Missing path to React Native application');
    process.exitCode = 1;
    return;
  }

  try {
    // Get app package.json
    const pkgJson = JSON.parse(
      fs.readFileSync(path.join(appRootDir, 'package.json')),
    );

    // Get dependencies for the app
    const dependencies = {...pkgJson.dependencies, ...pkgJson.devDependencies};

    const libraries = [];

    // Handle react-native core libraries.
    // This is required when react-native is outside of node_modules.
    console.log('[Codegen] Processing react-native core libraries');
    const reactNativePkgJson = path.join(RN_ROOT, CODEGEN_CONFIG_FILENAME);
    if (!fs.existsSync(reactNativePkgJson)) {
      throw '[Codegen] Error: Could not find config file for react-native.';
    }
    const reactNativeConfigFile = JSON.parse(
      fs.readFileSync(reactNativePkgJson),
    );
    if (
      reactNativeConfigFile[CODEGEN_CONFIG_KEY] == null ||
      reactNativeConfigFile[CODEGEN_CONFIG_KEY].libraries == null
    ) {
      throw '[Codegen] Error: Could not find codegen config for react-native.';
    }
    console.log('[Codegen] Found react-native');
    reactNativeConfigFile[CODEGEN_CONFIG_KEY].libraries.forEach(config => {
      const libraryConfig = {
        library: REACT_NATIVE_DEPENDENCY_NAME,
        config,
        libraryPath: RN_ROOT,
      };
      libraries.push(libraryConfig);
    });

    // Determine which of these are codegen-enabled libraries
    const confifDir = CODEGEN_CONFIG_FILE_DIR || path.join(RN_ROOT, '..');
    console.log(
      `\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in ${confifDir}`,
    );

    // Handle third-party libraries
    Object.keys(dependencies).forEach(dependency => {
      if (dependency === REACT_NATIVE_DEPENDENCY_NAME) {
        // react-native should already be added.
        return;
      }
      const codegenConfigFileDir = path.join(confifDir, dependency);
      const configFilePath = path.join(
        codegenConfigFileDir,
        CODEGEN_CONFIG_FILENAME,
      );
      if (fs.existsSync(configFilePath)) {
        const configFile = JSON.parse(fs.readFileSync(configFilePath));
        if (
          configFile[CODEGEN_CONFIG_KEY] != null &&
          configFile[CODEGEN_CONFIG_KEY].libraries != null
        ) {
          console.log(`[Codegen] Found ${dependency}`);
          configFile[CODEGEN_CONFIG_KEY].libraries.forEach(config => {
            const libraryConfig = {
              library: dependency,
              config,
              libraryPath: codegenConfigFileDir,
            };
            libraries.push(libraryConfig);
          });
        }
      }
    });

    console.log(
      '\n\n[Codegen] >>>>> Searching for codegen-enabled libraries in the app',
    );

    // Handle in-app libraries
    if (
      pkgJson[CODEGEN_CONFIG_KEY] != null &&
      pkgJson[CODEGEN_CONFIG_KEY].libraries != null
    ) {
      console.log(`[Codegen] Found ${pkgJson.name}`);
      pkgJson[CODEGEN_CONFIG_KEY].libraries.forEach(config => {
        const libraryConfig = {
          library: pkgJson.name,
          config,
          libraryPath: appRootDir,
        };
        libraries.push(libraryConfig);
      });
    }

    if (libraries.length === 0) {
      console.log('[Codegen] No codegen-enabled libraries found.');
      return;
    }

    // 4. Locate codegen package
    let codegenCliPath;
    if (fs.existsSync(CODEGEN_REPO_PATH)) {
      codegenCliPath = CODEGEN_REPO_PATH;

      if (!fs.existsSync(path.join(CODEGEN_REPO_PATH, 'lib'))) {
        console.log(
          '\n\n[Codegen] >>>>> Building react-native-codegen package',
        );
        execSync('yarn install', {
          cwd: codegenCliPath,
          stdio: 'inherit',
        });
        execSync('yarn build', {
          cwd: codegenCliPath,
          stdio: 'inherit',
        });
      }
    } else if (fs.existsSync(CODEGEN_NPM_PATH)) {
      codegenCliPath = CODEGEN_NPM_PATH;
    } else {
      throw "error: Could not determine react-native-codegen location. Try running 'yarn install' or 'npm install' in your project root.";
    }

    const schemaPaths = {};

    const iosOutputDir = path.join(
      outputPath ? outputPath : appRootDir,
      'build/generated/ios',
    );

    // 5. For each codegen-enabled library, generate the native code spec files
    libraries.forEach(library => {
      if (!CODEGEN_FABRIC_ENABLED && library.config.type === 'components') {
        console.log(
          `[Codegen] ${library.config.name} skipped because fabric is not enabled.`,
        );
        return;
      }
      const tmpDir = fs.mkdtempSync(
        path.join(os.tmpdir(), library.config.name),
      );
      const pathToSchema = path.join(tmpDir, 'schema.json');
      const pathToJavaScriptSources = path.join(
        library.libraryPath,
        library.config.jsSrcsDir,
      );
      const pathToOutputDirIOS = path.join(
        iosOutputDir,
        library.config.type === 'components'
          ? 'react/renderer/components'
          : './',
        library.config.name,
      );
      const pathToTempOutputDir = path.join(tmpDir, 'out');

      console.log(`\n\n[Codegen] >>>>> Processing ${library.config.name}`);
      // Generate one schema for the entire library...
      execSync(
        `node ${path.join(
          codegenCliPath,
          'lib',
          'cli',
          'combine',
          'combine-js-to-schema-cli.js',
        )} ${pathToSchema} ${pathToJavaScriptSources}`,
      );
      console.log(`[Codegen] Generated schema: ${pathToSchema}`);

      // ...then generate native code artifacts.
      const libraryTypeArg = library.config.type
        ? `--libraryType ${library.config.type}`
        : '';
      fs.mkdirSync(pathToTempOutputDir, {recursive: true});
      execSync(
        `node ${path.join(
          RN_ROOT,
          'scripts',
          'generate-specs-cli.js',
        )} --platform ios --schemaPath ${pathToSchema} --outputDir ${pathToTempOutputDir} --libraryName ${
          library.config.name
        } ${libraryTypeArg}`,
      );

      // Finally, copy artifacts to the final output directory.
      fs.mkdirSync(pathToOutputDirIOS, {recursive: true});
      execSync(`cp -R ${pathToTempOutputDir}/* ${pathToOutputDirIOS}`);
      console.log(`[Codegen] Generated artifacts: ${pathToOutputDirIOS}`);

      // Filter the react native core library out.
      // In the future, core library and third party library should
      // use the same way to generate/register the fabric components.
      if (!isReactNativeCoreLibrary(library.config.name)) {
        schemaPaths[library.config.name] = pathToSchema;
      }
    });

    if (CODEGEN_FABRIC_ENABLED) {
      console.log('\n\n>>>>> Creating component provider');
      // Save the list of spec paths to a temp file.
      const schemaListTmpPath = `${os.tmpdir()}/rn-tmp-schema-list.json`;
      const fd = fs.openSync(schemaListTmpPath, 'w');
      fs.writeSync(fd, JSON.stringify(schemaPaths));
      fs.closeSync(fd);
      console.log(`Generated schema list: ${schemaListTmpPath}`);

      // Generate FabricComponentProvider.
      // Only for iOS at this moment.
      execSync(
        `node ${path.join(
          RN_ROOT,
          'scripts',
          'generate-provider-cli.js',
        )} --platform ios --schemaListPath "${schemaListTmpPath}" --outputDir ${iosOutputDir}`,
      );
      console.log(`Generated provider in: ${iosOutputDir}`);
    }
  } catch (err) {
    console.error(err);
    process.exitCode = 1;
  }

  // 5. Done!
  console.log('\n\n[Codegen] Done.');
  return;
}