@hamedb89/localghost 0.1.15 → 0.3.0
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 +13 -2
- package/dist/cli.js +169 -27
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +40 -4
- package/dist/index.js +83 -6
- package/dist/index.js.map +1 -1
- package/dist/vite.js +13 -0
- package/dist/vite.js.map +1 -1
- package/docs/github.md +5 -5
- package/docs/localghost.1.md +6 -4
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { D as DevHostEntry, R as ReadDevHostsOptions, a as ResolvedDevHostsPath, b as ConstructGhostTunnelUrlInput, c as GhostTunnelTransportOptions, d as GhostTunnelTransportConfig, e as GhostTunnelRoute, f as GhostTunnelConfig, C as ConfigPattern, G as GhostTunnelOptions } from './tunnel-BA52DD9e.js';
|
|
2
2
|
export { g as GhostTunnelAdapterOptions, h as GhostTunnelAdapterProvider, i as GhostTunnelAdapterStrategy, j as GhostTunnelAdapterTransport, k as GhostTunnelDisplayDefaults, l as GhostTunnelDomainOptions, m as GhostTunnelMode, n as GhostTunnelNamespaceConfig, o as GhostTunnelNamespaceOptions, p as GhostTunnelNamespaceTag, q as GhostTunnelNamespaceValues, r as GhostTunnelPreviewOptions, s as GhostTunnelTransportKind, t as GhostTunnelTunnelStoreEnv, u as GhostTunnelTunnelStoreOptions, v as GhostTunnelTunnelStoreProvider, L as LOCALGHOST_CONFIG_FILE, w as assertSecureGhostTunnelRequest, x as constructGhostTunnelHost, y as constructGhostTunnelURL, z as constructGhostTunnelUrl, A as findLocalMdnsHosts, B as getConfigFileCandidates, E as getDevHostsPath, F as getGhostTunnelDefaultDisplayUrl, H as getGhostTunnelDisplayUrl, I as getGhostTunnelDisplayUrls, J as getGhostTunnelEntryHost, K as getGhostTunnelPreviewUrl, M as getGhostTunnelWildcardHost, N as getProjectName, O as parseDevHosts, P as parseGhostTunnelHost, Q as readDevHosts, S as resolveDevHostsPath, T as resolveGhostTunnelConfig, U as sanitizeProjectName } from './tunnel-BA52DD9e.js';
|
|
3
3
|
import * as execa from 'execa';
|
|
4
|
+
import { ChildProcess } from 'node:child_process';
|
|
4
5
|
|
|
5
6
|
declare const LOCALGHOST_ACTIVITY_VERSION = 1;
|
|
6
7
|
type LocalghostRunMode = "dev" | "run" | "vite";
|
|
@@ -15,6 +16,7 @@ type LocalghostRunRecord = {
|
|
|
15
16
|
configPath?: string;
|
|
16
17
|
caddyfilePath?: string;
|
|
17
18
|
caddyPid?: number;
|
|
19
|
+
caddyPgid?: number;
|
|
18
20
|
childPid?: number;
|
|
19
21
|
childCommand?: string[];
|
|
20
22
|
https?: boolean;
|
|
@@ -70,7 +72,7 @@ declare function unregisterLocalghostSetup(options: {
|
|
|
70
72
|
declare function renderLocalghostBanner(): string;
|
|
71
73
|
declare function renderCompactLocalghostBanner(): string;
|
|
72
74
|
|
|
73
|
-
declare const LOCALGHOST_AGENT_GUIDE = "# Localghost agent guide\n\nLocalghost owns the local development proxy and the app process boundary.\n\n## Preferred repository setup\n\nFor a normal repository, use this package script:\n\n \"dev\": \"localghost\"\n\nFor an explicit app command, keep the raw command separate:\n\n \"dev\": \"localghost run -- vite\"\n \"dev:raw\": \"vite\"\n\nUse `localghost dev` only when the Caddy proxy should run without starting the app.\n\n## Useful commands\n\n- `localghost`: detect and run the repository development command.\n- `localghost run -- <command>`: wrap an explicit app command.\n- `localghost dev`: run only the local Caddy proxy.\n- `localghost status --ready`: check project setup.\n- `localghost repair`: repair managed hosts and Caddy setup.\n- `localghost ps --json`: inspect Localghost-managed repositories, instances, and ports.\n- `localghost routes`: inspect hostname-to-port routing.\n- `localghost doctor`: check machine prerequisites.\n\n## Configuration\n\n- Commit repository defaults in `localghost.config.mjs`.\n- Keep hostname and requested-port routes in `.localghost`.\n- CLI flags override repository configuration for one invocation.\n- Localghost remembers active project and instance port assignments in user state under `~/.localghost`.\n- Do not edit the registry manually and do not start Caddy separately.\n\n## Port behavior\n\nLocalghost remembers ports by canonical repository path and instance key. Concurrent Localghost instances receive distinct ports. The operating-system bind check remains authoritative when another tool already owns a port.\n";
|
|
75
|
+
declare const LOCALGHOST_AGENT_GUIDE = "# Localghost agent guide\n\nLocalghost owns the local development proxy and the app process boundary.\n\n## Preferred repository setup\n\nFor a normal repository, use this package script:\n\n \"dev\": \"localghost\"\n\nFor an explicit app command, keep the raw command separate:\n\n \"dev\": \"localghost run -- vite\"\n \"dev:raw\": \"vite\"\n\nUse `localghost dev` only when the Caddy proxy should run without starting the app.\n\n## Useful commands\n\n- `localghost`: detect and run the repository development command.\n- `localghost run -- <command>`: wrap an explicit app command.\n- `localghost dev`: run only the local Caddy proxy.\n- `localghost status --ready`: check project setup.\n- `localghost repair`: repair managed hosts and Caddy setup.\n- `localghost ps --json`: inspect Localghost-managed repositories, instances, and ports.\n- `localghost routes`: inspect hostname-to-port routing.\n- `localghost doctor`: check machine prerequisites, ports, and registry state.\n- `localghost repair --reallocate-port`: move an occupied project port to a stable available port.\n\n## Configuration\n\n- Commit repository defaults in `localghost.config.mjs`.\n- Keep hostname and requested-port routes in `.localghost`.\n- CLI flags override repository configuration for one invocation.\n- Localghost remembers active project and instance port assignments in user state under `~/.localghost`.\n- Do not edit the registry manually and do not start Caddy separately.\n\n## Port behavior\n\nLocalghost remembers ports by canonical repository path and instance key. Concurrent Localghost instances receive distinct ports. The operating-system bind check remains authoritative when another tool already owns a port.\n";
|
|
74
76
|
declare function formatLocalghostAgentGuide(format?: "text" | "json"): string;
|
|
75
77
|
|
|
76
78
|
declare const LOCALGHOST_GHOST_TUNNEL_FILE = ".ghosttunnel";
|
|
@@ -338,6 +340,7 @@ declare function runCaddy(path: string): Promise<void>;
|
|
|
338
340
|
declare function startCaddy(path: string): execa.ResultPromise<{
|
|
339
341
|
cwd: string;
|
|
340
342
|
stdio: "inherit" | "pipe";
|
|
343
|
+
detached: boolean;
|
|
341
344
|
}>;
|
|
342
345
|
declare function stopCaddyProcesses(pids: Iterable<number>, killProcess?: CaddyProcessKiller): CaddyProcessStopResult;
|
|
343
346
|
declare function trustCaddy(path: string): Promise<void>;
|
|
@@ -465,9 +468,34 @@ type DoctorResult = {
|
|
|
465
468
|
version?: string;
|
|
466
469
|
installHint: string;
|
|
467
470
|
};
|
|
471
|
+
ports: {
|
|
472
|
+
configured?: number;
|
|
473
|
+
available?: boolean;
|
|
474
|
+
registryPath: string;
|
|
475
|
+
staleLeases: Array<{
|
|
476
|
+
projectCwd: string;
|
|
477
|
+
instanceKey: string;
|
|
478
|
+
port: number;
|
|
479
|
+
pid: number;
|
|
480
|
+
}>;
|
|
481
|
+
duplicateAllocations: Array<{
|
|
482
|
+
port: number;
|
|
483
|
+
projects: string[];
|
|
484
|
+
}>;
|
|
485
|
+
currentAllocation?: {
|
|
486
|
+
projectCwd: string;
|
|
487
|
+
instanceKey: string;
|
|
488
|
+
port: number;
|
|
489
|
+
};
|
|
490
|
+
};
|
|
491
|
+
};
|
|
492
|
+
type DoctorOptions = {
|
|
493
|
+
cwd?: string;
|
|
494
|
+
configFiles?: string[];
|
|
495
|
+
configPattern?: ConfigPattern;
|
|
468
496
|
};
|
|
469
497
|
declare function checkCaddy(): Promise<DoctorResult["caddy"]>;
|
|
470
|
-
declare function runDoctor(): Promise<DoctorResult>;
|
|
498
|
+
declare function runDoctor(options?: DoctorOptions): Promise<DoctorResult>;
|
|
471
499
|
|
|
472
500
|
type LocalghostEnvironment = NodeJS.ProcessEnv;
|
|
473
501
|
declare function getProductionReason(env?: LocalghostEnvironment): "LOCALGHOST_ENV=production" | "NODE_ENV=production" | "VERCEL_ENV=production" | "NETLIFY=true and CONTEXT=production" | "CF_PAGES_BRANCH matches CF_PAGES_PRODUCTION_BRANCH" | null;
|
|
@@ -522,6 +550,11 @@ type FindAvailablePortOptions = {
|
|
|
522
550
|
declare function isPortAvailable(port: number, host?: string): Promise<boolean>;
|
|
523
551
|
declare function findAvailablePort(startPort: number, options?: FindAvailablePortOptions): Promise<number>;
|
|
524
552
|
|
|
553
|
+
type ProcessSignal = NodeJS.Signals;
|
|
554
|
+
type ProcessKiller = (pid: number, signal: ProcessSignal) => void;
|
|
555
|
+
declare function signalManagedProcessPid(pid: number | undefined, signal: ProcessSignal, killProcess?: ProcessKiller): boolean;
|
|
556
|
+
declare function signalManagedProcess(child: Pick<ChildProcess, "pid" | "kill" | "killed">, signal: ProcessSignal): boolean;
|
|
557
|
+
|
|
525
558
|
declare const LOCALGHOST_REGISTRY_FILE = "registry.json";
|
|
526
559
|
declare const LOCALGHOST_REGISTRY_LOCK_FILE = "registry.lock";
|
|
527
560
|
type PortAvailabilityCheck = (port: number, host?: string) => boolean | Promise<boolean>;
|
|
@@ -577,6 +610,9 @@ type LocalghostRegistry = {
|
|
|
577
610
|
instanceKey: string;
|
|
578
611
|
}): Promise<boolean>;
|
|
579
612
|
read(): Promise<LocalghostRegistryData>;
|
|
613
|
+
prune(): Promise<{
|
|
614
|
+
removedLeases: number;
|
|
615
|
+
}>;
|
|
580
616
|
};
|
|
581
617
|
declare function getLocalghostRegistryRoot(env?: NodeJS.ProcessEnv): string;
|
|
582
618
|
declare function canonicalizeLocalghostProjectCwd(cwd?: string): string;
|
|
@@ -649,7 +685,7 @@ type CreateVercelGhostTunnelHandlerOptions = {
|
|
|
649
685
|
declare function createVercelGhostTunnelHandler(options: CreateVercelGhostTunnelHandlerOptions): (request: VercelGhostTunnelRequestLike, response: VercelGhostTunnelResponseLike) => Promise<void>;
|
|
650
686
|
|
|
651
687
|
declare const LOCALGHOST_PACKAGE_NAME = "@hamedb89/localghost";
|
|
652
|
-
declare const LOCALGHOST_VERSION = "0.
|
|
688
|
+
declare const LOCALGHOST_VERSION = "0.3.0";
|
|
653
689
|
declare const UPDATE_CHECK_CACHE_TTL_MS: number;
|
|
654
690
|
declare const UPDATE_CHECK_NOTIFY_TTL_MS: number;
|
|
655
691
|
declare const UPDATE_CHECK_TIMEOUT_MS = 900;
|
|
@@ -686,4 +722,4 @@ declare function maybeNotifyAboutUpdate(options?: {
|
|
|
686
722
|
disabled?: boolean;
|
|
687
723
|
}): Promise<void>;
|
|
688
724
|
|
|
689
|
-
export { type AcquireLocalghostPortOptions, type ActiveRelayRoute, type CaddyModeOptions, type CaddyProcessKiller, type CaddyProcessStopResult, ConfigPattern, type ConstructGhostTunnelIpUrlInput, ConstructGhostTunnelUrlInput, type CreateVercelGhostTunnelHandlerOptions, DEFAULT_GHOST_TUNNEL_IP_TRANSPORT_TTL_SECONDS, DEFAULT_GHOST_TUNNEL_RESPONSE_TTL_SECONDS, DEFAULT_GHOST_TUNNEL_TRANSPORT_QUERY_PARAM, DEFAULT_RELAY_ALLOWED_TARGET_HOSTS, DEFAULT_RELAY_BLOCKED_PORTS, DEFAULT_RELAY_LIMITS, DEFAULT_RELAY_TARGET_POLICY, type DetectedDevCommand, type DetectedDevService, DevHostEntry, type DoctorResult, type DomainRoute, type DomainRouteOptions, type FindAvailablePortOptions, type GhostTunnelAgent, type GhostTunnelAgentOptions, GhostTunnelConfig, type GhostTunnelHttpResponse, type GhostTunnelIpTransportClaim, GhostTunnelOptions, type GhostTunnelQueuedRequest, type GhostTunnelQueuedResponse, GhostTunnelRoute, type GhostTunnelRouteHeartbeat, type GhostTunnelStore, type GhostTunnelStoreEnv, GhostTunnelTransportConfig, GhostTunnelTransportOptions, type InitOptions, type InitResult, LOCALGHOST_ACTIVITY_VERSION, LOCALGHOST_AGENT_GUIDE, LOCALGHOST_GHOST_TUNNEL_FILE, LOCALGHOST_PACKAGE_NAME, LOCALGHOST_REGISTRY_FILE, LOCALGHOST_REGISTRY_LOCK_FILE, LOCALGHOST_STATE_FILE, LOCALGHOST_VERSION, type LocalghostActivity, type LocalghostContext, type LocalghostContextOptions, type LocalghostEnvironment, type LocalghostLease, type LocalghostPackageManager, type LocalghostProjectConfig, type LocalghostProjectConfigResult, type LocalghostRegistry, type LocalghostRegistryData, type LocalghostRegistryEntry, type LocalghostRegistryOptions, type LocalghostRunMode, type LocalghostRunRecord, type LocalghostServiceOptions, type LocalghostSetupRecord, type LocalghostState, type LocalghostStateAction, type PackageManager, type PortAvailabilityCheck, ReadDevHostsOptions, type ReadGhostTunnelOptions, type RedisGhostTunnelEnvResolution, type RedisGhostTunnelStoreOptions, type RegisterLocalghostRunInput, type RegisterLocalghostSetupInput, type RelayAccessMode, type RelayLimits, type RelayLocalTarget, type RelayOfflineResponse, type RelayProtocol, type RelayRouteClaim, type RelayRouteRegistrationInput, type RelayTargetPolicy, type RemoveSystemHostsResult, type ResolveGhostTunnelIpRedirectInput, type ResolveGhostTunnelRequestInput, ResolvedDevHostsPath, type ResolvedGhostTunnelIpRedirect, type ResolvedGhostTunnelRequest, type ServeGhostTunnelLocalRequestInput, type SignedGhostTunnelIpTransportClaim, type SignedRelayRouteClaim, UPDATE_CHECK_CACHE_TTL_MS, UPDATE_CHECK_NOTIFY_TTL_MS, UPDATE_CHECK_TIMEOUT_MS, type UpdateCheckCache, type UpdateCheckResult, type UpdateSystemHostsResult, type VercelGhostTunnelRequestLike, type VercelGhostTunnelResponseLike, type WriteLocalghostStateInput, assertExactRelayHost, assertLocalDevelopment, assertRelayLocalTarget, authenticateRelayAgentToken, canonicalizeLocalghostProjectCwd, checkCaddy, checkForUpdate, compareVersions, constructGhostTunnelIpUrl, createGhostTunnelQueuedRequest, createGhostTunnelRouteHeartbeat, createLocalghostRegistry, createMemoryGhostTunnelStore, createRedisGhostTunnelStore, createRedisGhostTunnelStoreFromEnv, createRelayRouteRegistration, createVercelGhostTunnelHandler, decodeGhostTunnelBody, defineLocalghostConfig, detectDevCommand, detectDevPackageManager, detectDevServices, detectPackageManager, encodeGhostTunnelBody, findAvailablePort, findGhostTunnelEntry, formatDetectedDevCommand, formatDetectedDevServices, formatDomainRoutes, formatGhostTunnel, formatLocalghostAgentGuide, formatUpdateMessage, getCaddyfilePath, getDomainRoutes, getGhostTunnelPath, getLocalghostActivityPath, getLocalghostRegistryRoot, getLocalghostStatePath, getProductionEnvKeys, getProductionReason, getSystemHostsPath, getUpdateCheckCachePath, initLocalghost, isNewerVersion, isPortAvailable, isProcessRunning, isProductionLike, isRelayRouteActive, isUpdateCheckDisabled, listGhostTunnelEntries, listLocalghostRuns, listLocalghostSetups, markUpdateNotified, maybeNotifyAboutUpdate, packageAddCommand, packageRunCommand, patchLocalghostState, pruneLocalghostActivity, readGhostTunnelEntries, readLocalghostActivity, readLocalghostProjectConfig, readLocalghostState, redactRelayHeaders, redactRelayLogUrl, registerLocalghostRun, registerLocalghostSetup, removeManagedBlock, removeSystemHosts, renderCaddyfile, renderCompactLocalghostBanner, renderGhostTunnelRelayOfflineResponse, renderGhostTunnelRouteMissingResponse, renderHostsBlock, renderLocalghostBanner, renderRelayOfflineResponse, resolveGhostTunnelIpRedirect, resolveGhostTunnelPath, resolveGhostTunnelRequest, resolveLocalghostContext, resolveRedisGhostTunnelEnv, runCaddy, runDoctor, serveGhostTunnelLocalRequest, shouldNotifyAboutUpdate, signGhostTunnelIpTransportClaim, signRelayRouteClaim, startCaddy, startGhostTunnelAgent, stopCaddyProcesses, stripRelayForwardHeaders, trustCaddy, unregisterLocalghostRun, unregisterLocalghostSetup, updateSystemHosts, upsertManagedBlock, validateCaddyfile, verifyGhostTunnelIpTransportClaim, verifyRelayRouteClaim, writeCaddyfile, writeLocalghostActivity, writeLocalghostState };
|
|
725
|
+
export { type AcquireLocalghostPortOptions, type ActiveRelayRoute, type CaddyModeOptions, type CaddyProcessKiller, type CaddyProcessStopResult, ConfigPattern, type ConstructGhostTunnelIpUrlInput, ConstructGhostTunnelUrlInput, type CreateVercelGhostTunnelHandlerOptions, DEFAULT_GHOST_TUNNEL_IP_TRANSPORT_TTL_SECONDS, DEFAULT_GHOST_TUNNEL_RESPONSE_TTL_SECONDS, DEFAULT_GHOST_TUNNEL_TRANSPORT_QUERY_PARAM, DEFAULT_RELAY_ALLOWED_TARGET_HOSTS, DEFAULT_RELAY_BLOCKED_PORTS, DEFAULT_RELAY_LIMITS, DEFAULT_RELAY_TARGET_POLICY, type DetectedDevCommand, type DetectedDevService, DevHostEntry, type DoctorOptions, type DoctorResult, type DomainRoute, type DomainRouteOptions, type FindAvailablePortOptions, type GhostTunnelAgent, type GhostTunnelAgentOptions, GhostTunnelConfig, type GhostTunnelHttpResponse, type GhostTunnelIpTransportClaim, GhostTunnelOptions, type GhostTunnelQueuedRequest, type GhostTunnelQueuedResponse, GhostTunnelRoute, type GhostTunnelRouteHeartbeat, type GhostTunnelStore, type GhostTunnelStoreEnv, GhostTunnelTransportConfig, GhostTunnelTransportOptions, type InitOptions, type InitResult, LOCALGHOST_ACTIVITY_VERSION, LOCALGHOST_AGENT_GUIDE, LOCALGHOST_GHOST_TUNNEL_FILE, LOCALGHOST_PACKAGE_NAME, LOCALGHOST_REGISTRY_FILE, LOCALGHOST_REGISTRY_LOCK_FILE, LOCALGHOST_STATE_FILE, LOCALGHOST_VERSION, type LocalghostActivity, type LocalghostContext, type LocalghostContextOptions, type LocalghostEnvironment, type LocalghostLease, type LocalghostPackageManager, type LocalghostProjectConfig, type LocalghostProjectConfigResult, type LocalghostRegistry, type LocalghostRegistryData, type LocalghostRegistryEntry, type LocalghostRegistryOptions, type LocalghostRunMode, type LocalghostRunRecord, type LocalghostServiceOptions, type LocalghostSetupRecord, type LocalghostState, type LocalghostStateAction, type PackageManager, type PortAvailabilityCheck, ReadDevHostsOptions, type ReadGhostTunnelOptions, type RedisGhostTunnelEnvResolution, type RedisGhostTunnelStoreOptions, type RegisterLocalghostRunInput, type RegisterLocalghostSetupInput, type RelayAccessMode, type RelayLimits, type RelayLocalTarget, type RelayOfflineResponse, type RelayProtocol, type RelayRouteClaim, type RelayRouteRegistrationInput, type RelayTargetPolicy, type RemoveSystemHostsResult, type ResolveGhostTunnelIpRedirectInput, type ResolveGhostTunnelRequestInput, ResolvedDevHostsPath, type ResolvedGhostTunnelIpRedirect, type ResolvedGhostTunnelRequest, type ServeGhostTunnelLocalRequestInput, type SignedGhostTunnelIpTransportClaim, type SignedRelayRouteClaim, UPDATE_CHECK_CACHE_TTL_MS, UPDATE_CHECK_NOTIFY_TTL_MS, UPDATE_CHECK_TIMEOUT_MS, type UpdateCheckCache, type UpdateCheckResult, type UpdateSystemHostsResult, type VercelGhostTunnelRequestLike, type VercelGhostTunnelResponseLike, type WriteLocalghostStateInput, assertExactRelayHost, assertLocalDevelopment, assertRelayLocalTarget, authenticateRelayAgentToken, canonicalizeLocalghostProjectCwd, checkCaddy, checkForUpdate, compareVersions, constructGhostTunnelIpUrl, createGhostTunnelQueuedRequest, createGhostTunnelRouteHeartbeat, createLocalghostRegistry, createMemoryGhostTunnelStore, createRedisGhostTunnelStore, createRedisGhostTunnelStoreFromEnv, createRelayRouteRegistration, createVercelGhostTunnelHandler, decodeGhostTunnelBody, defineLocalghostConfig, detectDevCommand, detectDevPackageManager, detectDevServices, detectPackageManager, encodeGhostTunnelBody, findAvailablePort, findGhostTunnelEntry, formatDetectedDevCommand, formatDetectedDevServices, formatDomainRoutes, formatGhostTunnel, formatLocalghostAgentGuide, formatUpdateMessage, getCaddyfilePath, getDomainRoutes, getGhostTunnelPath, getLocalghostActivityPath, getLocalghostRegistryRoot, getLocalghostStatePath, getProductionEnvKeys, getProductionReason, getSystemHostsPath, getUpdateCheckCachePath, initLocalghost, isNewerVersion, isPortAvailable, isProcessRunning, isProductionLike, isRelayRouteActive, isUpdateCheckDisabled, listGhostTunnelEntries, listLocalghostRuns, listLocalghostSetups, markUpdateNotified, maybeNotifyAboutUpdate, packageAddCommand, packageRunCommand, patchLocalghostState, pruneLocalghostActivity, readGhostTunnelEntries, readLocalghostActivity, readLocalghostProjectConfig, readLocalghostState, redactRelayHeaders, redactRelayLogUrl, registerLocalghostRun, registerLocalghostSetup, removeManagedBlock, removeSystemHosts, renderCaddyfile, renderCompactLocalghostBanner, renderGhostTunnelRelayOfflineResponse, renderGhostTunnelRouteMissingResponse, renderHostsBlock, renderLocalghostBanner, renderRelayOfflineResponse, resolveGhostTunnelIpRedirect, resolveGhostTunnelPath, resolveGhostTunnelRequest, resolveLocalghostContext, resolveRedisGhostTunnelEnv, runCaddy, runDoctor, serveGhostTunnelLocalRequest, shouldNotifyAboutUpdate, signGhostTunnelIpTransportClaim, signRelayRouteClaim, signalManagedProcess, signalManagedProcessPid, startCaddy, startGhostTunnelAgent, stopCaddyProcesses, stripRelayForwardHeaders, trustCaddy, unregisterLocalghostRun, unregisterLocalghostSetup, updateSystemHosts, upsertManagedBlock, validateCaddyfile, verifyGhostTunnelIpTransportClaim, verifyRelayRouteClaim, writeCaddyfile, writeLocalghostActivity, writeLocalghostState };
|
package/dist/index.js
CHANGED
|
@@ -80,6 +80,7 @@ function registerLocalghostRun(input, path = getLocalghostActivityPath()) {
|
|
|
80
80
|
...input.configPath ? { configPath: input.configPath } : {},
|
|
81
81
|
...input.caddyfilePath ? { caddyfilePath: input.caddyfilePath } : {},
|
|
82
82
|
...input.caddyPid ? { caddyPid: input.caddyPid } : {},
|
|
83
|
+
...input.caddyPgid ? { caddyPgid: input.caddyPgid } : {},
|
|
83
84
|
...input.childPid ? { childPid: input.childPid } : {},
|
|
84
85
|
...input.childCommand ? { childCommand: input.childCommand } : {},
|
|
85
86
|
...typeof input.https === "boolean" ? { https: input.https } : {},
|
|
@@ -301,7 +302,8 @@ Use \`localghost dev\` only when the Caddy proxy should run without starting the
|
|
|
301
302
|
- \`localghost repair\`: repair managed hosts and Caddy setup.
|
|
302
303
|
- \`localghost ps --json\`: inspect Localghost-managed repositories, instances, and ports.
|
|
303
304
|
- \`localghost routes\`: inspect hostname-to-port routing.
|
|
304
|
-
- \`localghost doctor\`: check machine prerequisites.
|
|
305
|
+
- \`localghost doctor\`: check machine prerequisites, ports, and registry state.
|
|
306
|
+
- \`localghost repair --reallocate-port\`: move an occupied project port to a stable available port.
|
|
305
307
|
|
|
306
308
|
## Configuration
|
|
307
309
|
|
|
@@ -1635,7 +1637,8 @@ async function runCaddy(path) {
|
|
|
1635
1637
|
function startCaddy(path) {
|
|
1636
1638
|
return execa("caddy", ["run", "--config", path], {
|
|
1637
1639
|
cwd: dirname3(path),
|
|
1638
|
-
stdio: caddyStdio()
|
|
1640
|
+
stdio: caddyStdio(),
|
|
1641
|
+
detached: process.platform !== "win32"
|
|
1639
1642
|
});
|
|
1640
1643
|
}
|
|
1641
1644
|
function stopCaddyProcesses(pids, killProcess = (pid, signal) => process.kill(pid, signal)) {
|
|
@@ -1816,6 +1819,18 @@ function createLocalghostRegistry(options = {}) {
|
|
|
1816
1819
|
lockPath,
|
|
1817
1820
|
ownerToken,
|
|
1818
1821
|
read: readRegistry,
|
|
1822
|
+
async prune() {
|
|
1823
|
+
const releaseLock = await lock();
|
|
1824
|
+
try {
|
|
1825
|
+
const registry = await readRegistry();
|
|
1826
|
+
const before = registry.leases.length;
|
|
1827
|
+
pruneRegistry(registry, now(), isRunning);
|
|
1828
|
+
await writeRegistry(registry);
|
|
1829
|
+
return { removedLeases: before - registry.leases.length };
|
|
1830
|
+
} finally {
|
|
1831
|
+
await releaseLock();
|
|
1832
|
+
}
|
|
1833
|
+
},
|
|
1819
1834
|
async acquirePort(acquireOptions) {
|
|
1820
1835
|
const projectCwd = canonicalizeLocalghostProjectCwd(acquireOptions.projectCwd ?? cwd);
|
|
1821
1836
|
if (!acquireOptions.instanceKey) throw new Error("instanceKey is required");
|
|
@@ -2126,11 +2141,52 @@ async function checkCaddy() {
|
|
|
2126
2141
|
};
|
|
2127
2142
|
}
|
|
2128
2143
|
}
|
|
2129
|
-
async function runDoctor() {
|
|
2144
|
+
async function runDoctor(options = {}) {
|
|
2130
2145
|
const caddy = await checkCaddy();
|
|
2146
|
+
const cwd = options.cwd ?? process.cwd();
|
|
2147
|
+
const registry = createLocalghostRegistry({ cwd });
|
|
2148
|
+
const data = await registry.read();
|
|
2149
|
+
const now = Date.now();
|
|
2150
|
+
const staleLeases = data.leases.filter((lease) => lease.expiresAt <= now || !isProcessRunning(lease.pid)).map(({ projectCwd, instanceKey, port, pid }) => ({ projectCwd, instanceKey, port, pid }));
|
|
2151
|
+
const allocationsByPort = /* @__PURE__ */ new Map();
|
|
2152
|
+
for (const allocation of data.allocations) {
|
|
2153
|
+
const projects = allocationsByPort.get(allocation.port) ?? [];
|
|
2154
|
+
projects.push(`${allocation.projectCwd}#${allocation.instanceKey}`);
|
|
2155
|
+
allocationsByPort.set(allocation.port, projects);
|
|
2156
|
+
}
|
|
2157
|
+
const duplicateAllocations = [...allocationsByPort.entries()].filter(([, projects]) => projects.length > 1).map(([port, projects]) => ({ port, projects }));
|
|
2158
|
+
let configured;
|
|
2159
|
+
let available;
|
|
2160
|
+
try {
|
|
2161
|
+
const context = await resolveLocalghostContext({
|
|
2162
|
+
cwd,
|
|
2163
|
+
...options.configFiles ? { configFiles: options.configFiles } : {},
|
|
2164
|
+
...options.configPattern ? { configPattern: options.configPattern } : {},
|
|
2165
|
+
dynamicPort: false
|
|
2166
|
+
});
|
|
2167
|
+
configured = context.requestedPort;
|
|
2168
|
+
available = await isPortAvailable(configured);
|
|
2169
|
+
} catch {
|
|
2170
|
+
}
|
|
2171
|
+
const currentProjectCwd = canonicalizeLocalghostProjectCwd(cwd);
|
|
2172
|
+
const currentAllocation = data.allocations.find((allocation) => allocation.projectCwd === currentProjectCwd);
|
|
2131
2173
|
return {
|
|
2132
|
-
ok: caddy.found,
|
|
2133
|
-
caddy
|
|
2174
|
+
ok: caddy.found && available !== false && staleLeases.length === 0 && duplicateAllocations.length === 0,
|
|
2175
|
+
caddy,
|
|
2176
|
+
ports: {
|
|
2177
|
+
...configured !== void 0 ? { configured } : {},
|
|
2178
|
+
...available !== void 0 ? { available } : {},
|
|
2179
|
+
registryPath: registry.registryPath,
|
|
2180
|
+
staleLeases,
|
|
2181
|
+
duplicateAllocations,
|
|
2182
|
+
...currentAllocation ? {
|
|
2183
|
+
currentAllocation: {
|
|
2184
|
+
projectCwd: currentAllocation.projectCwd,
|
|
2185
|
+
instanceKey: currentAllocation.instanceKey,
|
|
2186
|
+
port: currentAllocation.port
|
|
2187
|
+
}
|
|
2188
|
+
} : {}
|
|
2189
|
+
}
|
|
2134
2190
|
};
|
|
2135
2191
|
}
|
|
2136
2192
|
|
|
@@ -2471,6 +2527,25 @@ function initLocalghost(options = {}) {
|
|
|
2471
2527
|
};
|
|
2472
2528
|
}
|
|
2473
2529
|
|
|
2530
|
+
// src/process.ts
|
|
2531
|
+
function signalManagedProcessPid(pid, signal, killProcess = (value, processSignal) => process.kill(value, processSignal)) {
|
|
2532
|
+
if (typeof pid !== "number" || !Number.isInteger(pid) || pid < 1) return false;
|
|
2533
|
+
try {
|
|
2534
|
+
killProcess(process.platform === "win32" ? pid : -pid, signal);
|
|
2535
|
+
return true;
|
|
2536
|
+
} catch (error) {
|
|
2537
|
+
if (error instanceof Error && "code" in error && error.code === "ESRCH") return false;
|
|
2538
|
+
throw error;
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
function signalManagedProcess(child, signal) {
|
|
2542
|
+
if (process.platform === "win32") {
|
|
2543
|
+
if (!child.killed) child.kill(signal);
|
|
2544
|
+
return true;
|
|
2545
|
+
}
|
|
2546
|
+
return signalManagedProcessPid(child.pid, signal);
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2474
2549
|
// src/routes.ts
|
|
2475
2550
|
var ansi = {
|
|
2476
2551
|
cyan: "\x1B[36m",
|
|
@@ -2790,7 +2865,7 @@ import { existsSync as existsSync7, mkdirSync as mkdirSync3, readFileSync as rea
|
|
|
2790
2865
|
import { homedir as homedir3 } from "os";
|
|
2791
2866
|
import { dirname as dirname4, join as join10 } from "path";
|
|
2792
2867
|
var LOCALGHOST_PACKAGE_NAME = "@hamedb89/localghost";
|
|
2793
|
-
var LOCALGHOST_VERSION = "0.
|
|
2868
|
+
var LOCALGHOST_VERSION = "0.3.0";
|
|
2794
2869
|
var UPDATE_CHECK_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2795
2870
|
var UPDATE_CHECK_NOTIFY_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
2796
2871
|
var UPDATE_CHECK_TIMEOUT_MS = 900;
|
|
@@ -3077,6 +3152,8 @@ export {
|
|
|
3077
3152
|
shouldNotifyAboutUpdate,
|
|
3078
3153
|
signGhostTunnelIpTransportClaim,
|
|
3079
3154
|
signRelayRouteClaim,
|
|
3155
|
+
signalManagedProcess,
|
|
3156
|
+
signalManagedProcessPid,
|
|
3080
3157
|
startCaddy,
|
|
3081
3158
|
startGhostTunnelAgent,
|
|
3082
3159
|
stopCaddyProcesses,
|