Files
flipper/desktop/scripts/startWatchPlugins.tsx
Andrey Goncharov 3639feef61 Watch and rebuild plugins
Summary: Now, once we build all plugins before we start Flipper, we need to rebuild some of them when they change. Previously, it was handled by Metro when we included plugins int he bundle, but we no longer include them in the bundle.

Reviewed By: lblasa

Differential Revision: D39510213

fbshipit-source-id: a352d78946f844a25d9127ac09c26e43e6739ca9
2022-09-15 10:02:19 -07:00

90 lines
2.8 KiB
TypeScript

/**
* 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.
*
* @format
*/
import Watchman from './watchman';
import {getPluginSourceFolders, isPluginDir} from 'flipper-plugin-lib';
import path from 'path';
import chalk from 'chalk';
import {rebuildPlugin} from './build-utils';
export default async function startWatchPlugins(
onChanged?: () => void | Promise<void>,
) {
// eslint-disable-next-line no-console
console.log('🕵️‍ Watching for plugin changes');
let delayedCompilation: NodeJS.Timeout | undefined;
const kCompilationDelayMillis = 1000;
const onPluginChangeDetected = (root: string, files: string[]) => {
if (!delayedCompilation) {
delayedCompilation = setTimeout(async () => {
delayedCompilation = undefined;
// eslint-disable-next-line no-console
console.log(`🕵️‍ Detected plugin change`);
await Promise.all(
// https://facebook.github.io/watchman/docs/nodejs.html#subscribing-to-changes
files.map(async (file: string) => {
const filePathAbs = path.resolve(root, file);
let dirPath = path.dirname(filePathAbs);
while (
// Stop when we reach plugin root
!(await isPluginDir(dirPath))
) {
const relative = path.relative(root, dirPath);
// Stop when we reach desktop/plugins folder
if (!relative || relative.startsWith('..')) {
console.warn(
chalk.yellow('Failed to find a plugin root for path'),
filePathAbs,
);
return;
}
dirPath = path.resolve(dirPath, '..');
}
await rebuildPlugin(dirPath);
}),
);
onChanged?.();
}, kCompilationDelayMillis);
}
};
try {
await startWatchingPluginsUsingWatchman(onPluginChangeDetected);
} catch (err) {
console.error(
'Failed to start watching plugin files using Watchman, continue without hot reloading',
err,
);
}
}
async function startWatchingPluginsUsingWatchman(
onChange: (root: string, files: string[]) => void,
) {
const pluginFolders = await getPluginSourceFolders();
await Promise.all(
pluginFolders.map(async (pluginFolder) => {
const watchman = new Watchman(pluginFolder);
await watchman.initialize();
await watchman.startWatchFiles(
'.',
({files}) => onChange(pluginFolder, files),
{
excludes: [
'**/__tests__/**/*',
'**/node_modules/**/*',
'**/dist/*',
'**/.*',
],
},
);
}),
);
}