@hamedb89/localghost 0.1.6 → 0.1.8

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.d.ts CHANGED
@@ -57,10 +57,12 @@ declare function startCaddy(path: string): execa.ResultPromise<{
57
57
  cwd: string;
58
58
  stdio: "inherit";
59
59
  }>;
60
+ declare function trustCaddy(path: string): Promise<void>;
60
61
 
61
62
  type LocalghostContextOptions = {
62
63
  cwd?: string;
63
64
  project?: string;
65
+ localghostConfig?: string | false;
64
66
  fileName?: string;
65
67
  configFiles?: string[];
66
68
  configPattern?: ConfigPattern;
@@ -69,6 +71,7 @@ type LocalghostContextOptions = {
69
71
  bindHost?: string | boolean;
70
72
  primaryHost?: string;
71
73
  dynamicPort?: boolean;
74
+ wwwAlias?: boolean;
72
75
  };
73
76
  type LocalghostContext = {
74
77
  cwd: string;
@@ -85,6 +88,8 @@ type LocalghostContext = {
85
88
  bindHost: string | boolean;
86
89
  primaryHost: string;
87
90
  https: boolean;
91
+ wwwAlias: boolean;
92
+ projectConfigPath?: string;
88
93
  };
89
94
  declare function defineLocalghostConfig<T extends LocalghostContextOptions>(config: T): T;
90
95
  declare function resolveLocalghostContext(options?: LocalghostContextOptions): Promise<LocalghostContext>;
@@ -180,15 +185,18 @@ type LocalghostState = {
180
185
  caddyfilePath?: string;
181
186
  caddyfileRemoved?: boolean;
182
187
  caddyHttps?: boolean;
188
+ caddyTrustedAt?: string;
189
+ caddyTrustPromptedAt?: string;
183
190
  entries?: DevHostEntry[];
184
191
  };
185
192
  type WriteLocalghostStateInput = Omit<LocalghostState, "version" | "updatedAt">;
186
193
  declare function getLocalghostStatePath(cwd?: string): string;
187
194
  declare function readLocalghostState(cwd?: string): LocalghostState | null;
188
195
  declare function writeLocalghostState(cwd: string, state: WriteLocalghostStateInput): string;
196
+ declare function patchLocalghostState(cwd: string, patch: Partial<WriteLocalghostStateInput>): string | null;
189
197
 
190
198
  declare const LOCALGHOST_PACKAGE_NAME = "@hamedb89/localghost";
191
- declare const LOCALGHOST_VERSION = "0.1.6";
199
+ declare const LOCALGHOST_VERSION = "0.1.8";
192
200
  declare const UPDATE_CHECK_CACHE_TTL_MS: number;
193
201
  declare const UPDATE_CHECK_NOTIFY_TTL_MS: number;
194
202
  declare const UPDATE_CHECK_TIMEOUT_MS = 900;
@@ -225,4 +233,4 @@ declare function maybeNotifyAboutUpdate(options?: {
225
233
  disabled?: boolean;
226
234
  }): Promise<void>;
227
235
 
228
- export { type CaddyModeOptions, ConfigPattern, DevHostEntry, type DoctorResult, type DomainRoute, type DomainRouteOptions, type FindAvailablePortOptions, type InitOptions, type InitResult, LOCALGHOST_ACTIVITY_VERSION, LOCALGHOST_PACKAGE_NAME, LOCALGHOST_STATE_FILE, LOCALGHOST_VERSION, type LocalghostActivity, type LocalghostContext, type LocalghostContextOptions, type LocalghostEnvironment, type LocalghostRunMode, type LocalghostRunRecord, type LocalghostState, type LocalghostStateAction, type PackageManager, ReadDevHostsOptions, type RegisterLocalghostRunInput, type RemoveSystemHostsResult, UPDATE_CHECK_CACHE_TTL_MS, UPDATE_CHECK_NOTIFY_TTL_MS, UPDATE_CHECK_TIMEOUT_MS, type UpdateCheckCache, type UpdateCheckResult, type UpdateSystemHostsResult, type WriteLocalghostStateInput, assertLocalDevelopment, checkCaddy, checkForUpdate, compareVersions, defineLocalghostConfig, detectPackageManager, findAvailablePort, formatDomainRoutes, formatUpdateMessage, getCaddyfilePath, getDomainRoutes, getLocalghostActivityPath, getLocalghostStatePath, getProductionEnvKeys, getProductionReason, getSystemHostsPath, getUpdateCheckCachePath, initLocalghost, isNewerVersion, isPortAvailable, isProcessRunning, isProductionLike, isUpdateCheckDisabled, listLocalghostRuns, markUpdateNotified, maybeNotifyAboutUpdate, packageAddCommand, packageRunCommand, pruneLocalghostActivity, readLocalghostActivity, readLocalghostState, registerLocalghostRun, removeManagedBlock, removeSystemHosts, renderCaddyfile, renderHostsBlock, resolveLocalghostContext, runCaddy, runDoctor, shouldNotifyAboutUpdate, startCaddy, unregisterLocalghostRun, updateSystemHosts, upsertManagedBlock, validateCaddyfile, writeCaddyfile, writeLocalghostActivity, writeLocalghostState };
236
+ export { type CaddyModeOptions, ConfigPattern, DevHostEntry, type DoctorResult, type DomainRoute, type DomainRouteOptions, type FindAvailablePortOptions, type InitOptions, type InitResult, LOCALGHOST_ACTIVITY_VERSION, LOCALGHOST_PACKAGE_NAME, LOCALGHOST_STATE_FILE, LOCALGHOST_VERSION, type LocalghostActivity, type LocalghostContext, type LocalghostContextOptions, type LocalghostEnvironment, type LocalghostRunMode, type LocalghostRunRecord, type LocalghostState, type LocalghostStateAction, type PackageManager, ReadDevHostsOptions, type RegisterLocalghostRunInput, type RemoveSystemHostsResult, UPDATE_CHECK_CACHE_TTL_MS, UPDATE_CHECK_NOTIFY_TTL_MS, UPDATE_CHECK_TIMEOUT_MS, type UpdateCheckCache, type UpdateCheckResult, type UpdateSystemHostsResult, type WriteLocalghostStateInput, assertLocalDevelopment, checkCaddy, checkForUpdate, compareVersions, defineLocalghostConfig, detectPackageManager, findAvailablePort, formatDomainRoutes, formatUpdateMessage, getCaddyfilePath, getDomainRoutes, getLocalghostActivityPath, getLocalghostStatePath, getProductionEnvKeys, getProductionReason, getSystemHostsPath, getUpdateCheckCachePath, initLocalghost, isNewerVersion, isPortAvailable, isProcessRunning, isProductionLike, isUpdateCheckDisabled, listLocalghostRuns, markUpdateNotified, maybeNotifyAboutUpdate, packageAddCommand, packageRunCommand, patchLocalghostState, pruneLocalghostActivity, readLocalghostActivity, readLocalghostState, registerLocalghostRun, removeManagedBlock, removeSystemHosts, renderCaddyfile, renderHostsBlock, resolveLocalghostContext, runCaddy, runDoctor, shouldNotifyAboutUpdate, startCaddy, trustCaddy, unregisterLocalghostRun, updateSystemHosts, upsertManagedBlock, validateCaddyfile, writeCaddyfile, writeLocalghostActivity, writeLocalghostState };
package/dist/index.js CHANGED
@@ -283,6 +283,16 @@ function startCaddy(path) {
283
283
  stdio: "inherit"
284
284
  });
285
285
  }
286
+ async function trustCaddy(path) {
287
+ await execa("caddy", ["trust", "--config", path], {
288
+ cwd: dirname3(path),
289
+ stdio: "inherit"
290
+ });
291
+ }
292
+
293
+ // src/context.ts
294
+ import { existsSync as existsSync3 } from "fs";
295
+ import { pathToFileURL } from "url";
286
296
 
287
297
  // src/port.ts
288
298
  import { createServer } from "net";
@@ -311,6 +321,11 @@ async function findAvailablePort(startPort, options = {}) {
311
321
  }
312
322
 
313
323
  // src/context.ts
