@stacksjs/rpx
Version:
A modern and smart reverse proxy.
80 lines (79 loc) • 3.31 kB
TypeScript
import * as path from 'node:path';
import type { BasicAuthConfig, LoadBalancerConfig, PathRewrite, ProxyFrom, StaticRouteConfig } from './types';
/**
* Default location for the registry directory. The daemon's PID file and log
* sit alongside it under `~/.stacks/rpx/`.
*/
export declare function getRegistryDir(): string;
/**
* Validate an entry id. Rejects anything that could escape the registry dir
* (path traversal, slashes) or that would round-trip oddly through a filename.
*/
export declare function isValidId(id: string): boolean;
/**
* Check whether a PID is alive. `kill(pid, 0)` returns without sending a
* signal but throws ESRCH if the process is gone — exactly the probe we need.
* EPERM means the process exists but we don't own it; treat as alive.
*/
export declare function isPidAlive(pid: number): boolean;
/**
* Atomically write an entry to disk.
*
* Writes to a temp file in the same directory, then renames into place. POSIX
* rename within the same filesystem is atomic, so a concurrent reader either
* sees the old file or the new file — never a half-written one.
*/
export declare function writeEntry(entry: RegistryEntry, dir?: string, verbose?: boolean): Promise<void>;
/**
* Remove an entry by id. No-op if the file is already gone.
*/
export declare function removeEntry(id: string, dir?: string, verbose?: boolean): Promise<void>;
/**
* Read a single entry by id. Returns `null` if missing or malformed (malformed
* files are deleted so they don't keep poisoning subsequent reads).
*/
export declare function readEntry(id: string, dir?: string, verbose?: boolean): Promise<RegistryEntry | null>;
/**
* Read all entries from the registry directory. Malformed files are pruned.
* This does NOT GC stale PIDs — call `gcStaleEntries` for that explicitly.
*/
export declare function readAll(dir?: string, verbose?: boolean): Promise<RegistryEntry[]>;
/**
* Remove entries whose writer PID is no longer alive. Returns the count of
* entries removed. Safe to call repeatedly; intended to run on daemon startup
* and on a slow timer (e.g. every 5s) while the daemon is up.
*/
export declare function gcStaleEntries(dir?: string, verbose?: boolean): Promise<number>;
/**
* Watch the registry directory and invoke `onChange` with the full current
* entry list whenever something changes. Events are debounced so a flurry of
* rapid writes (e.g. several `./buddy dev` invocations starting in parallel)
* triggers at most one rebuild.
*
* The watcher tolerates a missing directory at startup — it creates the dir
* before opening the watch, so the first `writeEntry` doesn't race the daemon.
*/
export declare function watchRegistry(onChange: (entries: RegistryEntry[]) => void | Promise<void>, opts?: WatchOptions & { dir?: string }): WatchHandle;
export declare interface RegistryEntry {
id: string
from?: ProxyFrom
to: string
path?: string
pid?: number
cwd?: string
createdAt: string
pathRewrites?: PathRewrite[]
cleanUrls?: boolean
changeOrigin?: boolean
static?: string | StaticRouteConfig
auth?: BasicAuthConfig
loadBalancer?: LoadBalancerConfig
}
export declare interface WatchHandle {
close: () => void
}
export declare interface WatchOptions {
debounceMs?: number
pollMs?: number
verbose?: boolean
}