Files
2026-02-21 10:33:18 +01:00

107 lines
4.1 KiB
JavaScript

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDesiredPort = exports.testPortAvailableOnMultipleHosts = void 0;
const net_1 = __importDefault(require("net"));
const locks_1 = require("./locks");
const isPortAvailableOnHost = ({ portToTry, host, }) => {
return new Promise((resolve) => {
let status = 'unavailable';
const socket = new net_1.default.Socket();
socket.on('connect', () => {
status = 'unavailable';
socket.destroy();
});
socket.setTimeout(3000);
socket.on('timeout', () => {
status = 'unavailable';
socket.destroy();
resolve(status);
});
socket.on('error', () => {
status = 'available';
});
socket.on('close', () => resolve(status));
socket.connect(portToTry, host);
});
};
const testPortAvailableOnMultipleHosts = async ({ hosts, port, }) => {
const results = await Promise.all(hosts.map((host) => {
return isPortAvailableOnHost({ portToTry: port, host });
}));
return results.every((r) => r === 'available') ? 'available' : 'unavailable';
};
exports.testPortAvailableOnMultipleHosts = testPortAvailableOnMultipleHosts;
const getPort = async ({ from, to, hostsToTest, onPortUnavailable, }) => {
const ports = makeRange(from, to);
for (const port of ports) {
if ((await (0, exports.testPortAvailableOnMultipleHosts)({
port,
hosts: hostsToTest,
})) === 'available') {
return { port, didUsePort: false };
}
if (onPortUnavailable) {
const action = await onPortUnavailable(port);
if (action === 'stop') {
return { port, didUsePort: true };
}
}
}
throw new Error('No available ports found');
};
const portLocks = (0, locks_1.createLock)({ timeout: 10000 });
const getDesiredPort = async ({ desiredPort, from, hostsToTry, to, onPortUnavailable, }) => {
await portLocks.waitForAllToBeDone();
const lockPortSelection = portLocks.lock();
const unlockPort = () => portLocks.unlock(lockPortSelection);
if (typeof desiredPort !== 'undefined' &&
(await (0, exports.testPortAvailableOnMultipleHosts)({
port: desiredPort,
hosts: hostsToTry,
})) === 'available') {
return { port: desiredPort, unlockPort, didUsePort: false };
}
if (typeof desiredPort !== 'undefined' && onPortUnavailable) {
const action = await onPortUnavailable(desiredPort);
if (action === 'stop') {
return { port: desiredPort, unlockPort, didUsePort: true };
}
}
const result = await getPort({
from,
to,
hostsToTest: hostsToTry,
onPortUnavailable,
});
if (result.didUsePort) {
return { port: result.port, unlockPort, didUsePort: true };
}
// If did specify a port but did not get that one, fail hard.
if (desiredPort && desiredPort !== result.port) {
unlockPort();
throw new Error(`You specified port ${desiredPort} to be used for the HTTP server, but it is not available. Choose a different port or remove the setting to let Remotion automatically select a free port.`);
}
return { port: result.port, unlockPort, didUsePort: false };
};
exports.getDesiredPort = getDesiredPort;
const makeRange = (from, to) => {
if (!Number.isInteger(from) || !Number.isInteger(to)) {
throw new TypeError('`from` and `to` must be integer numbers');
}
if (from < 1024 || from > 65535) {
throw new RangeError('`from` must be between 1024 and 65535');
}
if (to < 1024 || to > 65536) {
throw new RangeError('`to` must be between 1024 and 65536');
}
if (to < from) {
throw new RangeError('`to` must be greater than or equal to `from`');
}
return new Array(to - from + 1).fill(true).map((_, i) => {
return i + from;
});
};