324
+ var LOCALGHOST_PROJECT_CONFIG_FILES = [
325
+ "localghost.config.mjs",
326
+ "localghost.config.js",
327
+ "localghost.config.cjs"
328
+ ];
314
329
  function parsePort(value) {
315
330
  if (!value) return void 0;
316
331
  const port = Number.parseInt(value, 10);
@@ -324,6 +339,11 @@ function envDynamicPort() {
324
339
  if (!value) return void 0;
325
340
  return ["1", "true", "yes", "on"].includes(value.toLowerCase());
326
341
  }
342
+ function envHttps() {
343
+ const value = process.env.LOCALGHOST_HTTPS;
344
+ if (!value) return void 0;
345
+ return ["1", "true", "yes", "on"].includes(value.toLowerCase());
346
+ }
327
347
  function readOptionsFromContext(options) {
328
348
  return {
329
349
  cwd: options.cwd ?? process.cwd(),
@@ -341,25 +361,61 @@ function withRuntimePort(entries, requestedPort, port) {
341
361
  function uniqueHosts(entries) {
342
362
  return [...new Set(entries.map((entry) => entry.host))];
343
363
  }
364
+ function isAliasableHost(host) {
365
+ return host.includes(".") && !host.startsWith("www.") && !host.includes(":");
366
+ }
367
+ function getDefaultWwwAlias(host) {
368
+ return isAliasableHost(host) ? `www.${host}` : null;
369
+ }
370
+ function addDefaultWwwAliases(entries) {
371
+ const seen = new Set(entries.map((entry) => entry.host));
372
+ const aliases = [];
373
+ for (const entry of entries) {
374
+ const alias = getDefaultWwwAlias(entry.host);
375
+ if (alias && !seen.has(alias)) {
376
+ aliases.push({ host: alias, port: entry.port, target: `127.0.0.1:${entry.port}` });
377
+ seen.add(alias);
378
+ }
379
+ }
380
+ return [...entries, ...aliases];
381
+ }
382
+ function defined(input) {
383
+ return Object.fromEntries(Object.entries(input).filter(([, value]) => typeof value !== "undefined"));
384
+ }
385
+ async function readProjectConfig(cwd, configFile) {
386
+ if (configFile === false) return {};
387
+ const candidates = configFile ? [configFile] : LOCALGHOST_PROJECT_CONFIG_FILES;
388
+ const path = candidates.map((candidate) => resolveDevHostsPath({ cwd, fileName: candidate }).path).find((candidate) => existsSync3(candidate));
389
+ if (!path) return {};
390
+ const imported = await import(`${pathToFileURL(path).href}?localghost=${Date.now()}`);
391
+ const config = imported.default ?? imported;
392
+ return { config, path };
393
+ }
344
394
  function defineLocalghostConfig(config) {
345
395
  return config;
346
396
  }
347
397
  async function resolveLocalghostContext(options = {}) {
348
398
  const cwd = options.cwd ?? process.cwd();
349
- const readOptions = readOptionsFromContext({ ...options, cwd });
399
+ const projectConfig = await readProjectConfig(cwd, options.localghostConfig);
400
+ const merged = {
401
+ ...projectConfig.config,
402
+ ...defined(options)
403
+ };
404
+ const readOptions = readOptionsFromContext({ ...merged, cwd });
350
405
  const resolvedPath = resolveDevHostsPath(readOptions);
351
406
  const configEntries = readDevHosts(readOptions);
352
- const requestedPort = options.port ?? envPort() ?? configEntries[0]?.port ?? 5173;
353
- const dynamicPort = options.dynamicPort ?? envDynamicPort() ?? false;
354
- const bindHost = options.bindHost ?? "127.0.0.1";
407
+ const requestedPort = merged.port ?? envPort() ?? configEntries[0]?.port ?? 5173;
408
+ const dynamicPort = merged.dynamicPort ?? envDynamicPort() ?? false;
409
+ const bindHost = merged.bindHost ?? "127.0.0.1";
355
410
  const probeHost = typeof bindHost === "string" ? bindHost : "127.0.0.1";
356
411
  const port = dynamicPort ? await findAvailablePort(requestedPort, { host: probeHost }) : requestedPort;
357
- const entries = withRuntimePort(configEntries, requestedPort, port);
412
+ const wwwAlias = merged.wwwAlias ?? true;
413
+ const entries = wwwAlias ? addDefaultWwwAliases(withRuntimePort(configEntries, requestedPort, port)) : withRuntimePort(configEntries, requestedPort, port);
358
414
  const hosts = uniqueHosts(entries);
359
- const primaryHost = options.primaryHost ?? entries.find((entry) => entry.port === port)?.host ?? hosts[0] ?? `${sanitizeProjectName(getProjectName(cwd))}.localhost`;
415
+ const primaryHost = merged.primaryHost ?? entries.find((entry) => entry.port === port)?.host ?? hosts[0] ?? `${sanitizeProjectName(getProjectName(cwd))}.localhost`;
360
416
  return {
361
417
  cwd,
362
- projectName: sanitizeProjectName(options.project ?? getProjectName(cwd)),
418
+ projectName: sanitizeProjectName(merged.project ?? getProjectName(cwd)),
363
419
  readOptions,
364
420
  configPath: resolvedPath.path,
365
421
  configFileName: resolvedPath.fileName,
@@ -371,7 +427,9 @@ async function resolveLocalghostContext(options = {}) {
371
427
  dynamicPort,
372
428
  bindHost,
373
429
  primaryHost,
374
- https: options.https === true
430
+ https: merged.https ?? envHttps() ?? false,
431
+ wwwAlias,
432
+ ...projectConfig.path ? { projectConfigPath: projectConfig.path } : {}
375
433
  };
376
434
  }
377
435
 
@@ -503,11 +561,11 @@ async function removeSystemHosts(projectName) {
503
561
  }
504
562
 
505
563
  // src/init.ts
506
- import { existsSync as existsSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
564
+ import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
507
565
  import { join as join5 } from "path";
508
566
  function detectPackageManager(cwd = process.cwd()) {
509
- if (existsSync3(join5(cwd, "pnpm-lock.yaml"))) return "pnpm";
510
- if (existsSync3(join5(cwd, "yarn.lock"))) return "yarn";
567
+ if (existsSync4(join5(cwd, "pnpm-lock.yaml"))) return "pnpm";
568
+ if (existsSync4(join5(cwd, "yarn.lock"))) return "yarn";
511
569
  return "npm";
512
570
  }
513
571
  function packageRunCommand(packageManager, script) {
@@ -556,6 +614,7 @@ function updatePackageScripts(packageJsonPath, configFile) {
556
614
  "localghost:proxy:https": scripts["localghost:proxy:https"] ?? `localghost dev${configFlag} --https`,
557
615
  "localghost:run": scripts["localghost:run"] ?? `localghost run${configFlag} --`,
558
616
  "localghost:ready": scripts["localghost:ready"] ?? `localghost status${configFlag} --ready`,
617
+ "localghost:trust": scripts["localghost:trust"] ?? `localghost trust${configFlag}`,
559
618
  "localghost:ps": scripts["localghost:ps"] ?? "localghost ps",
560
619
  "localghost:print": scripts["localghost:print"] ?? `localghost print${configFlag}`,
561
620
  "localghost:routes": scripts["localghost:routes"] ?? `localghost routes${configFlag}`,
@@ -584,7 +643,7 @@ function initLocalghost(options = {}) {
584
643
  const packageManager = options.packageManager ?? detectPackageManager(cwd);
585
644
  const configFile = options.configFile ?? LOCALGHOST_CONFIG_FILE;
586
645
  const configPath = join5(cwd, configFile);
587
- const configExists = existsSync3(configPath);
646
+ const configExists = existsSync4(configPath);
588
647
  if (configExists && !options.force) {
589
648
  return {
590
649
  configPath,
@@ -605,7 +664,7 @@ function initLocalghost(options = {}) {
605
664
  return {
606
665
  configPath,
607
666
  configCreated: true,
608
- ...existsSync3(packageJsonPath) ? { packageJsonPath } : {},
667
+ ...existsSync4(packageJsonPath) ? { packageJsonPath } : {},
609
668
  packageJsonChanged,
610
669
  packageManager,
611
670
  nextSteps: [
@@ -639,7 +698,7 @@ function formatDomainRoutes(entries, options = {}) {
639
698
  }
640
699
 
641
700
  // src/state.ts
642
- import { existsSync as existsSync4 } from "fs";
701
+ import { existsSync as existsSync5 } from "fs";
643
702
  import { join as join6 } from "path";
644
703
  var LOCALGHOST_STATE_FILE = "ops/local/localghost-state.json";
645
704
  function getLocalghostStatePath(cwd = process.cwd()) {
@@ -647,22 +706,27 @@ function getLocalghostStatePath(cwd = process.cwd()) {
647
706
  }
648
707
  function readLocalghostState(cwd = process.cwd()) {
649
708
  const path = getLocalghostStatePath(cwd);
650
- if (!existsSync4(path)) return null;
709
+ if (!existsSync5(path)) return null;
651
710
  return JSON.parse(readTextFile(path));
652
711
  }
653
712
  function writeLocalghostState(cwd, state) {
654
713
  const path = getLocalghostStatePath(cwd);
655
- writeTextFile(path, `${JSON.stringify({ version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...state }, null, 2)}
714
+ writeTextFile(path, `${JSON.stringify({ ...state, version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)}
656
715
  `);
657
716
  return path;
658
717
  }
718
+ function patchLocalghostState(cwd, patch) {
719
+ const current = readLocalghostState(cwd);
720
+ if (!current) return null;
721
+ return writeLocalghostState(cwd, { ...current, ...patch });
722
+ }
659
723
 
660
724
  // src/update-check.ts
661
- import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
725
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
662
726
  import { homedir as homedir2 } from "os";
663
727
  import { dirname as dirname4, join as join7 } from "path";
664
728
  var LOCALGHOST_PACKAGE_NAME = "@hamedb89/localghost";
665
- var LOCALGHOST_VERSION = "0.1.6";
729
+ var LOCALGHOST_VERSION = "0.1.8";
666
730
  var UPDATE_CHECK_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
667
731
  var UPDATE_CHECK_NOTIFY_TTL_MS = 24 * 60 * 60 * 1e3;
668
732
  var UPDATE_CHECK_TIMEOUT_MS = 900;
@@ -678,7 +742,7 @@ function getUpdateCheckCachePath(env = process.env) {
678
742
  return join7(cacheRoot, "localghost", "update-check.json");
679
743
  }
680
744
  function readCache(path = getUpdateCheckCachePath()) {
681
- if (!existsSync5(path)) return null;
745
+ if (!existsSync6(path)) return null;
682
746
  try {
683
747
  return JSON.parse(readFileSync5(path, "utf8"));
684
748
  } catch {
@@ -865,6 +929,7 @@ export {
865
929
  packageAddCommand,
866
930
  packageRunCommand,
867
931
  parseDevHosts,
932
+ patchLocalghostState,
868
933
  pruneLocalghostActivity,
869
934
  readDevHosts,
870
935
  readLocalghostActivity,
@@ -881,6 +946,7 @@ export {
881
946
  sanitizeProjectName,
882
947
  shouldNotifyAboutUpdate,
883
948
  startCaddy,
949
+ trustCaddy,
884
950
  unregisterLocalghostRun,
885
951
  updateSystemHosts,
886
952
  upsertManagedBlock,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/activity.ts","../src/config.ts","../src/parse.ts","../src/caddy.ts","../src/fs.ts","../src/port.ts","../src/context.ts","../src/doctor.ts","../src/env.ts","../src/hosts-file.ts","../src/init.ts","../src/routes.ts","../src/state.ts","../src/update-check.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport const LOCALGHOST_ACTIVITY_VERSION = 1;\n\nexport type LocalghostRunMode = \"dev\" | \"run\";\n\nexport type LocalghostRunRecord = {\n id: string;\n mode: LocalghostRunMode;\n pid: number;\n cwd: string;\n projectName: string;\n startedAt: string;\n updatedAt: string;\n configPath?: string;\n caddyfilePath?: string;\n caddyPid?: number;\n childPid?: number;\n childCommand?: string[];\n https?: boolean;\n requestedPort?: number;\n port?: number;\n dynamicPort?: boolean;\n entries: DevHostEntry[];\n};\n\nexport type LocalghostActivity = {\n version: typeof LOCALGHOST_ACTIVITY_VERSION;\n runs: LocalghostRunRecord[];\n};\n\nexport type RegisterLocalghostRunInput = Omit<LocalghostRunRecord, \"id\" | \"pid\" | \"startedAt\" | \"updatedAt\"> & {\n id?: string;\n pid?: number;\n startedAt?: string;\n};\n\nexport function getLocalghostActivityPath(env: NodeJS.ProcessEnv = process.env) {\n if (env.LOCALGHOST_ACTIVITY_PATH) return env.LOCALGHOST_ACTIVITY_PATH;\n\n const stateRoot = env.XDG_STATE_HOME || join(homedir(), \".local/state\");\n return join(stateRoot, \"localghost\", \"activity.json\");\n}\n\nexport function isProcessRunning(pid: number) {\n if (!Number.isInteger(pid) || pid < 1) return false;\n\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const code = typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n return code === \"EPERM\";\n }\n}\n\nfunction emptyActivity(): LocalghostActivity {\n return { version: LOCALGHOST_ACTIVITY_VERSION, runs: [] };\n}\n\nexport function readLocalghostActivity(path = getLocalghostActivityPath()): LocalghostActivity {\n if (!existsSync(path)) return emptyActivity();\n\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<LocalghostActivity>;\n return {\n version: LOCALGHOST_ACTIVITY_VERSION,\n runs: Array.isArray(parsed.runs) ? parsed.runs : []\n };\n } catch {\n return emptyActivity();\n }\n}\n\nexport function writeLocalghostActivity(activity: LocalghostActivity, path = getLocalghostActivityPath()) {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(activity, null, 2)}\\n`, \"utf8\");\n return path;\n}\n\nfunction createRunId(input: Pick<RegisterLocalghostRunInput, \"mode\" | \"cwd\" | \"projectName\">, pid: number) {\n return `${input.projectName}:${input.mode}:${pid}:${Date.now()}`;\n}\n\nexport function pruneLocalghostActivity(path = getLocalghostActivityPath()) {\n const activity = readLocalghostActivity(path);\n const activeRuns = activity.runs.filter((run) => isProcessRunning(run.pid));\n const pruned = activeRuns.length !== activity.runs.length;\n\n if (pruned) {\n writeLocalghostActivity({ version: LOCALGHOST_ACTIVITY_VERSION, runs: activeRuns }, path);\n }\n\n return {\n path,\n pruned,\n runs: activeRuns\n };\n}\n\nexport function listLocalghostRuns(path = getLocalghostActivityPath()) {\n return pruneLocalghostActivity(path).runs;\n}\n\nexport function registerLocalghostRun(input: RegisterLocalghostRunInput, path = getLocalghostActivityPath()) {\n const now = new Date().toISOString();\n const pid = input.pid ?? process.pid;\n const record: LocalghostRunRecord = {\n id: input.id ?? createRunId(input, pid),\n mode: input.mode,\n pid,\n cwd: input.cwd,\n projectName: input.projectName,\n startedAt: input.startedAt ?? now,\n updatedAt: now,\n ...(input.configPath ? { configPath: input.configPath } : {}),\n ...(input.caddyfilePath ? { caddyfilePath: input.caddyfilePath } : {}),\n ...(input.caddyPid ? { caddyPid: input.caddyPid } : {}),\n ...(input.childPid ? { childPid: input.childPid } : {}),\n ...(input.childCommand ? { childCommand: input.childCommand } : {}),\n ...(typeof input.https === \"boolean\" ? { https: input.https } : {}),\n ...(input.requestedPort ? { requestedPort: input.requestedPort } : {}),\n ...(input.port ? { port: input.port } : {}),\n ...(typeof input.dynamicPort === \"boolean\" ? { dynamicPort: input.dynamicPort } : {}),\n entries: input.entries\n };\n const current = pruneLocalghostActivity(path).runs.filter((run) => run.id !== record.id);\n writeLocalghostActivity({ version: LOCALGHOST_ACTIVITY_VERSION, runs: [...current, record] }, path);\n return record;\n}\n\nexport function unregisterLocalghostRun(id: string, path = getLocalghostActivityPath()) {\n const activity = readLocalghostActivity(path);\n const runs = activity.runs.filter((run) => run.id !== id);\n\n if (runs.length !== activity.runs.length) {\n writeLocalghostActivity({ version: LOCALGHOST_ACTIVITY_VERSION, runs }, path);\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { basename, join, resolve } from \"node:path\";\nimport { parseDevHosts } from \"./parse.js\";\n\nexport const LOCALGHOST_CONFIG_FILE = \".localghost\";\n\nexport type ConfigPattern = string | RegExp;\n\nexport type ReadDevHostsOptions = {\n cwd?: string;\n fileName?: string;\n configFiles?: string[];\n configPattern?: ConfigPattern;\n};\n\nexport type ResolvedDevHostsPath = {\n path: string;\n fileName: string;\n exists: boolean;\n searchedFiles: string[];\n configPattern?: ConfigPattern;\n};\n\nfunction unique(values: string[]) {\n return [...new Set(values.filter(Boolean))];\n}\n\nfunction toRegExp(pattern: ConfigPattern) {\n return typeof pattern === \"string\" ? new RegExp(pattern) : pattern;\n}\n\nfunction findPatternMatches(cwd: string, pattern: ConfigPattern) {\n const matcher = toRegExp(pattern);\n\n return readdirSync(cwd, { withFileTypes: true })\n .filter((entry) => entry.isFile())\n .map((entry) => entry.name)\n .filter((name) => {\n matcher.lastIndex = 0;\n return matcher.test(name);\n })\n .sort();\n}\n\nexport function getConfigFileCandidates(options: ReadDevHostsOptions = {}) {\n const cwd = options.cwd ?? process.cwd();\n const exactFiles = unique([\n ...(options.fileName ? [options.fileName] : []),\n ...(options.configFiles ?? [])\n ]);\n const patternFiles = options.configPattern ? findPatternMatches(cwd, options.configPattern) : [];\n const candidates = unique([...exactFiles, ...patternFiles]);\n\n if (candidates.length > 0) return candidates;\n if (exactFiles.length > 0 || options.configPattern) return [];\n return [LOCALGHOST_CONFIG_FILE];\n}\n\nexport function resolveDevHostsPath(options: ReadDevHostsOptions = {}): ResolvedDevHostsPath {\n const cwd = options.cwd ?? process.cwd();\n const searchedFiles = getConfigFileCandidates(options);\n\n for (const fileName of searchedFiles) {\n const path = resolve(cwd, fileName);\n if (existsSync(path)) {\n return {\n path,\n fileName: basename(fileName),\n exists: true,\n searchedFiles,\n ...(options.configPattern ? { configPattern: options.configPattern } : {})\n };\n }\n }\n\n const fileName = searchedFiles[0] ?? LOCALGHOST_CONFIG_FILE;\n\n return {\n path: resolve(cwd, fileName),\n fileName: basename(fileName),\n exists: false,\n searchedFiles,\n ...(options.configPattern ? { configPattern: options.configPattern } : {})\n };\n}\n\nexport function getDevHostsPath(options: ReadDevHostsOptions = {}) {\n return resolveDevHostsPath(options).path;\n}\n\nfunction formatSearchedFiles(files: string[], pattern?: ConfigPattern) {\n if (files.length > 0) return files.map((file) => `\\`${file}\\``).join(\", \");\n if (pattern) return `files matching ${pattern.toString()}`;\n return `\\`${LOCALGHOST_CONFIG_FILE}\\``;\n}\n\nexport function readDevHosts(options: ReadDevHostsOptions | string = {}) {\n const resolvedOptions = typeof options === \"string\" ? { cwd: options } : options;\n const resolvedPath = resolveDevHostsPath(resolvedOptions);\n\n if (!resolvedPath.exists) {\n const cwd = resolvedOptions.cwd ?? process.cwd();\n throw new Error(\n `Missing Localghost config in ${cwd}. Looked for ${formatSearchedFiles(resolvedPath.searchedFiles, resolvedPath.configPattern)}. Run \\`localghost init\\` or pass --config/--config-pattern.`\n );\n }\n\n return parseDevHosts(readFileSync(resolvedPath.path, \"utf8\"), resolvedPath.fileName);\n}\n\nexport function getProjectName(cwd = process.cwd()) {\n try {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as { name?: unknown };\n const name = typeof pkg.name === \"string\" && pkg.name ? pkg.name : \"app\";\n return sanitizeProjectName(name.replace(/^@/, \"\"));\n } catch {\n return \"app\";\n }\n}\n\nexport function sanitizeProjectName(value: string) {\n const projectName = value.replace(/[^\\w.-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n return projectName || \"app\";\n}\n","export type DevHostEntry = {\n host: string;\n port: number;\n target: string;\n};\n\nconst HOST_PATTERN = /^(?=.{1,253}$)(?!-)[a-z0-9-]+(\\.[a-z0-9-]+)*\\.?$/i;\n\nexport function parseDevHosts(input: string, fileName = \".localghost\"): DevHostEntry[] {\n const entries: DevHostEntry[] = [];\n\n input.split(/\\r?\\n/).forEach((rawLine, index) => {\n const line = rawLine.replace(/#.*/, \"\").trim();\n\n if (!line) {\n return;\n }\n\n const parts = line.split(/\\s+/);\n const host = parts[0];\n const portRaw = parts[1];\n\n if (!host || !portRaw || parts.length > 2) {\n throw new Error(`Invalid ${fileName} line ${index + 1}: \"${rawLine}\"`);\n }\n\n if (!HOST_PATTERN.test(host)) {\n throw new Error(`Invalid host on line ${index + 1}: \"${host}\"`);\n }\n\n const port = Number(portRaw);\n\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid port on line ${index + 1}: \"${portRaw}\"`);\n }\n\n entries.push({\n host: host.toLowerCase().replace(/\\.$/, \"\"),\n port,\n target: `127.0.0.1:${port}`\n });\n });\n\n return entries;\n}\n\nexport function findLocalMdnsHosts(entries: DevHostEntry[]): string[] {\n return [...new Set(entries.map((entry) => entry.host).filter((host) => host.endsWith(\".local\")))];\n}\n","import { dirname, join } from \"node:path\";\nimport { execa } from \"execa\";\nimport { writeTextFile } from \"./fs.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport type CaddyModeOptions = {\n https?: boolean;\n};\n\nfunction groupByPort(entries: DevHostEntry[]) {\n const groups = new Map<number, DevHostEntry[]>();\n\n for (const entry of entries) {\n const group = groups.get(entry.port) ?? [];\n group.push(entry);\n groups.set(entry.port, group);\n }\n\n return groups;\n}\n\nexport function getCaddyfilePath(cwd = process.cwd()) {\n return join(cwd, \"ops/local/Caddyfile\");\n}\n\nexport function renderCaddyfile(entries: DevHostEntry[], options: CaddyModeOptions = {}) {\n const groups = groupByPort(entries);\n const https = options.https === true;\n const blocks = [...groups.entries()]\n .sort(([leftPort], [rightPort]) => leftPort - rightPort)\n .map(([port, group]) => {\n const hosts = group\n .map((entry) => (https ? entry.host : `http://${entry.host}`))\n .sort()\n .join(\", \");\n\n return `${hosts} {\n reverse_proxy 127.0.0.1:${port}\n}`;\n });\n\n const globalOptions = https\n ? `{\n local_certs\n}\n\n`\n : \"\";\n\n return `${globalOptions}${blocks.join(\"\\n\\n\")}\n`;\n}\n\nexport async function writeCaddyfile(entries: DevHostEntry[], cwd = process.cwd(), options: CaddyModeOptions = {}) {\n const path = getCaddyfilePath(cwd);\n writeTextFile(path, renderCaddyfile(entries, options));\n return path;\n}\n\nexport async function validateCaddyfile(path: string) {\n await execa(\"caddy\", [\"validate\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n\nexport async function runCaddy(path: string) {\n await execa(\"caddy\", [\"run\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n\nexport function startCaddy(path: string) {\n return execa(\"caddy\", [\"run\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nexport function readTextFile(path: string) {\n return readFileSync(path, \"utf8\");\n}\n\nexport function writeTextFile(path: string, value: string) {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, value, \"utf8\");\n return path;\n}\n","import { createServer } from \"node:net\";\n\nexport type FindAvailablePortOptions = {\n host?: string;\n maxAttempts?: number;\n};\n\nexport async function isPortAvailable(port: number, host = \"127.0.0.1\") {\n return new Promise<boolean>((resolve) => {\n const server = createServer();\n\n server.once(\"error\", () => {\n resolve(false);\n });\n\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n\n server.listen(port, host);\n });\n}\n\nexport async function findAvailablePort(startPort: number, options: FindAvailablePortOptions = {}) {\n const host = options.host ?? \"127.0.0.1\";\n const maxAttempts = options.maxAttempts ?? 50;\n\n for (let offset = 0; offset < maxAttempts; offset += 1) {\n const port = startPort + offset;\n if (await isPortAvailable(port, host)) {\n return port;\n }\n }\n\n throw new Error(`No available port found from ${startPort} to ${startPort + maxAttempts - 1}.`);\n}\n","import {\n getProjectName,\n readDevHosts,\n resolveDevHostsPath,\n sanitizeProjectName,\n type ConfigPattern,\n type ReadDevHostsOptions\n} from \"./config.js\";\nimport { findAvailablePort } from \"./port.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport type LocalghostContextOptions = {\n cwd?: string;\n project?: string;\n fileName?: string;\n configFiles?: string[];\n configPattern?: ConfigPattern;\n port?: number;\n https?: boolean;\n bindHost?: string | boolean;\n primaryHost?: string;\n dynamicPort?: boolean;\n};\n\nexport type LocalghostContext = {\n cwd: string;\n projectName: string;\n readOptions: ReadDevHostsOptions;\n configPath: string;\n configFileName: string;\n configEntries: DevHostEntry[];\n entries: DevHostEntry[];\n hosts: string[];\n requestedPort: number;\n port: number;\n dynamicPort: boolean;\n bindHost: string | boolean;\n primaryHost: string;\n https: boolean;\n};\n\nfunction parsePort(value: string | undefined) {\n if (!value) return undefined;\n const port = Number.parseInt(value, 10);\n return Number.isInteger(port) && port > 0 && port <= 65535 ? port : undefined;\n}\n\nfunction envPort() {\n return parsePort(process.env.LOCALGHOST_PORT) ?? parsePort(process.env.VITE_PORT);\n}\n\nfunction envDynamicPort() {\n const value = process.env.LOCALGHOST_DYNAMIC_PORT;\n if (!value) return undefined;\n return [\"1\", \"true\", \"yes\", \"on\"].includes(value.toLowerCase());\n}\n\nfunction readOptionsFromContext(options: LocalghostContextOptions): ReadDevHostsOptions {\n return {\n cwd: options.cwd ?? process.cwd(),\n ...(options.fileName ? { fileName: options.fileName } : {}),\n ...(options.configFiles ? { configFiles: options.configFiles } : {}),\n ...(options.configPattern ? { configPattern: options.configPattern } : {})\n };\n}\n\nfunction withRuntimePort(entries: DevHostEntry[], requestedPort: number, port: number) {\n if (requestedPort === port) return entries;\n\n const hasRequestedPort = entries.some((entry) => entry.port === requestedPort);\n if (!hasRequestedPort) return entries;\n\n return entries.map((entry) => (entry.port === requestedPort ? { ...entry, port } : entry));\n}\n\nfunction uniqueHosts(entries: DevHostEntry[]) {\n return [...new Set(entries.map((entry) => entry.host))];\n}\n\nexport function defineLocalghostConfig<T extends LocalghostContextOptions>(config: T) {\n return config;\n}\n\nexport async function resolveLocalghostContext(options: LocalghostContextOptions = {}): Promise<LocalghostContext> {\n const cwd = options.cwd ?? process.cwd();\n const readOptions = readOptionsFromContext({ ...options, cwd });\n const resolvedPath = resolveDevHostsPath(readOptions);\n const configEntries = readDevHosts(readOptions);\n const requestedPort = options.port ?? envPort() ?? configEntries[0]?.port ?? 5173;\n const dynamicPort = options.dynamicPort ?? envDynamicPort() ?? false;\n const bindHost = options.bindHost ?? \"127.0.0.1\";\n const probeHost = typeof bindHost === \"string\" ? bindHost : \"127.0.0.1\";\n const port = dynamicPort ? await findAvailablePort(requestedPort, { host: probeHost }) : requestedPort;\n const entries = withRuntimePort(configEntries, requestedPort, port);\n const hosts = uniqueHosts(entries);\n const primaryHost =\n options.primaryHost ??\n entries.find((entry) => entry.port === port)?.host ??\n hosts[0] ??\n `${sanitizeProjectName(getProjectName(cwd))}.localhost`;\n\n return {\n cwd,\n projectName: sanitizeProjectName(options.project ?? getProjectName(cwd)),\n readOptions,\n configPath: resolvedPath.path,\n configFileName: resolvedPath.fileName,\n configEntries,\n entries,\n hosts,\n requestedPort,\n port,\n dynamicPort,\n bindHost,\n primaryHost,\n https: options.https === true\n };\n}\n","import { execa } from \"execa\";\n\nexport type DoctorResult = {\n ok: boolean;\n caddy: {\n found: boolean;\n version?: string;\n installHint: string;\n };\n};\n\nexport async function checkCaddy(): Promise<DoctorResult[\"caddy\"]> {\n try {\n const result = await execa(\"caddy\", [\"version\"], { reject: false });\n const version = [result.stdout, result.stderr].filter(Boolean).join(\"\\n\").trim();\n\n return {\n found: result.exitCode === 0,\n ...(version ? { version } : {}),\n installHint: \"brew install caddy\"\n };\n } catch {\n return {\n found: false,\n installHint: \"brew install caddy\"\n };\n }\n}\n\nexport async function runDoctor(): Promise<DoctorResult> {\n const caddy = await checkCaddy();\n return {\n ok: caddy.found,\n caddy\n };\n}\n","export type LocalghostEnvironment = NodeJS.ProcessEnv;\n\nconst PRODUCTION_ENV_KEYS = [\"NODE_ENV\", \"VERCEL_ENV\", \"NETLIFY\", \"CF_PAGES_BRANCH\", \"LOCALGHOST_ENV\"] as const;\n\nexport function getProductionReason(env: LocalghostEnvironment = process.env) {\n if (env.LOCALGHOST_ENV === \"production\") return \"LOCALGHOST_ENV=production\";\n if (env.NODE_ENV === \"production\") return \"NODE_ENV=production\";\n if (env.VERCEL_ENV === \"production\") return \"VERCEL_ENV=production\";\n if (env.NETLIFY === \"true\" && env.CONTEXT === \"production\") return \"NETLIFY=true and CONTEXT=production\";\n if (env.CF_PAGES_BRANCH && env.CF_PAGES_BRANCH === env.CF_PAGES_PRODUCTION_BRANCH) {\n return \"CF_PAGES_BRANCH matches CF_PAGES_PRODUCTION_BRANCH\";\n }\n\n return null;\n}\n\nexport function isProductionLike(env: LocalghostEnvironment = process.env) {\n return getProductionReason(env) !== null;\n}\n\nexport function assertLocalDevelopment(command: string, env: LocalghostEnvironment = process.env) {\n const reason = getProductionReason(env);\n if (!reason) return;\n\n throw new Error(`Localghost only runs in local development. Refusing \\`${command}\\` because ${reason}.`);\n}\n\nexport function getProductionEnvKeys() {\n return PRODUCTION_ENV_KEYS;\n}\n","import { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { execa } from \"execa\";\nimport { sanitizeProjectName } from \"./config.js\";\nimport { readTextFile } from \"./fs.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport type UpdateSystemHostsResult = {\n changed: boolean;\n hostsPath: string;\n tempPath?: string;\n};\n\nexport type RemoveSystemHostsResult = UpdateSystemHostsResult & {\n removed: boolean;\n};\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction getManagedBlockPattern(projectName: string) {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const start = `# localghost:start ${sanitizedProjectName}`;\n const end = `# localghost:end ${sanitizedProjectName}`;\n return new RegExp(`${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}\\\\n?`, \"m\");\n}\n\nexport function getSystemHostsPath() {\n return process.platform === \"win32\" ? \"C:\\\\Windows\\\\System32\\\\drivers\\\\etc\\\\hosts\" : \"/etc/hosts\";\n}\n\nexport function renderHostsBlock(projectName: string, entries: DevHostEntry[]) {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const hosts = [...new Set(entries.map((entry) => entry.host))].sort();\n\n return [\n `# localghost:start ${sanitizedProjectName}`,\n ...hosts.map((host) => `127.0.0.1 ${host}`),\n `# localghost:end ${sanitizedProjectName}`,\n \"\"\n ].join(\"\\n\");\n}\n\nexport function upsertManagedBlock(existing: string, projectName: string, block: string) {\n const pattern = getManagedBlockPattern(projectName);\n\n if (pattern.test(existing)) {\n return existing.replace(pattern, block);\n }\n\n return `${existing.trimEnd()}\\n\\n${block}`;\n}\n\nexport function removeManagedBlock(existing: string, projectName: string) {\n const pattern = getManagedBlockPattern(projectName);\n\n if (!pattern.test(existing)) {\n return existing;\n }\n\n return existing.replace(pattern, \"\").replace(/\\n{3,}/g, \"\\n\\n\").trimEnd() + \"\\n\";\n}\n\nasync function writeSystemHostsFile(hostsPath: string, next: string, projectName: string) {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const tempPath = join(tmpdir(), `localghost-${sanitizedProjectName}-hosts`);\n writeFileSync(tempPath, next, \"utf8\");\n\n if (process.platform === \"win32\") {\n throw new Error(`Windows support: run as administrator and copy ${tempPath} to ${hostsPath}.`);\n }\n\n await execa(\"sudo\", [\"cp\", tempPath, hostsPath], { stdio: \"inherit\" });\n\n return tempPath;\n}\n\nexport async function updateSystemHosts(projectName: string, entries: DevHostEntry[]): Promise<UpdateSystemHostsResult> {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const hostsPath = getSystemHostsPath();\n const existing = readTextFile(hostsPath);\n const block = renderHostsBlock(sanitizedProjectName, entries);\n const next = upsertManagedBlock(existing, sanitizedProjectName, block);\n\n if (next === existing) {\n return { changed: false, hostsPath };\n }\n\n const tempPath = await writeSystemHostsFile(hostsPath, next, sanitizedProjectName);\n\n return { changed: true, hostsPath, tempPath };\n}\n\nexport async function removeSystemHosts(projectName: string): Promise<RemoveSystemHostsResult> {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const hostsPath = getSystemHostsPath();\n const existing = readTextFile(hostsPath);\n const next = removeManagedBlock(existing, sanitizedProjectName);\n\n if (next === existing) {\n return { changed: false, removed: false, hostsPath };\n }\n\n const tempPath = await writeSystemHostsFile(hostsPath, next, sanitizedProjectName);\n\n return { changed: true, removed: true, hostsPath, tempPath };\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getProjectName, LOCALGHOST_CONFIG_FILE, sanitizeProjectName } from \"./config.js\";\nimport { writeTextFile } from \"./fs.js\";\n\nexport type PackageManager = \"npm\" | \"yarn\" | \"pnpm\";\n\nexport type InitOptions = {\n cwd?: string;\n host?: string;\n port?: number;\n apiHost?: string;\n apiPort?: number;\n force?: boolean;\n packageManager?: PackageManager;\n writeScripts?: boolean;\n configFile?: string;\n};\n\nexport type InitResult = {\n configPath: string;\n configCreated: boolean;\n packageJsonPath?: string;\n packageJsonChanged: boolean;\n packageManager: PackageManager;\n nextSteps: string[];\n};\n\nexport function detectPackageManager(cwd = process.cwd()): PackageManager {\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(cwd, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nexport function packageRunCommand(packageManager: PackageManager, script: string): string {\n if (packageManager === \"yarn\") return `yarn ${script}`;\n if (packageManager === \"pnpm\") return `pnpm ${script}`;\n return `npm run ${script}`;\n}\n\nexport function packageAddCommand(packageManager: PackageManager, packageName = \"@hamedb89/localghost\"): string {\n if (packageManager === \"yarn\") return `yarn add -D ${packageName}`;\n if (packageManager === \"pnpm\") return `pnpm add -D ${packageName}`;\n return `npm install -D ${packageName}`;\n}\n\nfunction renderConfig(options: Required<Pick<InitOptions, \"host\" | \"port\" | \"apiHost\" | \"apiPort\">>) {\n return [\n \"# Buh. Friendly names for local services.\",\n \"# Format: <host> <port>\",\n `${options.host} ${options.port}`,\n `www.${options.host} ${options.port}`,\n `${options.apiHost} ${options.apiPort}`,\n \"\"\n ].join(\"\\n\");\n}\n\nfunction readPackageJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction shellQuote(value: string) {\n if (/^[A-Za-z0-9_./:-]+$/.test(value)) return value;\n return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\nfunction getConfigFlag(configFile: string) {\n return configFile === LOCALGHOST_CONFIG_FILE ? \"\" : ` --config ${shellQuote(configFile)}`;\n}\n\nfunction updatePackageScripts(packageJsonPath: string, configFile: string): boolean {\n const pkg = readPackageJson(packageJsonPath);\n if (!pkg) return false;\n\n const scripts = typeof pkg.scripts === \"object\" && pkg.scripts ? (pkg.scripts as Record<string, unknown>) : {};\n const configFlag = getConfigFlag(configFile);\n const nextScripts = {\n ...scripts,\n \"localghost:setup\": scripts[\"localghost:setup\"] ?? `localghost setup${configFlag}`,\n \"localghost:proxy\": scripts[\"localghost:proxy\"] ?? `localghost dev${configFlag}`,\n \"localghost:proxy:https\": scripts[\"localghost:proxy:https\"] ?? `localghost dev${configFlag} --https`,\n \"localghost:run\": scripts[\"localghost:run\"] ?? `localghost run${configFlag} --`,\n \"localghost:ready\": scripts[\"localghost:ready\"] ?? `localghost status${configFlag} --ready`,\n \"localghost:ps\": scripts[\"localghost:ps\"] ?? \"localghost ps\",\n \"localghost:print\": scripts[\"localghost:print\"] ?? `localghost print${configFlag}`,\n \"localghost:routes\": scripts[\"localghost:routes\"] ?? `localghost routes${configFlag}`,\n \"localghost:status\": scripts[\"localghost:status\"] ?? \"localghost status\",\n \"localghost:reset\": scripts[\"localghost:reset\"] ?? \"localghost reset\",\n \"localghost:teardown\": scripts[\"localghost:teardown\"] ?? \"localghost teardown\",\n \"localghost:doctor\": scripts[\"localghost:doctor\"] ?? \"localghost doctor\",\n \"localghost:update\": scripts[\"localghost:update\"] ?? \"localghost update\",\n \"caddy:setup\": scripts[\"caddy:setup\"] ?? `localghost setup${configFlag}`,\n \"caddy:dev\": scripts[\"caddy:dev\"] ?? `localghost dev${configFlag}`\n };\n\n const changed = JSON.stringify(scripts) !== JSON.stringify(nextScripts);\n if (!changed) return false;\n\n pkg.scripts = nextScripts;\n writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\\n`, \"utf8\");\n return true;\n}\n\nexport function initLocalghost(options: InitOptions = {}): InitResult {\n const cwd = options.cwd ?? process.cwd();\n const projectName = sanitizeProjectName(getProjectName(cwd).split(\"/\").pop() ?? \"app\");\n const host = options.host ?? `${projectName}.localhost`;\n const port = options.port ?? 5173;\n const apiHost = options.apiHost ?? `api.${host}`;\n const apiPort = options.apiPort ?? 8787;\n const packageManager = options.packageManager ?? detectPackageManager(cwd);\n const configFile = options.configFile ?? LOCALGHOST_CONFIG_FILE;\n const configPath = join(cwd, configFile);\n const configExists = existsSync(configPath);\n\n if (configExists && !options.force) {\n return {\n configPath,\n configCreated: false,\n packageJsonChanged: false,\n packageManager,\n nextSteps: [\n packageRunCommand(packageManager, \"localghost:doctor\"),\n packageRunCommand(packageManager, \"localghost:setup\"),\n packageRunCommand(packageManager, \"localghost:ready\"),\n packageRunCommand(packageManager, \"localghost:proxy\")\n ]\n };\n }\n\n writeTextFile(configPath, renderConfig({ host, port, apiHost, apiPort }));\n\n const packageJsonPath = join(cwd, \"package.json\");\n const packageJsonChanged = options.writeScripts ? updatePackageScripts(packageJsonPath, configFile) : false;\n\n return {\n configPath,\n configCreated: true,\n ...(existsSync(packageJsonPath) ? { packageJsonPath } : {}),\n packageJsonChanged,\n packageManager,\n nextSteps: [\n packageRunCommand(packageManager, \"localghost:doctor\"),\n packageRunCommand(packageManager, \"localghost:setup\"),\n packageRunCommand(packageManager, \"localghost:ready\"),\n packageRunCommand(packageManager, \"localghost:proxy\")\n ]\n };\n}\n","import type { DevHostEntry } from \"./parse.js\";\n\nexport type DomainRoute = {\n host: string;\n port: number;\n url: string;\n upstream: string;\n};\n\nexport type DomainRouteOptions = {\n https?: boolean;\n};\n\nexport function getDomainRoutes(entries: DevHostEntry[], options: DomainRouteOptions = {}): DomainRoute[] {\n const protocol = options.https === true ? \"https\" : \"http\";\n\n return [...entries]\n .sort((left, right) => left.host.localeCompare(right.host) || left.port - right.port)\n .map((entry) => ({\n host: entry.host,\n port: entry.port,\n url: `${protocol}://${entry.host}/`,\n upstream: `http://${entry.target}`\n }));\n}\n\nexport function formatDomainRoutes(entries: DevHostEntry[], options: DomainRouteOptions = {}) {\n const routes = getDomainRoutes(entries, options);\n\n if (routes.length === 0) {\n return \"localghost routes\\n no routes\";\n }\n\n return [\n \"localghost routes\",\n ...routes.map((route) => ` ${route.url} -> ${route.upstream}`)\n ].join(\"\\n\");\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readTextFile, writeTextFile } from \"./fs.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport const LOCALGHOST_STATE_FILE = \"ops/local/localghost-state.json\";\n\nexport type LocalghostStateAction = \"setup\" | \"teardown\";\n\nexport type LocalghostState = {\n version: 1;\n action: LocalghostStateAction;\n updatedAt: string;\n projectName: string;\n cwd: string;\n configPath?: string;\n hostsPath?: string;\n hostsChanged?: boolean;\n hostsTempPath?: string;\n caddyfilePath?: string;\n caddyfileRemoved?: boolean;\n caddyHttps?: boolean;\n entries?: DevHostEntry[];\n};\n\nexport type WriteLocalghostStateInput = Omit<LocalghostState, \"version\" | \"updatedAt\">;\n\nexport function getLocalghostStatePath(cwd = process.cwd()) {\n return join(cwd, LOCALGHOST_STATE_FILE);\n}\n\nexport function readLocalghostState(cwd = process.cwd()): LocalghostState | null {\n const path = getLocalghostStatePath(cwd);\n if (!existsSync(path)) return null;\n return JSON.parse(readTextFile(path)) as LocalghostState;\n}\n\nexport function writeLocalghostState(cwd: string, state: WriteLocalghostStateInput) {\n const path = getLocalghostStatePath(cwd);\n writeTextFile(path, `${JSON.stringify({ version: 1, updatedAt: new Date().toISOString(), ...state }, null, 2)}\\n`);\n return path;\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport const LOCALGHOST_PACKAGE_NAME = \"@hamedb89/localghost\";\nexport const LOCALGHOST_VERSION = \"0.1.6\";\nexport const UPDATE_CHECK_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nexport const UPDATE_CHECK_NOTIFY_TTL_MS = 24 * 60 * 60 * 1000;\nexport const UPDATE_CHECK_TIMEOUT_MS = 900;\n\nexport type UpdateCheckCache = {\n checkedAt: string;\n latestVersion?: string;\n notifiedVersion?: string;\n notifiedAt?: string;\n};\n\nexport type UpdateCheckResult = {\n currentVersion: string;\n packageName: string;\n latestVersion?: string;\n updateAvailable: boolean;\n source: \"cache\" | \"registry\" | \"disabled\" | \"error\";\n error?: string;\n};\n\ntype RegistryPackageResponse = {\n \"dist-tags\"?: {\n latest?: unknown;\n };\n};\n\nfunction truthyEnv(value: string | undefined) {\n return value === \"1\" || value === \"true\" || value === \"yes\";\n}\n\nexport function isUpdateCheckDisabled(env: NodeJS.ProcessEnv = process.env) {\n return truthyEnv(env.LOCALGHOST_NO_UPDATE_CHECK);\n}\n\nexport function getUpdateCheckCachePath(env: NodeJS.ProcessEnv = process.env) {\n if (env.LOCALGHOST_UPDATE_CHECK_CACHE) return env.LOCALGHOST_UPDATE_CHECK_CACHE;\n\n const cacheRoot = env.XDG_CACHE_HOME || join(homedir(), \".cache\");\n return join(cacheRoot, \"localghost\", \"update-check.json\");\n}\n\nfunction readCache(path = getUpdateCheckCachePath()): UpdateCheckCache | null {\n if (!existsSync(path)) return null;\n\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as UpdateCheckCache;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(cache: UpdateCheckCache, path = getUpdateCheckCachePath()) {\n try {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(cache, null, 2)}\\n`, \"utf8\");\n } catch {\n // Update checks should never make the real command fail.\n }\n}\n\nfunction ageMs(date: string | undefined, now = Date.now()) {\n if (!date) return Number.POSITIVE_INFINITY;\n const time = Date.parse(date);\n return Number.isFinite(time) ? now - time : Number.POSITIVE_INFINITY;\n}\n\nfunction isCacheFresh(cache: UpdateCheckCache | null, ttlMs: number, now = Date.now()) {\n return Boolean(cache?.latestVersion && ageMs(cache.checkedAt, now) >= 0 && ageMs(cache.checkedAt, now) < ttlMs);\n}\n\ntype ParsedVersion = {\n major: number;\n minor: number;\n patch: number;\n prerelease?: string;\n};\n\nfunction parseVersion(version: string): ParsedVersion | null {\n const match = version.trim().replace(/^v/, \"\").match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?$/);\n if (!match) return null;\n\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n ...(match[4] ? { prerelease: match[4] } : {})\n };\n}\n\nexport function compareVersions(a: string, b: string) {\n const left = parseVersion(a);\n const right = parseVersion(b);\n\n if (!left || !right) return a.localeCompare(b);\n\n for (const key of [\"major\", \"minor\", \"patch\"] as const) {\n if (left[key] !== right[key]) return left[key] > right[key] ? 1 : -1;\n }\n\n if (left.prerelease === right.prerelease) return 0;\n if (!left.prerelease) return 1;\n if (!right.prerelease) return -1;\n return left.prerelease.localeCompare(right.prerelease);\n}\n\nexport function isNewerVersion(candidate: string | undefined, current = LOCALGHOST_VERSION) {\n return Boolean(candidate && compareVersions(candidate, current) > 0);\n}\n\nasync function fetchLatestVersion(packageName: string, timeoutMs: number) {\n const encodedName = packageName.startsWith(\"@\") ? `@${packageName.slice(1).replace(\"/\", \"%2f\")}` : packageName;\n const response = await fetch(`https://registry.npmjs.org/${encodedName}`, {\n signal: AbortSignal.timeout(timeoutMs),\n headers: {\n accept: \"application/vnd.npm.install-v1+json\"\n }\n });\n\n if (!response.ok) throw new Error(`npm registry returned ${response.status}`);\n\n const data = (await response.json()) as RegistryPackageResponse;\n const latest = data[\"dist-tags\"]?.latest;\n if (typeof latest !== \"string\" || latest.length === 0) throw new Error(\"npm registry response did not include latest dist-tag\");\n\n return latest;\n}\n\nexport async function checkForUpdate(options: {\n force?: boolean;\n packageName?: string;\n currentVersion?: string;\n timeoutMs?: number;\n cachePath?: string;\n env?: NodeJS.ProcessEnv;\n} = {}): Promise<UpdateCheckResult> {\n const env = options.env ?? process.env;\n const packageName = options.packageName ?? LOCALGHOST_PACKAGE_NAME;\n const currentVersion = options.currentVersion ?? LOCALGHOST_VERSION;\n const cachePath = options.cachePath ?? getUpdateCheckCachePath(env);\n\n if (!options.force && isUpdateCheckDisabled(env)) {\n return {\n currentVersion,\n packageName,\n updateAvailable: false,\n source: \"disabled\"\n };\n }\n\n const cache = readCache(cachePath);\n if (!options.force && isCacheFresh(cache, UPDATE_CHECK_CACHE_TTL_MS)) {\n const latestVersion = cache?.latestVersion;\n return {\n currentVersion,\n packageName,\n ...(latestVersion ? { latestVersion } : {}),\n updateAvailable: isNewerVersion(latestVersion, currentVersion),\n source: \"cache\"\n };\n }\n\n try {\n const latestVersion = await fetchLatestVersion(packageName, options.timeoutMs ?? UPDATE_CHECK_TIMEOUT_MS);\n writeCache({ checkedAt: new Date().toISOString(), latestVersion }, cachePath);\n\n return {\n currentVersion,\n packageName,\n latestVersion,\n updateAvailable: isNewerVersion(latestVersion, currentVersion),\n source: \"registry\"\n };\n } catch (error) {\n const latestVersion = cache?.latestVersion;\n return {\n currentVersion,\n packageName,\n ...(latestVersion ? { latestVersion } : {}),\n updateAvailable: isNewerVersion(latestVersion, currentVersion),\n source: \"error\",\n error: error instanceof Error ? error.message : String(error)\n };\n }\n}\n\nexport function formatUpdateMessage(result: UpdateCheckResult) {\n if (!result.updateAvailable || !result.latestVersion) return null;\n\n return [\n `localghost ${result.latestVersion} is available. Current: ${result.currentVersion}`,\n `Update with: npm i -g ${result.packageName}@latest`\n ].join(\"\\n\");\n}\n\nexport function shouldNotifyAboutUpdate(result: UpdateCheckResult, cachePath = getUpdateCheckCachePath(), now = Date.now()) {\n if (!result.updateAvailable || !result.latestVersion) return false;\n\n const cache = readCache(cachePath);\n if (cache?.notifiedVersion !== result.latestVersion) return true;\n\n return ageMs(cache.notifiedAt, now) >= UPDATE_CHECK_NOTIFY_TTL_MS;\n}\n\nexport function markUpdateNotified(result: UpdateCheckResult, cachePath = getUpdateCheckCachePath()) {\n if (!result.latestVersion) return;\n\n const cache = readCache(cachePath) ?? { checkedAt: new Date().toISOString() };\n writeCache(\n {\n ...cache,\n latestVersion: result.latestVersion,\n notifiedVersion: result.latestVersion,\n notifiedAt: new Date().toISOString()\n },\n cachePath\n );\n}\n\nexport async function maybeNotifyAboutUpdate(options: { disabled?: boolean } = {}) {\n if (options.disabled) return;\n\n const cachePath = getUpdateCheckCachePath();\n const result = await checkForUpdate({ cachePath });\n if (!shouldNotifyAboutUpdate(result, cachePath)) return;\n\n const message = formatUpdateMessage(result);\n if (!message) return;\n\n console.warn(`\\n${message}`);\n markUpdateNotified(result, cachePath);\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","fileName","existsSync","readFileSync","join","dirname","join","mkdirSync","readFileSync","writeFileSync","dirname","join","dirname","resolve","execa","writeFileSync","join","execa","join","writeFileSync","execa","existsSync","readFileSync","writeFileSync","join","existsSync","join","readFileSync","writeFileSync","existsSync","join","join","existsSync","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","dirname","join"]}
1
+ {"version":3,"sources":["../src/activity.ts","../src/config.ts","../src/parse.ts","../src/caddy.ts","../src/fs.ts","../src/context.ts","../src/port.ts","../src/doctor.ts","../src/env.ts","../src/hosts-file.ts","../src/init.ts","../src/routes.ts","../src/state.ts","../src/update-check.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport const LOCALGHOST_ACTIVITY_VERSION = 1;\n\nexport type LocalghostRunMode = \"dev\" | \"run\";\n\nexport type LocalghostRunRecord = {\n id: string;\n mode: LocalghostRunMode;\n pid: number;\n cwd: string;\n projectName: string;\n startedAt: string;\n updatedAt: string;\n configPath?: string;\n caddyfilePath?: string;\n caddyPid?: number;\n childPid?: number;\n childCommand?: string[];\n https?: boolean;\n requestedPort?: number;\n port?: number;\n dynamicPort?: boolean;\n entries: DevHostEntry[];\n};\n\nexport type LocalghostActivity = {\n version: typeof LOCALGHOST_ACTIVITY_VERSION;\n runs: LocalghostRunRecord[];\n};\n\nexport type RegisterLocalghostRunInput = Omit<LocalghostRunRecord, \"id\" | \"pid\" | \"startedAt\" | \"updatedAt\"> & {\n id?: string;\n pid?: number;\n startedAt?: string;\n};\n\nexport function getLocalghostActivityPath(env: NodeJS.ProcessEnv = process.env) {\n if (env.LOCALGHOST_ACTIVITY_PATH) return env.LOCALGHOST_ACTIVITY_PATH;\n\n const stateRoot = env.XDG_STATE_HOME || join(homedir(), \".local/state\");\n return join(stateRoot, \"localghost\", \"activity.json\");\n}\n\nexport function isProcessRunning(pid: number) {\n if (!Number.isInteger(pid) || pid < 1) return false;\n\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const code = typeof error === \"object\" && error !== null && \"code\" in error ? error.code : undefined;\n return code === \"EPERM\";\n }\n}\n\nfunction emptyActivity(): LocalghostActivity {\n return { version: LOCALGHOST_ACTIVITY_VERSION, runs: [] };\n}\n\nexport function readLocalghostActivity(path = getLocalghostActivityPath()): LocalghostActivity {\n if (!existsSync(path)) return emptyActivity();\n\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<LocalghostActivity>;\n return {\n version: LOCALGHOST_ACTIVITY_VERSION,\n runs: Array.isArray(parsed.runs) ? parsed.runs : []\n };\n } catch {\n return emptyActivity();\n }\n}\n\nexport function writeLocalghostActivity(activity: LocalghostActivity, path = getLocalghostActivityPath()) {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(activity, null, 2)}\\n`, \"utf8\");\n return path;\n}\n\nfunction createRunId(input: Pick<RegisterLocalghostRunInput, \"mode\" | \"cwd\" | \"projectName\">, pid: number) {\n return `${input.projectName}:${input.mode}:${pid}:${Date.now()}`;\n}\n\nexport function pruneLocalghostActivity(path = getLocalghostActivityPath()) {\n const activity = readLocalghostActivity(path);\n const activeRuns = activity.runs.filter((run) => isProcessRunning(run.pid));\n const pruned = activeRuns.length !== activity.runs.length;\n\n if (pruned) {\n writeLocalghostActivity({ version: LOCALGHOST_ACTIVITY_VERSION, runs: activeRuns }, path);\n }\n\n return {\n path,\n pruned,\n runs: activeRuns\n };\n}\n\nexport function listLocalghostRuns(path = getLocalghostActivityPath()) {\n return pruneLocalghostActivity(path).runs;\n}\n\nexport function registerLocalghostRun(input: RegisterLocalghostRunInput, path = getLocalghostActivityPath()) {\n const now = new Date().toISOString();\n const pid = input.pid ?? process.pid;\n const record: LocalghostRunRecord = {\n id: input.id ?? createRunId(input, pid),\n mode: input.mode,\n pid,\n cwd: input.cwd,\n projectName: input.projectName,\n startedAt: input.startedAt ?? now,\n updatedAt: now,\n ...(input.configPath ? { configPath: input.configPath } : {}),\n ...(input.caddyfilePath ? { caddyfilePath: input.caddyfilePath } : {}),\n ...(input.caddyPid ? { caddyPid: input.caddyPid } : {}),\n ...(input.childPid ? { childPid: input.childPid } : {}),\n ...(input.childCommand ? { childCommand: input.childCommand } : {}),\n ...(typeof input.https === \"boolean\" ? { https: input.https } : {}),\n ...(input.requestedPort ? { requestedPort: input.requestedPort } : {}),\n ...(input.port ? { port: input.port } : {}),\n ...(typeof input.dynamicPort === \"boolean\" ? { dynamicPort: input.dynamicPort } : {}),\n entries: input.entries\n };\n const current = pruneLocalghostActivity(path).runs.filter((run) => run.id !== record.id);\n writeLocalghostActivity({ version: LOCALGHOST_ACTIVITY_VERSION, runs: [...current, record] }, path);\n return record;\n}\n\nexport function unregisterLocalghostRun(id: string, path = getLocalghostActivityPath()) {\n const activity = readLocalghostActivity(path);\n const runs = activity.runs.filter((run) => run.id !== id);\n\n if (runs.length !== activity.runs.length) {\n writeLocalghostActivity({ version: LOCALGHOST_ACTIVITY_VERSION, runs }, path);\n }\n}\n","import { existsSync, readFileSync, readdirSync } from \"node:fs\";\nimport { basename, join, resolve } from \"node:path\";\nimport { parseDevHosts } from \"./parse.js\";\n\nexport const LOCALGHOST_CONFIG_FILE = \".localghost\";\n\nexport type ConfigPattern = string | RegExp;\n\nexport type ReadDevHostsOptions = {\n cwd?: string;\n fileName?: string;\n configFiles?: string[];\n configPattern?: ConfigPattern;\n};\n\nexport type ResolvedDevHostsPath = {\n path: string;\n fileName: string;\n exists: boolean;\n searchedFiles: string[];\n configPattern?: ConfigPattern;\n};\n\nfunction unique(values: string[]) {\n return [...new Set(values.filter(Boolean))];\n}\n\nfunction toRegExp(pattern: ConfigPattern) {\n return typeof pattern === \"string\" ? new RegExp(pattern) : pattern;\n}\n\nfunction findPatternMatches(cwd: string, pattern: ConfigPattern) {\n const matcher = toRegExp(pattern);\n\n return readdirSync(cwd, { withFileTypes: true })\n .filter((entry) => entry.isFile())\n .map((entry) => entry.name)\n .filter((name) => {\n matcher.lastIndex = 0;\n return matcher.test(name);\n })\n .sort();\n}\n\nexport function getConfigFileCandidates(options: ReadDevHostsOptions = {}) {\n const cwd = options.cwd ?? process.cwd();\n const exactFiles = unique([\n ...(options.fileName ? [options.fileName] : []),\n ...(options.configFiles ?? [])\n ]);\n const patternFiles = options.configPattern ? findPatternMatches(cwd, options.configPattern) : [];\n const candidates = unique([...exactFiles, ...patternFiles]);\n\n if (candidates.length > 0) return candidates;\n if (exactFiles.length > 0 || options.configPattern) return [];\n return [LOCALGHOST_CONFIG_FILE];\n}\n\nexport function resolveDevHostsPath(options: ReadDevHostsOptions = {}): ResolvedDevHostsPath {\n const cwd = options.cwd ?? process.cwd();\n const searchedFiles = getConfigFileCandidates(options);\n\n for (const fileName of searchedFiles) {\n const path = resolve(cwd, fileName);\n if (existsSync(path)) {\n return {\n path,\n fileName: basename(fileName),\n exists: true,\n searchedFiles,\n ...(options.configPattern ? { configPattern: options.configPattern } : {})\n };\n }\n }\n\n const fileName = searchedFiles[0] ?? LOCALGHOST_CONFIG_FILE;\n\n return {\n path: resolve(cwd, fileName),\n fileName: basename(fileName),\n exists: false,\n searchedFiles,\n ...(options.configPattern ? { configPattern: options.configPattern } : {})\n };\n}\n\nexport function getDevHostsPath(options: ReadDevHostsOptions = {}) {\n return resolveDevHostsPath(options).path;\n}\n\nfunction formatSearchedFiles(files: string[], pattern?: ConfigPattern) {\n if (files.length > 0) return files.map((file) => `\\`${file}\\``).join(\", \");\n if (pattern) return `files matching ${pattern.toString()}`;\n return `\\`${LOCALGHOST_CONFIG_FILE}\\``;\n}\n\nexport function readDevHosts(options: ReadDevHostsOptions | string = {}) {\n const resolvedOptions = typeof options === \"string\" ? { cwd: options } : options;\n const resolvedPath = resolveDevHostsPath(resolvedOptions);\n\n if (!resolvedPath.exists) {\n const cwd = resolvedOptions.cwd ?? process.cwd();\n throw new Error(\n `Missing Localghost config in ${cwd}. Looked for ${formatSearchedFiles(resolvedPath.searchedFiles, resolvedPath.configPattern)}. Run \\`localghost init\\` or pass --config/--config-pattern.`\n );\n }\n\n return parseDevHosts(readFileSync(resolvedPath.path, \"utf8\"), resolvedPath.fileName);\n}\n\nexport function getProjectName(cwd = process.cwd()) {\n try {\n const pkg = JSON.parse(readFileSync(join(cwd, \"package.json\"), \"utf8\")) as { name?: unknown };\n const name = typeof pkg.name === \"string\" && pkg.name ? pkg.name : \"app\";\n return sanitizeProjectName(name.replace(/^@/, \"\"));\n } catch {\n return \"app\";\n }\n}\n\nexport function sanitizeProjectName(value: string) {\n const projectName = value.replace(/[^\\w.-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n return projectName || \"app\";\n}\n","export type DevHostEntry = {\n host: string;\n port: number;\n target: string;\n};\n\nconst HOST_PATTERN = /^(?=.{1,253}$)(?!-)[a-z0-9-]+(\\.[a-z0-9-]+)*\\.?$/i;\n\nexport function parseDevHosts(input: string, fileName = \".localghost\"): DevHostEntry[] {\n const entries: DevHostEntry[] = [];\n\n input.split(/\\r?\\n/).forEach((rawLine, index) => {\n const line = rawLine.replace(/#.*/, \"\").trim();\n\n if (!line) {\n return;\n }\n\n const parts = line.split(/\\s+/);\n const host = parts[0];\n const portRaw = parts[1];\n\n if (!host || !portRaw || parts.length > 2) {\n throw new Error(`Invalid ${fileName} line ${index + 1}: \"${rawLine}\"`);\n }\n\n if (!HOST_PATTERN.test(host)) {\n throw new Error(`Invalid host on line ${index + 1}: \"${host}\"`);\n }\n\n const port = Number(portRaw);\n\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new Error(`Invalid port on line ${index + 1}: \"${portRaw}\"`);\n }\n\n entries.push({\n host: host.toLowerCase().replace(/\\.$/, \"\"),\n port,\n target: `127.0.0.1:${port}`\n });\n });\n\n return entries;\n}\n\nexport function findLocalMdnsHosts(entries: DevHostEntry[]): string[] {\n return [...new Set(entries.map((entry) => entry.host).filter((host) => host.endsWith(\".local\")))];\n}\n","import { dirname, join } from \"node:path\";\nimport { execa } from \"execa\";\nimport { writeTextFile } from \"./fs.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport type CaddyModeOptions = {\n https?: boolean;\n};\n\nfunction groupByPort(entries: DevHostEntry[]) {\n const groups = new Map<number, DevHostEntry[]>();\n\n for (const entry of entries) {\n const group = groups.get(entry.port) ?? [];\n group.push(entry);\n groups.set(entry.port, group);\n }\n\n return groups;\n}\n\nexport function getCaddyfilePath(cwd = process.cwd()) {\n return join(cwd, \"ops/local/Caddyfile\");\n}\n\nexport function renderCaddyfile(entries: DevHostEntry[], options: CaddyModeOptions = {}) {\n const groups = groupByPort(entries);\n const https = options.https === true;\n const blocks = [...groups.entries()]\n .sort(([leftPort], [rightPort]) => leftPort - rightPort)\n .map(([port, group]) => {\n const hosts = group\n .map((entry) => (https ? entry.host : `http://${entry.host}`))\n .sort()\n .join(\", \");\n\n return `${hosts} {\n reverse_proxy 127.0.0.1:${port}\n}`;\n });\n\n const globalOptions = https\n ? `{\n local_certs\n}\n\n`\n : \"\";\n\n return `${globalOptions}${blocks.join(\"\\n\\n\")}\n`;\n}\n\nexport async function writeCaddyfile(entries: DevHostEntry[], cwd = process.cwd(), options: CaddyModeOptions = {}) {\n const path = getCaddyfilePath(cwd);\n writeTextFile(path, renderCaddyfile(entries, options));\n return path;\n}\n\nexport async function validateCaddyfile(path: string) {\n await execa(\"caddy\", [\"validate\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n\nexport async function runCaddy(path: string) {\n await execa(\"caddy\", [\"run\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n\nexport function startCaddy(path: string) {\n return execa(\"caddy\", [\"run\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n\nexport async function trustCaddy(path: string) {\n await execa(\"caddy\", [\"trust\", \"--config\", path], {\n cwd: dirname(path),\n stdio: \"inherit\"\n });\n}\n","import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nexport function readTextFile(path: string) {\n return readFileSync(path, \"utf8\");\n}\n\nexport function writeTextFile(path: string, value: string) {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, value, \"utf8\");\n return path;\n}\n","import { existsSync } from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport {\n getProjectName,\n readDevHosts,\n resolveDevHostsPath,\n sanitizeProjectName,\n type ConfigPattern,\n type ReadDevHostsOptions\n} from \"./config.js\";\nimport { findAvailablePort } from \"./port.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport type LocalghostContextOptions = {\n cwd?: string;\n project?: string;\n localghostConfig?: string | false;\n fileName?: string;\n configFiles?: string[];\n configPattern?: ConfigPattern;\n port?: number;\n https?: boolean;\n bindHost?: string | boolean;\n primaryHost?: string;\n dynamicPort?: boolean;\n wwwAlias?: boolean;\n};\n\nexport type LocalghostContext = {\n cwd: string;\n projectName: string;\n readOptions: ReadDevHostsOptions;\n configPath: string;\n configFileName: string;\n configEntries: DevHostEntry[];\n entries: DevHostEntry[];\n hosts: string[];\n requestedPort: number;\n port: number;\n dynamicPort: boolean;\n bindHost: string | boolean;\n primaryHost: string;\n https: boolean;\n wwwAlias: boolean;\n projectConfigPath?: string;\n};\n\nexport type LocalghostProjectConfig = Omit<LocalghostContextOptions, \"cwd\" | \"localghostConfig\">;\n\nconst LOCALGHOST_PROJECT_CONFIG_FILES = [\n \"localghost.config.mjs\",\n \"localghost.config.js\",\n \"localghost.config.cjs\"\n];\n\nfunction parsePort(value: string | undefined) {\n if (!value) return undefined;\n const port = Number.parseInt(value, 10);\n return Number.isInteger(port) && port > 0 && port <= 65535 ? port : undefined;\n}\n\nfunction envPort() {\n return parsePort(process.env.LOCALGHOST_PORT) ?? parsePort(process.env.VITE_PORT);\n}\n\nfunction envDynamicPort() {\n const value = process.env.LOCALGHOST_DYNAMIC_PORT;\n if (!value) return undefined;\n return [\"1\", \"true\", \"yes\", \"on\"].includes(value.toLowerCase());\n}\n\nfunction envHttps() {\n const value = process.env.LOCALGHOST_HTTPS;\n if (!value) return undefined;\n return [\"1\", \"true\", \"yes\", \"on\"].includes(value.toLowerCase());\n}\n\nfunction readOptionsFromContext(options: LocalghostContextOptions): ReadDevHostsOptions {\n return {\n cwd: options.cwd ?? process.cwd(),\n ...(options.fileName ? { fileName: options.fileName } : {}),\n ...(options.configFiles ? { configFiles: options.configFiles } : {}),\n ...(options.configPattern ? { configPattern: options.configPattern } : {})\n };\n}\n\nfunction withRuntimePort(entries: DevHostEntry[], requestedPort: number, port: number) {\n if (requestedPort === port) return entries;\n\n const hasRequestedPort = entries.some((entry) => entry.port === requestedPort);\n if (!hasRequestedPort) return entries;\n\n return entries.map((entry) => (entry.port === requestedPort ? { ...entry, port } : entry));\n}\n\nfunction uniqueHosts(entries: DevHostEntry[]) {\n return [...new Set(entries.map((entry) => entry.host))];\n}\n\nfunction isAliasableHost(host: string) {\n return host.includes(\".\") && !host.startsWith(\"www.\") && !host.includes(\":\");\n}\n\nexport function getDefaultWwwAlias(host: string) {\n return isAliasableHost(host) ? `www.${host}` : null;\n}\n\nexport function addDefaultWwwAliases(entries: DevHostEntry[]) {\n const seen = new Set(entries.map((entry) => entry.host));\n const aliases: DevHostEntry[] = [];\n\n for (const entry of entries) {\n const alias = getDefaultWwwAlias(entry.host);\n if (alias && !seen.has(alias)) {\n aliases.push({ host: alias, port: entry.port, target: `127.0.0.1:${entry.port}` });\n seen.add(alias);\n }\n }\n\n return [...entries, ...aliases];\n}\n\nfunction defined<T extends Record<string, unknown>>(input: T) {\n return Object.fromEntries(Object.entries(input).filter(([, value]) => typeof value !== \"undefined\")) as Partial<T>;\n}\n\nasync function readProjectConfig(cwd: string, configFile: string | false | undefined) {\n if (configFile === false) return {};\n\n const candidates = configFile ? [configFile] : LOCALGHOST_PROJECT_CONFIG_FILES;\n const path = candidates.map((candidate) => resolveDevHostsPath({ cwd, fileName: candidate }).path).find((candidate) => existsSync(candidate));\n if (!path) return {};\n\n const imported = await import(`${pathToFileURL(path).href}?localghost=${Date.now()}`);\n const config = (imported.default ?? imported) as LocalghostProjectConfig;\n\n return { config, path };\n}\n\nexport function defineLocalghostConfig<T extends LocalghostContextOptions>(config: T) {\n return config;\n}\n\nexport async function resolveLocalghostContext(options: LocalghostContextOptions = {}): Promise<LocalghostContext> {\n const cwd = options.cwd ?? process.cwd();\n const projectConfig = await readProjectConfig(cwd, options.localghostConfig);\n const merged = {\n ...projectConfig.config,\n ...defined(options)\n } as LocalghostContextOptions;\n const readOptions = readOptionsFromContext({ ...merged, cwd });\n const resolvedPath = resolveDevHostsPath(readOptions);\n const configEntries = readDevHosts(readOptions);\n const requestedPort = merged.port ?? envPort() ?? configEntries[0]?.port ?? 5173;\n const dynamicPort = merged.dynamicPort ?? envDynamicPort() ?? false;\n const bindHost = merged.bindHost ?? \"127.0.0.1\";\n const probeHost = typeof bindHost === \"string\" ? bindHost : \"127.0.0.1\";\n const port = dynamicPort ? await findAvailablePort(requestedPort, { host: probeHost }) : requestedPort;\n const wwwAlias = merged.wwwAlias ?? true;\n const entries = wwwAlias\n ? addDefaultWwwAliases(withRuntimePort(configEntries, requestedPort, port))\n : withRuntimePort(configEntries, requestedPort, port);\n const hosts = uniqueHosts(entries);\n const primaryHost =\n merged.primaryHost ??\n entries.find((entry) => entry.port === port)?.host ??\n hosts[0] ??\n `${sanitizeProjectName(getProjectName(cwd))}.localhost`;\n\n return {\n cwd,\n projectName: sanitizeProjectName(merged.project ?? getProjectName(cwd)),\n readOptions,\n configPath: resolvedPath.path,\n configFileName: resolvedPath.fileName,\n configEntries,\n entries,\n hosts,\n requestedPort,\n port,\n dynamicPort,\n bindHost,\n primaryHost,\n https: merged.https ?? envHttps() ?? false,\n wwwAlias,\n ...(projectConfig.path ? { projectConfigPath: projectConfig.path } : {})\n };\n}\n","import { createServer } from \"node:net\";\n\nexport type FindAvailablePortOptions = {\n host?: string;\n maxAttempts?: number;\n};\n\nexport async function isPortAvailable(port: number, host = \"127.0.0.1\") {\n return new Promise<boolean>((resolve) => {\n const server = createServer();\n\n server.once(\"error\", () => {\n resolve(false);\n });\n\n server.once(\"listening\", () => {\n server.close(() => resolve(true));\n });\n\n server.listen(port, host);\n });\n}\n\nexport async function findAvailablePort(startPort: number, options: FindAvailablePortOptions = {}) {\n const host = options.host ?? \"127.0.0.1\";\n const maxAttempts = options.maxAttempts ?? 50;\n\n for (let offset = 0; offset < maxAttempts; offset += 1) {\n const port = startPort + offset;\n if (await isPortAvailable(port, host)) {\n return port;\n }\n }\n\n throw new Error(`No available port found from ${startPort} to ${startPort + maxAttempts - 1}.`);\n}\n","import { execa } from \"execa\";\n\nexport type DoctorResult = {\n ok: boolean;\n caddy: {\n found: boolean;\n version?: string;\n installHint: string;\n };\n};\n\nexport async function checkCaddy(): Promise<DoctorResult[\"caddy\"]> {\n try {\n const result = await execa(\"caddy\", [\"version\"], { reject: false });\n const version = [result.stdout, result.stderr].filter(Boolean).join(\"\\n\").trim();\n\n return {\n found: result.exitCode === 0,\n ...(version ? { version } : {}),\n installHint: \"brew install caddy\"\n };\n } catch {\n return {\n found: false,\n installHint: \"brew install caddy\"\n };\n }\n}\n\nexport async function runDoctor(): Promise<DoctorResult> {\n const caddy = await checkCaddy();\n return {\n ok: caddy.found,\n caddy\n };\n}\n","export type LocalghostEnvironment = NodeJS.ProcessEnv;\n\nconst PRODUCTION_ENV_KEYS = [\"NODE_ENV\", \"VERCEL_ENV\", \"NETLIFY\", \"CF_PAGES_BRANCH\", \"LOCALGHOST_ENV\"] as const;\n\nexport function getProductionReason(env: LocalghostEnvironment = process.env) {\n if (env.LOCALGHOST_ENV === \"production\") return \"LOCALGHOST_ENV=production\";\n if (env.NODE_ENV === \"production\") return \"NODE_ENV=production\";\n if (env.VERCEL_ENV === \"production\") return \"VERCEL_ENV=production\";\n if (env.NETLIFY === \"true\" && env.CONTEXT === \"production\") return \"NETLIFY=true and CONTEXT=production\";\n if (env.CF_PAGES_BRANCH && env.CF_PAGES_BRANCH === env.CF_PAGES_PRODUCTION_BRANCH) {\n return \"CF_PAGES_BRANCH matches CF_PAGES_PRODUCTION_BRANCH\";\n }\n\n return null;\n}\n\nexport function isProductionLike(env: LocalghostEnvironment = process.env) {\n return getProductionReason(env) !== null;\n}\n\nexport function assertLocalDevelopment(command: string, env: LocalghostEnvironment = process.env) {\n const reason = getProductionReason(env);\n if (!reason) return;\n\n throw new Error(`Localghost only runs in local development. Refusing \\`${command}\\` because ${reason}.`);\n}\n\nexport function getProductionEnvKeys() {\n return PRODUCTION_ENV_KEYS;\n}\n","import { writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { execa } from \"execa\";\nimport { sanitizeProjectName } from \"./config.js\";\nimport { readTextFile } from \"./fs.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport type UpdateSystemHostsResult = {\n changed: boolean;\n hostsPath: string;\n tempPath?: string;\n};\n\nexport type RemoveSystemHostsResult = UpdateSystemHostsResult & {\n removed: boolean;\n};\n\nfunction escapeRegExp(value: string) {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction getManagedBlockPattern(projectName: string) {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const start = `# localghost:start ${sanitizedProjectName}`;\n const end = `# localghost:end ${sanitizedProjectName}`;\n return new RegExp(`${escapeRegExp(start)}[\\\\s\\\\S]*?${escapeRegExp(end)}\\\\n?`, \"m\");\n}\n\nexport function getSystemHostsPath() {\n return process.platform === \"win32\" ? \"C:\\\\Windows\\\\System32\\\\drivers\\\\etc\\\\hosts\" : \"/etc/hosts\";\n}\n\nexport function renderHostsBlock(projectName: string, entries: DevHostEntry[]) {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const hosts = [...new Set(entries.map((entry) => entry.host))].sort();\n\n return [\n `# localghost:start ${sanitizedProjectName}`,\n ...hosts.map((host) => `127.0.0.1 ${host}`),\n `# localghost:end ${sanitizedProjectName}`,\n \"\"\n ].join(\"\\n\");\n}\n\nexport function upsertManagedBlock(existing: string, projectName: string, block: string) {\n const pattern = getManagedBlockPattern(projectName);\n\n if (pattern.test(existing)) {\n return existing.replace(pattern, block);\n }\n\n return `${existing.trimEnd()}\\n\\n${block}`;\n}\n\nexport function removeManagedBlock(existing: string, projectName: string) {\n const pattern = getManagedBlockPattern(projectName);\n\n if (!pattern.test(existing)) {\n return existing;\n }\n\n return existing.replace(pattern, \"\").replace(/\\n{3,}/g, \"\\n\\n\").trimEnd() + \"\\n\";\n}\n\nasync function writeSystemHostsFile(hostsPath: string, next: string, projectName: string) {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const tempPath = join(tmpdir(), `localghost-${sanitizedProjectName}-hosts`);\n writeFileSync(tempPath, next, \"utf8\");\n\n if (process.platform === \"win32\") {\n throw new Error(`Windows support: run as administrator and copy ${tempPath} to ${hostsPath}.`);\n }\n\n await execa(\"sudo\", [\"cp\", tempPath, hostsPath], { stdio: \"inherit\" });\n\n return tempPath;\n}\n\nexport async function updateSystemHosts(projectName: string, entries: DevHostEntry[]): Promise<UpdateSystemHostsResult> {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const hostsPath = getSystemHostsPath();\n const existing = readTextFile(hostsPath);\n const block = renderHostsBlock(sanitizedProjectName, entries);\n const next = upsertManagedBlock(existing, sanitizedProjectName, block);\n\n if (next === existing) {\n return { changed: false, hostsPath };\n }\n\n const tempPath = await writeSystemHostsFile(hostsPath, next, sanitizedProjectName);\n\n return { changed: true, hostsPath, tempPath };\n}\n\nexport async function removeSystemHosts(projectName: string): Promise<RemoveSystemHostsResult> {\n const sanitizedProjectName = sanitizeProjectName(projectName);\n const hostsPath = getSystemHostsPath();\n const existing = readTextFile(hostsPath);\n const next = removeManagedBlock(existing, sanitizedProjectName);\n\n if (next === existing) {\n return { changed: false, removed: false, hostsPath };\n }\n\n const tempPath = await writeSystemHostsFile(hostsPath, next, sanitizedProjectName);\n\n return { changed: true, removed: true, hostsPath, tempPath };\n}\n","import { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getProjectName, LOCALGHOST_CONFIG_FILE, sanitizeProjectName } from \"./config.js\";\nimport { writeTextFile } from \"./fs.js\";\n\nexport type PackageManager = \"npm\" | \"yarn\" | \"pnpm\";\n\nexport type InitOptions = {\n cwd?: string;\n host?: string;\n port?: number;\n apiHost?: string;\n apiPort?: number;\n force?: boolean;\n packageManager?: PackageManager;\n writeScripts?: boolean;\n configFile?: string;\n};\n\nexport type InitResult = {\n configPath: string;\n configCreated: boolean;\n packageJsonPath?: string;\n packageJsonChanged: boolean;\n packageManager: PackageManager;\n nextSteps: string[];\n};\n\nexport function detectPackageManager(cwd = process.cwd()): PackageManager {\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\";\n if (existsSync(join(cwd, \"yarn.lock\"))) return \"yarn\";\n return \"npm\";\n}\n\nexport function packageRunCommand(packageManager: PackageManager, script: string): string {\n if (packageManager === \"yarn\") return `yarn ${script}`;\n if (packageManager === \"pnpm\") return `pnpm ${script}`;\n return `npm run ${script}`;\n}\n\nexport function packageAddCommand(packageManager: PackageManager, packageName = \"@hamedb89/localghost\"): string {\n if (packageManager === \"yarn\") return `yarn add -D ${packageName}`;\n if (packageManager === \"pnpm\") return `pnpm add -D ${packageName}`;\n return `npm install -D ${packageName}`;\n}\n\nfunction renderConfig(options: Required<Pick<InitOptions, \"host\" | \"port\" | \"apiHost\" | \"apiPort\">>) {\n return [\n \"# Buh. Friendly names for local services.\",\n \"# Format: <host> <port>\",\n `${options.host} ${options.port}`,\n `www.${options.host} ${options.port}`,\n `${options.apiHost} ${options.apiPort}`,\n \"\"\n ].join(\"\\n\");\n}\n\nfunction readPackageJson(path: string): Record<string, unknown> | null {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nfunction shellQuote(value: string) {\n if (/^[A-Za-z0-9_./:-]+$/.test(value)) return value;\n return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\nfunction getConfigFlag(configFile: string) {\n return configFile === LOCALGHOST_CONFIG_FILE ? \"\" : ` --config ${shellQuote(configFile)}`;\n}\n\nfunction updatePackageScripts(packageJsonPath: string, configFile: string): boolean {\n const pkg = readPackageJson(packageJsonPath);\n if (!pkg) return false;\n\n const scripts = typeof pkg.scripts === \"object\" && pkg.scripts ? (pkg.scripts as Record<string, unknown>) : {};\n const configFlag = getConfigFlag(configFile);\n const nextScripts = {\n ...scripts,\n \"localghost:setup\": scripts[\"localghost:setup\"] ?? `localghost setup${configFlag}`,\n \"localghost:proxy\": scripts[\"localghost:proxy\"] ?? `localghost dev${configFlag}`,\n \"localghost:proxy:https\": scripts[\"localghost:proxy:https\"] ?? `localghost dev${configFlag} --https`,\n \"localghost:run\": scripts[\"localghost:run\"] ?? `localghost run${configFlag} --`,\n \"localghost:ready\": scripts[\"localghost:ready\"] ?? `localghost status${configFlag} --ready`,\n \"localghost:trust\": scripts[\"localghost:trust\"] ?? `localghost trust${configFlag}`,\n \"localghost:ps\": scripts[\"localghost:ps\"] ?? \"localghost ps\",\n \"localghost:print\": scripts[\"localghost:print\"] ?? `localghost print${configFlag}`,\n \"localghost:routes\": scripts[\"localghost:routes\"] ?? `localghost routes${configFlag}`,\n \"localghost:status\": scripts[\"localghost:status\"] ?? \"localghost status\",\n \"localghost:reset\": scripts[\"localghost:reset\"] ?? \"localghost reset\",\n \"localghost:teardown\": scripts[\"localghost:teardown\"] ?? \"localghost teardown\",\n \"localghost:doctor\": scripts[\"localghost:doctor\"] ?? \"localghost doctor\",\n \"localghost:update\": scripts[\"localghost:update\"] ?? \"localghost update\",\n \"caddy:setup\": scripts[\"caddy:setup\"] ?? `localghost setup${configFlag}`,\n \"caddy:dev\": scripts[\"caddy:dev\"] ?? `localghost dev${configFlag}`\n };\n\n const changed = JSON.stringify(scripts) !== JSON.stringify(nextScripts);\n if (!changed) return false;\n\n pkg.scripts = nextScripts;\n writeFileSync(packageJsonPath, `${JSON.stringify(pkg, null, 2)}\\n`, \"utf8\");\n return true;\n}\n\nexport function initLocalghost(options: InitOptions = {}): InitResult {\n const cwd = options.cwd ?? process.cwd();\n const projectName = sanitizeProjectName(getProjectName(cwd).split(\"/\").pop() ?? \"app\");\n const host = options.host ?? `${projectName}.localhost`;\n const port = options.port ?? 5173;\n const apiHost = options.apiHost ?? `api.${host}`;\n const apiPort = options.apiPort ?? 8787;\n const packageManager = options.packageManager ?? detectPackageManager(cwd);\n const configFile = options.configFile ?? LOCALGHOST_CONFIG_FILE;\n const configPath = join(cwd, configFile);\n const configExists = existsSync(configPath);\n\n if (configExists && !options.force) {\n return {\n configPath,\n configCreated: false,\n packageJsonChanged: false,\n packageManager,\n nextSteps: [\n packageRunCommand(packageManager, \"localghost:doctor\"),\n packageRunCommand(packageManager, \"localghost:setup\"),\n packageRunCommand(packageManager, \"localghost:ready\"),\n packageRunCommand(packageManager, \"localghost:proxy\")\n ]\n };\n }\n\n writeTextFile(configPath, renderConfig({ host, port, apiHost, apiPort }));\n\n const packageJsonPath = join(cwd, \"package.json\");\n const packageJsonChanged = options.writeScripts ? updatePackageScripts(packageJsonPath, configFile) : false;\n\n return {\n configPath,\n configCreated: true,\n ...(existsSync(packageJsonPath) ? { packageJsonPath } : {}),\n packageJsonChanged,\n packageManager,\n nextSteps: [\n packageRunCommand(packageManager, \"localghost:doctor\"),\n packageRunCommand(packageManager, \"localghost:setup\"),\n packageRunCommand(packageManager, \"localghost:ready\"),\n packageRunCommand(packageManager, \"localghost:proxy\")\n ]\n };\n}\n","import type { DevHostEntry } from \"./parse.js\";\n\nexport type DomainRoute = {\n host: string;\n port: number;\n url: string;\n upstream: string;\n};\n\nexport type DomainRouteOptions = {\n https?: boolean;\n};\n\nexport function getDomainRoutes(entries: DevHostEntry[], options: DomainRouteOptions = {}): DomainRoute[] {\n const protocol = options.https === true ? \"https\" : \"http\";\n\n return [...entries]\n .sort((left, right) => left.host.localeCompare(right.host) || left.port - right.port)\n .map((entry) => ({\n host: entry.host,\n port: entry.port,\n url: `${protocol}://${entry.host}/`,\n upstream: `http://${entry.target}`\n }));\n}\n\nexport function formatDomainRoutes(entries: DevHostEntry[], options: DomainRouteOptions = {}) {\n const routes = getDomainRoutes(entries, options);\n\n if (routes.length === 0) {\n return \"localghost routes\\n no routes\";\n }\n\n return [\n \"localghost routes\",\n ...routes.map((route) => ` ${route.url} -> ${route.upstream}`)\n ].join(\"\\n\");\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { readTextFile, writeTextFile } from \"./fs.js\";\nimport type { DevHostEntry } from \"./parse.js\";\n\nexport const LOCALGHOST_STATE_FILE = \"ops/local/localghost-state.json\";\n\nexport type LocalghostStateAction = \"setup\" | \"teardown\";\n\nexport type LocalghostState = {\n version: 1;\n action: LocalghostStateAction;\n updatedAt: string;\n projectName: string;\n cwd: string;\n configPath?: string;\n hostsPath?: string;\n hostsChanged?: boolean;\n hostsTempPath?: string;\n caddyfilePath?: string;\n caddyfileRemoved?: boolean;\n caddyHttps?: boolean;\n caddyTrustedAt?: string;\n caddyTrustPromptedAt?: string;\n entries?: DevHostEntry[];\n};\n\nexport type WriteLocalghostStateInput = Omit<LocalghostState, \"version\" | \"updatedAt\">;\n\nexport function getLocalghostStatePath(cwd = process.cwd()) {\n return join(cwd, LOCALGHOST_STATE_FILE);\n}\n\nexport function readLocalghostState(cwd = process.cwd()): LocalghostState | null {\n const path = getLocalghostStatePath(cwd);\n if (!existsSync(path)) return null;\n return JSON.parse(readTextFile(path)) as LocalghostState;\n}\n\nexport function writeLocalghostState(cwd: string, state: WriteLocalghostStateInput) {\n const path = getLocalghostStatePath(cwd);\n writeTextFile(path, `${JSON.stringify({ ...state, version: 1, updatedAt: new Date().toISOString() }, null, 2)}\\n`);\n return path;\n}\n\nexport function patchLocalghostState(cwd: string, patch: Partial<WriteLocalghostStateInput>) {\n const current = readLocalghostState(cwd);\n if (!current) return null;\n return writeLocalghostState(cwd, { ...(current as unknown as WriteLocalghostStateInput), ...patch });\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nexport const LOCALGHOST_PACKAGE_NAME = \"@hamedb89/localghost\";\nexport const LOCALGHOST_VERSION = \"0.1.8\";\nexport const UPDATE_CHECK_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\nexport const UPDATE_CHECK_NOTIFY_TTL_MS = 24 * 60 * 60 * 1000;\nexport const UPDATE_CHECK_TIMEOUT_MS = 900;\n\nexport type UpdateCheckCache = {\n checkedAt: string;\n latestVersion?: string;\n notifiedVersion?: string;\n notifiedAt?: string;\n};\n\nexport type UpdateCheckResult = {\n currentVersion: string;\n packageName: string;\n latestVersion?: string;\n updateAvailable: boolean;\n source: \"cache\" | \"registry\" | \"disabled\" | \"error\";\n error?: string;\n};\n\ntype RegistryPackageResponse = {\n \"dist-tags\"?: {\n latest?: unknown;\n };\n};\n\nfunction truthyEnv(value: string | undefined) {\n return value === \"1\" || value === \"true\" || value === \"yes\";\n}\n\nexport function isUpdateCheckDisabled(env: NodeJS.ProcessEnv = process.env) {\n return truthyEnv(env.LOCALGHOST_NO_UPDATE_CHECK);\n}\n\nexport function getUpdateCheckCachePath(env: NodeJS.ProcessEnv = process.env) {\n if (env.LOCALGHOST_UPDATE_CHECK_CACHE) return env.LOCALGHOST_UPDATE_CHECK_CACHE;\n\n const cacheRoot = env.XDG_CACHE_HOME || join(homedir(), \".cache\");\n return join(cacheRoot, \"localghost\", \"update-check.json\");\n}\n\nfunction readCache(path = getUpdateCheckCachePath()): UpdateCheckCache | null {\n if (!existsSync(path)) return null;\n\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as UpdateCheckCache;\n } catch {\n return null;\n }\n}\n\nfunction writeCache(cache: UpdateCheckCache, path = getUpdateCheckCachePath()) {\n try {\n mkdirSync(dirname(path), { recursive: true });\n writeFileSync(path, `${JSON.stringify(cache, null, 2)}\\n`, \"utf8\");\n } catch {\n // Update checks should never make the real command fail.\n }\n}\n\nfunction ageMs(date: string | undefined, now = Date.now()) {\n if (!date) return Number.POSITIVE_INFINITY;\n const time = Date.parse(date);\n return Number.isFinite(time) ? now - time : Number.POSITIVE_INFINITY;\n}\n\nfunction isCacheFresh(cache: UpdateCheckCache | null, ttlMs: number, now = Date.now()) {\n return Boolean(cache?.latestVersion && ageMs(cache.checkedAt, now) >= 0 && ageMs(cache.checkedAt, now) < ttlMs);\n}\n\ntype ParsedVersion = {\n major: number;\n minor: number;\n patch: number;\n prerelease?: string;\n};\n\nfunction parseVersion(version: string): ParsedVersion | null {\n const match = version.trim().replace(/^v/, \"\").match(/^(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?$/);\n if (!match) return null;\n\n return {\n major: Number(match[1]),\n minor: Number(match[2]),\n patch: Number(match[3]),\n ...(match[4] ? { prerelease: match[4] } : {})\n };\n}\n\nexport function compareVersions(a: string, b: string) {\n const left = parseVersion(a);\n const right = parseVersion(b);\n\n if (!left || !right) return a.localeCompare(b);\n\n for (const key of [\"major\", \"minor\", \"patch\"] as const) {\n if (left[key] !== right[key]) return left[key] > right[key] ? 1 : -1;\n }\n\n if (left.prerelease === right.prerelease) return 0;\n if (!left.prerelease) return 1;\n if (!right.prerelease) return -1;\n return left.prerelease.localeCompare(right.prerelease);\n}\n\nexport function isNewerVersion(candidate: string | undefined, current = LOCALGHOST_VERSION) {\n return Boolean(candidate && compareVersions(candidate, current) > 0);\n}\n\nasync function fetchLatestVersion(packageName: string, timeoutMs: number) {\n const encodedName = packageName.startsWith(\"@\") ? `@${packageName.slice(1).replace(\"/\", \"%2f\")}` : packageName;\n const response = await fetch(`https://registry.npmjs.org/${encodedName}`, {\n signal: AbortSignal.timeout(timeoutMs),\n headers: {\n accept: \"application/vnd.npm.install-v1+json\"\n }\n });\n\n if (!response.ok) throw new Error(`npm registry returned ${response.status}`);\n\n const data = (await response.json()) as RegistryPackageResponse;\n const latest = data[\"dist-tags\"]?.latest;\n if (typeof latest !== \"string\" || latest.length === 0) throw new Error(\"npm registry response did not include latest dist-tag\");\n\n return latest;\n}\n\nexport async function checkForUpdate(options: {\n force?: boolean;\n packageName?: string;\n currentVersion?: string;\n timeoutMs?: number;\n cachePath?: string;\n env?: NodeJS.ProcessEnv;\n} = {}): Promise<UpdateCheckResult> {\n const env = options.env ?? process.env;\n const packageName = options.packageName ?? LOCALGHOST_PACKAGE_NAME;\n const currentVersion = options.currentVersion ?? LOCALGHOST_VERSION;\n const cachePath = options.cachePath ?? getUpdateCheckCachePath(env);\n\n if (!options.force && isUpdateCheckDisabled(env)) {\n return {\n currentVersion,\n packageName,\n updateAvailable: false,\n source: \"disabled\"\n };\n }\n\n const cache = readCache(cachePath);\n if (!options.force && isCacheFresh(cache, UPDATE_CHECK_CACHE_TTL_MS)) {\n const latestVersion = cache?.latestVersion;\n return {\n currentVersion,\n packageName,\n ...(latestVersion ? { latestVersion } : {}),\n updateAvailable: isNewerVersion(latestVersion, currentVersion),\n source: \"cache\"\n };\n }\n\n try {\n const latestVersion = await fetchLatestVersion(packageName, options.timeoutMs ?? UPDATE_CHECK_TIMEOUT_MS);\n writeCache({ checkedAt: new Date().toISOString(), latestVersion }, cachePath);\n\n return {\n currentVersion,\n packageName,\n latestVersion,\n updateAvailable: isNewerVersion(latestVersion, currentVersion),\n source: \"registry\"\n };\n } catch (error) {\n const latestVersion = cache?.latestVersion;\n return {\n currentVersion,\n packageName,\n ...(latestVersion ? { latestVersion } : {}),\n updateAvailable: isNewerVersion(latestVersion, currentVersion),\n source: \"error\",\n error: error instanceof Error ? error.message : String(error)\n };\n }\n}\n\nexport function formatUpdateMessage(result: UpdateCheckResult) {\n if (!result.updateAvailable || !result.latestVersion) return null;\n\n return [\n `localghost ${result.latestVersion} is available. Current: ${result.currentVersion}`,\n `Update with: npm i -g ${result.packageName}@latest`\n ].join(\"\\n\");\n}\n\nexport function shouldNotifyAboutUpdate(result: UpdateCheckResult, cachePath = getUpdateCheckCachePath(), now = Date.now()) {\n if (!result.updateAvailable || !result.latestVersion) return false;\n\n const cache = readCache(cachePath);\n if (cache?.notifiedVersion !== result.latestVersion) return true;\n\n return ageMs(cache.notifiedAt, now) >= UPDATE_CHECK_NOTIFY_TTL_MS;\n}\n\nexport function markUpdateNotified(result: UpdateCheckResult, cachePath = getUpdateCheckCachePath()) {\n if (!result.latestVersion) return;\n\n const cache = readCache(cachePath) ?? { checkedAt: new Date().toISOString() };\n writeCache(\n {\n ...cache,\n latestVersion: result.latestVersion,\n notifiedVersion: result.latestVersion,\n notifiedAt: new Date().toISOString()\n },\n cachePath\n );\n}\n\nexport async function maybeNotifyAboutUpdate(options: { disabled?: boolean } = {}) {\n if (options.disabled) return;\n\n const cachePath = getUpdateCheckCachePath();\n const result = await checkForUpdate({ cachePath });\n if (!shouldNotifyAboutUpdate(result, cachePath)) return;\n\n const message = formatUpdateMessage(result);\n if (!message) return;\n\n console.warn(`\\n${message}`);\n markUpdateNotified(result, cachePath);\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","fileName","existsSync","readFileSync","join","dirname","join","mkdirSync","readFileSync","writeFileSync","dirname","join","dirname","existsSync","resolve","existsSync","execa","writeFileSync","join","execa","join","writeFileSync","execa","existsSync","readFileSync","writeFileSync","join","existsSync","join","readFileSync","writeFileSync","existsSync","join","join","existsSync","existsSync","mkdirSync","readFileSync","writeFileSync","homedir","dirname","join"]}
package/dist/vite.d.ts CHANGED
@@ -13,6 +13,8 @@ type LocalGhostPluginOptions = {
13
13
  primaryHost?: string;
14
14
  log?: boolean;
15
15
  setup?: boolean | "prompt";
16
+ localghostConfig?: string | false;
17
+ wwwAlias?: boolean;
16
18
  };
17
19
  declare function localGhostPlugin(options?: LocalGhostPluginOptions): Plugin;
18
20
  declare const localHostsPlugin: typeof localGhostPlugin;