Files
flipper/desktop/scripts/build-utils.ts
Anton Nikolaev 773b0b7f67 Fix tests failing on Windows (#1052)
Summary:
Pull Request resolved: https://github.com/facebook/flipper/pull/1052

Fixed tests failing on Windows because jest auto-mocks works differently there

Reviewed By: passy

Differential Revision: D21237618

fbshipit-source-id: 31c7e92b7f8ae84c1e65fd37428204452b3f1b00
2020-04-27 07:18:12 -07:00

220 lines
5.8 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import Metro from 'metro';
import tmp from 'tmp';
import path from 'path';
import fs from 'fs-extra';
import {spawn} from 'promisify-child-process';
import {getWatchFolders} from 'flipper-pkg-lib';
import getAppWatchFolders from './get-app-watch-folders';
import getPlugins from '../static/getPlugins';
import {
appDir,
staticDir,
defaultPluginsIndexDir,
headlessDir,
babelTransformationsDir,
} from './paths';
import getPluginFolders from '../static/getPluginFolders';
const dev = process.env.NODE_ENV !== 'production';
export function die(err: Error) {
console.error(err.stack);
process.exit(1);
}
export async function generatePluginEntryPoints() {
console.log('⚙️ Generating plugin entry points...');
const plugins = await getPlugins();
if (await fs.pathExists(defaultPluginsIndexDir)) {
await fs.remove(defaultPluginsIndexDir);
}
await fs.mkdirp(defaultPluginsIndexDir);
await fs.writeJSON(path.join(defaultPluginsIndexDir, 'index.json'), plugins);
const pluginRequres = plugins
.map((x) => ` '${x.name}': require('${x.name}')`)
.join(',\n');
const generatedIndex = `
/* eslint-disable */
// THIS FILE IS AUTO-GENERATED by function "generatePluginEntryPoints" in "build-utils.ts".
export default {\n${pluginRequres}\n} as any
`;
await fs.ensureDir(path.join(appDir, 'src', 'defaultPlugins'));
await fs.writeFile(
path.join(appDir, 'src', 'defaultPlugins', 'index.tsx'),
generatedIndex,
);
console.log('✅ Generated plugin entry points.');
}
const minifierConfig = {
minifierPath: require.resolve('metro-minify-terser'),
minifierConfig: {
// see: https://www.npmjs.com/package/terser
keep_fnames: true,
module: true,
warnings: true,
},
};
async function compile(
buildFolder: string,
projectRoot: string,
watchFolders: string[],
entry: string,
) {
await Metro.runBuild(
{
reporter: {update: () => {}},
projectRoot,
watchFolders,
serializer: {},
transformer: {
babelTransformerPath: path.join(
babelTransformationsDir,
'transform-app',
),
...minifierConfig,
},
resolver: {
resolverMainFields: ['flipperBundlerEntry', 'module', 'main'],
blacklistRE: /\.native\.js$/,
sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json', 'mjs'],
},
},
{
dev,
minify: !dev,
resetCache: !dev,
sourceMap: true,
entry,
out: path.join(buildFolder, 'bundle.js'),
},
);
}
export async function compileHeadless(buildFolder: string) {
console.log(`⚙️ Compiling headless bundle...`);
const watchFolders = [
headlessDir,
...(await getWatchFolders(staticDir)),
...(await getAppWatchFolders()),
...(await getPluginFolders()),
]
.filter((value, index, self) => self.indexOf(value) === index)
.filter(fs.pathExistsSync);
try {
await compile(
buildFolder,
headlessDir,
watchFolders,
path.join(headlessDir, 'index.tsx'),
);
console.log('✅ Compiled headless bundle.');
} catch (err) {
die(err);
}
}
export async function compileRenderer(buildFolder: string) {
console.log(`⚙️ Compiling renderer bundle...`);
const watchFolders = [
...(await getAppWatchFolders()),
...(await getPluginFolders()),
];
try {
await compile(
buildFolder,
appDir,
watchFolders,
path.join(appDir, 'src', 'init.tsx'),
);
console.log('✅ Compiled renderer bundle.');
} catch (err) {
die(err);
}
}
export async function compileMain() {
const out = path.join(staticDir, 'main.bundle.js');
process.env.FLIPPER_ELECTRON_VERSION = require('electron/package.json').version;
console.log('⚙️ Compiling main bundle...');
try {
const config = Object.assign({}, await Metro.loadConfig(), {
reporter: {update: () => {}},
projectRoot: staticDir,
watchFolders: await getWatchFolders(staticDir),
transformer: {
babelTransformerPath: path.join(
babelTransformationsDir,
'transform-main',
),
...minifierConfig,
},
resolver: {
sourceExts: ['tsx', 'ts', 'js'],
resolverMainFields: ['flipperBundlerEntry', 'module', 'main'],
blacklistRE: /\.native\.js$/,
},
});
await Metro.runBuild(config, {
platform: 'web',
entry: path.join(staticDir, 'main.ts'),
out,
dev,
minify: !dev,
sourceMap: true,
resetCache: !dev,
});
console.log('✅ Compiled main bundle.');
} catch (err) {
die(err);
}
}
export function buildFolder(): Promise<string> {
// eslint-disable-next-line no-console
console.log('Creating build directory');
return new Promise<string>((resolve, reject) => {
tmp.dir({prefix: 'flipper-build-'}, (err, buildFolder) => {
if (err) {
reject(err);
} else {
resolve(buildFolder);
}
});
}).catch((e) => {
die(e);
return '';
});
}
export function getVersionNumber() {
let {version} = require('../package.json');
const buildNumber = process.argv.join(' ').match(/--version=(\d+)/);
if (buildNumber && buildNumber.length > 0) {
version = [...version.split('.').slice(0, 2), buildNumber[1]].join('.');
}
return version;
}
// Asynchronously determine current mercurial revision as string or `null` in case of any error.
export function genMercurialRevision(): Promise<string | null> {
return spawn('hg', ['log', '-r', '.', '-T', '{node}'], {encoding: 'utf8'})
.then(
(res) =>
(res &&
(typeof res.stdout === 'string'
? res.stdout
: res.stdout?.toString())) ||
null,
)
.catch(() => null);
}