/** * Core interfaces for @push.rocks/smartserve * Uses Web Standards API (Request/Response) for cross-platform compatibility */ // ============================================================================= // HTTP Types // ============================================================================= export type THttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'ALL'; export type TRuntime = 'node' | 'deno' | 'bun'; // ============================================================================= // Request Context // ============================================================================= /** * Request context passed to handlers and interceptors * Wraps Web Standard Request with additional utilities */ export interface IRequestContext { /** Original Web Standards Request */ readonly request: Request; /** Parsed request body (typed) */ readonly body: TBody; /** URL path parameters extracted from route */ readonly params: Record; /** URL query parameters */ readonly query: Record; /** Request headers accessor */ readonly headers: Headers; /** Matched route path pattern */ readonly path: string; /** HTTP method */ readonly method: THttpMethod; /** Full URL object */ readonly url: URL; /** Runtime environment */ readonly runtime: TRuntime; /** Route-specific state bag for passing data between interceptors */ state: Record; } // ============================================================================= // Interceptor Types // ============================================================================= /** * Request interceptor - runs BEFORE the handler * Can: * - Return modified context to continue * - Return Response to short-circuit * - Return void/undefined to continue with original context * - Throw to trigger error handling */ export type TRequestInterceptor = ( ctx: IRequestContext ) => Promise | Response | void> | IRequestContext | Response | void; /** * Response interceptor - runs AFTER the handler * Can: * - Return modified response data * - Return a Response object directly */ export type TResponseInterceptor = ( response: TRes, ctx: IRequestContext ) => Promise | TRes | Response; /** * Guard function - simplified boolean check for authorization * Returns true to allow, false to reject with 403 */ export type TGuardFunction = ( ctx: IRequestContext ) => Promise | boolean; /** * Combined interceptor options for @Intercept decorator */ export interface IInterceptOptions { /** Request interceptors (run before handler) */ request?: TRequestInterceptor | TRequestInterceptor[]; /** Response interceptors (run after handler) */ response?: TResponseInterceptor | TResponseInterceptor[]; } /** * Options for @Guard decorator */ export interface IGuardOptions { /** Custom response when guard rejects (default: 403 Forbidden) */ onReject?: (ctx: IRequestContext) => Response | Promise; } // ============================================================================= // Route Handler Types // ============================================================================= /** * Route handler function signature */ export type TRouteHandler = ( ctx: IRequestContext ) => Promise | TRes; /** * Options for method decorators (@Get, @Post, etc.) */ export interface IMethodOptions { /** Path segment (appended to class route) */ path?: string; /** Content-Type for response */ contentType?: string; /** HTTP status code for successful response */ statusCode?: number; } /** * Options for @Route class decorator */ export interface IRouteOptions { /** Base path for all routes in this controller */ path?: string; } // ============================================================================= // WebSocket Types // ============================================================================= /** * WebSocket message types */ export interface IWebSocketMessage { type: 'text' | 'binary'; text?: string; data?: Uint8Array; size: number; } /** * WebSocket peer connection */ export interface IWebSocketPeer { /** Unique connection ID */ id: string; /** Connection URL */ url: string; /** WebSocket ready state */ readyState: 0 | 1 | 2 | 3; /** Negotiated subprotocol */ protocol: string; /** Negotiated extensions */ extensions: string; /** Send text message */ send(data: string): void; /** Send binary message */ sendBinary(data: Uint8Array | ArrayBuffer): void; /** Close connection */ close(code?: number, reason?: string): void; /** Send ping */ ping(data?: Uint8Array): void; /** Force close without handshake */ terminate(): void; /** Request context from upgrade */ context: IRequestContext; /** Custom per-peer data storage */ data: Map; } /** * WebSocket event hooks */ export interface IWebSocketHooks { onOpen?: (peer: IWebSocketPeer) => void | Promise; onMessage?: (peer: IWebSocketPeer, message: IWebSocketMessage) => void | Promise; onClose?: (peer: IWebSocketPeer, code: number, reason: string) => void | Promise; onError?: (peer: IWebSocketPeer, error: Error) => void | Promise; onPing?: (peer: IWebSocketPeer, data: Uint8Array) => void | Promise; onPong?: (peer: IWebSocketPeer, data: Uint8Array) => void | Promise; } // ============================================================================= // Server Configuration // ============================================================================= /** * TLS/SSL configuration */ export interface ITLSConfig { /** Certificate (PEM format) */ cert: string | Uint8Array; /** Private key (PEM format) */ key: string | Uint8Array; /** CA chain (PEM format) */ ca?: string | Uint8Array; /** ALPN protocols */ alpnProtocols?: string[]; /** Minimum TLS version */ minVersion?: 'TLSv1.2' | 'TLSv1.3'; /** Passphrase for encrypted key */ passphrase?: string; } /** * Keep-alive configuration */ export interface IKeepAliveConfig { enabled: boolean; timeout?: number; maxRequests?: number; } /** * Static file serving options */ export interface IStaticOptions { /** Root directory path */ root: string; /** Index files to look for */ index?: string[]; /** How to handle dotfiles */ dotFiles?: 'allow' | 'deny' | 'ignore'; /** Generate ETags */ etag?: boolean; /** Add Last-Modified header */ lastModified?: boolean; /** Cache-Control header value or function */ cacheControl?: string | ((path: string) => string); /** File extensions to try */ extensions?: string[]; /** Enable directory listing */ directoryListing?: boolean | IDirectoryListingOptions; } /** * Directory listing options */ export interface IDirectoryListingOptions { /** Custom template function */ template?: (files: IFileEntry[]) => string | Response; /** Show hidden files */ showHidden?: boolean; /** Sort field */ sortBy?: 'name' | 'size' | 'modified'; /** Sort order */ sortOrder?: 'asc' | 'desc'; } /** * File entry for directory listing */ export interface IFileEntry { name: string; path: string; isDirectory: boolean; size: number; modified: Date; } /** * WebDAV configuration */ export interface IWebDAVConfig { /** Root directory path */ root: string; /** Authentication handler */ auth?: (ctx: IRequestContext) => boolean | Promise; /** Enable locking */ locking?: boolean; } /** * Main server configuration */ export interface ISmartServeOptions { /** Port to listen on */ port: number; /** Hostname to bind to */ hostname?: string; /** TLS configuration for HTTPS */ tls?: ITLSConfig; /** WebSocket configuration */ websocket?: IWebSocketHooks; /** Static file serving */ static?: IStaticOptions | string; /** WebDAV configuration */ webdav?: IWebDAVConfig; /** Connection timeout (ms) */ connectionTimeout?: number; /** Keep-alive settings */ keepAlive?: IKeepAliveConfig; /** Global error handler */ onError?: (error: Error, request?: Request) => Response | Promise; } // ============================================================================= // Server Instance // ============================================================================= /** * Server statistics */ export interface IServerStats { uptime: number; requestsTotal: number; requestsActive: number; connectionsTotal: number; connectionsActive: number; bytesReceived: number; bytesSent: number; } /** * Running server instance */ export interface ISmartServeInstance { /** Listening port */ port: number; /** Bound hostname */ hostname: string; /** Is HTTPS enabled */ secure: boolean; /** Runtime environment */ runtime: TRuntime; /** Stop the server */ stop(): Promise; /** Get server statistics */ stats(): IServerStats; } // ============================================================================= // Connection Info // ============================================================================= /** * Connection information */ export interface IConnectionInfo { remoteAddr: string; remotePort: number; localAddr: string; localPort: number; encrypted: boolean; tlsVersion?: string; }