Start FlipperServerImpl as part of flipper-server
Summary: The previous started up a dev / web server for bundling in flipper-server, this diff starts the flipper server itself, so that we can connect the client to it (done in next diffs) Reviewed By: passy, aigoncharov Differential Revision: D32627390 fbshipit-source-id: b48de20f076e1e13842368d16a090708d533b69e
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0dfc73da93
commit
1308edc790
@@ -25,7 +25,6 @@ import {
|
||||
import type {RenderHost} from 'flipper-ui-core';
|
||||
import fs from 'fs';
|
||||
import {setupMenuBar} from './setupMenuBar';
|
||||
import os from 'os';
|
||||
import {FlipperServer, FlipperServerConfig} from 'flipper-common';
|
||||
|
||||
declare global {
|
||||
@@ -36,15 +35,6 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'development' && os.platform() === 'darwin') {
|
||||
// By default Node.JS has its internal certificate storage and doesn't use
|
||||
// the system store. Because of this, it's impossible to access ondemand / devserver
|
||||
// which are signed using some internal self-issued FB certificates. These certificates
|
||||
// are automatically installed to MacOS system store on FB machines, so here we're using
|
||||
// this "mac-ca" library to load them into Node.JS.
|
||||
global.electronRequire('mac-ca');
|
||||
}
|
||||
|
||||
export function initializeElectron(
|
||||
flipperServer: FlipperServer,
|
||||
flipperServerConfig: FlipperServerConfig,
|
||||
|
||||
@@ -160,7 +160,7 @@ export type FlipperServerCommands = {
|
||||
'keychain-unset': (service: string) => Promise<void>;
|
||||
};
|
||||
|
||||
type ENVIRONMENT_VARIABLES =
|
||||
export type ENVIRONMENT_VARIABLES =
|
||||
| 'NODE_ENV'
|
||||
| 'DEV_SERVER_URL'
|
||||
| 'CONFIG'
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
"dependencies": {
|
||||
"chalk": "^4.1.2",
|
||||
"express": "^4.15.2",
|
||||
"flipper-common": "0.0.0",
|
||||
"flipper-pkg-lib": "0.0.0",
|
||||
"flipper-server-core": "0.0.0",
|
||||
"fs-extra": "^9.0.0",
|
||||
"mac-ca": "^1.0.6",
|
||||
"p-filter": "^2.1.0",
|
||||
"socket.io": "^4.3.1"
|
||||
},
|
||||
|
||||
@@ -11,9 +11,35 @@
|
||||
// needs to be come independently runnable, prebundled, distributed, etc!
|
||||
// in future require conditionally
|
||||
import {startWebServerDev} from './startWebServerDev';
|
||||
import {startFlipperServer} from './startFlipperServer';
|
||||
import {startBaseServer} from './startBaseServer';
|
||||
import chalk from 'chalk';
|
||||
import path from 'path';
|
||||
|
||||
startWebServerDev().catch((e) => {
|
||||
console.error(chalk.red('Server error: '), e);
|
||||
process.exit(1);
|
||||
});
|
||||
const PORT = 52342;
|
||||
const rootDir = path.resolve(__dirname, '..', '..');
|
||||
const staticDir = path.join(rootDir, 'static');
|
||||
|
||||
async function start() {
|
||||
const {app, server, socket} = await startBaseServer({
|
||||
port: PORT,
|
||||
staticDir,
|
||||
entry: 'index.web.dev.html',
|
||||
});
|
||||
|
||||
return Promise.all([
|
||||
startFlipperServer(rootDir, staticDir),
|
||||
startWebServerDev(app, server, socket, rootDir),
|
||||
]);
|
||||
}
|
||||
|
||||
start()
|
||||
.then(() => {
|
||||
console.log(
|
||||
`Flipper DEV server started at http://localhost:${PORT}/index.web.dev.html`,
|
||||
);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(chalk.red('Server error: '), e);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
95
desktop/flipper-server/src/startBaseServer.tsx
Normal file
95
desktop/flipper-server/src/startBaseServer.tsx
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* 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 chalk from 'chalk';
|
||||
import express, {Express} from 'express';
|
||||
import http from 'http';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import socketio from 'socket.io';
|
||||
import {hostname} from 'os';
|
||||
|
||||
type Config = {
|
||||
port: number;
|
||||
staticDir: string;
|
||||
entry: string;
|
||||
};
|
||||
|
||||
export async function startBaseServer(config: Config): Promise<{
|
||||
app: Express;
|
||||
server: http.Server;
|
||||
socket: socketio.Server;
|
||||
}> {
|
||||
checkDevServer();
|
||||
const {app, server} = await startAssetServer(config);
|
||||
const socket = addWebsocket(server);
|
||||
return {
|
||||
app,
|
||||
server,
|
||||
socket,
|
||||
};
|
||||
}
|
||||
|
||||
function startAssetServer(
|
||||
config: Config,
|
||||
): Promise<{app: Express; server: http.Server}> {
|
||||
const app = express();
|
||||
|
||||
app.use((_req, res, next) => {
|
||||
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
||||
res.header('Expires', '-1');
|
||||
res.header('Pragma', 'no-cache');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/', (_req, res) => {
|
||||
fs.readFile(path.join(config.staticDir, config.entry), (_err, content) => {
|
||||
res.end(content);
|
||||
});
|
||||
});
|
||||
|
||||
app.use(express.static(config.staticDir));
|
||||
|
||||
const server = http.createServer(app);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
server.listen(config.port, 'localhost', () => resolve({app, server}));
|
||||
});
|
||||
}
|
||||
|
||||
function addWebsocket(server: http.Server) {
|
||||
const io = new socketio.Server(server); // 3.1.0 socket.io doesn't have type definitions
|
||||
|
||||
io.on('connection', (client) => {
|
||||
console.log(chalk.green(`Client connected ${client.id}`));
|
||||
});
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
function looksLikeDevServer(): boolean {
|
||||
const hn = hostname();
|
||||
if (/^devvm.*\.facebook\.com$/.test(hn)) {
|
||||
return true;
|
||||
}
|
||||
if (hn.endsWith('.od.fbinfra.net')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkDevServer() {
|
||||
if (looksLikeDevServer()) {
|
||||
console.log(
|
||||
chalk.red(
|
||||
`✖ It looks like you're trying to start Flipper on your OnDemand or DevServer, which is not supported. Please run this in a local checkout on your laptop or desktop instead.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
120
desktop/flipper-server/src/startFlipperServer.tsx
Normal file
120
desktop/flipper-server/src/startFlipperServer.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 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 os from 'os';
|
||||
import {
|
||||
FlipperServerImpl,
|
||||
getGatekeepers,
|
||||
loadLauncherSettings,
|
||||
loadProcessConfig,
|
||||
loadSettings,
|
||||
} from 'flipper-server-core';
|
||||
import {
|
||||
ENVIRONMENT_VARIABLES,
|
||||
isTest,
|
||||
Logger,
|
||||
setLoggerInstance,
|
||||
} from 'flipper-common';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export async function startFlipperServer(rootDir: string, staticDir: string) {
|
||||
if (os.platform() === 'darwin') {
|
||||
// By default Node.JS has its internal certificate storage and doesn't use
|
||||
// the system store. Because of this, it's impossible to access ondemand / devserver
|
||||
// which are signed using some internal self-issued FB certificates. These certificates
|
||||
// are automatically installed to MacOS system store on FB machines, so here we're using
|
||||
// this "mac-ca" library to load them into Node.JS.
|
||||
require('mac-ca');
|
||||
}
|
||||
|
||||
const execPath = process.execPath;
|
||||
const appPath = rootDir;
|
||||
const isProduction =
|
||||
process.env.NODE_ENV !== 'development' && process.env.NODE_ENV !== 'test';
|
||||
const env = process.env;
|
||||
let desktopPath = path.resolve(os.homedir(), 'Desktop');
|
||||
|
||||
// eslint-disable-next-line node/no-sync
|
||||
if (!fs.existsSync(desktopPath)) {
|
||||
console.warn('Failed to find desktop path, falling back to homedir');
|
||||
desktopPath = os.homedir();
|
||||
}
|
||||
|
||||
const logger = createLogger();
|
||||
setLoggerInstance(logger);
|
||||
|
||||
let keytar: any = undefined;
|
||||
try {
|
||||
if (!isTest()) {
|
||||
keytar = require(path.join(
|
||||
staticDir,
|
||||
'native-modules',
|
||||
`keytar-${process.platform}.node`,
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load keytar:', e);
|
||||
}
|
||||
|
||||
const envVars: Partial<Record<ENVIRONMENT_VARIABLES, string | undefined>> =
|
||||
Object.fromEntries(
|
||||
([] as ENVIRONMENT_VARIABLES[]).map((v) => [v, process.env[v]] as const),
|
||||
);
|
||||
const flipperServer = new FlipperServerImpl(
|
||||
{
|
||||
env: envVars,
|
||||
gatekeepers: getGatekeepers(),
|
||||
isProduction,
|
||||
paths: {
|
||||
appPath,
|
||||
homePath: os.homedir(),
|
||||
execPath,
|
||||
staticPath: staticDir,
|
||||
tempPath: os.tmpdir(),
|
||||
desktopPath: desktopPath,
|
||||
},
|
||||
launcherSettings: await loadLauncherSettings(),
|
||||
processConfig: loadProcessConfig(env),
|
||||
settings: await loadSettings(),
|
||||
validWebSocketOrigins: ['localhost:', 'http://localhost:'],
|
||||
},
|
||||
logger,
|
||||
keytar,
|
||||
);
|
||||
|
||||
await flipperServer.connect();
|
||||
}
|
||||
|
||||
function createLogger(): Logger {
|
||||
return {
|
||||
track(..._args: [any, any, any?, any?]) {
|
||||
// TODO: only if verbose console.debug(...args);
|
||||
// console.warn('(skipper track)', args);
|
||||
},
|
||||
trackTimeSince(..._args: [any, any, any?]) {
|
||||
// TODO: only if verbose console.debug(...args);
|
||||
// console.warn('(skipped trackTimeSince)', args);
|
||||
},
|
||||
debug(..._args: any[]) {
|
||||
// TODO: only if verbose console.debug(...args);
|
||||
},
|
||||
error(...args: any[]) {
|
||||
console.error(...args);
|
||||
console.warn('(skipped error reporting)');
|
||||
},
|
||||
warn(...args: any[]) {
|
||||
console.warn(...args);
|
||||
console.warn('(skipped error reporting)');
|
||||
},
|
||||
info(...args: any[]) {
|
||||
console.info(...args);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -7,9 +7,8 @@
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {hostname} from 'os';
|
||||
import chalk from 'chalk';
|
||||
import express, {Express} from 'express';
|
||||
import {Express} from 'express';
|
||||
import http from 'http';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
@@ -18,15 +17,6 @@ import {getWatchFolders} from 'flipper-pkg-lib';
|
||||
import Metro from 'metro';
|
||||
import pFilter from 'p-filter';
|
||||
|
||||
const PORT = 52342;
|
||||
const rootDir = path.resolve(__dirname, '..', '..');
|
||||
const staticDir = path.join(rootDir, 'static');
|
||||
const babelTransformationsDir = path.resolve(
|
||||
rootDir,
|
||||
'babel-transformer',
|
||||
'src',
|
||||
);
|
||||
|
||||
const uiSourceDirs = [
|
||||
'flipper-ui-browser',
|
||||
'flipper-ui-core',
|
||||
@@ -35,79 +25,22 @@ const uiSourceDirs = [
|
||||
];
|
||||
|
||||
// This file is heavily inspired by scripts/start-dev-server.ts!
|
||||
export async function startWebServerDev() {
|
||||
checkDevServer();
|
||||
export async function startWebServerDev(
|
||||
app: Express,
|
||||
server: http.Server,
|
||||
socket: socketio.Server,
|
||||
rootDir: string,
|
||||
) {
|
||||
// await prepareDefaultPlugins(
|
||||
// process.env.FLIPPER_RELEASE_CHANNEL === 'insiders',
|
||||
// );
|
||||
// await ensurePluginFoldersWatchable();
|
||||
const {app, server} = await startAssetServer(PORT);
|
||||
const socket = await addWebsocket(server);
|
||||
await startMetroServer(app, server, socket);
|
||||
await startMetroServer(app, server, socket, rootDir);
|
||||
// await compileMain();
|
||||
// if (dotenv && dotenv.parsed) {
|
||||
// console.log('✅ Loaded env vars from .env file: ', dotenv.parsed);
|
||||
// }
|
||||
// shutdownElectron = launchElectron(port);
|
||||
console.log(
|
||||
`Flipper DEV server started at http://localhost:${PORT}/index.web.dev.html`,
|
||||
);
|
||||
}
|
||||
|
||||
function looksLikeDevServer(): boolean {
|
||||
const hn = hostname();
|
||||
if (/^devvm.*\.facebook\.com$/.test(hn)) {
|
||||
return true;
|
||||
}
|
||||
if (hn.endsWith('.od.fbinfra.net')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkDevServer() {
|
||||
if (looksLikeDevServer()) {
|
||||
console.log(
|
||||
chalk.red(
|
||||
`✖ It looks like you're trying to start Flipper on your OnDemand or DevServer, which is not supported. Please run this in a local checkout on your laptop or desktop instead.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function startAssetServer(
|
||||
port: number,
|
||||
): Promise<{app: Express; server: http.Server}> {
|
||||
const app = express();
|
||||
|
||||
app.use((_req, res, next) => {
|
||||
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
|
||||
res.header('Expires', '-1');
|
||||
res.header('Pragma', 'no-cache');
|
||||
next();
|
||||
});
|
||||
|
||||
app.get('/', (_req, res) => {
|
||||
fs.readFile(path.join(staticDir, 'index.web.dev.html'), (_err, content) => {
|
||||
res.end(content);
|
||||
});
|
||||
});
|
||||
|
||||
app.use(express.static(staticDir));
|
||||
|
||||
const server = http.createServer(app);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
server.listen(port, 'localhost', () => resolve({app, server}));
|
||||
});
|
||||
}
|
||||
|
||||
async function addWebsocket(server: http.Server) {
|
||||
const io = new socketio.Server(server); // 3.1.0 socket.io doesn't have type definitions
|
||||
|
||||
io.on('connection', (client) => {
|
||||
console.log(chalk.green(`Client connected ${client.id}`));
|
||||
});
|
||||
|
||||
// Refresh the app on changes.
|
||||
// When Fast Refresh enabled, reloads are performed by HMRClient, so don't need to watch manually here.
|
||||
@@ -115,14 +48,20 @@ async function addWebsocket(server: http.Server) {
|
||||
// await startWatchChanges(io);
|
||||
// }
|
||||
|
||||
return io;
|
||||
console.log('DEV webserver started.');
|
||||
}
|
||||
|
||||
async function startMetroServer(
|
||||
app: Express,
|
||||
server: http.Server,
|
||||
socket: socketio.Server,
|
||||
rootDir: string,
|
||||
) {
|
||||
const babelTransformationsDir = path.resolve(
|
||||
rootDir,
|
||||
'babel-transformer',
|
||||
'src',
|
||||
);
|
||||
const watchFolders = await dedupeFolders(
|
||||
(
|
||||
await Promise.all(
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
"rootDir": "src"
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../flipper-common"
|
||||
},
|
||||
{
|
||||
"path": "../flipper-server-core"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user