ecs-pf
Version:
CLI for port-forwarding to RDS via AWS ECS
93 lines (92 loc) • 3.06 kB
JavaScript
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];
}