@oxog/port-terminator
Version:
Cross-platform utility to terminate processes on ports with zero dependencies
183 lines • 9.36 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isLinux = exports.isMacOS = exports.isWindows = exports.getPlatform = exports.parsePortRange = exports.validatePorts = exports.validatePort = exports.Logger = exports.PortScanner = exports.ProcessKiller = exports.ProcessFinder = exports.PortTerminator = void 0;
exports.killPort = killPort;
exports.killPorts = killPorts;
exports.getProcessOnPort = getProcessOnPort;
exports.getProcessesOnPort = getProcessesOnPort;
exports.isPortAvailable = isPortAvailable;
exports.waitForPort = waitForPort;
const process_finder_1 = require("./core/process-finder");
const process_killer_1 = require("./core/process-killer");
const validators_1 = require("./utils/validators");
const errors_1 = require("./errors");
const logger_1 = require("./utils/logger");
class PortTerminator {
constructor(options = {}) {
this.processFinder = new process_finder_1.ProcessFinder();
this.processKiller = new process_killer_1.ProcessKiller();
this.options = {
method: options.method || 'both',
timeout: options.timeout || 30000,
force: options.force || false,
silent: options.silent || false,
gracefulTimeout: options.gracefulTimeout || 5000,
};
this.logger = new logger_1.Logger('info', this.options.silent);
}
async terminate(port) {
const ports = Array.isArray(port) ? port : [port];
const validatedPorts = (0, validators_1.validatePorts)(ports);
this.logger.info(`Terminating processes on port${ports.length > 1 ? 's' : ''}: ${validatedPorts.join(', ')}`);
const results = await this.terminateMultiple(validatedPorts);
return Array.from(results.values()).every((success) => success);
}
async terminateMultiple(ports) {
const validatedPorts = (0, validators_1.validatePorts)(ports);
const results = new Map();
const protocol = this.options.method;
await Promise.all(validatedPorts.map(async (port) => {
try {
this.logger.debug(`Finding processes on port ${port}`);
const processes = await this.processFinder.findByPort(port, protocol);
if (processes.length === 0) {
this.logger.warn(`No processes found on port ${port}`);
results.set(port, true);
return;
}
this.logger.info(`Found ${processes.length} process(es) on port ${port}`);
const killedProcesses = await this.processKiller.killProcessesByPort(port, this.options.force, this.options.gracefulTimeout, protocol);
const success = killedProcesses.length === processes.length;
results.set(port, success);
if (success) {
this.logger.info(`Successfully terminated ${killedProcesses.length} process(es) on port ${port}`);
}
else {
this.logger.error(`Failed to terminate some processes on port ${port}`);
}
}
catch (error) {
this.logger.error(`Error terminating processes on port ${port}: ${error instanceof Error ? error.message : 'Unknown error'}`);
results.set(port, false);
}
}));
return results;
}
async getProcesses(port) {
const validatedPort = (0, validators_1.validatePort)(port);
const protocol = this.options.method;
this.logger.debug(`Getting processes on port ${validatedPort}`);
return this.processFinder.findByPort(validatedPort, protocol);
}
async isPortAvailable(port) {
const validatedPort = (0, validators_1.validatePort)(port);
const protocol = this.options.method;
return this.processFinder.isPortAvailable(validatedPort, protocol);
}
async waitForPort(port, timeout) {
const validatedPort = (0, validators_1.validatePort)(port);
const timeoutMs = timeout ? (0, validators_1.validateTimeout)(timeout) : this.options.timeout;
const protocol = this.options.method;
this.logger.debug(`Waiting for port ${validatedPort} to become available (timeout: ${timeoutMs}ms)`);
const success = await this.processFinder.waitForPortToBeAvailable(validatedPort, timeoutMs, protocol);
if (!success) {
throw new errors_1.TimeoutError(`waitForPort(${validatedPort})`, timeoutMs);
}
return success;
}
async terminateWithDetails(ports) {
const validatedPorts = (0, validators_1.validatePorts)(ports);
const results = [];
const protocol = this.options.method;
for (const port of validatedPorts) {
try {
const processes = await this.processFinder.findByPort(port, protocol);
if (processes.length === 0) {
results.push({
port,
success: true,
processes: [],
});
continue;
}
const killedProcesses = await this.processKiller.killProcessesByPort(port, this.options.force, this.options.gracefulTimeout, protocol);
results.push({
port,
success: killedProcesses.length === processes.length,
processes: killedProcesses,
});
}
catch (error) {
results.push({
port,
success: false,
processes: [],
error: error instanceof Error ? error.message : 'Unknown error',
});
}
}
return results;
}
}
exports.PortTerminator = PortTerminator;
// Convenience functions
async function killPort(port, options = {}) {
const terminator = new PortTerminator(options);
return terminator.terminate(port);
}
async function killPorts(ports, options = {}) {
const terminator = new PortTerminator(options);
return terminator.terminateMultiple(ports);
}
async function getProcessOnPort(port, options = {}) {
const terminator = new PortTerminator(options);
const processes = await terminator.getProcesses(port);
return processes.length > 0 ? processes[0] : null;
}
async function getProcessesOnPort(port, options = {}) {
const terminator = new PortTerminator(options);
return terminator.getProcesses(port);
}
async function isPortAvailable(port, options = {}) {
const terminator = new PortTerminator(options);
return terminator.isPortAvailable(port);
}
async function waitForPort(port, timeout, options = {}) {
const terminator = new PortTerminator(options);
return terminator.waitForPort(port, timeout);
}
// Re-export types and errors
__exportStar(require("./types"), exports);
__exportStar(require("./errors"), exports);
var process_finder_2 = require("./core/process-finder");
Object.defineProperty(exports, "ProcessFinder", { enumerable: true, get: function () { return process_finder_2.ProcessFinder; } });
var process_killer_2 = require("./core/process-killer");
Object.defineProperty(exports, "ProcessKiller", { enumerable: true, get: function () { return process_killer_2.ProcessKiller; } });
var port_scanner_1 = require("./core/port-scanner");
Object.defineProperty(exports, "PortScanner", { enumerable: true, get: function () { return port_scanner_1.PortScanner; } });
var logger_2 = require("./utils/logger");
Object.defineProperty(exports, "Logger", { enumerable: true, get: function () { return logger_2.Logger; } });
var validators_2 = require("./utils/validators");
Object.defineProperty(exports, "validatePort", { enumerable: true, get: function () { return validators_2.validatePort; } });
Object.defineProperty(exports, "validatePorts", { enumerable: true, get: function () { return validators_2.validatePorts; } });
Object.defineProperty(exports, "parsePortRange", { enumerable: true, get: function () { return validators_2.parsePortRange; } });
var platform_1 = require("./utils/platform");
Object.defineProperty(exports, "getPlatform", { enumerable: true, get: function () { return platform_1.getPlatform; } });
Object.defineProperty(exports, "isWindows", { enumerable: true, get: function () { return platform_1.isWindows; } });
Object.defineProperty(exports, "isMacOS", { enumerable: true, get: function () { return platform_1.isMacOS; } });
Object.defineProperty(exports, "isLinux", { enumerable: true, get: function () { return platform_1.isLinux; } });
//# sourceMappingURL=index.js.map