diff --git a/desktop/babel-transformer/src/electron-requires-server.tsx b/desktop/babel-transformer/src/electron-requires-server.tsx index f0e83eb0e..25e312408 100644 --- a/desktop/babel-transformer/src/electron-requires-server.tsx +++ b/desktop/babel-transformer/src/electron-requires-server.tsx @@ -10,10 +10,20 @@ import {CallExpression} from '@babel/types'; 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 = () => ({ name: 'change-require-to-electronRequire-in-server', visitor: { - CallExpression(path: NodePath) { + CallExpression(path: NodePath, state: any) { const node = path.node; if ( node.type === 'CallExpression' && @@ -25,13 +35,22 @@ module.exports = () => ({ const source = node.arguments[0].value; if ( // relative files should be bundled - !source.startsWith('./') && - !source.startsWith('../') && + source.startsWith('./') || + source.startsWith('../') || // 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 ( node.callee.type === 'MemberExpression' && diff --git a/desktop/babel-transformer/src/electron-requires.tsx b/desktop/babel-transformer/src/electron-requires.tsx index 77e6da457..3bec31215 100644 --- a/desktop/babel-transformer/src/electron-requires.tsx +++ b/desktop/babel-transformer/src/electron-requires.tsx @@ -10,7 +10,7 @@ import {CallExpression, identifier} from '@babel/types'; import {NodePath} from '@babel/traverse'; -const BUILTINS = [ +export const BUILTINS = [ 'electron', 'buffer', 'child_process', diff --git a/desktop/babel-transformer/src/transform-server-dev.tsx b/desktop/babel-transformer/src/transform-server-dev.tsx index 4599b9183..505238e3c 100644 --- a/desktop/babel-transformer/src/transform-server-dev.tsx +++ b/desktop/babel-transformer/src/transform-server-dev.tsx @@ -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 -const plugins = [require('./electron-requires-server'), require('./fb-stubs')]; +const plugins = [ + require('./electron-requires-server'), + require('./plugin-flipper-requires'), + require('./fb-stubs'), +]; module.exports = { transform, diff --git a/desktop/babel-transformer/src/transform-server-prod.tsx b/desktop/babel-transformer/src/transform-server-prod.tsx index 4095df0b6..c84d8fe3c 100644 --- a/desktop/babel-transformer/src/transform-server-prod.tsx +++ b/desktop/babel-transformer/src/transform-server-prod.tsx @@ -26,7 +26,11 @@ const presets = [ // 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" // (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 = { transform, diff --git a/desktop/flipper-plugin/src/server.tsx b/desktop/flipper-plugin/src/server.tsx new file mode 100644 index 000000000..3b3da44c1 --- /dev/null +++ b/desktop/flipper-plugin/src/server.tsx @@ -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'; diff --git a/desktop/flipper-server-core/package.json b/desktop/flipper-server-core/package.json index 1f378f75c..a4e149a8d 100644 --- a/desktop/flipper-server-core/package.json +++ b/desktop/flipper-server-core/package.json @@ -20,6 +20,7 @@ "flipper-common": "0.0.0", "flipper-doctor": "0.0.0", "flipper-plugin-lib": "0.0.0", + "flipper-plugin": "0.0.0", "form-data": "^4.0.0", "fs-extra": "^10.0.0", "invariant": "^2.2.4", diff --git a/desktop/flipper-server-core/src/plugins/loadServerAddOn.tsx b/desktop/flipper-server-core/src/plugins/loadServerAddOn.tsx index 2691dce45..d3fe04c63 100644 --- a/desktop/flipper-server-core/src/plugins/loadServerAddOn.tsx +++ b/desktop/flipper-server-core/src/plugins/loadServerAddOn.tsx @@ -12,9 +12,24 @@ import { ServerAddOnStartDetails, } from 'flipper-common'; 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" -// @ts-ignore -import defaultPlugins from '../defaultPlugins'; +const defaultPlugins = require('../defaultPlugins').default; interface ServerAddOnModule { default: ServerAddOnFn; diff --git a/desktop/flipper-server-core/tsconfig.json b/desktop/flipper-server-core/tsconfig.json index a78eb8413..9d2a11e6b 100644 --- a/desktop/flipper-server-core/tsconfig.json +++ b/desktop/flipper-server-core/tsconfig.json @@ -18,6 +18,9 @@ { "path": "../flipper-common" }, + { + "path": "../flipper-plugin" + }, { "path": "../plugin-lib" }