@stacksjs/rpx 0.4.1 → 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/index.js CHANGED
@@ -17,11 +17,10 @@ var __toESM = (mod, isNodeMode, target) => {
17
17
  };
18
18
 
19
19
  // src/start.ts
20
- import * as fs5 from "fs";
21
20
  import * as http from "http";
22
21
  import * as https from "https";
23
22
  import * as net from "net";
24
- import process20 from "process";
23
+ import process9 from "process";
25
24
 
26
25
  // node_modules/@stacksjs/cli/dist/index.js
27
26
  import { formatWithOptions } from "util";
@@ -20468,18 +20467,255 @@ var quotes = collect([
20468
20467
  ]);
20469
20468
  var export_prompts = import_prompts.default;
20470
20469
  // package.json
20471
- var version = "0.4.1";
20470
+ var version = "0.5.1";
20471
+
20472
+ // src/config.ts
20473
+ import { homedir } from "os";
20474
+ import { join as join2 } from "path";
20475
+
20476
+ // node_modules/bun-config/dist/index.js
20477
+ import { resolve } from "path";
20478
+ import process2 from "process";
20479
+ function deepMerge(target, source) {
20480
+ if (Array.isArray(source) && !Array.isArray(target)) {
20481
+ return source;
20482
+ }
20483
+ if (Array.isArray(source) && Array.isArray(target)) {
20484
+ return source.map((sourceItem, index) => {
20485
+ const targetItem = target[index];
20486
+ if (isObject3(sourceItem) && isObject3(targetItem)) {
20487
+ return deepMerge(targetItem, sourceItem);
20488
+ }
20489
+ return sourceItem;
20490
+ });
20491
+ }
20492
+ if (!isObject3(source) || !isObject3(target)) {
20493
+ return source;
20494
+ }
20495
+ const merged = { ...target };
20496
+ for (const key in source) {
20497
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
20498
+ const sourceValue = source[key];
20499
+ const targetValue = merged[key];
20500
+ if (sourceValue === null || sourceValue === undefined) {
20501
+ merged[key] = sourceValue;
20502
+ } else if (isObject3(sourceValue) && isObject3(targetValue)) {
20503
+ merged[key] = deepMerge(targetValue, sourceValue);
20504
+ } else {
20505
+ merged[key] = sourceValue;
20506
+ }
20507
+ }
20508
+ }
20509
+ return merged;
20510
+ }
20511
+ function isObject3(item) {
20512
+ return Boolean(item && typeof item === "object" && !Array.isArray(item));
20513
+ }
20514
+ async function loadConfig({ name, cwd, defaultConfig }) {
20515
+ const configPath = resolve(cwd || process2.cwd(), `${name}.config`);
20516
+ try {
20517
+ const importedConfig = await import(configPath);
20518
+ const loadedConfig = importedConfig.default || importedConfig;
20519
+ return deepMerge(defaultConfig, loadedConfig);
20520
+ } catch (error) {
20521
+ return defaultConfig;
20522
+ }
20523
+ }
20524
+
20525
+ // src/config.ts
20526
+ var defaultConfig = {
20527
+ from: "localhost:5173",
20528
+ to: "stacks.localhost",
20529
+ https: {
20530
+ basePath: "",
20531
+ caCertPath: join2(homedir(), ".stacks", "ssl", `stacks.localhost.ca.crt`),
20532
+ certPath: join2(homedir(), ".stacks", "ssl", `stacks.localhost.crt`),
20533
+ keyPath: join2(homedir(), ".stacks", "ssl", `stacks.localhost.crt.key`)
20534
+ },
20535
+ etcHostsCleanup: true,
20536
+ verbose: true
20537
+ };
20538
+ var config4 = await loadConfig({
20539
+ name: "reverse-proxy",
20540
+ defaultConfig
20541
+ });
20472
20542
 
20473
20543
  // src/hosts.ts
20474
- import { spawn } from "child_process";
20475
- import fs3 from "fs";
20476
- import os7 from "os";
20477
- import path7 from "path";
20478
- import process9 from "process";
20544
+ import { exec } from "child_process";
20545
+ import fs from "fs";
20546
+ import os2 from "os";
20547
+ import path from "path";
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
+ }
20479
20714
 
20480
20715
  // src/https.ts
20481
- import os5 from "os";
20482
- import path6 from "path";
20716
+ import fs5 from "fs/promises";
20717
+ import { homedir as homedir2 } from "os";
20718
+ import { join as join4 } from "path";
20483
20719
 
20484
20720
  // node_modules/@stacksjs/tlsx/dist/index.js
20485
20721
  import fs2 from "fs";
@@ -20503,7 +20739,7 @@ import {
20503
20739
  dirname as dirname3,
20504
20740
  extname as extname2,
20505
20741
  isAbsolute as isAbsolute2,
20506
- join as join2,
20742
+ join as join3,
20507
20743
  normalize as normalize2,
20508
20744
  parse as parse2,
20509
20745
  relative as relative2,
@@ -20518,7 +20754,7 @@ import process8 from "process";
20518
20754
  import process102 from "process";
20519
20755
  import process182 from "process";
20520
20756
  import process112 from "process";
20521
- import os2 from "os";
20757
+ import os3 from "os";
20522
20758
  import tty32 from "tty";
20523
20759
  import process142 from "process";
20524
20760
  import process132 from "process";
@@ -20527,11 +20763,11 @@ import process162 from "process";
20527
20763
  import process172 from "process";
20528
20764
  import process192 from "process";
20529
20765
  import os22 from "os";
20530
- import path from "path";
20531
- import { resolve } from "path";
20532
- import process2 from "process";
20533
- import fs from "fs";
20534
20766
  import path2 from "path";
20767
+ import { resolve as resolve3 } from "path";
20768
+ import process22 from "process";
20769
+ import fs3 from "fs";
20770
+ import path22 from "path";
20535
20771
  var __create3 = Object.create;
20536
20772
  var __getProtoOf3 = Object.getPrototypeOf;
20537
20773
  var __defProp3 = Object.defineProperty;
@@ -36874,11 +37110,11 @@ var __export3 = (target, all) => {
36874
37110
  });
36875
37111
  };
36876
37112
  var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
