@stacksjs/rpx 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +62 -103
- package/dist/hosts.d.ts +2 -1
- package/dist/https.d.ts +0 -4
- package/dist/index.js +309 -349
- package/dist/utils.d.ts +6 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20467,7 +20467,7 @@ var quotes = collect([
|
|
|
20467
20467
|
]);
|
|
20468
20468
|
var export_prompts = import_prompts.default;
|
|
20469
20469
|
// package.json
|
|
20470
|
-
var version = "0.5.
|
|
20470
|
+
var version = "0.5.1";
|
|
20471
20471
|
|
|
20472
20472
|
// src/config.ts
|
|
20473
20473
|
import { homedir } from "os";
|
|
@@ -20541,14 +20541,179 @@ var config4 = await loadConfig({
|
|
|
20541
20541
|
});
|
|
20542
20542
|
|
|
20543
20543
|
// src/hosts.ts
|
|
20544
|
-
import {
|
|
20545
|
-
import
|
|
20546
|
-
import
|
|
20547
|
-
import
|
|
20544
|
+
import { exec } from "child_process";
|
|
20545
|
+
import fs from "fs";
|
|
20546
|
+
import os2 from "os";
|
|
20547
|
+
import path from "path";
|
|
20548
20548
|
import process3 from "process";
|
|
20549
|
+
import { promisify } from "util";
|
|
20550
|
+
|
|
20551
|
+
// src/utils.ts
|
|
20552
|
+
function debugLog(category, message, verbose) {
|
|
20553
|
+
if (verbose) {
|
|
20554
|
+
console.debug(`[rpx:${category}] ${message}`);
|
|
20555
|
+
}
|
|
20556
|
+
}
|
|
20557
|
+
function extractHostname(options2) {
|
|
20558
|
+
if (isMultiProxyOptions(options2)) {
|
|
20559
|
+
return options2.proxies.map((proxy) => {
|
|
20560
|
+
const domain = proxy.to || "stacks.localhost";
|
|
20561
|
+
return domain.startsWith("http") ? new URL(domain).hostname : domain;
|
|
20562
|
+
});
|
|
20563
|
+
}
|
|
20564
|
+
if (isSingleProxyOptions(options2)) {
|
|
20565
|
+
const domain = options2.to || "stacks.localhost";
|
|
20566
|
+
return [domain.startsWith("http") ? new URL(domain).hostname : domain];
|
|
20567
|
+
}
|
|
20568
|
+
return ["stacks.localhost"];
|
|
20569
|
+
}
|
|
20570
|
+
function isValidRootCA(value) {
|
|
20571
|
+
return typeof value === "object" && value !== null && "certificate" in value && "privateKey" in value && typeof value.certificate === "string" && typeof value.privateKey === "string";
|
|
20572
|
+
}
|
|
20573
|
+
function getPrimaryDomain(options2) {
|
|
20574
|
+
if (!options2)
|
|
20575
|
+
return "stacks.localhost";
|
|
20576
|
+
if (isMultiProxyOptions(options2) && options2.proxies.length > 0)
|
|
20577
|
+
return options2.proxies[0].to || "stacks.localhost";
|
|
20578
|
+
if (isSingleProxyOptions(options2))
|
|
20579
|
+
return options2.to || "stacks.localhost";
|
|
20580
|
+
return "stacks.localhost";
|
|
20581
|
+
}
|
|
20582
|
+
function isMultiProxyConfig(options2) {
|
|
20583
|
+
return "proxies" in options2 && Array.isArray(options2.proxies);
|
|
20584
|
+
}
|
|
20585
|
+
function isMultiProxyOptions(options2) {
|
|
20586
|
+
return "proxies" in options2 && Array.isArray(options2.proxies);
|
|
20587
|
+
}
|
|
20588
|
+
function isSingleProxyOptions(options2) {
|
|
20589
|
+
return "to" in options2 && typeof options2.to === "string";
|
|
20590
|
+
}
|
|
20591
|
+
|
|
20592
|
+
// src/hosts.ts
|
|
20593
|
+
var execAsync = promisify(exec);
|
|
20594
|
+
var hostsFilePath = process3.platform === "win32" ? path.join(process3.env.windir || "C:\\Windows", "System32", "drivers", "etc", "hosts") : "/etc/hosts";
|
|
20595
|
+
async function execSudo(command) {
|
|
20596
|
+
if (process3.platform === "win32")
|
|
20597
|
+
throw new Error("Administrator privileges required on Windows");
|
|
20598
|
+
try {
|
|
20599
|
+
await execAsync(`sudo ${command}`);
|
|
20600
|
+
} catch (error) {
|
|
20601
|
+
throw new Error(`Failed to execute sudo command: ${error.message}`);
|
|
20602
|
+
}
|
|
20603
|
+
}
|
|
20604
|
+
async function addHosts(hosts, verbose) {
|
|
20605
|
+
debugLog("hosts", `Adding hosts: ${hosts.join(", ")}`, verbose);
|
|
20606
|
+
debugLog("hosts", `Using hosts file at: ${hostsFilePath}`, verbose);
|
|
20607
|
+
try {
|
|
20608
|
+
const existingContent = await fs.promises.readFile(hostsFilePath, "utf-8");
|
|
20609
|
+
const newEntries = hosts.filter((host) => {
|
|
20610
|
+
const ipv4Entry = `127.0.0.1 ${host}`;
|
|
20611
|
+
const ipv6Entry = `::1 ${host}`;
|
|
20612
|
+
return !existingContent.includes(ipv4Entry) && !existingContent.includes(ipv6Entry);
|
|
20613
|
+
});
|
|
20614
|
+
if (newEntries.length === 0) {
|
|
20615
|
+
debugLog("hosts", "All hosts already exist in hosts file", verbose);
|
|
20616
|
+
log.info("All hosts are already in the hosts file");
|
|
20617
|
+
return;
|
|
20618
|
+
}
|
|
20619
|
+
const hostEntries = newEntries.map((host) => `
|
|
20620
|
+
# Added by rpx
|
|
20621
|
+
127.0.0.1 ${host}
|
|
20622
|
+
::1 ${host}`).join(`
|
|
20623
|
+
`);
|
|
20624
|
+
const tmpFile = path.join(os2.tmpdir(), "hosts.tmp");
|
|
20625
|
+
await fs.promises.writeFile(tmpFile, existingContent + hostEntries, "utf8");
|
|
20626
|
+
try {
|
|
20627
|
+
await execSudo(`cp "${tmpFile}" "${hostsFilePath}"`);
|
|
20628
|
+
log.success(`Added new hosts: ${newEntries.join(", ")}`);
|
|
20629
|
+
} catch (error) {
|
|
20630
|
+
log.error("Failed to modify hosts file automatically");
|
|
20631
|
+
log.warn("Please add these entries to your hosts file manually:");
|
|
20632
|
+
hostEntries.split(`
|
|
20633
|
+
`).forEach((entry) => log.warn(entry));
|
|
20634
|
+
if (process3.platform === "win32") {
|
|
20635
|
+
log.warn(`
|
|
20636
|
+
On Windows:`);
|
|
20637
|
+
log.warn("1. Run notepad as administrator");
|
|
20638
|
+
log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
|
|
20639
|
+
} else {
|
|
20640
|
+
log.warn(`
|
|
20641
|
+
On Unix systems:`);
|
|
20642
|
+
log.warn(`sudo nano ${hostsFilePath}`);
|
|
20643
|
+
}
|
|
20644
|
+
throw new Error("Failed to modify hosts file: manual intervention required");
|
|
20645
|
+
} finally {
|
|
20646
|
+
fs.unlinkSync(tmpFile);
|
|
20647
|
+
}
|
|
20648
|
+
} catch (err2) {
|
|
20649
|
+
const error = err2;
|
|
20650
|
+
log.error(`Failed to manage hosts file: ${error.message}`);
|
|
20651
|
+
throw error;
|
|
20652
|
+
}
|
|
20653
|
+
}
|
|
20654
|
+
async function removeHosts(hosts, verbose) {
|
|
20655
|
+
debugLog("hosts", `Removing hosts: ${hosts.join(", ")}`, verbose);
|
|
20656
|
+
try {
|
|
20657
|
+
const content = await fs.promises.readFile(hostsFilePath, "utf-8");
|
|
20658
|
+
const lines = content.split(`
|
|
20659
|
+
`);
|
|
20660
|
+
const filteredLines = lines.filter((line, index) => {
|
|
20661
|
+
if (line.trim() === "# Added by rpx") {
|
|
20662
|
+
lines.splice(index + 1, 2);
|
|
20663
|
+
return false;
|
|
20664
|
+
}
|
|
20665
|
+
return true;
|
|
20666
|
+
});
|
|
20667
|
+
while (filteredLines[filteredLines.length - 1]?.trim() === "")
|
|
20668
|
+
filteredLines.pop();
|
|
20669
|
+
const newContent = `${filteredLines.join(`
|
|
20670
|
+
`)}
|
|
20671
|
+
`;
|
|
20672
|
+
const tmpFile = path.join(os2.tmpdir(), "hosts.tmp");
|
|
20673
|
+
await fs.promises.writeFile(tmpFile, newContent, "utf8");
|
|
20674
|
+
try {
|
|
20675
|
+
await execSudo(`cp "${tmpFile}" "${hostsFilePath}"`);
|
|
20676
|
+
log.success("Hosts removed successfully");
|
|
20677
|
+
} catch (error) {
|
|
20678
|
+
log.error("Failed to modify hosts file automatically");
|
|
20679
|
+
log.warn("Please remove these entries from your hosts file manually:");
|
|
20680
|
+
hosts.forEach((host) => {
|
|
20681
|
+
log.warn("# Added by rpx");
|
|
20682
|
+
log.warn(`127.0.0.1 ${host}`);
|
|
20683
|
+
log.warn(`::1 ${host}`);
|
|
20684
|
+
});
|
|
20685
|
+
if (process3.platform === "win32") {
|
|
20686
|
+
log.warn(`
|
|
20687
|
+
On Windows:`);
|
|
20688
|
+
log.warn("1. Run notepad as administrator");
|
|
20689
|
+
log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
|
|
20690
|
+
} else {
|
|
20691
|
+
log.warn(`
|
|
20692
|
+
On Unix systems:`);
|
|
20693
|
+
log.warn(`sudo nano ${hostsFilePath}`);
|
|
20694
|
+
}
|
|
20695
|
+
throw new Error("Failed to modify hosts file: manual intervention required");
|
|
20696
|
+
} finally {
|
|
20697
|
+
fs.unlinkSync(tmpFile);
|
|
20698
|
+
}
|
|
20699
|
+
} catch (err2) {
|
|
20700
|
+
const error = err2;
|
|
20701
|
+
log.error(`Failed to remove hosts: ${error.message}`);
|
|
20702
|
+
throw error;
|
|
20703
|
+
}
|
|
20704
|
+
}
|
|
20705
|
+
async function checkHosts(hosts, verbose) {
|
|
20706
|
+
debugLog("hosts", `Checking hosts: ${hosts}`, verbose);
|
|
20707
|
+
const content = await fs.promises.readFile(hostsFilePath, "utf-8");
|
|
20708
|
+
return hosts.map((host) => {
|
|
20709
|
+
const ipv4Entry = `127.0.0.1 ${host}`;
|
|
20710
|
+
const ipv6Entry = `::1 ${host}`;
|
|
20711
|
+
return content.includes(ipv4Entry) || content.includes(ipv6Entry);
|
|
20712
|
+
});
|
|
20713
|
+
}
|
|
20549
20714
|
|
|
20550
20715
|
// src/https.ts
|
|
20551
|
-
import
|
|
20716
|
+
import fs5 from "fs/promises";
|
|
20552
20717
|
import { homedir as homedir2 } from "os";
|
|
20553
20718
|
import { join as join4 } from "path";
|
|
20554
20719
|
|
|
@@ -20589,7 +20754,7 @@ import process8 from "process";
|
|
|
20589
20754
|
import process102 from "process";
|
|
20590
20755
|
import process182 from "process";
|
|
20591
20756
|
import process112 from "process";
|
|
20592
|
-
import
|
|
20757
|
+
import os3 from "os";
|
|
20593
20758
|
import tty32 from "tty";
|
|
20594
20759
|
import process142 from "process";
|
|
20595
20760
|
import process132 from "process";
|
|
@@ -20598,11 +20763,11 @@ import process162 from "process";
|
|
|
20598
20763
|
import process172 from "process";
|
|
20599
20764
|
import process192 from "process";
|
|
20600
20765
|
import os22 from "os";
|
|
20601
|
-
import
|
|
20766
|
+
import path2 from "path";
|
|
20602
20767
|
import { resolve as resolve3 } from "path";
|
|
20603
20768
|
import process22 from "process";
|
|
20604
|
-
import
|
|
20605
|
-
import
|
|
20769
|
+
import fs3 from "fs";
|
|
20770
|
+
import path22 from "path";
|
|
20606
20771
|
var __create3 = Object.create;
|
|
20607
20772
|
var __getProtoOf3 = Object.getPrototypeOf;
|
|
20608
20773
|
var __defProp3 = Object.defineProperty;
|
|
@@ -48126,29 +48291,29 @@ var log2 = {
|
|
|
48126
48291
|
},
|
|
48127
48292
|
echo: (...args) => console.log(...args)
|
|
48128
48293
|
};
|
|
48129
|
-
function userDatabasePath2(
|
|
48130
|
-
return projectPath2(`database/${
|
|
48294
|
+
function userDatabasePath2(path23) {
|
|
48295
|
+
return projectPath2(`database/${path23 || ""}`);
|
|
48131
48296
|
}
|
|
48132
|
-
function appPath2(
|
|
48133
|
-
return projectPath2(`app/${
|
|
48297
|
+
function appPath2(path23) {
|
|
48298
|
+
return projectPath2(`app/${path23 || ""}`);
|
|
48134
48299
|
}
|
|
48135
|
-
function commandsPath2(
|
|
48136
|
-
return appPath2(`Commands/${
|
|
48300
|
+
function commandsPath2(path23) {
|
|
48301
|
+
return appPath2(`Commands/${path23 || ""}`);
|
|
48137
48302
|
}
|
|
48138
|
-
function logsPath2(
|
|
48139
|
-
return storagePath2(`logs/${
|
|
48303
|
+
function logsPath2(path23) {
|
|
48304
|
+
return storagePath2(`logs/${path23 || ""}`);
|
|
48140
48305
|
}
|
|
48141
48306
|
function projectPath2(filePath = "", options2) {
|
|
48142
|
-
let
|
|
48143
|
-
while (
|
|
48144
|
-
|
|
48145
|
-
const finalPath = resolve22(
|
|
48307
|
+
let path23 = process52.cwd();
|
|
48308
|
+
while (path23.includes("storage"))
|
|
48309
|
+
path23 = resolve22(path23, "..");
|
|
48310
|
+
const finalPath = resolve22(path23, filePath);
|
|
48146
48311
|
if (options2?.relative)
|
|
48147
48312
|
return relative2(process52.cwd(), finalPath);
|
|
48148
48313
|
return finalPath;
|
|
48149
48314
|
}
|
|
48150
|
-
function storagePath2(
|
|
48151
|
-
return projectPath2(`storage/${
|
|
48315
|
+
function storagePath2(path23) {
|
|
48316
|
+
return projectPath2(`storage/${path23 || ""}`);
|
|
48152
48317
|
}
|
|
48153
48318
|
var config6 = {
|
|
48154
48319
|
ai: {
|
|
@@ -53763,7 +53928,7 @@ class Err2 {
|
|
|
53763
53928
|
}
|
|
53764
53929
|
var fromThrowable2 = Result2.fromThrowable;
|
|
53765
53930
|
var import_prompts2 = __toESM22(require_prompts32(), 1);
|
|
53766
|
-
async function
|
|
53931
|
+
async function exec2(command, options2) {
|
|
53767
53932
|
const cmd = Array.isArray(command) ? command : command.match(/(?:[^\s"]|"[^"]*")+/g);
|
|
53768
53933
|
log2.debug("exec:", Array.isArray(command) ? command.join(" ") : command, options2);
|
|
53769
53934
|
log2.debug("cmd:", cmd);
|
|
@@ -53809,7 +53974,7 @@ async function runCommand(command, options2) {
|
|
|
53809
53974
|
stdio: options2?.stdio ?? [options2?.stdin ?? "inherit", "pipe", "pipe"],
|
|
53810
53975
|
verbose: options2?.verbose ?? false
|
|
53811
53976
|
};
|
|
53812
|
-
return await
|
|
53977
|
+
return await exec2(command, opts);
|
|
53813
53978
|
}
|
|
53814
53979
|
var exports_esm2 = {};
|
|
53815
53980
|
__export3(exports_esm2, {
|
|
@@ -54235,7 +54400,7 @@ function _supportsColor2(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
|
|
|
54235
54400
|
return min;
|
|
54236
54401
|
}
|
|
54237
54402
|
if (process112.platform === "win32") {
|
|
54238
|
-
const osRelease =
|
|
54403
|
+
const osRelease = os3.release().split(".");
|
|
54239
54404
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
54240
54405
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
54241
54406
|
}
|
|
@@ -56832,9 +56997,9 @@ var defaultConfig2 = {
|
|
|
56832
56997
|
domain: "stacks.localhost",
|
|
56833
56998
|
rootCA: { certificate: "", privateKey: "" },
|
|
56834
56999
|
basePath: "",
|
|
56835
|
-
caCertPath:
|
|
56836
|
-
certPath:
|
|
56837
|
-
keyPath:
|
|
57000
|
+
caCertPath: path2.join(os22.homedir(), ".stacks", "ssl", `stacks.localhost.ca.crt`),
|
|
57001
|
+
certPath: path2.join(os22.homedir(), ".stacks", "ssl", `stacks.localhost.crt`),
|
|
57002
|
+
keyPath: path2.join(os22.homedir(), ".stacks", "ssl", `stacks.localhost.crt.key`),
|
|
56838
57003
|
verbose: false
|
|
56839
57004
|
};
|
|
56840
57005
|
var config42 = await loadConfig2({
|
|
@@ -56853,10 +57018,10 @@ function findFoldersWithFile(rootDir, fileName) {
|
|
|
56853
57018
|
const result = [];
|
|
56854
57019
|
function search(dir) {
|
|
56855
57020
|
try {
|
|
56856
|
-
const files =
|
|
57021
|
+
const files = fs3.readdirSync(dir);
|
|
56857
57022
|
for (const file of files) {
|
|
56858
|
-
const filePath =
|
|
56859
|
-
const stats =
|
|
57023
|
+
const filePath = path22.join(dir, file);
|
|
57024
|
+
const stats = fs3.lstatSync(filePath);
|
|
56860
57025
|
if (stats.isDirectory()) {
|
|
56861
57026
|
search(filePath);
|
|
56862
57027
|
} else if (file === fileName) {
|
|
@@ -56870,26 +57035,26 @@ function findFoldersWithFile(rootDir, fileName) {
|
|
|
56870
57035
|
search(rootDir);
|
|
56871
57036
|
return result;
|
|
56872
57037
|
}
|
|
56873
|
-
function
|
|
57038
|
+
function debugLog2(category, message, verbose) {
|
|
56874
57039
|
if (verbose || config42.verbose) {
|
|
56875
57040
|
console.debug(`[tlsx:${category}] ${message}`);
|
|
56876
57041
|
}
|
|
56877
57042
|
}
|
|
56878
57043
|
function generateRandomSerial(verbose) {
|
|
56879
|
-
|
|
57044
|
+
debugLog2("cert", "Generating random serial number", verbose);
|
|
56880
57045
|
const serialNumber = makeNumberPositive(import_node_forge2.default.util.bytesToHex(import_node_forge2.default.random.getBytesSync(20)));
|
|
56881
|
-
|
|
57046
|
+
debugLog2("cert", `Generated serial number: ${serialNumber}`, verbose);
|
|
56882
57047
|
return serialNumber;
|
|
56883
57048
|
}
|
|
56884
57049
|
function calculateValidityDates(options22) {
|
|
56885
57050
|
const notBeforeDays = options22.notBeforeDays ?? 2;
|
|
56886
57051
|
const validityDays = options22.validityDays ?? (options22.validityYears ? options22.validityYears * 365 : 180);
|
|
56887
|
-
|
|
57052
|
+
debugLog2("cert", "Calculating certificate validity dates", options22.verbose);
|
|
56888
57053
|
const notBefore = new Date(Date.now() - 86400 * notBeforeDays * 1000);
|
|
56889
57054
|
const notAfter = new Date(notBefore.getTime() + validityDays * 24 * 60 * 60 * 1000);
|
|
56890
57055
|
notBefore.setUTCHours(0, 0, 0, 0);
|
|
56891
57056
|
notAfter.setUTCHours(23, 59, 59, 999);
|
|
56892
|
-
|
|
57057
|
+
debugLog2("cert", `Validity period: ${notBefore.toISOString()} to ${notAfter.toISOString()}`, options22.verbose);
|
|
56893
57058
|
return { notBefore, notAfter };
|
|
56894
57059
|
}
|
|
56895
57060
|
function generateCertificateExtensions(options22) {
|
|
@@ -56922,9 +57087,9 @@ function generateCertificateExtensions(options22) {
|
|
|
56922
57087
|
return extensions;
|
|
56923
57088
|
}
|
|
56924
57089
|
async function createRootCA(options22 = {}) {
|
|
56925
|
-
|
|
57090
|
+
debugLog2("ca", "Creating new Root CA Certificate", options22.verbose);
|
|
56926
57091
|
const keySize = options22.keySize || 2048;
|
|
56927
|
-
|
|
57092
|
+
debugLog2("ca", `Generating ${keySize}-bit RSA key pair`, options22.verbose);
|
|
56928
57093
|
const { privateKey, publicKey } = import_node_forge2.pki.rsa.generateKeyPair(keySize);
|
|
56929
57094
|
const attributes = [
|
|
56930
57095
|
{ shortName: "C", value: options22.countryName || config42.countryName },
|
|
@@ -56971,14 +57136,14 @@ async function createRootCA(options22 = {}) {
|
|
|
56971
57136
|
};
|
|
56972
57137
|
}
|
|
56973
57138
|
async function generateCertificate(options22) {
|
|
56974
|
-
|
|
56975
|
-
|
|
57139
|
+
debugLog2("cert", "Generating new certificate", options22.verbose);
|
|
57140
|
+
debugLog2("cert", `Options: ${JSON.stringify(options22)}`, options22.verbose);
|
|
56976
57141
|
if (!options22.rootCA?.certificate || !options22.rootCA?.privateKey) {
|
|
56977
57142
|
throw new Error("Root CA certificate and private key are required");
|
|
56978
57143
|
}
|
|
56979
57144
|
const caCert = import_node_forge2.pki.certificateFromPem(options22.rootCA.certificate);
|
|
56980
57145
|
const caKey = import_node_forge2.pki.privateKeyFromPem(options22.rootCA.privateKey);
|
|
56981
|
-
|
|
57146
|
+
debugLog2("cert", "Generating 2048-bit RSA key pair for host certificate", options22.verbose);
|
|
56982
57147
|
const keySize = 2048;
|
|
56983
57148
|
const { privateKey, publicKey } = import_node_forge2.pki.rsa.generateKeyPair(keySize);
|
|
56984
57149
|
const attributes = options22.certificateAttributes || [
|
|
@@ -57009,81 +57174,81 @@ async function generateCertificate(options22) {
|
|
|
57009
57174
|
};
|
|
57010
57175
|
}
|
|
57011
57176
|
async function addCertToSystemTrustStoreAndSaveCert(cert, caCert, options22) {
|
|
57012
|
-
|
|
57013
|
-
|
|
57177
|
+
debugLog2("trust", `Adding certificate to system trust store with options: ${JSON.stringify(options22)}`, options22?.verbose);
|
|
57178
|
+
debugLog2("trust", "Storing certificate and private key", options22?.verbose);
|
|
57014
57179
|
const certPath = storeCertificate(cert, options22);
|
|
57015
|
-
|
|
57180
|
+
debugLog2("trust", "Storing CA certificate", options22?.verbose);
|
|
57016
57181
|
const caCertPath = storeCACertificate(caCert, options22);
|
|
57017
57182
|
const platform22 = os4.platform();
|
|
57018
|
-
|
|
57183
|
+
debugLog2("trust", `Detected platform: ${platform22}`, options22?.verbose);
|
|
57019
57184
|
const args = "TC, C, C";
|
|
57020
57185
|
if (platform22 === "darwin") {
|
|
57021
|
-
|
|
57186
|
+
debugLog2("trust", "Adding certificate to macOS keychain", options22?.verbose);
|
|
57022
57187
|
await runCommand(`sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${caCertPath}`);
|
|
57023
57188
|
} else if (platform22 === "win32") {
|
|
57024
|
-
|
|
57189
|
+
debugLog2("trust", "Adding certificate to Windows certificate store", options22?.verbose);
|
|
57025
57190
|
await runCommand(`certutil -f -v -addstore -enterprise Root ${caCertPath}`);
|
|
57026
57191
|
} else if (platform22 === "linux") {
|
|
57027
|
-
|
|
57192
|
+
debugLog2("trust", "Adding certificate to Linux certificate store", options22?.verbose);
|
|
57028
57193
|
const rootDirectory = os4.homedir();
|
|
57029
57194
|
const targetFileName = "cert9.db";
|
|
57030
|
-
|
|
57195
|
+
debugLog2("trust", `Searching for certificate databases in ${rootDirectory}`, options22?.verbose);
|
|
57031
57196
|
const foldersWithFile = findFoldersWithFile(rootDirectory, targetFileName);
|
|
57032
57197
|
for (const folder of foldersWithFile) {
|
|
57033
|
-
|
|
57198
|
+
debugLog2("trust", `Processing certificate database in ${folder}`, options22?.verbose);
|
|
57034
57199
|
try {
|
|
57035
|
-
|
|
57200
|
+
debugLog2("trust", `Attempting to delete existing cert for ${config42.commonName}`, options22?.verbose);
|
|
57036
57201
|
await runCommand(`certutil -d sql:${folder} -D -n ${config42.commonName}`);
|
|
57037
57202
|
} catch (error) {
|
|
57038
|
-
|
|
57203
|
+
debugLog2("trust", `Warning: Error deleting existing cert: ${error}`, options22?.verbose);
|
|
57039
57204
|
console.warn(`Error deleting existing cert: ${error}`);
|
|
57040
57205
|
}
|
|
57041
|
-
|
|
57206
|
+
debugLog2("trust", `Adding new certificate to ${folder}`, options22?.verbose);
|
|
57042
57207
|
await runCommand(`certutil -d sql:${folder} -A -t ${args} -n ${config42.commonName} -i ${caCertPath}`);
|
|
57043
57208
|
log2.info(`Cert added to ${folder}`);
|
|
57044
57209
|
}
|
|
57045
57210
|
} else {
|
|
57046
|
-
|
|
57211
|
+
debugLog2("trust", `Error: Unsupported platform ${platform22}`, options22?.verbose);
|
|
57047
57212
|
throw new Error(`Unsupported platform: ${platform22}`);
|
|
57048
57213
|
}
|
|
57049
|
-
|
|
57214
|
+
debugLog2("trust", "Certificate successfully added to system trust store", options22?.verbose);
|
|
57050
57215
|
return certPath;
|
|
57051
57216
|
}
|
|
57052
57217
|
function storeCertificate(cert, options22) {
|
|
57053
|
-
|
|
57218
|
+
debugLog2("storage", `Storing certificate and private key with options: ${JSON.stringify(options22)}`, options22?.verbose);
|
|
57054
57219
|
const certPath = path3.join(options22?.basePath || config42.basePath, options22?.certPath || config42.certPath);
|
|
57055
57220
|
const certKeyPath = path3.join(options22?.basePath || config42.basePath, options22?.keyPath || config42.keyPath);
|
|
57056
|
-
|
|
57057
|
-
|
|
57221
|
+
debugLog2("storage", `Certificate path: ${certPath}`, options22?.verbose);
|
|
57222
|
+
debugLog2("storage", `Private key path: ${certKeyPath}`, options22?.verbose);
|
|
57058
57223
|
const certDir = path3.dirname(certPath);
|
|
57059
57224
|
if (!fs2.existsSync(certDir)) {
|
|
57060
|
-
|
|
57225
|
+
debugLog2("storage", `Creating certificate directory: ${certDir}`, options22?.verbose);
|
|
57061
57226
|
fs2.mkdirSync(certDir, { recursive: true });
|
|
57062
57227
|
}
|
|
57063
|
-
|
|
57228
|
+
debugLog2("storage", "Writing certificate file", options22?.verbose);
|
|
57064
57229
|
fs2.writeFileSync(certPath, cert.certificate);
|
|
57065
57230
|
const certKeyDir = path3.dirname(certKeyPath);
|
|
57066
57231
|
if (!fs2.existsSync(certKeyDir)) {
|
|
57067
|
-
|
|
57232
|
+
debugLog2("storage", `Creating private key directory: ${certKeyDir}`, options22?.verbose);
|
|
57068
57233
|
fs2.mkdirSync(certKeyDir, { recursive: true });
|
|
57069
57234
|
}
|
|
57070
|
-
|
|
57235
|
+
debugLog2("storage", "Writing private key file", options22?.verbose);
|
|
57071
57236
|
fs2.writeFileSync(certKeyPath, cert.privateKey);
|
|
57072
|
-
|
|
57237
|
+
debugLog2("storage", "Certificate and private key stored successfully", options22?.verbose);
|
|
57073
57238
|
return certPath;
|
|
57074
57239
|
}
|
|
57075
57240
|
function storeCACertificate(caCert, options22) {
|
|
57076
|
-
|
|
57241
|
+
debugLog2("storage", "Storing CA certificate", options22?.verbose);
|
|
57077
57242
|
const caCertPath = path3.join(options22?.basePath || config42.basePath, options22?.caCertPath || config42.caCertPath);
|
|
57078
|
-
|
|
57243
|
+
debugLog2("storage", `CA certificate path: ${caCertPath}`, options22?.verbose);
|
|
57079
57244
|
const caCertDir = path3.dirname(caCertPath);
|
|
57080
57245
|
if (!fs2.existsSync(caCertDir)) {
|
|
57081
|
-
|
|
57246
|
+
debugLog2("storage", `Creating CA certificate directory: ${caCertDir}`, options22?.verbose);
|
|
57082
57247
|
fs2.mkdirSync(caCertDir, { recursive: true });
|
|
57083
57248
|
}
|
|
57084
|
-
|
|
57249
|
+
debugLog2("storage", "Writing CA certificate file", options22?.verbose);
|
|
57085
57250
|
fs2.writeFileSync(caCertPath, caCert);
|
|
57086
|
-
|
|
57251
|
+
debugLog2("storage", "CA certificate stored successfully", options22?.verbose);
|
|
57087
57252
|
return caCertPath;
|
|
57088
57253
|
}
|
|
57089
57254
|
var export_tls = import_node_forge2.tls;
|
|
@@ -57092,15 +57257,6 @@ var export_forge = import_node_forge2.default;
|
|
|
57092
57257
|
|
|
57093
57258
|
// src/https.ts
|
|
57094
57259
|
var cachedSSLConfig = null;
|
|
57095
|
-
function isMultiProxyConfig(options3) {
|
|
57096
|
-
return "proxies" in options3 && Array.isArray(options3.proxies);
|
|
57097
|
-
}
|
|
57098
|
-
function isMultiProxyOptions(options3) {
|
|
57099
|
-
return "proxies" in options3 && Array.isArray(options3.proxies);
|
|
57100
|
-
}
|
|
57101
|
-
function isSingleProxyOptions(options3) {
|
|
57102
|
-
return "to" in options3 && typeof options3.to === "string";
|
|
57103
|
-
}
|
|
57104
57260
|
function resolveSSLPaths(options3, defaultConfig3) {
|
|
57105
57261
|
const domain = isMultiProxyConfig(options3) ? options3.proxies[0].to || "stacks.localhost" : options3.to || "stacks.localhost";
|
|
57106
57262
|
if (typeof options3.https === "object" && typeof defaultConfig3.https === "object") {
|
|
@@ -57144,15 +57300,6 @@ function generateWildcardPatterns(domain) {
|
|
|
57144
57300
|
patterns.add(`*.${parts.slice(1).join(".")}`);
|
|
57145
57301
|
return Array.from(patterns);
|
|
57146
57302
|
}
|
|
57147
|
-
function getPrimaryDomain(options3) {
|
|
57148
|
-
if (!options3)
|
|
57149
|
-
return "stacks.localhost";
|
|
57150
|
-
if (isMultiProxyOptions(options3) && options3.proxies.length > 0)
|
|
57151
|
-
return options3.proxies[0].to || "stacks.localhost";
|
|
57152
|
-
if (isSingleProxyOptions(options3))
|
|
57153
|
-
return options3.to || "stacks.localhost";
|
|
57154
|
-
return "stacks.localhost";
|
|
57155
|
-
}
|
|
57156
57303
|
function generateSSLPaths(options3) {
|
|
57157
57304
|
const domain = getPrimaryDomain(options3);
|
|
57158
57305
|
let basePath = "";
|
|
@@ -57190,51 +57337,50 @@ function getAllDomains(options3) {
|
|
|
57190
57337
|
return domains;
|
|
57191
57338
|
}
|
|
57192
57339
|
async function loadSSLConfig(options3) {
|
|
57193
|
-
|
|
57340
|
+
debugLog("ssl", `Loading SSL configuration`, options3.verbose);
|
|
57194
57341
|
const mergedOptions = {
|
|
57195
57342
|
...config4,
|
|
57196
57343
|
...options3
|
|
57197
57344
|
};
|
|
57198
57345
|
options3.https = httpsConfig(mergedOptions);
|
|
57199
57346
|
if (!options3.https?.keyPath && !options3.https?.certPath) {
|
|
57200
|
-
|
|
57347
|
+
debugLog("ssl", "No SSL configuration provided", options3.verbose);
|
|
57201
57348
|
return null;
|
|
57202
57349
|
}
|
|
57203
57350
|
if (options3.https?.keyPath && !options3.https?.certPath || !options3.https?.keyPath && options3.https?.certPath) {
|
|
57204
57351
|
const missing = !options3.https?.keyPath ? "keyPath" : "certPath";
|
|
57205
|
-
|
|
57352
|
+
debugLog("ssl", `Invalid SSL configuration - missing ${missing}`, options3.verbose);
|
|
57206
57353
|
throw new Error(`SSL Configuration requires both keyPath and certPath. Missing: ${missing}`);
|
|
57207
57354
|
}
|
|
57208
57355
|
try {
|
|
57209
57356
|
if (!options3.https?.keyPath || !options3.https?.certPath)
|
|
57210
57357
|
return null;
|
|
57211
57358
|
try {
|
|
57212
|
-
|
|
57213
|
-
const key = await
|
|
57214
|
-
const cert = await
|
|
57215
|
-
|
|
57359
|
+
debugLog("ssl", "Reading SSL certificate files", options3.verbose);
|
|
57360
|
+
const key = await fs5.readFile(options3.https?.keyPath, "utf8");
|
|
57361
|
+
const cert = await fs5.readFile(options3.https?.certPath, "utf8");
|
|
57362
|
+
debugLog("ssl", "SSL configuration loaded successfully", options3.verbose);
|
|
57216
57363
|
return { key, cert };
|
|
57217
57364
|
} catch (error) {
|
|
57218
|
-
|
|
57365
|
+
debugLog("ssl", `Failed to read certificates: ${error}`, options3.verbose);
|
|
57219
57366
|
return null;
|
|
57220
57367
|
}
|
|
57221
57368
|
} catch (err3) {
|
|
57222
|
-
|
|
57369
|
+
debugLog("ssl", `SSL configuration error: ${err3}`, options3.verbose);
|
|
57223
57370
|
throw err3;
|
|
57224
57371
|
}
|
|
57225
57372
|
}
|
|
57226
57373
|
async function generateCertificate2(options3) {
|
|
57227
57374
|
if (cachedSSLConfig) {
|
|
57228
|
-
|
|
57375
|
+
debugLog("ssl", "Using cached SSL configuration", options3.verbose);
|
|
57229
57376
|
return;
|
|
57230
57377
|
}
|
|
57231
57378
|
const domains = isMultiProxyOptions(options3) ? options3.proxies.map((proxy) => proxy.to) : [options3.to];
|
|
57232
|
-
|
|
57379
|
+
debugLog("ssl", `Generating certificate for domains: ${domains.join(", ")}`, options3.verbose);
|
|
57233
57380
|
const rootCAConfig = httpsConfig(options3, options3.verbose);
|
|
57234
57381
|
log.info("Generating Root CA certificate...");
|
|
57235
57382
|
const caCert = await createRootCA(rootCAConfig);
|
|
57236
57383
|
const hostConfig = httpsConfig(options3, options3.verbose);
|
|
57237
|
-
console.log("hostConfig", hostConfig);
|
|
57238
57384
|
log.info(`Generating host certificate for: ${domains.join(", ")}`);
|
|
57239
57385
|
const hostCert = await generateCertificate({
|
|
57240
57386
|
...hostConfig,
|
|
@@ -57250,7 +57396,7 @@ async function generateCertificate2(options3) {
|
|
|
57250
57396
|
ca: caCert.certificate
|
|
57251
57397
|
};
|
|
57252
57398
|
log.success(`Certificate generated successfully for ${domains.length} domain${domains.length > 1 ? "s" : ""}`);
|
|
57253
|
-
|
|
57399
|
+
debugLog("ssl", `Certificate includes domains: ${domains.join(", ")}`, options3.verbose);
|
|
57254
57400
|
}
|
|
57255
57401
|
function getSSLConfig() {
|
|
57256
57402
|
return cachedSSLConfig;
|
|
@@ -57259,29 +57405,29 @@ async function checkExistingCertificates(options3) {
|
|
|
57259
57405
|
const name = getPrimaryDomain(options3);
|
|
57260
57406
|
const paths = generateSSLPaths(options3);
|
|
57261
57407
|
try {
|
|
57262
|
-
|
|
57263
|
-
|
|
57264
|
-
|
|
57265
|
-
|
|
57266
|
-
const key = await
|
|
57267
|
-
const cert = await
|
|
57408
|
+
debugLog("ssl", `Checking certificates for ${name} at paths:`, options3?.verbose);
|
|
57409
|
+
debugLog("ssl", `CA: ${paths.caCertPath}`, options3?.verbose);
|
|
57410
|
+
debugLog("ssl", `Cert: ${paths.certPath}`, options3?.verbose);
|
|
57411
|
+
debugLog("ssl", `Key: ${paths.keyPath}`, options3?.verbose);
|
|
57412
|
+
const key = await fs5.readFile(paths.keyPath, "utf8");
|
|
57413
|
+
const cert = await fs5.readFile(paths.certPath, "utf8");
|
|
57268
57414
|
let ca;
|
|
57269
57415
|
if (paths.caCertPath) {
|
|
57270
57416
|
try {
|
|
57271
|
-
ca = await
|
|
57417
|
+
ca = await fs5.readFile(paths.caCertPath, "utf8");
|
|
57272
57418
|
} catch (err3) {
|
|
57273
|
-
|
|
57419
|
+
debugLog("ssl", `Failed to read CA cert: ${err3}`, options3?.verbose);
|
|
57274
57420
|
}
|
|
57275
57421
|
}
|
|
57276
57422
|
return { key, cert, ca };
|
|
57277
57423
|
} catch (err3) {
|
|
57278
|
-
|
|
57424
|
+
debugLog("ssl", `Failed to read certificates: ${err3}`, options3?.verbose);
|
|
57279
57425
|
return null;
|
|
57280
57426
|
}
|
|
57281
57427
|
}
|
|
57282
57428
|
function httpsConfig(options3, verbose) {
|
|
57283
57429
|
const primaryDomain = getPrimaryDomain(options3);
|
|
57284
|
-
|
|
57430
|
+
debugLog("ssl", `Primary domain: ${primaryDomain}`, verbose);
|
|
57285
57431
|
const defaultPaths = generateSSLPaths(options3);
|
|
57286
57432
|
if (typeof options3.https === "object") {
|
|
57287
57433
|
const config5 = {
|
|
@@ -57331,227 +57477,41 @@ function httpsConfig(options3, verbose) {
|
|
|
57331
57477
|
};
|
|
57332
57478
|
}
|
|
57333
57479
|
|
|
57334
|
-
// src/utils.ts
|
|
57335
|
-
function debugLog2(category, message, verbose) {
|
|
57336
|
-
if (verbose) {
|
|
57337
|
-
console.debug(`[rpx:${category}] ${message}`);
|
|
57338
|
-
}
|
|
57339
|
-
}
|
|
57340
|
-
function extractHostname(options3) {
|
|
57341
|
-
if (isMultiProxyOptions(options3)) {
|
|
57342
|
-
return options3.proxies.map((proxy) => {
|
|
57343
|
-
const domain = proxy.to || "stacks.localhost";
|
|
57344
|
-
return domain.startsWith("http") ? new URL(domain).hostname : domain;
|
|
57345
|
-
});
|
|
57346
|
-
}
|
|
57347
|
-
if (isSingleProxyOptions(options3)) {
|
|
57348
|
-
const domain = options3.to || "stacks.localhost";
|
|
57349
|
-
return [domain.startsWith("http") ? new URL(domain).hostname : domain];
|
|
57350
|
-
}
|
|
57351
|
-
return ["stacks.localhost"];
|
|
57352
|
-
}
|
|
57353
|
-
function isValidRootCA(value) {
|
|
57354
|
-
return typeof value === "object" && value !== null && "certificate" in value && "privateKey" in value && typeof value.certificate === "string" && typeof value.privateKey === "string";
|
|
57355
|
-
}
|
|
57356
|
-
|
|
57357
|
-
// src/hosts.ts
|
|
57358
|
-
var hostsFilePath = process3.platform === "win32" ? path4.join(process3.env.windir || "C:\\Windows", "System32", "drivers", "etc", "hosts") : "/etc/hosts";
|
|
57359
|
-
async function sudoWrite(operation, content) {
|
|
57360
|
-
return new Promise((resolve4, reject) => {
|
|
57361
|
-
if (process3.platform === "win32") {
|
|
57362
|
-
reject(new Error("Administrator privileges required on Windows"));
|
|
57363
|
-
return;
|
|
57364
|
-
}
|
|
57365
|
-
const tmpFile = path4.join(os3.tmpdir(), "hosts.tmp");
|
|
57366
|
-
try {
|
|
57367
|
-
if (operation === "append") {
|
|
57368
|
-
const currentContent = fs5.readFileSync(hostsFilePath, "utf8");
|
|
57369
|
-
fs5.writeFileSync(tmpFile, currentContent + content, "utf8");
|
|
57370
|
-
} else {
|
|
57371
|
-
fs5.writeFileSync(tmpFile, content, "utf8");
|
|
57372
|
-
}
|
|
57373
|
-
const sudo = spawn("sudo", ["cp", tmpFile, hostsFilePath]);
|
|
57374
|
-
sudo.on("close", (code) => {
|
|
57375
|
-
try {
|
|
57376
|
-
fs5.unlinkSync(tmpFile);
|
|
57377
|
-
if (code === 0)
|
|
57378
|
-
resolve4();
|
|
57379
|
-
else
|
|
57380
|
-
reject(new Error(`sudo process exited with code ${code}`));
|
|
57381
|
-
} catch (err3) {
|
|
57382
|
-
reject(err3);
|
|
57383
|
-
}
|
|
57384
|
-
});
|
|
57385
|
-
sudo.on("error", (err3) => {
|
|
57386
|
-
try {
|
|
57387
|
-
fs5.unlinkSync(tmpFile);
|
|
57388
|
-
} catch {
|
|
57389
|
-
}
|
|
57390
|
-
reject(err3);
|
|
57391
|
-
});
|
|
57392
|
-
} catch (err3) {
|
|
57393
|
-
reject(err3);
|
|
57394
|
-
}
|
|
57395
|
-
});
|
|
57396
|
-
}
|
|
57397
|
-
async function addHosts(hosts, verbose) {
|
|
57398
|
-
debugLog2("hosts", `Adding hosts: ${hosts.join(", ")}`, verbose);
|
|
57399
|
-
debugLog2("hosts", `Using hosts file at: ${hostsFilePath}`, verbose);
|
|
57400
|
-
try {
|
|
57401
|
-
const existingContent = await fs5.promises.readFile(hostsFilePath, "utf-8");
|
|
57402
|
-
const newEntries = hosts.filter((host) => {
|
|
57403
|
-
const ipv4Entry = `127.0.0.1 ${host}`;
|
|
57404
|
-
const ipv6Entry = `::1 ${host}`;
|
|
57405
|
-
return !existingContent.includes(ipv4Entry) && !existingContent.includes(ipv6Entry);
|
|
57406
|
-
});
|
|
57407
|
-
if (newEntries.length === 0) {
|
|
57408
|
-
debugLog2("hosts", "All hosts already exist in hosts file", verbose);
|
|
57409
|
-
log.info("All hosts are already in the hosts file");
|
|
57410
|
-
return;
|
|
57411
|
-
}
|
|
57412
|
-
const hostEntries = newEntries.map((host) => `
|
|
57413
|
-
# Added by rpx
|
|
57414
|
-
127.0.0.1 ${host}
|
|
57415
|
-
::1 ${host}`).join(`
|
|
57416
|
-
`);
|
|
57417
|
-
try {
|
|
57418
|
-
await fs5.promises.appendFile(hostsFilePath, hostEntries, { flag: "a" });
|
|
57419
|
-
log.success(`Added new hosts: ${newEntries.join(", ")}`);
|
|
57420
|
-
} catch (writeErr) {
|
|
57421
|
-
if (writeErr.code === "EACCES") {
|
|
57422
|
-
debugLog2("hosts", "Permission denied, attempting with sudo", verbose);
|
|
57423
|
-
try {
|
|
57424
|
-
await sudoWrite("append", hostEntries);
|
|
57425
|
-
log.success(`Added new hosts with sudo: ${newEntries.join(", ")}`);
|
|
57426
|
-
} catch (sudoErr) {
|
|
57427
|
-
log.error("Failed to modify hosts file automatically");
|
|
57428
|
-
log.warn("Please add these entries to your hosts file manually:");
|
|
57429
|
-
hostEntries.split(`
|
|
57430
|
-
`).forEach((entry) => log.warn(entry));
|
|
57431
|
-
if (process3.platform === "win32") {
|
|
57432
|
-
log.warn(`
|
|
57433
|
-
On Windows:`);
|
|
57434
|
-
log.warn("1. Run notepad as administrator");
|
|
57435
|
-
log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
|
|
57436
|
-
} else {
|
|
57437
|
-
log.warn(`
|
|
57438
|
-
On Unix systems:`);
|
|
57439
|
-
log.warn(`sudo nano ${hostsFilePath}`);
|
|
57440
|
-
}
|
|
57441
|
-
throw new Error("Failed to modify hosts file: manual intervention required");
|
|
57442
|
-
}
|
|
57443
|
-
} else {
|
|
57444
|
-
throw writeErr;
|
|
57445
|
-
}
|
|
57446
|
-
}
|
|
57447
|
-
} catch (err3) {
|
|
57448
|
-
const error = err3;
|
|
57449
|
-
log.error(`Failed to manage hosts file: ${error.message}`);
|
|
57450
|
-
throw error;
|
|
57451
|
-
}
|
|
57452
|
-
}
|
|
57453
|
-
async function removeHosts(hosts, verbose) {
|
|
57454
|
-
debugLog2("hosts", `Removing hosts: ${hosts.join(", ")}`, verbose);
|
|
57455
|
-
try {
|
|
57456
|
-
const content = await fs5.promises.readFile(hostsFilePath, "utf-8");
|
|
57457
|
-
const lines = content.split(`
|
|
57458
|
-
`);
|
|
57459
|
-
const filteredLines = lines.filter((line, index) => {
|
|
57460
|
-
if (line.trim() === "# Added by rpx") {
|
|
57461
|
-
lines.splice(index + 1, 2);
|
|
57462
|
-
return false;
|
|
57463
|
-
}
|
|
57464
|
-
return true;
|
|
57465
|
-
});
|
|
57466
|
-
while (filteredLines[filteredLines.length - 1]?.trim() === "")
|
|
57467
|
-
filteredLines.pop();
|
|
57468
|
-
const newContent = `${filteredLines.join(`
|
|
57469
|
-
`)}
|
|
57470
|
-
`;
|
|
57471
|
-
try {
|
|
57472
|
-
await fs5.promises.writeFile(hostsFilePath, newContent);
|
|
57473
|
-
log.success("Hosts removed successfully");
|
|
57474
|
-
} catch (writeErr) {
|
|
57475
|
-
if (writeErr.code === "EACCES") {
|
|
57476
|
-
debugLog2("hosts", "Permission denied, attempting with sudo", verbose);
|
|
57477
|
-
try {
|
|
57478
|
-
await sudoWrite("write", newContent);
|
|
57479
|
-
log.success("Hosts removed successfully with sudo");
|
|
57480
|
-
} catch (sudoErr) {
|
|
57481
|
-
log.error("Failed to modify hosts file automatically");
|
|
57482
|
-
log.warn("Please remove these entries from your hosts file manually:");
|
|
57483
|
-
hosts.forEach((host) => {
|
|
57484
|
-
log.warn("# Added by rpx");
|
|
57485
|
-
log.warn(`127.0.0.1 ${host}`);
|
|
57486
|
-
log.warn(`::1 ${host}`);
|
|
57487
|
-
});
|
|
57488
|
-
if (process3.platform === "win32") {
|
|
57489
|
-
log.warn(`
|
|
57490
|
-
On Windows:`);
|
|
57491
|
-
log.warn("1. Run notepad as administrator");
|
|
57492
|
-
log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
|
|
57493
|
-
} else {
|
|
57494
|
-
log.warn(`
|
|
57495
|
-
On Unix systems:`);
|
|
57496
|
-
log.warn(`sudo nano ${hostsFilePath}`);
|
|
57497
|
-
}
|
|
57498
|
-
throw new Error("Failed to modify hosts file: manual intervention required");
|
|
57499
|
-
}
|
|
57500
|
-
} else {
|
|
57501
|
-
throw writeErr;
|
|
57502
|
-
}
|
|
57503
|
-
}
|
|
57504
|
-
} catch (err3) {
|
|
57505
|
-
const error = err3;
|
|
57506
|
-
log.error(`Failed to remove hosts: ${error.message}`);
|
|
57507
|
-
throw error;
|
|
57508
|
-
}
|
|
57509
|
-
}
|
|
57510
|
-
async function checkHosts(hosts, verbose) {
|
|
57511
|
-
debugLog2("hosts", `Checking hosts: ${hosts}`, verbose);
|
|
57512
|
-
const content = await fs5.promises.readFile(hostsFilePath, "utf-8");
|
|
57513
|
-
return hosts.map((host) => {
|
|
57514
|
-
const ipv4Entry = `127.0.0.1 ${host}`;
|
|
57515
|
-
const ipv6Entry = `::1 ${host}`;
|
|
57516
|
-
return content.includes(ipv4Entry) || content.includes(ipv6Entry);
|
|
57517
|
-
});
|
|
57518
|
-
}
|
|
57519
|
-
|
|
57520
57480
|
// src/start.ts
|
|
57521
57481
|
var activeServers = new Set;
|
|
57522
57482
|
async function cleanup(options3) {
|
|
57523
|
-
|
|
57483
|
+
debugLog("cleanup", "Starting cleanup process", options3?.verbose);
|
|
57524
57484
|
console.log(`
|
|
57525
57485
|
`);
|
|
57526
57486
|
log.info("Shutting down proxy servers...");
|
|
57527
57487
|
const cleanupPromises = [];
|
|
57528
57488
|
const serverClosePromises = Array.from(activeServers).map((server) => new Promise((resolve4) => {
|
|
57529
57489
|
server.close(() => {
|
|
57530
|
-
|
|
57490
|
+
debugLog("cleanup", "Server closed successfully", options3?.verbose);
|
|
57531
57491
|
resolve4();
|
|
57532
57492
|
});
|
|
57533
57493
|
}));
|
|
57534
57494
|
cleanupPromises.push(...serverClosePromises);
|
|
57535
57495
|
if (options3?.etcHostsCleanup && options3.domains?.length) {
|
|
57536
|
-
|
|
57496
|
+
debugLog("cleanup", "Cleaning up hosts file entries", options3?.verbose);
|
|
57537
57497
|
const domainsToClean = options3.domains.filter((domain) => !domain.includes("localhost"));
|
|
57538
57498
|
if (domainsToClean.length > 0) {
|
|
57539
57499
|
log.info("Cleaning up hosts file entries...");
|
|
57540
57500
|
cleanupPromises.push(removeHosts(domainsToClean, options3?.verbose).then(() => {
|
|
57541
|
-
|
|
57501
|
+
debugLog("cleanup", `Removed hosts entries for ${domainsToClean.join(", ")}`, options3?.verbose);
|
|
57542
57502
|
}).catch((err3) => {
|
|
57543
|
-
|
|
57503
|
+
debugLog("cleanup", `Failed to remove hosts entries: ${err3}`, options3?.verbose);
|
|
57544
57504
|
log.warn(`Failed to clean up hosts file entries for ${domainsToClean.join(", ")}:`, err3);
|
|
57545
57505
|
}));
|
|
57546
57506
|
}
|
|
57547
57507
|
}
|
|
57548
57508
|
try {
|
|
57549
57509
|
await Promise.all(cleanupPromises);
|
|
57550
|
-
|
|
57510
|
+
debugLog("cleanup", "All cleanup tasks completed successfully", options3?.verbose);
|
|
57551
57511
|
log.success("All cleanup tasks completed successfully");
|
|
57552
57512
|
process9.exit(0);
|
|
57553
57513
|
} catch (err3) {
|
|
57554
|
-
|
|
57514
|
+
debugLog("cleanup", `Error during cleanup: ${err3}`, options3?.verbose);
|
|
57555
57515
|
log.error("Error during cleanup:", err3);
|
|
57556
57516
|
process9.exit(1);
|
|
57557
57517
|
}
|
|
@@ -57559,22 +57519,22 @@ async function cleanup(options3) {
|
|
|
57559
57519
|
process9.on("SIGINT", cleanup);
|
|
57560
57520
|
process9.on("SIGTERM", cleanup);
|
|
57561
57521
|
process9.on("uncaughtException", (err3) => {
|
|
57562
|
-
|
|
57522
|
+
debugLog("process", `Uncaught exception: ${err3}`, true);
|
|
57563
57523
|
log.error("Uncaught exception:", err3);
|
|
57564
57524
|
cleanup();
|
|
57565
57525
|
});
|
|
57566
57526
|
function isPortInUse(port, hostname, verbose) {
|
|
57567
|
-
|
|
57527
|
+
debugLog("port", `Checking if port ${port} is in use on ${hostname}`, verbose);
|
|
57568
57528
|
return new Promise((resolve4) => {
|
|
57569
57529
|
const server = net.createServer();
|
|
57570
57530
|
server.once("error", (err3) => {
|
|
57571
57531
|
if (err3.code === "EADDRINUSE") {
|
|
57572
|
-
|
|
57532
|
+
debugLog("port", `Port ${port} is in use`, verbose);
|
|
57573
57533
|
resolve4(true);
|
|
57574
57534
|
}
|
|
57575
57535
|
});
|
|
57576
57536
|
server.once("listening", () => {
|
|
57577
|
-
|
|
57537
|
+
debugLog("port", `Port ${port} is available`, verbose);
|
|
57578
57538
|
server.close();
|
|
57579
57539
|
resolve4(false);
|
|
57580
57540
|
});
|
|
@@ -57582,17 +57542,17 @@ function isPortInUse(port, hostname, verbose) {
|
|
|
57582
57542
|
});
|
|
57583
57543
|
}
|
|
57584
57544
|
async function findAvailablePort(startPort, hostname, verbose) {
|
|
57585
|
-
|
|
57545
|
+
debugLog("port", `Finding available port starting from ${startPort}`, verbose);
|
|
57586
57546
|
let port = startPort;
|
|
57587
57547
|
while (await isPortInUse(port, hostname, verbose)) {
|
|
57588
|
-
|
|
57548
|
+
debugLog("port", `Port ${port} is in use, trying ${port + 1}`, verbose);
|
|
57589
57549
|
port++;
|
|
57590
57550
|
}
|
|
57591
|
-
|
|
57551
|
+
debugLog("port", `Found available port: ${port}`, verbose);
|
|
57592
57552
|
return port;
|
|
57593
57553
|
}
|
|
57594
57554
|
async function testConnection(hostname, port, verbose) {
|
|
57595
|
-
|
|
57555
|
+
debugLog("connection", `Testing connection to ${hostname}:${port}`, verbose);
|
|
57596
57556
|
return new Promise((resolve4, reject) => {
|
|
57597
57557
|
const socket = net.connect({
|
|
57598
57558
|
host: hostname,
|
|
@@ -57600,30 +57560,30 @@ async function testConnection(hostname, port, verbose) {
|
|
|
57600
57560
|
timeout: 5000
|
|
57601
57561
|
});
|
|
57602
57562
|
socket.once("connect", () => {
|
|
57603
|
-
|
|
57563
|
+
debugLog("connection", `Successfully connected to ${hostname}:${port}`, verbose);
|
|
57604
57564
|
socket.end();
|
|
57605
57565
|
resolve4();
|
|
57606
57566
|
});
|
|
57607
57567
|
socket.once("timeout", () => {
|
|
57608
|
-
|
|
57568
|
+
debugLog("connection", `Connection to ${hostname}:${port} timed out`, verbose);
|
|
57609
57569
|
socket.destroy();
|
|
57610
57570
|
reject(new Error(`Connection to ${hostname}:${port} timed out`));
|
|
57611
57571
|
});
|
|
57612
57572
|
socket.once("error", (err3) => {
|
|
57613
|
-
|
|
57573
|
+
debugLog("connection", `Failed to connect to ${hostname}:${port}: ${err3}`, verbose);
|
|
57614
57574
|
socket.destroy();
|
|
57615
57575
|
reject(new Error(`Failed to connect to ${hostname}:${port}: ${err3.message}`));
|
|
57616
57576
|
});
|
|
57617
57577
|
});
|
|
57618
57578
|
}
|
|
57619
57579
|
async function startServer(options3) {
|
|
57620
|
-
|
|
57580
|
+
debugLog("server", `Starting server with options: ${JSON.stringify(options3)}`, options3.verbose);
|
|
57621
57581
|
const fromUrl = new URL((options3.from?.startsWith("http") ? options3.from : `http://${options3.from}`) || "localhost:5173");
|
|
57622
57582
|
const toUrl = new URL((options3.to?.startsWith("http") ? options3.to : `http://${options3.to}`) || "stacks.localhost");
|
|
57623
57583
|
const fromPort = Number.parseInt(fromUrl.port) || (fromUrl.protocol.includes("https:") ? 443 : 80);
|
|
57624
57584
|
const hostsToCheck = [toUrl.hostname];
|
|
57625
57585
|
if (!toUrl.hostname.includes("localhost") && !toUrl.hostname.includes("127.0.0.1")) {
|
|
57626
|
-
|
|
57586
|
+
debugLog("hosts", `Checking if hosts file entry exists for: ${toUrl.hostname}`, options3?.verbose);
|
|
57627
57587
|
try {
|
|
57628
57588
|
const hostsExist = await checkHosts(hostsToCheck, options3.verbose);
|
|
57629
57589
|
if (!hostsExist[0]) {
|
|
@@ -57646,7 +57606,7 @@ async function startServer(options3) {
|
|
|
57646
57606
|
}
|
|
57647
57607
|
}
|
|
57648
57608
|
} else {
|
|
57649
|
-
|
|
57609
|
+
debugLog("hosts", `Host entry already exists for ${toUrl.hostname}`, options3.verbose);
|
|
57650
57610
|
}
|
|
57651
57611
|
} catch (checkError) {
|
|
57652
57612
|
log.error("Failed to check hosts file:", checkError.message);
|
|
@@ -57655,7 +57615,7 @@ async function startServer(options3) {
|
|
|
57655
57615
|
try {
|
|
57656
57616
|
await testConnection(fromUrl.hostname, fromPort, options3.verbose);
|
|
57657
57617
|
} catch (err3) {
|
|
57658
|
-
|
|
57618
|
+
debugLog("server", `Connection test failed: ${err3}`, options3.verbose);
|
|
57659
57619
|
log.error(err3.message);
|
|
57660
57620
|
process9.exit(1);
|
|
57661
57621
|
}
|
|
@@ -57669,17 +57629,17 @@ async function startServer(options3) {
|
|
|
57669
57629
|
});
|
|
57670
57630
|
}
|
|
57671
57631
|
try {
|
|
57672
|
-
|
|
57632
|
+
debugLog("ssl", `Attempting to load SSL configuration for ${toUrl.hostname}`, options3.verbose);
|
|
57673
57633
|
sslConfig = await loadSSLConfig({
|
|
57674
57634
|
...options3,
|
|
57675
57635
|
to: toUrl.hostname,
|
|
57676
57636
|
https: options3.https
|
|
57677
57637
|
});
|
|
57678
57638
|
} catch (loadError) {
|
|
57679
|
-
|
|
57639
|
+
debugLog("ssl", `Failed to load certificates, will generate new ones: ${loadError}`, options3.verbose);
|
|
57680
57640
|
}
|
|
57681
57641
|
if (!sslConfig) {
|
|
57682
|
-
|
|
57642
|
+
debugLog("ssl", `Generating new certificates for ${toUrl.hostname}`, options3.verbose);
|
|
57683
57643
|
await generateCertificate2({
|
|
57684
57644
|
...options3,
|
|
57685
57645
|
from: fromUrl.toString(),
|
|
@@ -57696,11 +57656,11 @@ async function startServer(options3) {
|
|
|
57696
57656
|
}
|
|
57697
57657
|
}
|
|
57698
57658
|
} catch (err3) {
|
|
57699
|
-
|
|
57659
|
+
debugLog("server", `SSL setup failed: ${err3}`, options3.verbose);
|
|
57700
57660
|
throw err3;
|
|
57701
57661
|
}
|
|
57702
57662
|
}
|
|
57703
|
-
|
|
57663
|
+
debugLog("server", `Setting up reverse proxy with SSL config for ${toUrl.hostname}`, options3.verbose);
|
|
57704
57664
|
await setupReverseProxy({
|
|
57705
57665
|
...options3,
|
|
57706
57666
|
from: options3.from || "localhost:5173",
|
|
@@ -57714,9 +57674,9 @@ async function startServer(options3) {
|
|
|
57714
57674
|
});
|
|
57715
57675
|
}
|
|
57716
57676
|
async function createProxyServer(from, to, fromPort, listenPort, hostname, sourceUrl, ssl, verbose) {
|
|
57717
|
-
|
|
57677
|
+
debugLog("proxy", `Creating proxy server ${from} -> ${to}`, verbose);
|
|
57718
57678
|
const requestHandler = (req, res) => {
|
|
57719
|
-
|
|
57679
|
+
debugLog("request", `Incoming request: ${req.method} ${req.url}`, verbose);
|
|
57720
57680
|
const proxyOptions = {
|
|
57721
57681
|
hostname: sourceUrl.hostname,
|
|
57722
57682
|
port: fromPort,
|
|
@@ -57727,9 +57687,9 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
|
|
|
57727
57687
|
host: sourceUrl.host
|
|
57728
57688
|
}
|
|
57729
57689
|
};
|
|
57730
|
-
|
|
57690
|
+
debugLog("request", `Proxy request options: ${JSON.stringify(proxyOptions)}`, verbose);
|
|
57731
57691
|
const proxyReq = http.request(proxyOptions, (proxyRes) => {
|
|
57732
|
-
|
|
57692
|
+
debugLog("response", `Proxy response received with status ${proxyRes.statusCode}`, verbose);
|
|
57733
57693
|
const headers = {
|
|
57734
57694
|
...proxyRes.headers,
|
|
57735
57695
|
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
|
|
@@ -57739,7 +57699,7 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
|
|
|
57739
57699
|
proxyRes.pipe(res);
|
|
57740
57700
|
});
|
|
57741
57701
|
proxyReq.on("error", (err3) => {
|
|
57742
|
-
|
|
57702
|
+
debugLog("request", `Proxy request failed: ${err3}`, verbose);
|
|
57743
57703
|
log.error("Proxy request failed:", err3);
|
|
57744
57704
|
res.writeHead(502);
|
|
57745
57705
|
res.end(`Proxy Error: ${err3.message}`);
|
|
@@ -57766,11 +57726,11 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
|
|
|
57766
57726
|
allowHTTP1: true,
|
|
57767
57727
|
ALPNProtocols: ["h2", "http/1.1"]
|
|
57768
57728
|
} : undefined;
|
|
57769
|
-
|
|
57729
|
+
debugLog("server", `Creating server with SSL config: ${!!ssl}`, verbose);
|
|
57770
57730
|
const server = ssl && serverOptions ? https.createServer(serverOptions, requestHandler) : http.createServer(requestHandler);
|
|
57771
57731
|
if (ssl) {
|
|
57772
57732
|
server.on("secureConnection", (tlsSocket) => {
|
|
57773
|
-
|
|
57733
|
+
debugLog("tls", `TLS Connection established: ${JSON.stringify({
|
|
57774
57734
|
protocol: tlsSocket.getProtocol?.(),
|
|
57775
57735
|
cipher: tlsSocket.getCipher?.(),
|
|
57776
57736
|
authorized: tlsSocket.authorized,
|
|
@@ -57781,7 +57741,7 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
|
|
|
57781
57741
|
activeServers.add(server);
|
|
57782
57742
|
return new Promise((resolve4, reject) => {
|
|
57783
57743
|
server.listen(listenPort, hostname, () => {
|
|
57784
|
-
|
|
57744
|
+
debugLog("server", `Server listening on port ${listenPort}`, verbose);
|
|
57785
57745
|
console.log("");
|
|
57786
57746
|
console.log(` ${green(bold("reverse-proxy"))} ${green(`v${version}`)}`);
|
|
57787
57747
|
console.log("");
|
|
@@ -57798,13 +57758,13 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
|
|
|
57798
57758
|
resolve4();
|
|
57799
57759
|
});
|
|
57800
57760
|
server.on("error", (err3) => {
|
|
57801
|
-
|
|
57761
|
+
debugLog("server", `Server error: ${err3}`, verbose);
|
|
57802
57762
|
reject(err3);
|
|
57803
57763
|
});
|
|
57804
57764
|
});
|
|
57805
57765
|
}
|
|
57806
57766
|
async function setupReverseProxy(options3) {
|
|
57807
|
-
|
|
57767
|
+
debugLog("setup", `Setting up reverse proxy: ${JSON.stringify(options3)}`, options3.verbose);
|
|
57808
57768
|
const { from, to, fromPort, sourceUrl, ssl, verbose, etcHostsCleanup, portManager } = options3;
|
|
57809
57769
|
const httpPort = 80;
|
|
57810
57770
|
const httpsPort = 443;
|
|
@@ -57813,11 +57773,11 @@ async function setupReverseProxy(options3) {
|
|
|
57813
57773
|
if (ssl && !portManager?.usedPorts.has(httpPort)) {
|
|
57814
57774
|
const isHttpPortBusy = await isPortInUse(httpPort, hostname, verbose);
|
|
57815
57775
|
if (!isHttpPortBusy) {
|
|
57816
|
-
|
|
57776
|
+
debugLog("setup", "Starting HTTP redirect server", verbose);
|
|
57817
57777
|
startHttpRedirectServer(verbose);
|
|
57818
57778
|
portManager?.usedPorts.add(httpPort);
|
|
57819
57779
|
} else {
|
|
57820
|
-
|
|
57780
|
+
debugLog("setup", "Port 80 is in use, skipping HTTP redirect", verbose);
|
|
57821
57781
|
log.warn("Port 80 is in use, HTTP to HTTPS redirect will not be available");
|
|
57822
57782
|
}
|
|
57823
57783
|
}
|
|
@@ -57835,7 +57795,7 @@ async function setupReverseProxy(options3) {
|
|
|
57835
57795
|
}
|
|
57836
57796
|
await createProxyServer(from, to, fromPort, finalPort, hostname, sourceUrl, ssl, verbose);
|
|
57837
57797
|
} catch (err3) {
|
|
57838
|
-
|
|
57798
|
+
debugLog("setup", `Setup failed: ${err3}`, verbose);
|
|
57839
57799
|
log.error(`Failed to setup reverse proxy: ${err3.message}`);
|
|
57840
57800
|
cleanup({
|
|
57841
57801
|
domains: [to],
|
|
@@ -57845,24 +57805,24 @@ async function setupReverseProxy(options3) {
|
|
|
57845
57805
|
}
|
|
57846
57806
|
}
|
|
57847
57807
|
function startHttpRedirectServer(verbose) {
|
|
57848
|
-
|
|
57808
|
+
debugLog("redirect", "Starting HTTP redirect server", verbose);
|
|
57849
57809
|
const server = http.createServer((req, res) => {
|
|
57850
57810
|
const host = req.headers.host || "";
|
|
57851
|
-
|
|
57811
|
+
debugLog("redirect", `Redirecting request from ${host}${req.url} to HTTPS`, verbose);
|
|
57852
57812
|
res.writeHead(301, {
|
|
57853
57813
|
Location: `https://${host}${req.url}`
|
|
57854
57814
|
});
|
|
57855
57815
|
res.end();
|
|
57856
57816
|
}).listen(80);
|
|
57857
57817
|
activeServers.add(server);
|
|
57858
|
-
|
|
57818
|
+
debugLog("redirect", "HTTP redirect server started", verbose);
|
|
57859
57819
|
}
|
|
57860
57820
|
function startProxy(options3) {
|
|
57861
57821
|
const mergedOptions = {
|
|
57862
57822
|
...config4,
|
|
57863
57823
|
...options3
|
|
57864
57824
|
};
|
|
57865
|
-
|
|
57825
|
+
debugLog("proxy", `Starting proxy with options: ${JSON.stringify(mergedOptions)}`, mergedOptions?.verbose);
|
|
57866
57826
|
const serverOptions = {
|
|
57867
57827
|
from: mergedOptions.from,
|
|
57868
57828
|
to: mergedOptions.to,
|
|
@@ -57872,7 +57832,7 @@ function startProxy(options3) {
|
|
|
57872
57832
|
};
|
|
57873
57833
|
console.log("serverOptions", serverOptions);
|
|
57874
57834
|
startServer(serverOptions).catch((err3) => {
|
|
57875
|
-
|
|
57835
|
+
debugLog("proxy", `Failed to start proxy: ${err3}`, mergedOptions.verbose);
|
|
57876
57836
|
log.error(`Failed to start proxy: ${err3.message}`);
|
|
57877
57837
|
cleanup({
|
|
57878
57838
|
domains: [mergedOptions.to],
|
|
@@ -57882,7 +57842,7 @@ function startProxy(options3) {
|
|
|
57882
57842
|
});
|
|
57883
57843
|
}
|
|
57884
57844
|
async function startProxies(options3) {
|
|
57885
|
-
|
|
57845
|
+
debugLog("proxies", "Starting proxy setup", options3?.verbose);
|
|
57886
57846
|
const mergedOptions = {
|
|
57887
57847
|
...config4,
|
|
57888
57848
|
...options3
|
|
@@ -57891,10 +57851,10 @@ async function startProxies(options3) {
|
|
|
57891
57851
|
if (mergedOptions.https) {
|
|
57892
57852
|
const existingSSLConfig = await checkExistingCertificates(mergedOptions);
|
|
57893
57853
|
if (existingSSLConfig) {
|
|
57894
|
-
|
|
57854
|
+
debugLog("ssl", `Using existing certificates for ${primaryDomain}`, mergedOptions.verbose);
|
|
57895
57855
|
mergedOptions._cachedSSLConfig = existingSSLConfig;
|
|
57896
57856
|
} else {
|
|
57897
|
-
|
|
57857
|
+
debugLog("ssl", `No valid certificates found for ${primaryDomain}, generating new ones`, mergedOptions.verbose);
|
|
57898
57858
|
await generateCertificate2(mergedOptions);
|
|
57899
57859
|
const sslConfig2 = await checkExistingCertificates(mergedOptions);
|
|
57900
57860
|
if (!sslConfig2) {
|
|
@@ -57927,14 +57887,14 @@ async function startProxies(options3) {
|
|
|
57927
57887
|
process9.on("SIGINT", cleanupHandler);
|
|
57928
57888
|
process9.on("SIGTERM", cleanupHandler);
|
|
57929
57889
|
process9.on("uncaughtException", (err3) => {
|
|
57930
|
-
|
|
57890
|
+
debugLog("process", `Uncaught exception: ${err3}`, true);
|
|
57931
57891
|
console.error("Uncaught exception:", err3);
|
|
57932
57892
|
cleanupHandler();
|
|
57933
57893
|
});
|
|
57934
57894
|
for (const option of proxyOptions) {
|
|
57935
57895
|
try {
|
|
57936
57896
|
const domain = option.to || "stacks.localhost";
|
|
57937
|
-
|
|
57897
|
+
debugLog("proxy", `Starting proxy for ${domain} with SSL config: ${!!sslConfig}`, option.verbose);
|
|
57938
57898
|
await startServer({
|
|
57939
57899
|
from: option.from || "localhost:5173",
|
|
57940
57900
|
to: domain,
|
|
@@ -57944,7 +57904,7 @@ async function startProxies(options3) {
|
|
|
57944
57904
|
_cachedSSLConfig: sslConfig
|
|
57945
57905
|
});
|
|
57946
57906
|
} catch (err3) {
|
|
57947
|
-
|
|
57907
|
+
debugLog("proxies", `Failed to start proxy for ${option.to}: ${err3}`, option.verbose);
|
|
57948
57908
|
console.error(`Failed to start proxy for ${option.to}:`, err3);
|
|
57949
57909
|
cleanupHandler();
|
|
57950
57910
|
}
|
|
@@ -57976,7 +57936,7 @@ export {
|
|
|
57976
57936
|
generateCertificate2 as generateCertificate,
|
|
57977
57937
|
extractHostname,
|
|
57978
57938
|
src_default as default,
|
|
57979
|
-
|
|
57939
|
+
debugLog,
|
|
57980
57940
|
config4 as config,
|
|
57981
57941
|
cleanup,
|
|
57982
57942
|
checkHosts,
|