Expose a subset of flipper-plugin to flipper server

Summary: Flipper plugins rely on 'flipper-plugin' package being accessible from 'global'. Expose a subset (without UI stuff) of flipper-plugin to server add-ons

Reviewed By: mweststrate

Differential Revision: D34400811

fbshipit-source-id: e0079ddfa67e66c1b24ab02d7682917ddfc84aaf
This commit is contained in:
Andrey Goncharov
2022-02-28 03:50:34 -08:00
committed by Facebook GitHub Bot
parent 9449f61adb
commit aec05533d7
8 changed files with 80 additions and 10 deletions

View File

@@ -10,10 +10,20 @@
import {CallExpression} from '@babel/types'; import {CallExpression} from '@babel/types';
import {NodePath} from '@babel/traverse'; import {NodePath} from '@babel/traverse';
import {resolve} from 'path';
import {BUILTINS} from './electron-requires';
const pluginsRootDir = resolve(__dirname, '../../plugins');
function isPlugin(path: string) {
// We should bundle dependencies for plugins
return path.startsWith(pluginsRootDir);
}
module.exports = () => ({ module.exports = () => ({
name: 'change-require-to-electronRequire-in-server', name: 'change-require-to-electronRequire-in-server',
visitor: { visitor: {
CallExpression(path: NodePath<CallExpression>) { CallExpression(path: NodePath<CallExpression>, state: any) {
const node = path.node; const node = path.node;
if ( if (
node.type === 'CallExpression' && node.type === 'CallExpression' &&
@@ -25,13 +35,22 @@ module.exports = () => ({
const source = node.arguments[0].value; const source = node.arguments[0].value;
if ( if (
// relative files should be bundled // relative files should be bundled
!source.startsWith('./') && source.startsWith('./') ||
!source.startsWith('../') && source.startsWith('../') ||
// other packages from the workspace should be bundled up and transformed! // other packages from the workspace should be bundled up and transformed!
!source.startsWith('flipper-') source.startsWith('flipper-') ||
// Dependencies for bundled plugins (server add-ons) should be included
(isPlugin(state.file.opts.filename) &&
// yet we should exclude built-ins
!(
BUILTINS.includes(source) ||
BUILTINS.some((moduleName) => source.startsWith(`${moduleName}/`))
))
) { ) {
node.callee.name = 'electronRequire'; return;
} }
node.callee.name = 'electronRequire';
} }
if ( if (
node.callee.type === 'MemberExpression' && node.callee.type === 'MemberExpression' &&

View File

@@ -10,7 +10,7 @@
import {CallExpression, identifier} from '@babel/types'; import {CallExpression, identifier} from '@babel/types';
import {NodePath} from '@babel/traverse'; import {NodePath} from '@babel/traverse';
const BUILTINS = [ export const BUILTINS = [
'electron', 'electron',
'buffer', 'buffer',
'child_process', 'child_process',

View File

@@ -22,7 +22,11 @@ const presets = [
]; ];
// In DEV builds, we keep node_modules as is, as to not waste resources on trying to bundle them // In DEV builds, we keep node_modules as is, as to not waste resources on trying to bundle them
const plugins = [require('./electron-requires-server'), require('./fb-stubs')]; const plugins = [
require('./electron-requires-server'),
require('./plugin-flipper-requires'),
require('./fb-stubs'),
];
module.exports = { module.exports = {
transform, transform,

View File

@@ -26,7 +26,11 @@ const presets = [
// This is also the reason that all server deps are DEV deps // This is also the reason that all server deps are DEV deps
// electron-requires makes sure that *only* requires of built in node_modules are using "electronRequire" // electron-requires makes sure that *only* requires of built in node_modules are using "electronRequire"
// (which effectively makes them external, as electronRequire === require, but not rolled up with Metro) // (which effectively makes them external, as electronRequire === require, but not rolled up with Metro)
const plugins = [require('./electron-requires'), require('./fb-stubs')]; const plugins = [
require('./electron-requires'),
require('./plugin-flipper-requires'),
require('./fb-stubs'),
];
module.exports = { module.exports = {
transform, transform,

View File

@@ -0,0 +1,24 @@
/**
* 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
*/
// Exports for server add-ons
import * as path from './utils/path';
export {path};
export * from './utils/uuid';
export {safeStringify} from './utils/safeStringify';
export {
sleep,
timeout,
createControlledPromise,
ServerAddOn,
ServerAddOnPluginConnection,
FlipperServerForServerAddOn,
} from 'flipper-common';

View File

@@ -20,6 +20,7 @@
"flipper-common": "0.0.0", "flipper-common": "0.0.0",
"flipper-doctor": "0.0.0", "flipper-doctor": "0.0.0",
"flipper-plugin-lib": "0.0.0", "flipper-plugin-lib": "0.0.0",
"flipper-plugin": "0.0.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"fs-extra": "^10.0.0", "fs-extra": "^10.0.0",
"invariant": "^2.2.4", "invariant": "^2.2.4",

View File

@@ -12,9 +12,24 @@ import {
ServerAddOnStartDetails, ServerAddOnStartDetails,
} from 'flipper-common'; } from 'flipper-common';
import {assertNotNull} from '../comms/Utilities'; import {assertNotNull} from '../comms/Utilities';
// Special subset of flipper-plugin exports designed for server-side usage
// eslint-disable-next-line no-restricted-imports
import * as FlipperPluginSDK from 'flipper-plugin/src/server';
declare global {
// eslint-disable-next-line no-var
var FlipperPlugin: typeof FlipperPluginSDK;
}
global.FlipperPlugin = FlipperPluginSDK;
// defaultPlugins has to be required after we set FlipperPlugin.
// In server add-ons, developers might import utilities from 'flipper-plugin'
// In babel-transformer/plugin-flipper-requires flipper-plugin is replaces with global.FlipperPlugin.
// If defaultPlugins is required before we set global.FlipperPlugin,
// then flipper-plugin replaced with global.FlipperPlugin is evaluated in server add-ons before we set it - to undefined.
//
// The file is generated automatically by "prepareDefaultPlugins" in "scripts" // The file is generated automatically by "prepareDefaultPlugins" in "scripts"
// @ts-ignore const defaultPlugins = require('../defaultPlugins').default;
import defaultPlugins from '../defaultPlugins';
interface ServerAddOnModule { interface ServerAddOnModule {
default: ServerAddOnFn<any, any>; default: ServerAddOnFn<any, any>;

View File

@@ -18,6 +18,9 @@
{ {
"path": "../flipper-common" "path": "../flipper-common"
}, },
{
"path": "../flipper-plugin"
},
{ {
"path": "../plugin-lib" "path": "../plugin-lib"
} }