@stacksjs/rpx
Version:
A modern and smart reverse proxy.
77 lines (76 loc) • 3.81 kB
TypeScript
import { execSync } from 'node:child_process';
import type { MultiProxyConfig, PathRewrite, ProxyConfigs, ProxyOption, ProxyOptions, SingleProxyConfig } from './types';
/**
* Get sudo password from environment variable if set
*/
export declare function getSudoPassword(): string | undefined;
/** True when the process can write system paths without `sudo` (e.g. rpx daemon started via sudo). */
export declare function isProcessElevated(): boolean;
/**
* Ensure rpx may perform its privileged setup work without hiding a prompt in
* daemon startup. Normal dev-server probes are non-interactive and return
* false immediately. Explicit setup commands opt into one visible `sudo -v`
* prompt, which also seeds sudo's credential cache for the daemon launch.
*/
export declare function authorizeSystemAccess(options?: SystemAuthorizationOptions): boolean;
/**
* Execute a command with sudo, using SUDO_PASSWORD if available
*/
export declare function execSudoSync(command: string): string;
export declare function debugLog(category: string, message: string, verbose?: boolean): void;
/**
* Whether the proxy's listeners should set `reusePort`. Off by default: rpx is a
* single-instance local-dev proxy, and one instance gains nothing from
* `SO_REUSEPORT` while losing the helpful "port 443 already in use" guard.
*
* Opt in with `RPX_REUSE_PORT=1` when running **multiple** rpx instances behind a
* process manager (systemd/pm2/k8s) on **Linux**, where the kernel load-balances
* accepted connections across them for multi-core scaling. It is a no-op on
* macOS/BSD, whose `SO_REUSEPORT` does not load-balance across processes — so
* rpx never spawns a worker cluster itself; scaling is left to the OS + your
* supervisor, which is where it belongs for a dev proxy.
*/
export declare function shouldReusePort(): boolean;
export declare function redactSensitive(value: unknown): unknown;
export declare function safeStringify(value: unknown, space?: number): string;
/**
* Extracts hostnames from proxy configuration
*/
export declare function extractHostname(options: ProxyOption | ProxyOptions): string[];
export declare function isValidRootCA(value: unknown): value is RootCA;
export declare function getPrimaryDomain(options?: ProxyOption | ProxyOptions): string;
/**
* Type guard for multi-proxy configuration
*/
export declare function isMultiProxyConfig(options: ProxyConfigs | ProxyOptions): options is MultiProxyConfig;
/**
* Type guard to check if options are for multi-proxy configuration
*/
export declare function isMultiProxyOptions(options: ProxyOption | ProxyOptions): options is MultiProxyConfig;
/**
* Type guard to check if options are for single-proxy configuration
*/
export declare function isSingleProxyOptions(options: ProxyOption | ProxyOptions): options is SingleProxyConfig;
export declare function isSingleProxyConfig(options: ProxyConfigs | ProxyOptions): options is SingleProxyConfig;
/**
* Resolve a path against a list of `pathRewrites`.
*
* Returns `null` if no rewrite matches; otherwise returns `{ targetHost, targetPath }`
* with the prefix preserved by default (or stripped when `stripPrefix === true`).
*
* Matching rule: rewrite matches if `pathname` is exactly `from` OR starts with
* `from + '/'`. So `/api` matches `/api`, `/api/`, `/api/cart` — but not `/apidocs`.
*/
export declare function resolvePathRewrite(pathname: string, rewrites: PathRewrite[] | undefined): { targetHost: string, targetPath: string } | null;
/**
* Safely delete a file if it exists
*/
export declare function safeDeleteFile(filePath: string, verbose?: boolean): Promise<void>;
export declare interface SystemAuthorizationOptions {
interactive?: boolean
exec?: typeof execSync
}
declare interface RootCA {
certificate: string
privateKey: string
}