main
js 152 lines 4.39 KB
Raw
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
8 'use strict';
9
10 const chalk = require('chalk');
11 const fs = require('fs');
12 const path = require('path');
13 const mkdirp = require('mkdirp');
14 const inlinedHostConfigs = require('../shared/inlinedHostConfigs');
15 const flowVersion = require('../../package.json').devDependencies['flow-bin'];
16
17 const configTemplate = fs
18 .readFileSync(__dirname + '/config/flowconfig')
19 .toString();
20
21 // stores all forks discovered during config generation
22 const allForks = new Set();
23 // maps forked file to the base path containing it and it's forks (it's parent)
24 const forkedFiles = new Map();
25
26 function findForks(file) {
27 const basePath = path.join(file, '..');
28 const forksPath = path.join(basePath, 'forks');
29 const forks = fs.readdirSync(path.join('packages', forksPath));
30 forks.forEach(f => allForks.add('forks/' + f));
31 forkedFiles.set(file, basePath);
32 return basePath;
33 }
34
35 function addFork(forks, renderer, file) {
36 let basePath = forkedFiles.get(file);
37 if (!basePath) {
38 basePath = findForks(file);
39 }
40
41 const baseFilename = file.slice(basePath.length + 1);
42
43 const parts = renderer.split('-');
44 while (parts.length) {
45 const candidate = `forks/${baseFilename}.${parts.join('-')}.js`;
46 if (allForks.has(candidate)) {
47 forks.set(candidate, `${baseFilename}$$`);
48 return;
49 }
50 parts.pop();
51 }
52 throw new Error(`Cannot find fork for ${file} for renderer ${renderer}`);
53 }
54
55 function writeConfig(
56 renderer,
57 rendererInfo,
58 isServerSupported,
59 isFlightSupported,
60 ) {
61 const folder = __dirname + '/' + renderer;
62 mkdirp.sync(folder);
63
64 isFlightSupported =
65 isFlightSupported === true ||
66 (isServerSupported && isFlightSupported !== false);
67
68 const serverRenderer = isServerSupported ? renderer : 'custom';
69 const flightRenderer = isFlightSupported ? renderer : 'custom';
70
71 const ignoredPaths = [];
72
73 inlinedHostConfigs.forEach(otherRenderer => {
74 if (otherRenderer === rendererInfo) {
75 return;
76 }
77 otherRenderer.paths.forEach(otherPath => {
78 if (rendererInfo.paths.indexOf(otherPath) !== -1) {
79 return;
80 }
81 ignoredPaths.push(`.*/packages/${otherPath}`);
82 });
83 });
84
85 const forks = new Map();
86 addFork(forks, renderer, 'react-reconciler/src/ReactFiberConfig');
87 addFork(forks, serverRenderer, 'react-server/src/ReactServerStreamConfig');
88 addFork(forks, serverRenderer, 'react-server/src/ReactFizzConfig');
89 addFork(forks, flightRenderer, 'react-server/src/ReactFlightServerConfig');
90 addFork(forks, flightRenderer, 'react-client/src/ReactFlightClientConfig');
91 forks.set(
92 'react-devtools-shared/src/config/DevToolsFeatureFlags.default',
93 'react-devtools-feature-flags',
94 );
95
96 allForks.forEach(fork => {
97 if (!forks.has(fork)) {
98 ignoredPaths.push(`.*/packages/.*/${fork}`);
99 }
100 });
101
102 let moduleMappings = '';
103 forks.forEach((source, target) => {
104 moduleMappings += `module.name_mapper='${source.slice(
105 source.lastIndexOf('/') + 1,
106 )}' -> '${target}'\n`;
107 });
108
109 const config = configTemplate
110 .replace('%REACT_RENDERER_FLOW_OPTIONS%', moduleMappings.trim())
111 .replace('%REACT_RENDERER_FLOW_IGNORES%', ignoredPaths.join('\n'))
112 .replace('%FLOW_VERSION%', flowVersion);
113
114 const disclaimer = `
115 # ---------------------------------------------------------------#
116 # NOTE: this file is generated. #
117 # If you want to edit it, open ./scripts/flow/config/flowconfig. #
118 # Then run Yarn for changes to take effect. #
119 # ---------------------------------------------------------------#
120 `.trim();
121
122 const configFile = folder + '/.flowconfig';
123 let oldConfig;
124 try {
125 oldConfig = fs.readFileSync(configFile).toString();
126 } catch (err) {
127 oldConfig = null;
128 }
129 const newConfig = `
130 ${disclaimer}
131 ${config}
132 ${disclaimer}
133 `.trim();
134
135 if (newConfig !== oldConfig) {
136 fs.writeFileSync(configFile, newConfig);
137 console.log(chalk.dim('Wrote a Flow config to ' + configFile));
138 }
139 }
140
141 // Write multiple configs in different folders
142 // so that we can run those checks in parallel if we want.
143 inlinedHostConfigs.forEach(rendererInfo => {
144 if (rendererInfo.isFlowTyped) {
145 writeConfig(
146 rendererInfo.shortName,
147 rendererInfo,
148 rendererInfo.isServerSupported,
149 rendererInfo.isFlightSupported,
150 );
151 }
152 });