36877
- function isObject3(value) {
37113
+ function isObject5(value) {
36878
37114
  return value !== null && typeof value === "object";
36879
37115
  }
36880
37116
  function _defu2(baseObject, defaults, namespace = ".", merger) {
36881
- if (!isObject3(defaults)) {
37117
+ if (!isObject5(defaults)) {
36882
37118
  return _defu2(baseObject, {}, namespace, merger);
36883
37119
  }
36884
37120
  const object = Object.assign({}, defaults);
@@ -36895,7 +37131,7 @@ function _defu2(baseObject, defaults, namespace = ".", merger) {
36895
37131
  }
36896
37132
  if (Array.isArray(value) && Array.isArray(object[key])) {
36897
37133
  object[key] = [...value, ...object[key]];
36898
- } else if (isObject3(value) && isObject3(object[key])) {
37134
+ } else if (isObject5(value) && isObject5(object[key])) {
36899
37135
  object[key] = _defu2(value, object[key], (namespace ? `${namespace}.` : "") + key.toString(), merger);
36900
37136
  } else {
36901
37137
  object[key] = value;
@@ -41302,7 +41538,7 @@ var require_prompt3 = __commonJS22((exports, module) => {
41302
41538
  module.exports = Prompt;
41303
41539
  });
41304
41540
  var require_text3 = __commonJS22((exports, module) => {
41305
- function asyncGeneratorStep(gen, resolve3, reject, _next, _throw, key, arg) {
41541
+ function asyncGeneratorStep(gen, resolve32, reject, _next, _throw, key, arg) {
41306
41542
  try {
41307
41543
  var info = gen[key](arg);
41308
41544
  var value = info.value;
@@ -41311,7 +41547,7 @@ var require_text3 = __commonJS22((exports, module) => {
41311
41547
  return;
41312
41548
  }
41313
41549
  if (info.done) {
41314
- resolve3(value);
41550
+ resolve32(value);
41315
41551
  } else {
41316
41552
  Promise.resolve(value).then(_next, _throw);
41317
41553
  }
@@ -41319,13 +41555,13 @@ var require_text3 = __commonJS22((exports, module) => {
41319
41555
  function _asyncToGenerator(fn) {
41320
41556
  return function() {
41321
41557
  var self2 = this, args = arguments;
41322
- return new Promise(function(resolve3, reject) {
41558
+ return new Promise(function(resolve32, reject) {
41323
41559
  var gen = fn.apply(self2, args);
41324
41560
  function _next(value) {
41325
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "next", value);
41561
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "next", value);
41326
41562
  }
41327
41563
  function _throw(err2) {
41328
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "throw", err2);
41564
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "throw", err2);
41329
41565
  }
41330
41566
  _next(undefined);
41331
41567
  });
@@ -42017,7 +42253,7 @@ var require_dateparts3 = __commonJS22((exports, module) => {
42017
42253
  };
42018
42254
  });
42019
42255
  var require_date3 = __commonJS22((exports, module) => {
42020
- function asyncGeneratorStep(gen, resolve3, reject, _next, _throw, key, arg) {
42256
+ function asyncGeneratorStep(gen, resolve32, reject, _next, _throw, key, arg) {
42021
42257
  try {
42022
42258
  var info = gen[key](arg);
42023
42259
  var value = info.value;
@@ -42026,7 +42262,7 @@ var require_date3 = __commonJS22((exports, module) => {
42026
42262
  return;
42027
42263
  }
42028
42264
  if (info.done) {
42029
- resolve3(value);
42265
+ resolve32(value);
42030
42266
  } else {
42031
42267
  Promise.resolve(value).then(_next, _throw);
42032
42268
  }
@@ -42034,13 +42270,13 @@ var require_date3 = __commonJS22((exports, module) => {
42034
42270
  function _asyncToGenerator(fn) {
42035
42271
  return function() {
42036
42272
  var self2 = this, args = arguments;
42037
- return new Promise(function(resolve3, reject) {
42273
+ return new Promise(function(resolve32, reject) {
42038
42274
  var gen = fn.apply(self2, args);
42039
42275
  function _next(value) {
42040
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "next", value);
42276
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "next", value);
42041
42277
  }
42042
42278
  function _throw(err2) {
42043
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "throw", err2);
42279
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "throw", err2);
42044
42280
  }
42045
42281
  _next(undefined);
42046
42282
  });
@@ -42242,7 +42478,7 @@ ${i ? ` ` : figures.pointerSmall} ${color.red().italic(l3)}`, ``);
42242
42478
  module.exports = DatePrompt;
42243
42479
  });
42244
42480
  var require_number3 = __commonJS22((exports, module) => {
42245
- function asyncGeneratorStep(gen, resolve3, reject, _next, _throw, key, arg) {
42481
+ function asyncGeneratorStep(gen, resolve32, reject, _next, _throw, key, arg) {
42246
42482
  try {
42247
42483
  var info = gen[key](arg);
42248
42484
  var value = info.value;
@@ -42251,7 +42487,7 @@ var require_number3 = __commonJS22((exports, module) => {
42251
42487
  return;
42252
42488
  }
42253
42489
  if (info.done) {
42254
- resolve3(value);
42490
+ resolve32(value);
42255
42491
  } else {
42256
42492
  Promise.resolve(value).then(_next, _throw);
42257
42493
  }
@@ -42259,13 +42495,13 @@ var require_number3 = __commonJS22((exports, module) => {
42259
42495
  function _asyncToGenerator(fn) {
42260
42496
  return function() {
42261
42497
  var self2 = this, args = arguments;
42262
- return new Promise(function(resolve3, reject) {
42498
+ return new Promise(function(resolve32, reject) {
42263
42499
  var gen = fn.apply(self2, args);
42264
42500
  function _next(value) {
42265
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "next", value);
42501
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "next", value);
42266
42502
  }
42267
42503
  function _throw(err2) {
42268
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "throw", err2);
42504
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "throw", err2);
42269
42505
  }
42270
42506
  _next(undefined);
42271
42507
  });
@@ -42697,7 +42933,7 @@ Instructions:
42697
42933
  module.exports = MultiselectPrompt;
42698
42934
  });
42699
42935
  var require_autocomplete3 = __commonJS22((exports, module) => {
42700
- function asyncGeneratorStep(gen, resolve3, reject, _next, _throw, key, arg) {
42936
+ function asyncGeneratorStep(gen, resolve32, reject, _next, _throw, key, arg) {
42701
42937
  try {
42702
42938
  var info = gen[key](arg);
42703
42939
  var value = info.value;
@@ -42706,7 +42942,7 @@ var require_autocomplete3 = __commonJS22((exports, module) => {
42706
42942
  return;
42707
42943
  }
42708
42944
  if (info.done) {
42709
- resolve3(value);
42945
+ resolve32(value);
42710
42946
  } else {
42711
42947
  Promise.resolve(value).then(_next, _throw);
42712
42948
  }
@@ -42714,13 +42950,13 @@ var require_autocomplete3 = __commonJS22((exports, module) => {
42714
42950
  function _asyncToGenerator(fn) {
42715
42951
  return function() {
42716
42952
  var self2 = this, args = arguments;
42717
- return new Promise(function(resolve3, reject) {
42953
+ return new Promise(function(resolve32, reject) {
42718
42954
  var gen = fn.apply(self2, args);
42719
42955
  function _next(value) {
42720
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "next", value);
42956
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "next", value);
42721
42957
  }
42722
42958
  function _throw(err2) {
42723
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "throw", err2);
42959
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "throw", err2);
42724
42960
  }
42725
42961
  _next(undefined);
42726
42962
  });
@@ -43369,7 +43605,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
43369
43605
  arr2[i] = arr[i];
43370
43606
  return arr2;
43371
43607
  }
43372
- function asyncGeneratorStep(gen, resolve3, reject, _next, _throw, key, arg) {
43608
+ function asyncGeneratorStep(gen, resolve32, reject, _next, _throw, key, arg) {
43373
43609
  try {
43374
43610
  var info = gen[key](arg);
43375
43611
  var value = info.value;
@@ -43378,7 +43614,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
43378
43614
  return;
43379
43615
  }
43380
43616
  if (info.done) {
43381
- resolve3(value);
43617
+ resolve32(value);
43382
43618
  } else {
43383
43619
  Promise.resolve(value).then(_next, _throw);
43384
43620
  }
@@ -43386,13 +43622,13 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
43386
43622
  function _asyncToGenerator(fn) {
43387
43623
  return function() {
43388
43624
  var self2 = this, args = arguments;
43389
- return new Promise(function(resolve3, reject) {
43625
+ return new Promise(function(resolve32, reject) {
43390
43626
  var gen = fn.apply(self2, args);
43391
43627
  function _next(value) {
43392
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "next", value);
43628
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "next", value);
43393
43629
  }
43394
43630
  function _throw(err2) {
43395
- asyncGeneratorStep(gen, resolve3, reject, _next, _throw, "throw", err2);
43631
+ asyncGeneratorStep(gen, resolve32, reject, _next, _throw, "throw", err2);
43396
43632
  }
43397
43633
  _next(undefined);
43398
43634
  });
@@ -48055,31 +48291,31 @@ var log2 = {
48055
48291
  },
48056
48292
  echo: (...args) => console.log(...args)
48057
48293
  };
48058
- function userDatabasePath2(path22) {
48059
- return projectPath2(`database/${path22 || ""}`);
48294
+ function userDatabasePath2(path23) {
48295
+ return projectPath2(`database/${path23 || ""}`);
48060
48296
  }
48061
- function appPath2(path22) {
48062
- return projectPath2(`app/${path22 || ""}`);
48297
+ function appPath2(path23) {
48298
+ return projectPath2(`app/${path23 || ""}`);
48063
48299
  }
48064
- function commandsPath2(path22) {
48065
- return appPath2(`Commands/${path22 || ""}`);
48300
+ function commandsPath2(path23) {
48301
+ return appPath2(`Commands/${path23 || ""}`);
48066
48302
  }
48067
- function logsPath2(path22) {
48068
- return storagePath2(`logs/${path22 || ""}`);
48303
+ function logsPath2(path23) {
48304
+ return storagePath2(`logs/${path23 || ""}`);
48069
48305
  }
48070
48306
  function projectPath2(filePath = "", options2) {
48071
- let path22 = process52.cwd();
48072
- while (path22.includes("storage"))
48073
- path22 = resolve22(path22, "..");
48074
- const finalPath = resolve22(path22, filePath);
48307
+ let path23 = process52.cwd();
48308
+ while (path23.includes("storage"))
48309
+ path23 = resolve22(path23, "..");
48310
+ const finalPath = resolve22(path23, filePath);
48075
48311
  if (options2?.relative)
48076
48312
  return relative2(process52.cwd(), finalPath);
48077
48313
  return finalPath;
48078
48314
  }
48079
- function storagePath2(path22) {
48080
- return projectPath2(`storage/${path22 || ""}`);
48315
+ function storagePath2(path23) {
48316
+ return projectPath2(`storage/${path23 || ""}`);
48081
48317
  }
48082
- var config4 = {
48318
+ var config6 = {
48083
48319
  ai: {
48084
48320
  deploy: false,
48085
48321
  models: [
@@ -48656,7 +48892,7 @@ var config4 = {
48656
48892
  }
48657
48893
  }
48658
48894
  };
48659
- var defaults_default2 = config4;
48895
+ var defaults_default2 = config6;
48660
48896
  var ai_default2 = {
48661
48897
  default: "meta.llama2-70b-chat-v1",
48662
48898
  models: [
@@ -53276,11 +53512,11 @@ var createNeverThrowError2 = (message, result, config5 = defaultErrorConfig2) =>
53276
53512
  };
53277
53513
  function __awaiter2(thisArg, _arguments, P22, generator) {
53278
53514
  function adopt(value) {
53279
- return value instanceof P22 ? value : new P22(function(resolve3) {
53280
- resolve3(value);
53515
+ return value instanceof P22 ? value : new P22(function(resolve32) {
53516
+ resolve32(value);
53281
53517
  });
53282
53518
  }
53283
- return new (P22 || (P22 = Promise))(function(resolve3, reject) {
53519
+ return new (P22 || (P22 = Promise))(function(resolve32, reject) {
53284
53520
  function fulfilled(value) {
53285
53521
  try {
53286
53522
  step(generator.next(value));
@@ -53296,7 +53532,7 @@ function __awaiter2(thisArg, _arguments, P22, generator) {
53296
53532
  }
53297
53533
  }
53298
53534
  function step(result) {
53299
- result.done ? resolve3(result.value) : adopt(result.value).then(fulfilled, rejected);
53535
+ result.done ? resolve32(result.value) : adopt(result.value).then(fulfilled, rejected);
53300
53536
  }
53301
53537
  step((generator = generator.apply(thisArg, _arguments || [])).next());
53302
53538
  });
@@ -53384,14 +53620,14 @@ function __asyncValues2(o) {
53384
53620
  }, i);
53385
53621
  function verb(n) {
53386
53622
  i[n] = o[n] && function(v22) {
53387
- return new Promise(function(resolve3, reject) {
53388
- v22 = o[n](v22), settle(resolve3, reject, v22.done, v22.value);
53623
+ return new Promise(function(resolve32, reject) {
53624
+ v22 = o[n](v22), settle(resolve32, reject, v22.done, v22.value);
53389
53625
  });
53390
53626
  };
53391
53627
  }
53392
- function settle(resolve3, reject, d, v22) {
53628
+ function settle(resolve32, reject, d, v22) {
53393
53629
  Promise.resolve(v22).then(function(v3) {
53394
- resolve3({ value: v3, done: d });
53630
+ resolve32({ value: v3, done: d });
53395
53631
  }, reject);
53396
53632
  }
53397
53633
  }
@@ -53692,7 +53928,7 @@ class Err2 {
53692
53928
  }
53693
53929
  var fromThrowable2 = Result2.fromThrowable;
53694
53930
  var import_prompts2 = __toESM22(require_prompts32(), 1);
53695
- async function exec(command, options2) {
53931
+ async function exec2(command, options2) {
53696
53932
  const cmd = Array.isArray(command) ? command : command.match(/(?:[^\s"]|"[^"]*")+/g);
53697
53933
  log2.debug("exec:", Array.isArray(command) ? command.join(" ") : command, options2);
53698
53934
  log2.debug("cmd:", cmd);
@@ -53738,7 +53974,7 @@ async function runCommand(command, options2) {
53738
53974
  stdio: options2?.stdio ?? [options2?.stdin ?? "inherit", "pipe", "pipe"],
53739
53975
  verbose: options2?.verbose ?? false
53740
53976
  };
53741
- return await exec(command, opts);
53977
+ return await exec2(command, opts);
53742
53978
  }
53743
53979
  var exports_esm2 = {};
53744
53980
  __export3(exports_esm2, {
@@ -54164,7 +54400,7 @@ function _supportsColor2(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
54164
54400
  return min;
54165
54401
  }
54166
54402
  if (process112.platform === "win32") {
54167
- const osRelease = os2.release().split(".");
54403
+ const osRelease = os3.release().split(".");
54168
54404
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
54169
54405
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
54170
54406
  }
@@ -56703,7 +56939,7 @@ var quotes2 = collect2([
56703
56939
  ]);
56704
56940
  var export_prompts2 = import_prompts2.default;
56705
56941
  var import_node_forge2 = __toESM3(require_lib2(), 1);
56706
- function deepMerge(target, source) {
56942
+ function deepMerge2(target, source) {
56707
56943
  if (Array.isArray(source) && !Array.isArray(target)) {
56708
56944
  return source;
56709
56945
  }
@@ -56711,7 +56947,7 @@ function deepMerge(target, source) {
56711
56947
  return source.map((sourceItem, index) => {
56712
56948
  const targetItem = target[index];
56713
56949
  if (isObject32(sourceItem) && isObject32(targetItem)) {
56714
- return deepMerge(targetItem, sourceItem);
56950
+ return deepMerge2(targetItem, sourceItem);
56715
56951
  }
56716
56952
  return sourceItem;
56717
56953
  });
@@ -56727,7 +56963,7 @@ function deepMerge(target, source) {
56727
56963
  if (sourceValue === null || sourceValue === undefined) {
56728
56964
  merged[key] = sourceValue;
56729
56965
  } else if (isObject32(sourceValue) && isObject32(targetValue)) {
56730
- merged[key] = deepMerge(targetValue, sourceValue);
56966
+ merged[key] = deepMerge2(targetValue, sourceValue);
56731
56967
  } else {
56732
56968
  merged[key] = sourceValue;
56733
56969
  }
@@ -56738,35 +56974,37 @@ function deepMerge(target, source) {
56738
56974
  function isObject32(item) {
56739
56975
  return Boolean(item && typeof item === "object" && !Array.isArray(item));
56740
56976
  }
56741
- async function loadConfig({ name, cwd, defaultConfig }) {
56742
- const configPath = resolve(cwd || process2.cwd(), `${name}.config`);
56977
+ async function loadConfig2({ name, cwd, defaultConfig: defaultConfig2 }) {
56978
+ const configPath = resolve3(cwd || process22.cwd(), `${name}.config`);
56743
56979
  try {
56744
56980
  const importedConfig = await import(configPath);
56745
56981
  const loadedConfig = importedConfig.default || importedConfig;
56746
- return deepMerge(defaultConfig, loadedConfig);
56982
+ return deepMerge2(defaultConfig2, loadedConfig);
56747
56983
  } catch (error) {
56748
- return defaultConfig;
56749
- }
56750
- }
56751
- var config42 = await loadConfig({
56984
+ return defaultConfig2;
56985
+ }
56986
+ }
56987
+ var defaultConfig2 = {
56988
+ altNameIPs: ["127.0.0.1"],
56989
+ altNameURIs: ["localhost"],
56990
+ organizationName: "Local Development",
56991
+ countryName: "US",
56992
+ stateName: "California",
56993
+ localityName: "Playa Vista",
56994
+ commonName: "stacks.localhost",
56995
+ validityDays: 825,
56996
+ hostCertCN: "stacks.localhost",
56997
+ domain: "stacks.localhost",
56998
+ rootCA: { certificate: "", privateKey: "" },
56999
+ basePath: "",
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`),
57003
+ verbose: false
57004
+ };
57005
+ var config42 = await loadConfig2({
56752
57006
  name: "tls",
56753
- defaultConfig: {
56754
- altNameIPs: ["127.0.0.1"],
56755
- altNameURIs: ["localhost"],
56756
- organizationName: "Local Development",
56757
- countryName: "US",
56758
- stateName: "California",
56759
- localityName: "Playa Vista",
56760
- commonName: "stacks.localhost",
56761
- validityDays: 825,
56762
- hostCertCN: "stacks.localhost",
56763
- domain: "stacks.localhost",
56764
- rootCAObject: { certificate: "", privateKey: "" },
56765
- caCertPath: path.join(os22.homedir(), ".stacks", "ssl", `stacks.localhost.ca.crt`),
56766
- certPath: path.join(os22.homedir(), ".stacks", "ssl", `stacks.localhost.crt`),
56767
- keyPath: path.join(os22.homedir(), ".stacks", "ssl", `stacks.localhost.crt.key`),
56768
- verbose: false
56769
- }
57007
+ defaultConfig: defaultConfig2
56770
57008
  });
56771
57009
  var import_node_forge = __toESM3(require_lib2(), 1);
56772
57010
  function makeNumberPositive(hexString) {
@@ -56780,10 +57018,10 @@ function findFoldersWithFile(rootDir, fileName) {
56780
57018
  const result = [];
56781
57019
  function search(dir) {
56782
57020
  try {
56783
- const files = fs.readdirSync(dir);
57021
+ const files = fs3.readdirSync(dir);
56784
57022
  for (const file of files) {
56785
- const filePath = path2.join(dir, file);
56786
- const stats = fs.lstatSync(filePath);
57023
+ const filePath = path22.join(dir, file);
57024
+ const stats = fs3.lstatSync(filePath);
56787
57025
  if (stats.isDirectory()) {
56788
57026
  search(filePath);
56789
57027
  } else if (file === fileName) {
@@ -56797,26 +57035,26 @@ function findFoldersWithFile(rootDir, fileName) {
56797
57035
  search(rootDir);
56798
57036
  return result;
56799
57037
  }
56800
- function debugLog(category, message, verbose) {
57038
+ function debugLog2(category, message, verbose) {
56801
57039
  if (verbose || config42.verbose) {
56802
57040
  console.debug(`[tlsx:${category}] ${message}`);
56803
57041
  }
56804
57042
  }
56805
57043
  function generateRandomSerial(verbose) {
56806
- debugLog("cert", "Generating random serial number", verbose);
57044
+ debugLog2("cert", "Generating random serial number", verbose);
56807
57045
  const serialNumber = makeNumberPositive(import_node_forge2.default.util.bytesToHex(import_node_forge2.default.random.getBytesSync(20)));
56808
- debugLog("cert", `Generated serial number: ${serialNumber}`, verbose);
57046
+ debugLog2("cert", `Generated serial number: ${serialNumber}`, verbose);
56809
57047
  return serialNumber;
56810
57048
  }
56811
57049
  function calculateValidityDates(options22) {
56812
57050
  const notBeforeDays = options22.notBeforeDays ?? 2;
56813
57051
  const validityDays = options22.validityDays ?? (options22.validityYears ? options22.validityYears * 365 : 180);
56814
- debugLog("cert", "Calculating certificate validity dates", options22.verbose);
57052
+ debugLog2("cert", "Calculating certificate validity dates", options22.verbose);
56815
57053
  const notBefore = new Date(Date.now() - 86400 * notBeforeDays * 1000);
56816
57054
  const notAfter = new Date(notBefore.getTime() + validityDays * 24 * 60 * 60 * 1000);
56817
57055
  notBefore.setUTCHours(0, 0, 0, 0);
56818
57056
  notAfter.setUTCHours(23, 59, 59, 999);
56819
- debugLog("cert", `Validity period: ${notBefore.toISOString()} to ${notAfter.toISOString()}`, options22.verbose);
57057
+ debugLog2("cert", `Validity period: ${notBefore.toISOString()} to ${notAfter.toISOString()}`, options22.verbose);
56820
57058
  return { notBefore, notAfter };
56821
57059
  }
56822
57060
  function generateCertificateExtensions(options22) {
@@ -56849,9 +57087,9 @@ function generateCertificateExtensions(options22) {
56849
57087
  return extensions;
56850
57088
  }
56851
57089
  async function createRootCA(options22 = {}) {
56852
- debugLog("ca", "Creating new Root CA Certificate", options22.verbose);
57090
+ debugLog2("ca", "Creating new Root CA Certificate", options22.verbose);
56853
57091
  const keySize = options22.keySize || 2048;
56854
- debugLog("ca", `Generating ${keySize}-bit RSA key pair`, options22.verbose);
57092
+ debugLog2("ca", `Generating ${keySize}-bit RSA key pair`, options22.verbose);
56855
57093
  const { privateKey, publicKey } = import_node_forge2.pki.rsa.generateKeyPair(keySize);
56856
57094
  const attributes = [
56857
57095
  { shortName: "C", value: options22.countryName || config42.countryName },
@@ -56898,14 +57136,14 @@ async function createRootCA(options22 = {}) {
56898
57136
  };
56899
57137
  }
56900
57138
  async function generateCertificate(options22) {
56901
- debugLog("cert", "Generating new certificate", options22.verbose);
56902
- debugLog("cert", `Options: ${JSON.stringify(options22)}`, options22.verbose);
56903
- if (!options22.rootCAObject?.certificate || !options22.rootCAObject?.privateKey) {
57139
+ debugLog2("cert", "Generating new certificate", options22.verbose);
57140
+ debugLog2("cert", `Options: ${JSON.stringify(options22)}`, options22.verbose);
57141
+ if (!options22.rootCA?.certificate || !options22.rootCA?.privateKey) {
56904
57142
  throw new Error("Root CA certificate and private key are required");
56905
57143
  }
56906
- const caCert = import_node_forge2.pki.certificateFromPem(options22.rootCAObject.certificate);
56907
- const caKey = import_node_forge2.pki.privateKeyFromPem(options22.rootCAObject.privateKey);
56908
- debugLog("cert", "Generating 2048-bit RSA key pair for host certificate", options22?.verbose);
57144
+ const caCert = import_node_forge2.pki.certificateFromPem(options22.rootCA.certificate);
57145
+ const caKey = import_node_forge2.pki.privateKeyFromPem(options22.rootCA.privateKey);
57146
+ debugLog2("cert", "Generating 2048-bit RSA key pair for host certificate", options22.verbose);
56909
57147
  const keySize = 2048;
56910
57148
  const { privateKey, publicKey } = import_node_forge2.pki.rsa.generateKeyPair(keySize);
56911
57149
  const attributes = options22.certificateAttributes || [
@@ -56936,253 +57174,217 @@ async function generateCertificate(options22) {
56936
57174
  };
56937
57175
  }
56938
57176
  async function addCertToSystemTrustStoreAndSaveCert(cert, caCert, options22) {
56939
- debugLog("trust", `Adding certificate to system trust store with options: ${JSON.stringify(options22)}`, options22?.verbose);
56940
- debugLog("trust", "Storing certificate and private key", options22?.verbose);
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);
56941
57179
  const certPath = storeCertificate(cert, options22);
56942
- debugLog("trust", "Storing CA certificate", options22?.verbose);
57180
+ debugLog2("trust", "Storing CA certificate", options22?.verbose);
56943
57181
  const caCertPath = storeCACertificate(caCert, options22);
56944
57182
  const platform22 = os4.platform();
56945
- debugLog("trust", `Detected platform: ${platform22}`, options22?.verbose);
57183
+ debugLog2("trust", `Detected platform: ${platform22}`, options22?.verbose);
56946
57184
  const args = "TC, C, C";
56947
57185
  if (platform22 === "darwin") {
56948
- debugLog("trust", "Adding certificate to macOS keychain", options22?.verbose);
57186
+ debugLog2("trust", "Adding certificate to macOS keychain", options22?.verbose);
56949
57187
  await runCommand(`sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${caCertPath}`);
56950
57188
  } else if (platform22 === "win32") {
56951
- debugLog("trust", "Adding certificate to Windows certificate store", options22?.verbose);
57189
+ debugLog2("trust", "Adding certificate to Windows certificate store", options22?.verbose);
56952
57190
  await runCommand(`certutil -f -v -addstore -enterprise Root ${caCertPath}`);
56953
57191
  } else if (platform22 === "linux") {
56954
- debugLog("trust", "Adding certificate to Linux certificate store", options22?.verbose);
57192
+ debugLog2("trust", "Adding certificate to Linux certificate store", options22?.verbose);
56955
57193
  const rootDirectory = os4.homedir();
56956
57194
  const targetFileName = "cert9.db";
56957
- debugLog("trust", `Searching for certificate databases in ${rootDirectory}`, options22?.verbose);
57195
+ debugLog2("trust", `Searching for certificate databases in ${rootDirectory}`, options22?.verbose);
56958
57196
  const foldersWithFile = findFoldersWithFile(rootDirectory, targetFileName);
56959
57197
  for (const folder of foldersWithFile) {
56960
- debugLog("trust", `Processing certificate database in ${folder}`, options22?.verbose);
57198
+ debugLog2("trust", `Processing certificate database in ${folder}`, options22?.verbose);
56961
57199
  try {
56962
- debugLog("trust", `Attempting to delete existing cert for ${config42.commonName}`, options22?.verbose);
57200
+ debugLog2("trust", `Attempting to delete existing cert for ${config42.commonName}`, options22?.verbose);
56963
57201
  await runCommand(`certutil -d sql:${folder} -D -n ${config42.commonName}`);
56964
57202
  } catch (error) {
56965
- debugLog("trust", `Warning: Error deleting existing cert: ${error}`, options22?.verbose);
57203
+ debugLog2("trust", `Warning: Error deleting existing cert: ${error}`, options22?.verbose);
56966
57204
  console.warn(`Error deleting existing cert: ${error}`);
56967
57205
  }
56968
- debugLog("trust", `Adding new certificate to ${folder}`, options22?.verbose);
57206
+ debugLog2("trust", `Adding new certificate to ${folder}`, options22?.verbose);
56969
57207
  await runCommand(`certutil -d sql:${folder} -A -t ${args} -n ${config42.commonName} -i ${caCertPath}`);
56970
57208
  log2.info(`Cert added to ${folder}`);
56971
57209
  }
56972
57210
  } else {
56973
- debugLog("trust", `Error: Unsupported platform ${platform22}`, options22?.verbose);
57211
+ debugLog2("trust", `Error: Unsupported platform ${platform22}`, options22?.verbose);
56974
57212
  throw new Error(`Unsupported platform: ${platform22}`);
56975
57213
  }
56976
- debugLog("trust", "Certificate successfully added to system trust store", options22?.verbose);
57214
+ debugLog2("trust", "Certificate successfully added to system trust store", options22?.verbose);
56977
57215
  return certPath;
56978
57216
  }
56979
57217
  function storeCertificate(cert, options22) {
56980
- debugLog("storage", `Storing certificate and private key with options: ${JSON.stringify(options22)}`, options22?.verbose);
56981
- const certPath = options22?.certPath || config42.certPath;
56982
- const certKeyPath = options22?.keyPath || config42.keyPath;
56983
- debugLog("storage", `Certificate path: ${certPath}`, options22?.verbose);
56984
- debugLog("storage", `Private key path: ${certKeyPath}`, options22?.verbose);
57218
+ debugLog2("storage", `Storing certificate and private key with options: ${JSON.stringify(options22)}`, options22?.verbose);
57219
+ const certPath = path3.join(options22?.basePath || config42.basePath, options22?.certPath || config42.certPath);
57220
+ const certKeyPath = path3.join(options22?.basePath || config42.basePath, options22?.keyPath || config42.keyPath);
57221
+ debugLog2("storage", `Certificate path: ${certPath}`, options22?.verbose);
57222
+ debugLog2("storage", `Private key path: ${certKeyPath}`, options22?.verbose);
56985
57223
  const certDir = path3.dirname(certPath);
56986
57224
  if (!fs2.existsSync(certDir)) {
56987
- debugLog("storage", `Creating certificate directory: ${certDir}`, options22?.verbose);
57225
+ debugLog2("storage", `Creating certificate directory: ${certDir}`, options22?.verbose);
56988
57226
  fs2.mkdirSync(certDir, { recursive: true });
56989
57227
  }
56990
- debugLog("storage", "Writing certificate file", options22?.verbose);
57228
+ debugLog2("storage", "Writing certificate file", options22?.verbose);
56991
57229
  fs2.writeFileSync(certPath, cert.certificate);
56992
57230
  const certKeyDir = path3.dirname(certKeyPath);
56993
57231
  if (!fs2.existsSync(certKeyDir)) {
56994
- debugLog("storage", `Creating private key directory: ${certKeyDir}`, options22?.verbose);
57232
+ debugLog2("storage", `Creating private key directory: ${certKeyDir}`, options22?.verbose);
56995
57233
  fs2.mkdirSync(certKeyDir, { recursive: true });
56996
57234
  }
56997
- debugLog("storage", "Writing private key file", options22?.verbose);
57235
+ debugLog2("storage", "Writing private key file", options22?.verbose);
56998
57236
  fs2.writeFileSync(certKeyPath, cert.privateKey);
56999
- debugLog("storage", "Certificate and private key stored successfully", options22?.verbose);
57237
+ debugLog2("storage", "Certificate and private key stored successfully", options22?.verbose);
57000
57238
  return certPath;
57001
57239
  }
57002
57240
  function storeCACertificate(caCert, options22) {
57003
- debugLog("storage", "Storing CA certificate", options22?.verbose);
57004
- const caCertPath = options22?.caCertPath || config42.caCertPath;
57005
- debugLog("storage", `CA certificate path: ${caCertPath}`, options22?.verbose);
57241
+ debugLog2("storage", "Storing CA certificate", options22?.verbose);
57242
+ const caCertPath = path3.join(options22?.basePath || config42.basePath, options22?.caCertPath || config42.caCertPath);
57243
+ debugLog2("storage", `CA certificate path: ${caCertPath}`, options22?.verbose);
57006
57244
  const caCertDir = path3.dirname(caCertPath);
57007
57245
  if (!fs2.existsSync(caCertDir)) {
57008
- debugLog("storage", `Creating CA certificate directory: ${caCertDir}`, options22?.verbose);
57246
+ debugLog2("storage", `Creating CA certificate directory: ${caCertDir}`, options22?.verbose);
57009
57247
  fs2.mkdirSync(caCertDir, { recursive: true });
57010
57248
  }
57011
- debugLog("storage", "Writing CA certificate file", options22?.verbose);
57249
+ debugLog2("storage", "Writing CA certificate file", options22?.verbose);
57012
57250
  fs2.writeFileSync(caCertPath, caCert);
57013
- debugLog("storage", "CA certificate stored successfully", options22?.verbose);
57251
+ debugLog2("storage", "CA certificate stored successfully", options22?.verbose);
57014
57252
  return caCertPath;
57015
57253
  }
57016
57254
  var export_tls = import_node_forge2.tls;
57017
57255
  var export_pki = import_node_forge2.pki;
57018
57256
  var export_forge = import_node_forge2.default;
57019
57257
 
57020
- // src/config.ts
57021
- import os3 from "os";
57022
- import path4 from "path";
57023
-
57024
- // node_modules/bun-config/dist/index.js
57025
- import { resolve as resolve3 } from "path";
57026
- import process3 from "process";
57027
- function deepMerge2(target, source) {
57028
- if (Array.isArray(source) && !Array.isArray(target)) {
57029
- return source;
57030
- }
57031
- if (Array.isArray(source) && Array.isArray(target)) {
57032
- return source.map((sourceItem, index) => {
57033
- const targetItem = target[index];
57034
- if (isObject5(sourceItem) && isObject5(targetItem)) {
57035
- return deepMerge2(targetItem, sourceItem);
57036
- }
57037
- return sourceItem;
57038
- });
57039
- }
57040
- if (!isObject5(source) || !isObject5(target)) {
57041
- return source;
57042
- }
57043
- const merged = { ...target };
57044
- for (const key in source) {
57045
- if (Object.prototype.hasOwnProperty.call(source, key)) {
57046
- const sourceValue = source[key];
57047
- const targetValue = merged[key];
57048
- if (sourceValue === null || sourceValue === undefined) {
57049
- merged[key] = sourceValue;
57050
- } else if (isObject5(sourceValue) && isObject5(targetValue)) {
57051
- merged[key] = deepMerge2(targetValue, sourceValue);
57052
- } else {
57053
- merged[key] = sourceValue;
57054
- }
57055
- }
57056
- }
57057
- return merged;
57058
- }
57059
- function isObject5(item) {
57060
- return Boolean(item && typeof item === "object" && !Array.isArray(item));
57061
- }
57062
- async function loadConfig2({ name, cwd, defaultConfig }) {
57063
- const configPath = resolve3(cwd || process3.cwd(), `${name}.config`);
57064
- try {
57065
- const importedConfig = await import(configPath);
57066
- const loadedConfig = importedConfig.default || importedConfig;
57067
- return deepMerge2(defaultConfig, loadedConfig);
57068
- } catch (error) {
57069
- return defaultConfig;
57070
- }
57071
- }
57072
-
57073
- // src/config.ts
57074
- var config6 = await loadConfig2({
57075
- name: "reverse-proxy",
57076
- defaultConfig: {
57077
- from: "localhost:5173",
57078
- to: "stacks.localhost",
57079
- https: {
57080
- caCertPath: path4.join(os3.homedir(), ".stacks", "ssl", `stacks.localhost.ca.crt`),
57081
- certPath: path4.join(os3.homedir(), ".stacks", "ssl", `stacks.localhost.crt`),
57082
- keyPath: path4.join(os3.homedir(), ".stacks", "ssl", `stacks.localhost.crt.key`)
57083
- },
57084
- etcHostsCleanup: true,
57085
- verbose: false
57086
- }
57087
- });
57088
-
57089
57258
  // src/https.ts
57090
57259
  var cachedSSLConfig = null;
57091
- function isMultiProxyConfig(options3) {
57092
- return "proxies" in options3;
57260
+ function resolveSSLPaths(options3, defaultConfig3) {
57261
+ const domain = isMultiProxyConfig(options3) ? options3.proxies[0].to || "stacks.localhost" : options3.to || "stacks.localhost";
57262
+ if (typeof options3.https === "object" && typeof defaultConfig3.https === "object") {
57263
+ const hasAllPaths = options3.https.caCertPath && options3.https.certPath && options3.https.keyPath;
57264
+ if (hasAllPaths) {
57265
+ const baseConfig = httpsConfig({
57266
+ ...options3,
57267
+ to: domain,
57268
+ https: defaultConfig3.https
57269
+ });
57270
+ const altNameIPs = options3.https.altNameIPs?.filter((ip) => ip !== undefined) || baseConfig.altNameIPs;
57271
+ const altNameURIs = options3.https.altNameURIs?.filter((uri) => uri !== undefined) || baseConfig.altNameURIs;
57272
+ return {
57273
+ ...baseConfig,
57274
+ caCertPath: options3.https.caCertPath || baseConfig.caCertPath,
57275
+ certPath: options3.https.certPath || baseConfig.certPath,
57276
+ keyPath: options3.https.keyPath || baseConfig.keyPath,
57277
+ basePath: options3.https.basePath || baseConfig.basePath,
57278
+ commonName: options3.https.commonName || baseConfig.commonName,
57279
+ organizationName: options3.https.organizationName || baseConfig.organizationName,
57280
+ countryName: options3.https.countryName || baseConfig.countryName,
57281
+ stateName: options3.https.stateName || baseConfig.stateName,
57282
+ localityName: options3.https.localityName || baseConfig.localityName,
57283
+ validityDays: options3.https.validityDays || baseConfig.validityDays,
57284
+ altNameIPs,
57285
+ altNameURIs,
57286
+ verbose: options3.verbose || baseConfig.verbose
57287
+ };
57288
+ }
57289
+ }
57290
+ return httpsConfig({
57291
+ ...options3,
57292
+ to: domain
57293
+ });
57093
57294
  }
57094
57295
  function generateWildcardPatterns(domain) {
57095
57296
  const patterns = new Set;
57096
57297
  patterns.add(domain);
57097
57298
  const parts = domain.split(".");
57098
- if (parts.length >= 2) {
57299
+ if (parts.length >= 2)
57099
57300
  patterns.add(`*.${parts.slice(1).join(".")}`);
57100
- }
57101
57301
  return Array.from(patterns);
57102
57302
  }
57103
- function generateBaseConfig(options3, verbose) {
57104
- const domains = extractDomains(options3);
57105
- const sslBase = path6.join(os5.homedir(), ".stacks", "ssl");
57106
- const httpsConfig = options3.https === true ? {
57107
- caCertPath: path6.join(sslBase, "rpx-ca.crt"),
57108
- certPath: path6.join(sslBase, "rpx.crt"),
57109
- keyPath: path6.join(sslBase, "rpx.key")
57110
- } : typeof config6.https === "object" ? {
57111
- ...options3.https,
57112
- ...config6.https
57113
- } : {};
57114
- debugLog2("ssl", `Extracted domains: ${domains.join(", ")}`, verbose);
57115
- debugLog2("ssl", `Using SSL base path: ${sslBase}`, verbose);
57116
- debugLog2("ssl", `Using HTTPS config: ${JSON.stringify(httpsConfig)}`, verbose);
57117
- const allPatterns = new Set;
57118
- domains.forEach((domain) => {
57119
- allPatterns.add(domain);
57120
- generateWildcardPatterns(domain).forEach((pattern) => allPatterns.add(pattern));
57121
- });
57122
- allPatterns.add("localhost");
57123
- allPatterns.add("*.localhost");
57124
- const uniqueDomains = Array.from(allPatterns);
57125
- debugLog2("ssl", `Generated domain patterns: ${uniqueDomains.join(", ")}`, verbose);
57303
+ function generateSSLPaths(options3) {
57304
+ const domain = getPrimaryDomain(options3);
57305
+ let basePath = "";
57306
+ if (typeof options3?.https === "object") {
57307
+ basePath = options3.https.basePath || "";
57308
+ return {
57309
+ caCertPath: options3.https.caCertPath || join4(basePath, `${domain}.ca.crt`),
57310
+ certPath: options3.https.certPath || join4(basePath, `${domain}.crt`),
57311
+ keyPath: options3.https.keyPath || join4(basePath, `${domain}.key`)
57312
+ };
57313
+ }
57314
+ const sslBase = basePath || join4(homedir2(), ".stacks", "ssl");
57315
+ const sanitizedDomain = domain.replace(/\*/g, "wildcard");
57126
57316
  return {
57127
- domain: domains[0],
57128
- hostCertCN: domains[0],
57129
- caCertPath: httpsConfig?.caCertPath ?? path6.join(sslBase, "rpx-ca.crt"),
57130
- certPath: httpsConfig?.certPath ?? path6.join(sslBase, "rpx.crt"),
57131
- keyPath: httpsConfig?.keyPath ?? path6.join(sslBase, "rpx.key"),
57132
- altNameIPs: httpsConfig?.altNameIPs ?? ["127.0.0.1", "::1"],
57133
- altNameURIs: httpsConfig?.altNameURIs ?? [],
57134
- commonName: httpsConfig?.commonName ?? domains[0],
57135
- organizationName: httpsConfig?.organizationName ?? "Local Development",
57136
- countryName: httpsConfig?.countryName ?? "US",
57137
- stateName: httpsConfig?.stateName ?? "California",
57138
- localityName: httpsConfig?.localityName ?? "Playa Vista",
57139
- validityDays: httpsConfig?.validityDays ?? 825,
57140
- verbose: verbose ?? false,
57141
- subjectAltNames: uniqueDomains.map((domain) => ({
57142
- type: 2,
57143
- value: domain
57144
- }))
57317
+ caCertPath: join4(sslBase, `${sanitizedDomain}.ca.crt`),
57318
+ certPath: join4(sslBase, `${sanitizedDomain}.crt`),
57319
+ keyPath: join4(sslBase, `${sanitizedDomain}.key`)
57145
57320
  };
57146
57321
  }
57147
- function generateRootCAConfig(verbose = false) {
57148
- const sslBase = path6.join(os5.homedir(), ".stacks", "ssl");
57149
- return {
57150
- domain: "stacks.localhost",
57151
- hostCertCN: "stacks.localhost",
57152
- caCertPath: path6.join(sslBase, "rpx-root-ca.crt"),
57153
- certPath: path6.join(sslBase, "rpx-certificate.crt"),
57154
- keyPath: path6.join(sslBase, "rpx-certificate.key"),
57155
- altNameIPs: ["127.0.0.1", "::1"],
57156
- altNameURIs: [],
57157
- organizationName: "Stacks Local Development",
57158
- countryName: "US",
57159
- stateName: "California",
57160
- localityName: "Playa Vista",
57161
- commonName: "stacks.localhost",
57162
- validityDays: 3650,
57163
- verbose
57164
- };
57322
+ function getAllDomains(options3) {
57323
+ const domains = new Set;
57324
+ if (isMultiProxyOptions(options3)) {
57325
+ options3.proxies.forEach((proxy) => {
57326
+ const domain = proxy.to || "stacks.localhost";
57327
+ generateWildcardPatterns(domain).forEach((pattern) => domains.add(pattern));
57328
+ });
57329
+ } else if (isSingleProxyOptions(options3)) {
57330
+ const domain = options3.to || "stacks.localhost";
57331
+ generateWildcardPatterns(domain).forEach((pattern) => domains.add(pattern));
57332
+ } else {
57333
+ domains.add("stacks.localhost");
57334
+ }
57335
+ domains.add("localhost");
57336
+ domains.add("*.localhost");
57337
+ return domains;
57165
57338
  }
57166
- function httpsConfig(options3) {
57167
- return generateBaseConfig(options3, options3.verbose);
57339
+ async function loadSSLConfig(options3) {
57340
+ debugLog("ssl", `Loading SSL configuration`, options3.verbose);
57341
+ const mergedOptions = {
57342
+ ...config4,
57343
+ ...options3
57344
+ };
57345
+ options3.https = httpsConfig(mergedOptions);
57346
+ if (!options3.https?.keyPath && !options3.https?.certPath) {
57347
+ debugLog("ssl", "No SSL configuration provided", options3.verbose);
57348
+ return null;
57349
+ }
57350
+ if (options3.https?.keyPath && !options3.https?.certPath || !options3.https?.keyPath && options3.https?.certPath) {
57351
+ const missing = !options3.https?.keyPath ? "keyPath" : "certPath";
57352
+ debugLog("ssl", `Invalid SSL configuration - missing ${missing}`, options3.verbose);
57353
+ throw new Error(`SSL Configuration requires both keyPath and certPath. Missing: ${missing}`);
57354
+ }
57355
+ try {
57356
+ if (!options3.https?.keyPath || !options3.https?.certPath)
57357
+ return null;
57358
+ try {
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);
57363
+ return { key, cert };
57364
+ } catch (error) {
57365
+ debugLog("ssl", `Failed to read certificates: ${error}`, options3.verbose);
57366
+ return null;
57367
+ }
57368
+ } catch (err3) {
57369
+ debugLog("ssl", `SSL configuration error: ${err3}`, options3.verbose);
57370
+ throw err3;
57371
+ }
57168
57372
  }
57169
57373
  async function generateCertificate2(options3) {
57170
57374
  if (cachedSSLConfig) {
57171
- const verbose2 = isMultiProxyConfig(options3) ? options3.verbose : options3.verbose;
57172
- debugLog2("ssl", "Using cached SSL configuration", verbose2);
57375
+ debugLog("ssl", "Using cached SSL configuration", options3.verbose);
57173
57376
  return;
57174
57377
  }
57175
- const domains = isMultiProxyConfig(options3) ? [options3.proxies[0].to, ...options3.proxies.map((proxy) => proxy.to)] : [options3.to];
57176
- const verbose = isMultiProxyConfig(options3) ? options3.verbose : options3.verbose;
57177
- debugLog2("ssl", `Generating certificate for domains: ${domains.join(", ")}`, verbose);
57178
- const rootCAConfig = generateRootCAConfig(verbose);
57378
+ const domains = isMultiProxyOptions(options3) ? options3.proxies.map((proxy) => proxy.to) : [options3.to];
57379
+ debugLog("ssl", `Generating certificate for domains: ${domains.join(", ")}`, options3.verbose);
57380
+ const rootCAConfig = httpsConfig(options3, options3.verbose);
57179
57381
  log.info("Generating Root CA certificate...");
57180
57382
  const caCert = await createRootCA(rootCAConfig);
57181
- const hostConfig = generateBaseConfig(options3, verbose);
57383
+ const hostConfig = httpsConfig(options3, options3.verbose);
57182
57384
  log.info(`Generating host certificate for: ${domains.join(", ")}`);
57183
57385
  const hostCert = await generateCertificate({
57184
57386
  ...hostConfig,
57185
- rootCAObject: {
57387
+ rootCA: {
57186
57388
  certificate: caCert.certificate,
57187
57389
  privateKey: caCert.privateKey
57188
57390
  }
@@ -57194,283 +57396,145 @@ async function generateCertificate2(options3) {
57194
57396
  ca: caCert.certificate
57195
57397
  };
57196
57398
  log.success(`Certificate generated successfully for ${domains.length} domain${domains.length > 1 ? "s" : ""}`);
57197
- debugLog2("ssl", `Certificate includes domains: ${domains.join(", ")}`, verbose);
57399
+ debugLog("ssl", `Certificate includes domains: ${domains.join(", ")}`, options3.verbose);
57198
57400
  }
57199
57401
  function getSSLConfig() {
57200
57402
  return cachedSSLConfig;
57201
57403
  }
57202
-
57203
- // src/utils.ts
57204
- function debugLog2(category, message, verbose) {
57205
- if (verbose) {
57206
- console.debug(`[rpx:${category}] ${message}`);
57207
- }
57208
- }
57209
- function extractDomains(options3) {
57210
- if (isMultiProxyConfig(options3)) {
57211
- return options3.proxies.map((proxy) => {
57212
- const domain2 = proxy.to || "stacks.localhost";
57213
- return domain2.startsWith("http") ? new URL(domain2).hostname : domain2;
57214
- });
57215
- }
57216
- const domain = options3.to || "stacks.localhost";
57217
- return [domain.startsWith("http") ? new URL(domain).hostname : domain];
57218
- }
57219
-
57220
- // src/hosts.ts
57221
- var hostsFilePath = process9.platform === "win32" ? path7.join(process9.env.windir || "C:\\Windows", "System32", "drivers", "etc", "hosts") : "/etc/hosts";
57222
- async function sudoWrite(operation, content) {
57223
- return new Promise((resolve4, reject) => {
57224
- if (process9.platform === "win32") {
57225
- reject(new Error("Administrator privileges required on Windows"));
57226
- return;
57227
- }
57228
- const tmpFile = path7.join(os7.tmpdir(), "hosts.tmp");
57229
- try {
57230
- if (operation === "append") {
57231
- const currentContent = fs3.readFileSync(hostsFilePath, "utf8");
57232
- fs3.writeFileSync(tmpFile, currentContent + content, "utf8");
57233
- } else {
57234
- fs3.writeFileSync(tmpFile, content, "utf8");
57235
- }
57236
- const sudo = spawn("sudo", ["cp", tmpFile, hostsFilePath]);
57237
- sudo.on("close", (code) => {
57238
- try {
57239
- fs3.unlinkSync(tmpFile);
57240
- if (code === 0)
57241
- resolve4();
57242
- else
57243
- reject(new Error(`sudo process exited with code ${code}`));
57244
- } catch (err3) {
57245
- reject(err3);
57246
- }
57247
- });
57248
- sudo.on("error", (err3) => {
57249
- try {
57250
- fs3.unlinkSync(tmpFile);
57251
- } catch {
57252
- }
57253
- reject(err3);
57254
- });
57255
- } catch (err3) {
57256
- reject(err3);
57257
- }
57258
- });
57259
- }
57260
- async function addHosts(hosts, verbose) {
57261
- debugLog2("hosts", `Adding hosts: ${hosts.join(", ")}`, verbose);
57262
- debugLog2("hosts", `Using hosts file at: ${hostsFilePath}`, verbose);
57404
+ async function checkExistingCertificates(options3) {
57405
+ const name = getPrimaryDomain(options3);
57406
+ const paths = generateSSLPaths(options3);
57263
57407
  try {
57264
- const existingContent = await fs3.promises.readFile(hostsFilePath, "utf-8");
57265
- const newEntries = hosts.filter((host) => {
57266
- const ipv4Entry = `127.0.0.1 ${host}`;
57267
- const ipv6Entry = `::1 ${host}`;
57268
- return !existingContent.includes(ipv4Entry) && !existingContent.includes(ipv6Entry);
57269
- });
57270
- if (newEntries.length === 0) {
57271
- debugLog2("hosts", "All hosts already exist in hosts file", verbose);
57272
- log.info("All hosts are already in the hosts file");
57273
- return;
57274
- }
57275
- const hostEntries = newEntries.map((host) => `
57276
- # Added by rpx
57277
- 127.0.0.1 ${host}
57278
- ::1 ${host}`).join(`
57279
- `);
57280
- try {
57281
- await fs3.promises.appendFile(hostsFilePath, hostEntries, { flag: "a" });
57282
- log.success(`Added new hosts: ${newEntries.join(", ")}`);
57283
- } catch (writeErr) {
57284
- if (writeErr.code === "EACCES") {
57285
- debugLog2("hosts", "Permission denied, attempting with sudo", verbose);
57286
- try {
57287
- await sudoWrite("append", hostEntries);
57288
- log.success(`Added new hosts with sudo: ${newEntries.join(", ")}`);
57289
- } catch (sudoErr) {
57290
- log.error("Failed to modify hosts file automatically");
57291
- log.warn("Please add these entries to your hosts file manually:");
57292
- hostEntries.split(`
57293
- `).forEach((entry) => log.warn(entry));
57294
- if (process9.platform === "win32") {
57295
- log.warn(`
57296
- On Windows:`);
57297
- log.warn("1. Run notepad as administrator");
57298
- log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
57299
- } else {
57300
- log.warn(`
57301
- On Unix systems:`);
57302
- log.warn(`sudo nano ${hostsFilePath}`);
57303
- }
57304
- throw new Error("Failed to modify hosts file: manual intervention required");
57305
- }
57306
- } else {
57307
- throw writeErr;
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");
57414
+ let ca;
57415
+ if (paths.caCertPath) {
57416
+ try {
57417
+ ca = await fs5.readFile(paths.caCertPath, "utf8");
57418
+ } catch (err3) {
57419
+ debugLog("ssl", `Failed to read CA cert: ${err3}`, options3?.verbose);
57308
57420
  }
57309
57421
  }
57422
+ return { key, cert, ca };
57310
57423
  } catch (err3) {
57311
- const error = err3;
57312
- log.error(`Failed to manage hosts file: ${error.message}`);
57313
- throw error;
57424
+ debugLog("ssl", `Failed to read certificates: ${err3}`, options3?.verbose);
57425
+ return null;
57314
57426
  }
57315
57427
  }
57316
- async function removeHosts(hosts, verbose) {
57317
- debugLog2("hosts", `Removing hosts: ${hosts.join(", ")}`, verbose);
57318
- try {
57319
- const content = await fs3.promises.readFile(hostsFilePath, "utf-8");
57320
- const lines = content.split(`
57321
- `);
57322
- const filteredLines = lines.filter((line, index) => {
57323
- if (line.trim() === "# Added by rpx") {
57324
- lines.splice(index + 1, 2);
57325
- return false;
57326
- }
57327
- return true;
57328
- });
57329
- while (filteredLines[filteredLines.length - 1]?.trim() === "")
57330
- filteredLines.pop();
57331
- const newContent = `${filteredLines.join(`
57332
- `)}
57333
- `;
57334
- try {
57335
- await fs3.promises.writeFile(hostsFilePath, newContent);
57336
- log.success("Hosts removed successfully");
57337
- } catch (writeErr) {
57338
- if (writeErr.code === "EACCES") {
57339
- debugLog2("hosts", "Permission denied, attempting with sudo", verbose);
57340
- try {
57341
- await sudoWrite("write", newContent);
57342
- log.success("Hosts removed successfully with sudo");
57343
- } catch (sudoErr) {
57344
- log.error("Failed to modify hosts file automatically");
57345
- log.warn("Please remove these entries from your hosts file manually:");
57346
- hosts.forEach((host) => {
57347
- log.warn("# Added by rpx");
57348
- log.warn(`127.0.0.1 ${host}`);
57349
- log.warn(`::1 ${host}`);
57350
- });
57351
- if (process9.platform === "win32") {
57352
- log.warn(`
57353
- On Windows:`);
57354
- log.warn("1. Run notepad as administrator");
57355
- log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
57356
- } else {
57357
- log.warn(`
57358
- On Unix systems:`);
57359
- log.warn(`sudo nano ${hostsFilePath}`);
57360
- }
57361
- throw new Error("Failed to modify hosts file: manual intervention required");
57362
- }
57363
- } else {
57364
- throw writeErr;
57365
- }
57366
- }
57367
- } catch (err3) {
57368
- const error = err3;
57369
- log.error(`Failed to remove hosts: ${error.message}`);
57370
- throw error;
57428
+ function httpsConfig(options3, verbose) {
57429
+ const primaryDomain = getPrimaryDomain(options3);
57430
+ debugLog("ssl", `Primary domain: ${primaryDomain}`, verbose);
57431
+ const defaultPaths = generateSSLPaths(options3);
57432
+ if (typeof options3.https === "object") {
57433
+ const config5 = {
57434
+ domain: primaryDomain,
57435
+ hostCertCN: primaryDomain,
57436
+ basePath: options3.https.basePath || "",
57437
+ caCertPath: options3.https.caCertPath || defaultPaths.caCertPath,
57438
+ certPath: options3.https.certPath || defaultPaths.certPath,
57439
+ keyPath: options3.https.keyPath || defaultPaths.keyPath,
57440
+ altNameIPs: ["127.0.0.1", "::1"],
57441
+ altNameURIs: [],
57442
+ commonName: options3.https.commonName || primaryDomain,
57443
+ organizationName: options3.https.organizationName || "Local Development",
57444
+ countryName: options3.https.countryName || "US",
57445
+ stateName: options3.https.stateName || "California",
57446
+ localityName: options3.https.localityName || "Playa Vista",
57447
+ validityDays: options3.https.validityDays || 825,
57448
+ verbose: verbose || false,
57449
+ subjectAltNames: Array.from(getAllDomains(options3)).map((domain) => ({
57450
+ type: 2,
57451
+ value: domain
57452
+ }))
57453
+ };
57454
+ if (isValidRootCA(options3.https.rootCA)) {
57455
+ config5.rootCA = options3.https.rootCA;
57456
+ }
57457
+ return config5;
57371
57458
  }
57372
- }
57373
- async function checkHosts(hosts, verbose) {
57374
- debugLog2("hosts", `Checking hosts: ${hosts}`, verbose);
57375
- const content = await fs3.promises.readFile(hostsFilePath, "utf-8");
57376
- return hosts.map((host) => {
57377
- const ipv4Entry = `127.0.0.1 ${host}`;
57378
- const ipv6Entry = `::1 ${host}`;
57379
- return content.includes(ipv4Entry) || content.includes(ipv6Entry);
57380
- });
57459
+ return {
57460
+ domain: primaryDomain,
57461
+ hostCertCN: primaryDomain,
57462
+ basePath: "",
57463
+ ...defaultPaths,
57464
+ altNameIPs: ["127.0.0.1", "::1"],
57465
+ altNameURIs: [],
57466
+ commonName: primaryDomain,
57467
+ organizationName: "Local Development",
57468
+ countryName: "US",
57469
+ stateName: "California",
57470
+ localityName: "Playa Vista",
57471
+ validityDays: 825,
57472
+ verbose: verbose || false,
57473
+ subjectAltNames: Array.from(getAllDomains(options3)).map((domain) => ({
57474
+ type: 2,
57475
+ value: domain
57476
+ }))
57477
+ };
57381
57478
  }
57382
57479
 
57383
57480
  // src/start.ts
57384
57481
  var activeServers = new Set;
57385
57482
  async function cleanup(options3) {
57386
- debugLog2("cleanup", "Starting cleanup process", options3?.verbose);
57483
+ debugLog("cleanup", "Starting cleanup process", options3?.verbose);
57387
57484
  console.log(`
57388
57485
  `);
57389
57486
  log.info("Shutting down proxy servers...");
57390
57487
  const cleanupPromises = [];
57391
57488
  const serverClosePromises = Array.from(activeServers).map((server) => new Promise((resolve4) => {
57392
57489
  server.close(() => {
57393
- debugLog2("cleanup", "Server closed successfully", options3?.verbose);
57490
+ debugLog("cleanup", "Server closed successfully", options3?.verbose);
57394
57491
  resolve4();
57395
57492
  });
57396
57493
  }));
57397
57494
  cleanupPromises.push(...serverClosePromises);
57398
57495
  if (options3?.etcHostsCleanup && options3.domains?.length) {
57399
- debugLog2("cleanup", "Cleaning up hosts file entries", options3?.verbose);
57496
+ debugLog("cleanup", "Cleaning up hosts file entries", options3?.verbose);
57400
57497
  const domainsToClean = options3.domains.filter((domain) => !domain.includes("localhost"));
57401
57498
  if (domainsToClean.length > 0) {
57402
57499
  log.info("Cleaning up hosts file entries...");
57403
57500
  cleanupPromises.push(removeHosts(domainsToClean, options3?.verbose).then(() => {
57404
- debugLog2("cleanup", `Removed hosts entries for ${domainsToClean.join(", ")}`, options3?.verbose);
57501
+ debugLog("cleanup", `Removed hosts entries for ${domainsToClean.join(", ")}`, options3?.verbose);
57405
57502
  }).catch((err3) => {
57406
- debugLog2("cleanup", `Failed to remove hosts entries: ${err3}`, options3?.verbose);
57503
+ debugLog("cleanup", `Failed to remove hosts entries: ${err3}`, options3?.verbose);
57407
57504
  log.warn(`Failed to clean up hosts file entries for ${domainsToClean.join(", ")}:`, err3);
57408
57505
  }));
57409
57506
  }
57410
57507
  }
57411
57508
  try {
57412
57509
  await Promise.all(cleanupPromises);
57413
- debugLog2("cleanup", "All cleanup tasks completed successfully", options3?.verbose);
57510
+ debugLog("cleanup", "All cleanup tasks completed successfully", options3?.verbose);
57414
57511
  log.success("All cleanup tasks completed successfully");
57415
- process20.exit(0);
57512
+ process9.exit(0);
57416
57513
  } catch (err3) {
57417
- debugLog2("cleanup", `Error during cleanup: ${err3}`, options3?.verbose);
57514
+ debugLog("cleanup", `Error during cleanup: ${err3}`, options3?.verbose);
57418
57515
  log.error("Error during cleanup:", err3);
57419
- process20.exit(1);
57516
+ process9.exit(1);
57420
57517
  }
57421
57518
  }
57422
- process20.on("SIGINT", cleanup);
57423
- process20.on("SIGTERM", cleanup);
57424
- process20.on("uncaughtException", (err3) => {
57425
- debugLog2("process", `Uncaught exception: ${err3}`, true);
57519
+ process9.on("SIGINT", cleanup);
57520
+ process9.on("SIGTERM", cleanup);
57521
+ process9.on("uncaughtException", (err3) => {
57522
+ debugLog("process", `Uncaught exception: ${err3}`, true);
57426
57523
  log.error("Uncaught exception:", err3);
57427
57524
  cleanup();
57428
57525
  });
57429
- async function loadSSLConfig(options3) {
57430
- debugLog2("ssl", `Loading SSL configuration`, options3.verbose);
57431
- if (options3.https === true)
57432
- options3.https = httpsConfig(options3);
57433
- else if (options3.https === false)
57434
- return null;
57435
- if (!options3.https?.keyPath && !options3.https?.certPath) {
57436
- debugLog2("ssl", "No SSL configuration provided", options3.verbose);
57437
- return null;
57438
- }
57439
- if (options3.https?.keyPath && !options3.https?.certPath || !options3.https?.keyPath && options3.https?.certPath) {
57440
- const missing = !options3.https?.keyPath ? "keyPath" : "certPath";
57441
- debugLog2("ssl", `Invalid SSL configuration - missing ${missing}`, options3.verbose);
57442
- throw new Error(`SSL Configuration requires both keyPath and certPath. Missing: ${missing}`);
57443
- }
57444
- try {
57445
- if (!options3.https?.keyPath || !options3.https?.certPath)
57446
- return null;
57447
- try {
57448
- debugLog2("ssl", "Reading SSL certificate files", options3.verbose);
57449
- const key = await fs5.promises.readFile(options3.https?.keyPath, "utf8");
57450
- const cert = await fs5.promises.readFile(options3.https?.certPath, "utf8");
57451
- debugLog2("ssl", "SSL configuration loaded successfully", options3.verbose);
57452
- return { key, cert };
57453
- } catch (error) {
57454
- debugLog2("ssl", `Failed to read certificates: ${error}`, options3.verbose);
57455
- return null;
57456
- }
57457
- } catch (err3) {
57458
- debugLog2("ssl", `SSL configuration error: ${err3}`, options3.verbose);
57459
- throw err3;
57460
- }
57461
- }
57462
57526
  function isPortInUse(port, hostname, verbose) {
57463
- debugLog2("port", `Checking if port ${port} is in use on ${hostname}`, verbose);
57527
+ debugLog("port", `Checking if port ${port} is in use on ${hostname}`, verbose);
57464
57528
  return new Promise((resolve4) => {
57465
57529
  const server = net.createServer();
57466
57530
  server.once("error", (err3) => {
57467
57531
  if (err3.code === "EADDRINUSE") {
57468
- debugLog2("port", `Port ${port} is in use`, verbose);
57532
+ debugLog("port", `Port ${port} is in use`, verbose);
57469
57533
  resolve4(true);
57470
57534
  }
57471
57535
  });
57472
57536
  server.once("listening", () => {
57473
- debugLog2("port", `Port ${port} is available`, verbose);
57537
+ debugLog("port", `Port ${port} is available`, verbose);
57474
57538
  server.close();
57475
57539
  resolve4(false);
57476
57540
  });
@@ -57478,17 +57542,17 @@ function isPortInUse(port, hostname, verbose) {
57478
57542
  });
57479
57543
  }
57480
57544
  async function findAvailablePort(startPort, hostname, verbose) {
57481
- debugLog2("port", `Finding available port starting from ${startPort}`, verbose);
57545
+ debugLog("port", `Finding available port starting from ${startPort}`, verbose);
57482
57546
  let port = startPort;
57483
57547
  while (await isPortInUse(port, hostname, verbose)) {
57484
- debugLog2("port", `Port ${port} is in use, trying ${port + 1}`, verbose);
57548
+ debugLog("port", `Port ${port} is in use, trying ${port + 1}`, verbose);
57485
57549
  port++;
57486
57550
  }
57487
- debugLog2("port", `Found available port: ${port}`, verbose);
57551
+ debugLog("port", `Found available port: ${port}`, verbose);
57488
57552
  return port;
57489
57553
  }
57490
57554
  async function testConnection(hostname, port, verbose) {
57491
- debugLog2("connection", `Testing connection to ${hostname}:${port}`, verbose);
57555
+ debugLog("connection", `Testing connection to ${hostname}:${port}`, verbose);
57492
57556
  return new Promise((resolve4, reject) => {
57493
57557
  const socket = net.connect({
57494
57558
  host: hostname,
@@ -57496,30 +57560,30 @@ async function testConnection(hostname, port, verbose) {
57496
57560
  timeout: 5000
57497
57561
  });
57498
57562
  socket.once("connect", () => {
57499
- debugLog2("connection", `Successfully connected to ${hostname}:${port}`, verbose);
57563
+ debugLog("connection", `Successfully connected to ${hostname}:${port}`, verbose);
57500
57564
  socket.end();
57501
57565
  resolve4();
57502
57566
  });
57503
57567
  socket.once("timeout", () => {
57504
- debugLog2("connection", `Connection to ${hostname}:${port} timed out`, verbose);
57568
+ debugLog("connection", `Connection to ${hostname}:${port} timed out`, verbose);
57505
57569
  socket.destroy();
57506
57570
  reject(new Error(`Connection to ${hostname}:${port} timed out`));
57507
57571
  });
57508
57572
  socket.once("error", (err3) => {
57509
- debugLog2("connection", `Failed to connect to ${hostname}:${port}: ${err3}`, verbose);
57573
+ debugLog("connection", `Failed to connect to ${hostname}:${port}: ${err3}`, verbose);
57510
57574
  socket.destroy();
57511
57575
  reject(new Error(`Failed to connect to ${hostname}:${port}: ${err3.message}`));
57512
57576
  });
57513
57577
  });
57514
57578
  }
57515
57579
  async function startServer(options3) {
57516
- debugLog2("server", `Starting server with options: ${JSON.stringify(options3)}`, options3.verbose);
57517
- const fromUrl = new URL(options3.from.startsWith("http") ? options3.from : `http://${options3.from}`);
57518
- const toUrl = new URL(options3.to.startsWith("http") ? options3.to : `http://${options3.to}`);
57580
+ debugLog("server", `Starting server with options: ${JSON.stringify(options3)}`, options3.verbose);
57581
+ const fromUrl = new URL((options3.from?.startsWith("http") ? options3.from : `http://${options3.from}`) || "localhost:5173");
57582
+ const toUrl = new URL((options3.to?.startsWith("http") ? options3.to : `http://${options3.to}`) || "stacks.localhost");
57519
57583
  const fromPort = Number.parseInt(fromUrl.port) || (fromUrl.protocol.includes("https:") ? 443 : 80);
57520
57584
  const hostsToCheck = [toUrl.hostname];
57521
57585
  if (!toUrl.hostname.includes("localhost") && !toUrl.hostname.includes("127.0.0.1")) {
57522
- debugLog2("hosts", `Checking if hosts file entry exists for: ${toUrl.hostname}`, options3?.verbose);
57586
+ debugLog("hosts", `Checking if hosts file entry exists for: ${toUrl.hostname}`, options3?.verbose);
57523
57587
  try {
57524
57588
  const hostsExist = await checkHosts(hostsToCheck, options3.verbose);
57525
57589
  if (!hostsExist[0]) {
@@ -57532,7 +57596,7 @@ async function startServer(options3) {
57532
57596
  log.warn("You can manually add this entry to your hosts file:");
57533
57597
  log.warn(`127.0.0.1 ${toUrl.hostname}`);
57534
57598
  log.warn(`::1 ${toUrl.hostname}`);
57535
- if (process20.platform === "win32") {
57599
+ if (process9.platform === "win32") {
57536
57600
  log.warn("On Windows:");
57537
57601
  log.warn("1. Run notepad as administrator");
57538
57602
  log.warn("2. Open C:\\Windows\\System32\\drivers\\etc\\hosts");
@@ -57542,7 +57606,7 @@ async function startServer(options3) {
57542
57606
  }
57543
57607
  }
57544
57608
  } else {
57545
- debugLog2("hosts", `Host entry already exists for ${toUrl.hostname}`, options3.verbose);
57609
+ debugLog("hosts", `Host entry already exists for ${toUrl.hostname}`, options3.verbose);
57546
57610
  }
57547
57611
  } catch (checkError) {
57548
57612
  log.error("Failed to check hosts file:", checkError.message);
@@ -57551,9 +57615,9 @@ async function startServer(options3) {
57551
57615
  try {
57552
57616
  await testConnection(fromUrl.hostname, fromPort, options3.verbose);
57553
57617
  } catch (err3) {
57554
- debugLog2("server", `Connection test failed: ${err3}`, options3.verbose);
57618
+ debugLog("server", `Connection test failed: ${err3}`, options3.verbose);
57555
57619
  log.error(err3.message);
57556
- process20.exit(1);
57620
+ process9.exit(1);
57557
57621
  }
57558
57622
  let sslConfig = options3._cachedSSLConfig || null;
57559
57623
  if (options3.https) {
@@ -57565,17 +57629,17 @@ async function startServer(options3) {
57565
57629
  });
57566
57630
  }
57567
57631
  try {
57568
- debugLog2("ssl", `Attempting to load SSL configuration for ${toUrl.hostname}`, options3.verbose);
57632
+ debugLog("ssl", `Attempting to load SSL configuration for ${toUrl.hostname}`, options3.verbose);
57569
57633
  sslConfig = await loadSSLConfig({
57570
57634
  ...options3,
57571
57635
  to: toUrl.hostname,
57572
57636
  https: options3.https
57573
57637
  });
57574
57638
  } catch (loadError) {
57575
- debugLog2("ssl", `Failed to load certificates, will generate new ones: ${loadError}`, options3.verbose);
57639
+ debugLog("ssl", `Failed to load certificates, will generate new ones: ${loadError}`, options3.verbose);
57576
57640
  }
57577
57641
  if (!sslConfig) {
57578
- debugLog2("ssl", `Generating new certificates for ${toUrl.hostname}`, options3.verbose);
57642
+ debugLog("ssl", `Generating new certificates for ${toUrl.hostname}`, options3.verbose);
57579
57643
  await generateCertificate2({
57580
57644
  ...options3,
57581
57645
  from: fromUrl.toString(),
@@ -57592,14 +57656,14 @@ async function startServer(options3) {
57592
57656
  }
57593
57657
  }
57594
57658
  } catch (err3) {
57595
- debugLog2("server", `SSL setup failed: ${err3}`, options3.verbose);
57659
+ debugLog("server", `SSL setup failed: ${err3}`, options3.verbose);
57596
57660
  throw err3;
57597
57661
  }
57598
57662
  }
57599
- debugLog2("server", `Setting up reverse proxy with SSL config for ${toUrl.hostname}`, options3.verbose);
57663
+ debugLog("server", `Setting up reverse proxy with SSL config for ${toUrl.hostname}`, options3.verbose);
57600
57664
  await setupReverseProxy({
57601
57665
  ...options3,
57602
- from: options3.from,
57666
+ from: options3.from || "localhost:5173",
57603
57667
  to: toUrl.hostname,
57604
57668
  fromPort,
57605
57669
  sourceUrl: {
@@ -57610,9 +57674,9 @@ async function startServer(options3) {
57610
57674
  });
57611
57675
  }
57612
57676
  async function createProxyServer(from, to, fromPort, listenPort, hostname, sourceUrl, ssl, verbose) {
57613
- debugLog2("proxy", `Creating proxy server ${from} -> ${to}`, verbose);
57677
+ debugLog("proxy", `Creating proxy server ${from} -> ${to}`, verbose);
57614
57678
  const requestHandler = (req, res) => {
57615
- debugLog2("request", `Incoming request: ${req.method} ${req.url}`, verbose);
57679
+ debugLog("request", `Incoming request: ${req.method} ${req.url}`, verbose);
57616
57680
  const proxyOptions = {
57617
57681
  hostname: sourceUrl.hostname,
57618
57682
  port: fromPort,
@@ -57623,9 +57687,9 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
57623
57687
  host: sourceUrl.host
57624
57688
  }
57625
57689
  };
57626
- debugLog2("request", `Proxy request options: ${JSON.stringify(proxyOptions)}`, verbose);
57690
+ debugLog("request", `Proxy request options: ${JSON.stringify(proxyOptions)}`, verbose);
57627
57691
  const proxyReq = http.request(proxyOptions, (proxyRes) => {
57628
- debugLog2("response", `Proxy response received with status ${proxyRes.statusCode}`, verbose);
57692
+ debugLog("response", `Proxy response received with status ${proxyRes.statusCode}`, verbose);
57629
57693
  const headers = {
57630
57694
  ...proxyRes.headers,
57631
57695
  "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
@@ -57635,7 +57699,7 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
57635
57699
  proxyRes.pipe(res);
57636
57700
  });
57637
57701
  proxyReq.on("error", (err3) => {
57638
- debugLog2("request", `Proxy request failed: ${err3}`, verbose);
57702
+ debugLog("request", `Proxy request failed: ${err3}`, verbose);
57639
57703
  log.error("Proxy request failed:", err3);
57640
57704
  res.writeHead(502);
57641
57705
  res.end(`Proxy Error: ${err3.message}`);
@@ -57662,11 +57726,11 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
57662
57726
  allowHTTP1: true,
57663
57727
  ALPNProtocols: ["h2", "http/1.1"]
57664
57728
  } : undefined;
57665
- debugLog2("server", `Creating server with SSL config: ${!!ssl}`, verbose);
57729
+ debugLog("server", `Creating server with SSL config: ${!!ssl}`, verbose);
57666
57730
  const server = ssl && serverOptions ? https.createServer(serverOptions, requestHandler) : http.createServer(requestHandler);
57667
57731
  if (ssl) {
57668
57732
  server.on("secureConnection", (tlsSocket) => {
57669
- debugLog2("tls", `TLS Connection established: ${JSON.stringify({
57733
+ debugLog("tls", `TLS Connection established: ${JSON.stringify({
57670
57734
  protocol: tlsSocket.getProtocol?.(),
57671
57735
  cipher: tlsSocket.getCipher?.(),
57672
57736
  authorized: tlsSocket.authorized,
@@ -57677,7 +57741,7 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
57677
57741
  activeServers.add(server);
57678
57742
  return new Promise((resolve4, reject) => {
57679
57743
  server.listen(listenPort, hostname, () => {
57680
- debugLog2("server", `Server listening on port ${listenPort}`, verbose);
57744
+ debugLog("server", `Server listening on port ${listenPort}`, verbose);
57681
57745
  console.log("");
57682
57746
  console.log(` ${green(bold("reverse-proxy"))} ${green(`v${version}`)}`);
57683
57747
  console.log("");
@@ -57694,13 +57758,13 @@ async function createProxyServer(from, to, fromPort, listenPort, hostname, sourc
57694
57758
  resolve4();
57695
57759
  });
57696
57760
  server.on("error", (err3) => {
57697
- debugLog2("server", `Server error: ${err3}`, verbose);
57761
+ debugLog("server", `Server error: ${err3}`, verbose);
57698
57762
  reject(err3);
57699
57763
  });
57700
57764
  });
57701
57765
  }
57702
57766
  async function setupReverseProxy(options3) {
57703
- debugLog2("setup", `Setting up reverse proxy: ${JSON.stringify(options3)}`, options3.verbose);
57767
+ debugLog("setup", `Setting up reverse proxy: ${JSON.stringify(options3)}`, options3.verbose);
57704
57768
  const { from, to, fromPort, sourceUrl, ssl, verbose, etcHostsCleanup, portManager } = options3;
57705
57769
  const httpPort = 80;
57706
57770
  const httpsPort = 443;
@@ -57709,11 +57773,11 @@ async function setupReverseProxy(options3) {
57709
57773
  if (ssl && !portManager?.usedPorts.has(httpPort)) {
57710
57774
  const isHttpPortBusy = await isPortInUse(httpPort, hostname, verbose);
57711
57775
  if (!isHttpPortBusy) {
57712
- debugLog2("setup", "Starting HTTP redirect server", verbose);
57776
+ debugLog("setup", "Starting HTTP redirect server", verbose);
57713
57777
  startHttpRedirectServer(verbose);
57714
57778
  portManager?.usedPorts.add(httpPort);
57715
57779
  } else {
57716
- debugLog2("setup", "Port 80 is in use, skipping HTTP redirect", verbose);
57780
+ debugLog("setup", "Port 80 is in use, skipping HTTP redirect", verbose);
57717
57781
  log.warn("Port 80 is in use, HTTP to HTTPS redirect will not be available");
57718
57782
  }
57719
57783
  }
@@ -57731,7 +57795,7 @@ async function setupReverseProxy(options3) {
57731
57795
  }
57732
57796
  await createProxyServer(from, to, fromPort, finalPort, hostname, sourceUrl, ssl, verbose);
57733
57797
  } catch (err3) {
57734
- debugLog2("setup", `Setup failed: ${err3}`, verbose);
57798
+ debugLog("setup", `Setup failed: ${err3}`, verbose);
57735
57799
  log.error(`Failed to setup reverse proxy: ${err3.message}`);
57736
57800
  cleanup({
57737
57801
  domains: [to],
@@ -57741,70 +57805,96 @@ async function setupReverseProxy(options3) {
57741
57805
  }
57742
57806
  }
57743
57807
  function startHttpRedirectServer(verbose) {
57744
- debugLog2("redirect", "Starting HTTP redirect server", verbose);
57808
+ debugLog("redirect", "Starting HTTP redirect server", verbose);
57745
57809
  const server = http.createServer((req, res) => {
57746
57810
  const host = req.headers.host || "";
57747
- debugLog2("redirect", `Redirecting request from ${host}${req.url} to HTTPS`, verbose);
57811
+ debugLog("redirect", `Redirecting request from ${host}${req.url} to HTTPS`, verbose);
57748
57812
  res.writeHead(301, {
57749
57813
  Location: `https://${host}${req.url}`
57750
57814
  });
57751
57815
  res.end();
57752
57816
  }).listen(80);
57753
57817
  activeServers.add(server);
57754
- debugLog2("redirect", "HTTP redirect server started", verbose);
57818
+ debugLog("redirect", "HTTP redirect server started", verbose);
57755
57819
  }
57756
57820
  function startProxy(options3) {
57757
- debugLog2("proxy", `Starting proxy with options: ${JSON.stringify(options3)}`, options3?.verbose);
57821
+ const mergedOptions = {
57822
+ ...config4,
57823
+ ...options3
57824
+ };
57825
+ debugLog("proxy", `Starting proxy with options: ${JSON.stringify(mergedOptions)}`, mergedOptions?.verbose);
57758
57826
  const serverOptions = {
57759
- from: options3?.from || "localhost:5173",
57760
- to: options3?.to || "stacks.localhost",
57761
- https: httpsConfig(options3),
57762
- etcHostsCleanup: options3?.etcHostsCleanup || false,
57763
- verbose: options3?.verbose || false
57827
+ from: mergedOptions.from,
57828
+ to: mergedOptions.to,
57829
+ https: httpsConfig(mergedOptions),
57830
+ etcHostsCleanup: mergedOptions.etcHostsCleanup,
57831
+ verbose: mergedOptions.verbose
57764
57832
  };
57765
57833
  console.log("serverOptions", serverOptions);
57766
57834
  startServer(serverOptions).catch((err3) => {
57767
- debugLog2("proxy", `Failed to start proxy: ${err3}`, options3.verbose);
57835
+ debugLog("proxy", `Failed to start proxy: ${err3}`, mergedOptions.verbose);
57768
57836
  log.error(`Failed to start proxy: ${err3.message}`);
57769
57837
  cleanup({
57770
- domains: [options3.to],
57771
- etcHostsCleanup: options3.etcHostsCleanup,
57772
- verbose: options3.verbose
57838
+ domains: [mergedOptions.to],
57839
+ etcHostsCleanup: mergedOptions.etcHostsCleanup,
57840
+ verbose: mergedOptions.verbose
57773
57841
  });
57774
57842
  });
57775
57843
  }
57776
57844
  async function startProxies(options3) {
57777
- if (!options3)
57778
- return;
57779
- debugLog2("proxies", "Starting proxies setup", isMultiProxyConfig2(options3) ? options3.verbose : options3.verbose);
57780
- if (options3.https) {
57781
- await generateCertificate2(options3);
57845
+ debugLog("proxies", "Starting proxy setup", options3?.verbose);
57846
+ const mergedOptions = {
57847
+ ...config4,
57848
+ ...options3
57849
+ };
57850
+ const primaryDomain = isMultiProxyConfig(mergedOptions) ? mergedOptions.proxies[0].to || "stacks.localhost" : mergedOptions.to || "stacks.localhost";
57851
+ if (mergedOptions.https) {
57852
+ const existingSSLConfig = await checkExistingCertificates(mergedOptions);
57853
+ if (existingSSLConfig) {
57854
+ debugLog("ssl", `Using existing certificates for ${primaryDomain}`, mergedOptions.verbose);
57855
+ mergedOptions._cachedSSLConfig = existingSSLConfig;
57856
+ } else {
57857
+ debugLog("ssl", `No valid certificates found for ${primaryDomain}, generating new ones`, mergedOptions.verbose);
57858
+ await generateCertificate2(mergedOptions);
57859
+ const sslConfig2 = await checkExistingCertificates(mergedOptions);
57860
+ if (!sslConfig2) {
57861
+ throw new Error(`Failed to load SSL certificates after generation for ${primaryDomain}. Please check file permissions and paths.`);
57862
+ }
57863
+ mergedOptions._cachedSSLConfig = sslConfig2;
57864
+ }
57782
57865
  }
57783
- const proxyOptions = isMultiProxyConfig2(options3) ? options3.proxies.map((proxy) => ({
57866
+ const proxyOptions = isMultiProxyConfig(mergedOptions) ? mergedOptions.proxies.map((proxy) => ({
57784
57867
  ...proxy,
57785
- https: options3.https,
57786
- etcHostsCleanup: options3.etcHostsCleanup,
57787
- verbose: options3.verbose,
57788
- _cachedSSLConfig: options3._cachedSSLConfig
57789
- })) : [options3];
57790
- const domains = extractDomains(options3);
57791
- const sslConfig = options3.https ? getSSLConfig() : null;
57868
+ https: mergedOptions.https,
57869
+ etcHostsCleanup: mergedOptions.etcHostsCleanup,
57870
+ verbose: mergedOptions.verbose,
57871
+ _cachedSSLConfig: mergedOptions._cachedSSLConfig
57872
+ })) : [{
57873
+ from: mergedOptions.from || "localhost:5173",
57874
+ to: mergedOptions.to || "stacks.localhost",
57875
+ https: mergedOptions.https,
57876
+ etcHostsCleanup: mergedOptions.etcHostsCleanup,
57877
+ verbose: mergedOptions.verbose,
57878
+ _cachedSSLConfig: mergedOptions._cachedSSLConfig
57879
+ }];
57880
+ const domains = proxyOptions.map((opt) => opt.to || "stacks.localhost");
57881
+ const sslConfig = mergedOptions._cachedSSLConfig;
57792
57882
  const cleanupHandler = () => cleanup({
57793
57883
  domains,
57794
- etcHostsCleanup: isMultiProxyConfig2(options3) ? options3.etcHostsCleanup : options3.etcHostsCleanup || false,
57795
- verbose: isMultiProxyConfig2(options3) ? options3.verbose : options3.verbose || false
57884
+ etcHostsCleanup: mergedOptions.etcHostsCleanup || false,
57885
+ verbose: mergedOptions.verbose || false
57796
57886
  });
57797
- process20.on("SIGINT", cleanupHandler);
57798
- process20.on("SIGTERM", cleanupHandler);
57799
- process20.on("uncaughtException", (err3) => {
57800
- debugLog2("process", `Uncaught exception: ${err3}`, true);
57801
- log.error("Uncaught exception:", err3);
57887
+ process9.on("SIGINT", cleanupHandler);
57888
+ process9.on("SIGTERM", cleanupHandler);
57889
+ process9.on("uncaughtException", (err3) => {
57890
+ debugLog("process", `Uncaught exception: ${err3}`, true);
57891
+ console.error("Uncaught exception:", err3);
57802
57892
  cleanupHandler();
57803
57893
  });
57804
57894
  for (const option of proxyOptions) {
57805
57895
  try {
57806
57896
  const domain = option.to || "stacks.localhost";
57807
- debugLog2("proxy", `Starting proxy for ${domain} with SSL config: ${!!sslConfig}`, option.verbose);
57897
+ debugLog("proxy", `Starting proxy for ${domain} with SSL config: ${!!sslConfig}`, option.verbose);
57808
57898
  await startServer({
57809
57899
  from: option.from || "localhost:5173",
57810
57900
  to: domain,
@@ -57814,15 +57904,12 @@ async function startProxies(options3) {
57814
57904
  _cachedSSLConfig: sslConfig
57815
57905
  });
57816
57906
  } catch (err3) {
57817
- debugLog2("proxies", `Failed to start proxy for ${option.to}: ${err3}`, option.verbose);
57818
- log.error(`Failed to start proxy for ${option.to}:`, err3);
57907
+ debugLog("proxies", `Failed to start proxy for ${option.to}: ${err3}`, option.verbose);
57908
+ console.error(`Failed to start proxy for ${option.to}:`, err3);
57819
57909
  cleanupHandler();
57820
57910
  }
57821
57911
  }
57822
57912
  }
57823
- function isMultiProxyConfig2(options3) {
57824
- return "proxies" in options3;
57825
- }
57826
57913
 
57827
57914
  // src/index.ts
57828
57915
  var src_default = startProxies;
@@ -57832,17 +57919,27 @@ export {
57832
57919
  startProxies,
57833
57920
  startHttpRedirectServer,
57834
57921
  setupReverseProxy,
57922
+ resolveSSLPaths,
57835
57923
  removeHosts,
57924
+ loadSSLConfig,
57925
+ isValidRootCA,
57926
+ isSingleProxyOptions,
57927
+ isMultiProxyOptions,
57836
57928
  isMultiProxyConfig,
57837
57929
  httpsConfig,
57838
57930
  hostsFilePath,
57839
57931
  getSSLConfig,
57932
+ getPrimaryDomain,
57933
+ getAllDomains,
57934
+ generateWildcardPatterns,
57935
+ generateSSLPaths,
57840
57936
  generateCertificate2 as generateCertificate,
57841
- extractDomains,
57937
+ extractHostname,
57842
57938
  src_default as default,
57843
- debugLog2 as debugLog,
57844
- config6 as config,
57939
+ debugLog,
57940
+ config4 as config,
57845
57941
  cleanup,
57846
57942
  checkHosts,
57943
+ checkExistingCertificates,
57847
57944
  addHosts
57848
57945
  };