/*** 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.*/'use strict';
const chalk = require('chalk');
const fs = require('fs');
const path = require('path');
const mkdirp = require('mkdirp');
const inlinedHostConfigs = require('../shared/inlinedHostConfigs');
const configTemplate = fs
.readFileSync(__dirname + '/config/flowconfig')
.toString();
// stores all forks discovered during config generationconst allForks = new Set();
// maps forked file to the base path containing it and it's forks (it's parent)const forkedFiles = new Map();
function findForks(file) {
const basePath = path.join(file, '..');
const forksPath = path.join(basePath, 'forks');
const forks = fs.readdirSync(path.join('packages', forksPath));
forks.forEach(f => allForks.add('forks/' + f));
forkedFiles.set(file, basePath);
return basePath;
}function addFork(forks, renderer, file) {
let basePath = forkedFiles.get(file);
if (!basePath) {
basePath = findForks(file);
}const baseFilename = file.slice(basePath.length + 1);
const parts = renderer.split('-');
while (parts.length) {
const candidate = `forks/${baseFilename}.${parts.join('-')}.js`;
if (allForks.has(candidate)) {
forks.set(candidate, `${baseFilename}$$`);
return;
}parts.pop();
}throw new Error(`Cannot find fork for ${file} for renderer ${renderer}`);
}function writeConfig(
renderer,rendererInfo,isServerSupported,isFlightSupported,) {const folder = __dirname + '/' + renderer;
mkdirp.sync(folder);
isFlightSupported =
isFlightSupported === true ||
(isServerSupported && isFlightSupported !== false);
const serverRenderer = isServerSupported ? renderer : 'custom';
const flightRenderer = isFlightSupported ? renderer : 'custom';
const ignoredPaths = [];
inlinedHostConfigs.forEach(otherRenderer => {
if (otherRenderer === rendererInfo) {
return;
}otherRenderer.paths.forEach(otherPath => {
if (rendererInfo.paths.indexOf(otherPath) !== -1) {
return;
}ignoredPaths.push(`.*/packages/${otherPath}`);
});});const forks = new Map();
addFork(forks, renderer, 'react-reconciler/src/ReactFiberConfig');
addFork(forks, serverRenderer, 'react-server/src/ReactServerStreamConfig');
addFork(forks, serverRenderer, 'react-server/src/ReactFizzConfig');
addFork(forks, flightRenderer, 'react-server/src/ReactFlightServerConfig');
addFork(forks, flightRenderer, 'react-client/src/ReactFlightClientConfig');
forks.set(
'react-devtools-shared/src/config/DevToolsFeatureFlags.default',
'react-devtools-feature-flags',
);allForks.forEach(fork => {
if (!forks.has(fork)) {
ignoredPaths.push(`.*/packages/.*/${fork}`);
}});let moduleMappings = '';
forks.forEach((source, target) => {
moduleMappings += `module.name_mapper='${source.slice(
source.lastIndexOf('/') + 1,
)}' -> '${target}'\n`;
});const config = configTemplate
.replace(
'%CI_MAX_WORKERS%\n',
// On CI, we seem to need to limit workers.
process.env.CI ? 'server.max_workers=4\n' : '',
).replace('%REACT_RENDERER_FLOW_OPTIONS%', moduleMappings.trim())
.replace('%REACT_RENDERER_FLOW_IGNORES%', ignoredPaths.join('\n'));
const disclaimer = `
# ---------------------------------------------------------------## NOTE: this file is generated. ## If you want to edit it, open ./scripts/flow/config/flowconfig. ## Then run Yarn for changes to take effect. ## ---------------------------------------------------------------#`.trim();
const configFile = folder + '/.flowconfig';
let oldConfig;
try {
oldConfig = fs.readFileSync(configFile).toString();
} catch (err) {
oldConfig = null;
}const newConfig = `
${disclaimer}
${config}
${disclaimer}
`.trim();
if (newConfig !== oldConfig) {
fs.writeFileSync(configFile, newConfig);
console.log(chalk.dim('Wrote a Flow config to ' + configFile));
}}// Write multiple configs in different folders// so that we can run those checks in parallel if we want.inlinedHostConfigs.forEach(rendererInfo => {
if (rendererInfo.isFlowTyped) {
writeConfig(
rendererInfo.shortName,
rendererInfo,
rendererInfo.isServerSupported,
rendererInfo.isFlightSupported,
);}});