locadot
Version:
Secure your local development environment with HTTPS and custom domains like dev.localhost.
140 lines (139 loc) • 5.9 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const http_proxy_1 = __importDefault(require("http-proxy"));
const certs_1 = require("./utils/certs");
const https_1 = __importDefault(require("https"));
const http_1 = __importDefault(require("http"));
const locadot_file_1 = __importDefault(require("./lib/locadot-file"));
const child_process_1 = require("child_process");
const file_1 = __importDefault(require("./utils/file"));
const logger_1 = __importDefault(require("./utils/logger"));
const http_2 = __importDefault(require("./lib/http"));
class ProxyHandler {
async startCentralProxy() {
try {
let domainMap = await locadot_file_1.default.getRegistry();
const proxy = http_proxy_1.default.createProxyServer({});
const defaultCert = await (0, certs_1.createSSL)("localhost");
const watcher = await locadot_file_1.default.watchRegistry(async () => {
logger_1.default.info("🔄 Updated domain mapping");
domainMap = await locadot_file_1.default.getRegistry();
});
process.on("SIGINT", async (err) => {
logger_1.default.error("🛑 Proxy stopped. Proxy soft destroyed as process SIGINT", err);
await locadot_file_1.default.softDestroy(watcher);
});
process.on("SIGTERM", async (err) => {
logger_1.default.error("🛑 Proxy stopped. Proxy soft destroyed as process SIGTERM", err);
await locadot_file_1.default.softDestroy(watcher);
});
// process.on("exit", (code: string, signal: string) => {
// logger.error(`Process exited with error ${code} and signal ${signal}`);
// locadotFile.softDestroy(watcher);
// });
const httpsServer = https_1.default.createServer(defaultCert, (req, res) => {
http_2.default.requestHandler(req, res, proxy, domainMap);
});
const httpServer = http_1.default.createServer((req, res) => {
http_2.default.requestHandler(req, res, proxy, domainMap);
});
httpsServer.listen(443, () => {
logger_1.default.info("🛜 HTTPS proxy running on port 443");
});
httpsServer.on("upgrade", (req, res, head) => {
http_2.default.requestUpgrade(req, res, head, proxy, domainMap);
});
httpServer.listen(80, () => {
logger_1.default.info("🛜 HTTP proxy running on port 80");
});
httpServer.on("upgrade", (req, socket, head) => {
http_2.default.requestUpgrade(req, socket, head, proxy, domainMap);
});
}
catch (error) {
logger_1.default.error("Failed to start central proxy", error);
}
}
static async isProxyRunning() {
try {
const pid = Number(await locadot_file_1.default.getProcessId());
if (!pid || isNaN(pid)) {
return false;
}
process.kill(pid, 0);
return true;
}
catch (error) {
return false;
}
}
async startProxy() {
try {
if (await ProxyHandler.isProxyRunning()) {
logger_1.default.error("Proxy is already running");
return;
}
const command = locadot_file_1.default.getStartProxyFile();
const proxyProcess = (0, child_process_1.spawn)(command.command, command.path, {
detached: true,
stdio: ["ignore", "ignore", "pipe"],
});
const logStream = file_1.default.writeFileStream("LOGS", true);
proxyProcess.stderr.pipe(logStream);
proxyProcess.on("error", (err) => {
console.error("Failed to start child process:", err);
});
if (!proxyProcess.pid) {
logger_1.default.error("❌ Central proxy failed to start");
process.exit(1);
}
else {
locadot_file_1.default.createLockFile(proxyProcess.pid?.toString());
}
proxyProcess.unref();
logger_1.default.info("🚀 Central proxy started in background.");
}
catch (error) {
logger_1.default.error("Failed to start central proxy", error);
}
}
async addProxy(domain, port) {
if (!(await ProxyHandler.isProxyRunning())) {
await this.startProxy();
}
let registry = await locadot_file_1.default.getRegistry();
if (registry[domain]) {
console.error(`❌ ${domain} already mapped to port ${registry[domain]} use update instead.`);
process.exit(1);
}
await locadot_file_1.default.addRegistry(domain, port);
logger_1.default.info(`✅ ${domain} => http://localhost:${port}`);
}
async removeProxy(domain) {
if (!(await ProxyHandler.isProxyRunning())) {
await this.startProxy();
}
await locadot_file_1.default.deleteRegistry(domain);
}
async updateProxy(domain, port) {
if (!(await ProxyHandler.isProxyRunning())) {
await this.startProxy();
}
await locadot_file_1.default.updateRegistry(domain, port);
}
async stopProxy() {
await locadot_file_1.default.softDestroy();
}
async killProxy() {
await locadot_file_1.default.destroy();
}
async restartProxy() {
await locadot_file_1.default.softDestroy();
await this.startProxy();
}
}
const locadotProxy = new ProxyHandler();
exports.default = locadotProxy;