UNPKG

ecs-pf

Version:

CLI for port-forwarding to RDS via AWS ECS

93 lines (92 loc) 3.06 kB
import * as net from "node:net"; import { safeParse } from "valibot"; import { ConnectOptionsSchema, ExecOptionsSchema, failure, parsePort, success, } from "../types.js"; import { messages } from "./messages.js"; export function formatValidationErrors(issues) { return issues.map((issue) => issue.message).join(", "); } export function parseConnectOptions(rawOptions) { const result = safeParse(ConnectOptionsSchema, rawOptions); if (result.success) { return success(result.output); } else { return failure(result.issues); } } export function parseExecOptions(rawOptions) { const result = safeParse(ExecOptionsSchema, rawOptions); if (result.success) { return success(result.output); } else { return failure(result.issues); } } export function displayParsingErrors(issues) { messages.error("Invalid CLI options:"); for (const issue of issues) { messages.error(` • ${issue.path?.[0]?.key || "Unknown"}: ${issue.message}`); } } export async function isPortAvailableSafe(port) { return new Promise((resolve) => { const server = net.createServer(); server.listen(port, "localhost", () => { server.close(() => { resolve(true); }); }); server.on("error", () => { resolve(false); }); }); } export async function isPortAvailable(port) { const parseResult = parsePort(port.toString()); if (!parseResult.success) { return false; } return isPortAvailableSafe(parseResult.data); } export async function findAvailablePortSafe(startPort = 8888) { const parseResult = parsePort(startPort.toString()); if (!parseResult.success) { return failure(`Invalid starting port: ${startPort}`); } const [, maxPort] = getPortRange(); const findPort = async (currentPort) => { if (Number(currentPort) > maxPort) { return failure(`No available ports found starting from ${startPort}`); } if (await isPortAvailableSafe(currentPort)) { return success(currentPort); } const nextPortNumber = Number(currentPort) + 1; if (nextPortNumber > maxPort) { return failure(`No available ports found starting from ${startPort}`); } const nextPortResult = parsePort(nextPortNumber.toString()); if (!nextPortResult.success) { return failure(`Port range exceeded maximum value: ${maxPort}`); } return findPort(nextPortResult.data); }; return findPort(parseResult.data); } export async function findAvailablePort(startPort = 8888) { const result = await findAvailablePortSafe(startPort); if (result.success) { return Number(result.data); } throw new Error(result.error); } export function isPortRange(port) { return parsePort(port).success; } export function areAllPortsInRange(ports) { return ports.every(isPortRange); } export function getPortRange() { return [1, 65535]; }