/** * 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 net from 'net'; import fetch from 'node-fetch'; import {EnvironmentInfo} from 'flipper-common'; import semver from 'semver'; /** * Checks if a port is in use. * @param port The port to check. * @returns True if the port is in use. Otherwise, false. */ export async function checkPortInUse(port: number): Promise { interface HttpError extends Error { code?: string; } return new Promise((resolve, reject) => { const tester = net .createServer() .once('error', function (err: HttpError) { if (err.code != 'EADDRINUSE') return reject(err); resolve(true); }) .once('listening', function () { tester .once('close', function () { resolve(false); }) .close(); }) .listen(port); }); } /** * Checks if a running Flipper server is available on the given port. * @param port The port to check. * @returns If successful, it will return the version of the running * Flipper server. Otherwise, undefined. */ export async function checkServerRunning( port: number, ): Promise { try { const response = await fetch(`http://localhost:${port}/info`); if (response.status >= 200 && response.status < 300) { const environmentInfo: EnvironmentInfo = await response.json(); return environmentInfo.appVersion; } else { console.info( '[flipper-server] Running instance found, failed with HTTP status code: ', response.status, ); } } catch (e) { console.info( `[flipper-server] No running instance found, error found: ${e}`, ); } } /** * Attempts to shutdown an existing Flipper server instance. * @param port The port of the running Flipper server * @returns Returns true if the shutdown was successful. Otherwise, false. */ export async function shutdownRunningInstance(port: number): Promise { try { const response = await fetch(`http://localhost:${port}/shutdown`); if (response.status >= 200 && response.status < 300) { const json = await response.json(); console.info( `[flipper-server] Shutdown request acknowledge: ${json?.success}`, ); return json?.success; } else { console.warn( '[flipper-server] Shutdown request not handled, HTTP status code: ', response.status, ); } } catch (e) { console.warn('[flipper-server] Shutdown request failed with error: ', e); } return false; } /** * Compares two versions excluding build identifiers * (the bit after + in the semantic version string). * @return 0 if v1 == v2, 1 if v1 is greater, -1 if v2 is greater. */ export function compareServerVersion(v1: string, v2: string): number { return semver.compare(v1, v2); }