@hamedb89/localghost 0.1.0 → 0.1.6
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/README.md +100 -13
- package/dist/cli.js +645 -83
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +102 -6
- package/dist/index.js +294 -50
- package/dist/index.js.map +1 -1
- package/dist/vite.d.ts +3 -0
- package/dist/vite.js +460 -16
- package/dist/vite.js.map +1 -1
- package/docs/flows.md +27 -5
- package/docs/github.md +46 -8
- package/docs/localghost.1.md +45 -9
- package/package.json +7 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/parse.ts","../src/caddy.ts","../src/fs.ts","../src/doctor.ts","../src/hosts-file.ts","../src/init.ts","../src/routes.ts","../src/state.ts","../src/update-check.ts"],"sourcesContent":["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\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[]) {\n const groups = groupByPort(entries);\n const blocks = [...groups.entries()]\n .sort(([leftPort], [rightPort]) => leftPort - rightPort)\n .map(([port, group]) => {\n const hosts = group\n .map((entry) => entry.host)\n .sort()\n .join(\", \");\n\n return `${hosts} {\n reverse_proxy 127.0.0.1:${port}\n}`;\n });\n\n return `{\n local_certs\n}\n\n${blocks.join(\"\\n\\n\")}\n`;\n}\n\nexport async function writeCaddyfile(entries: DevHostEntry[], cwd = process.cwd()) {\n const path = getCaddyfilePath(cwd);\n writeTextFile(path, renderCaddyfile(entries));\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","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 { 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","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: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:teardown\": scripts[\"localghost:teardown\"] ?? \"localghost teardown\",\n \"localghost:doctor\": scripts[\"localghost:doctor\"] ?? \"localghost doctor\",\n \"localghost:update\": scripts[\"localghost:update\"] ?? \"localghost update\"\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: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: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 === false ? \"http\" : \"https\";\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 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.0\";\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":["fileName","dirname","join","readFileSync","join","dirname","execa","writeFileSync","join","execa","join","writeFileSync","execa","existsSync","readFileSync","writeFileSync","join","existsSync","join","readFileSync","writeFileSync","existsSync","join","join","existsSync","existsSync","mkdirSync","readFileSync","writeFileSync","dirname","join"]}
|
|
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"]}
|
package/dist/vite.d.ts
CHANGED
|
@@ -8,8 +8,11 @@ type LocalGhostPluginOptions = {
|
|
|
8
8
|
configPattern?: ConfigPattern;
|
|
9
9
|
port?: number;
|
|
10
10
|
https?: boolean;
|
|
11
|
+
bindHost?: string | boolean;
|
|
12
|
+
dynamicPort?: boolean;
|
|
11
13
|
primaryHost?: string;
|
|
12
14
|
log?: boolean;
|
|
15
|
+
setup?: boolean | "prompt";
|
|
13
16
|
};
|
|
14
17
|
declare function localGhostPlugin(options?: LocalGhostPluginOptions): Plugin;
|
|
15
18
|
declare const localHostsPlugin: typeof localGhostPlugin;
|