UNPKG

@stacksjs/rpx

Version:

A modern and smart reverse proxy.

80 lines (79 loc) 3.31 kB
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 }