lacis
Version:
Zero-dependency TypeScript web framework
340 lines (325 loc) • 14.5 kB
TypeScript
import { S as ServerConfig, A as AdapterRequest, a as AdapterResponse, R as Request, b as Response, L as Locals, C as CorsConfig, M as MiddlewareCallback, c as SSEOptions, d as SSEClientOptions, e as SSEEventHandlers, f as SSEClient } from './index-BkN4XkvG.js';
export { g as Adapter, h as AdapterContext, i as ClusterConfig, j as CookieOptions, H as Handler, k as MiddlewareModule, l as MiddlewareType, N as NotFoundHook, P as PathMiddlewares, m as PlatformContext, n as RequestCookies, o as ResponseCookies, p as Route, q as RouteHandlers, r as SSEContext, s as ServerlessConfig, t as ServerlessMiddleware, u as ServerlessRoute, v as ShutdownHook, U as UploadedFile } from './index-BkN4XkvG.js';
import { Server, ServerResponse, IncomingMessage } from 'http';
interface VercelRequest {
url?: string;
method?: string;
headers: Record<string, string | string[] | undefined>;
cookies: Record<string, string>;
body?: any;
query?: Record<string, string | string[]>;
}
interface VercelResponse {
statusCode?: number;
headersSent: boolean;
status: (statusCode: number) => VercelResponse;
json: (body: any) => VercelResponse;
send: (body: any) => VercelResponse;
redirect: (statusOrUrl: string | number, url?: string) => VercelResponse;
setHeader: (name: string, value: string | string[]) => VercelResponse;
getHeader: (name: string) => string | string[] | undefined;
end: (data?: any) => void;
}
interface NetlifyEvent {
rawUrl: string;
rawQuery: string;
path: string;
httpMethod: string;
headers: Record<string, string | undefined>;
multiValueHeaders: Record<string, string[] | undefined>;
queryStringParameters: Record<string, string | undefined> | null;
multiValueQueryStringParameters: Record<string, string[] | undefined> | null;
body: string | null;
isBase64Encoded: boolean;
route?: string;
}
interface NetlifyContext {
callbackWaitsForEmptyEventLoop: boolean;
functionName: string;
functionVersion: string;
invokedFunctionArn: string;
memoryLimitInMB: string;
awsRequestId: string;
logGroupName: string;
logStreamName: string;
identity?: Record<string, any>;
clientContext?: Record<string, any>;
getRemainingTimeInMillis(): number;
}
interface NetlifyResponse {
statusCode: number;
headers?: Record<string, boolean | number | string>;
multiValueHeaders?: Record<string, readonly (boolean | number | string)[]>;
body?: string;
isBase64Encoded?: boolean;
}
type NetlifyHandler = (event: NetlifyEvent, context: NetlifyContext) => Promise<NetlifyResponse>;
type PlatformHandler = ((config?: ServerConfig) => Server) | ((req: AdapterRequest, res: AdapterResponse) => Promise<void>) | ((event: NetlifyEvent, context: NetlifyContext) => Promise<NetlifyResponse>);
interface MetricValue {
min: number;
max: number;
avg: number;
count: number;
sum: number;
p50?: number;
p90?: number;
p99?: number;
}
interface Metrics {
timestamp: number;
uptime: number;
requestCount: number;
activeRequests: number;
errorCount: number;
responseTimes: MetricValue;
statusCodes: Record<number, number>;
memory: {
rss: number;
heapTotal: number;
heapUsed: number;
external: number;
arrayBuffers: number;
};
cpu: {
usage: number;
system: number;
user: number;
};
systemLoad: number[];
systemMemory: {
total: number;
free: number;
used: number;
};
}
interface PerformanceData {
startTime: number;
requestCount: number;
activeRequests: number;
errorCount: number;
responseTimes: number[];
statusCodes: Record<number, number>;
responseTimesBucket: number[];
lastReport: number;
lastReset: number;
}
interface MonitorOptions {
sampleInterval?: number;
reportInterval?: number;
resetInterval?: number;
enableHistogram?: boolean;
logToConsole?: boolean;
thresholds?: {
cpu?: number;
memory?: number;
responseTime?: number;
errorRate?: number;
};
}
interface AlarmStatus {
cpu: boolean;
memory: boolean;
responseTime: boolean;
errorRate: boolean;
}
declare function getConfig(customConfig?: Partial<ServerConfig>): ServerConfig;
declare function createServer(routesDir: string, config?: ServerConfig): Promise<unknown>;
interface StandardSchema<Input = unknown, Output = Input> {
readonly "~standard": {
readonly version: 1;
readonly vendor: string;
readonly validate: (value: unknown) => StandardResult<Output> | Promise<StandardResult<Output>>;
readonly types?: {
readonly input: Input;
readonly output: Output;
};
};
}
type StandardResult<Output> = {
readonly value: Output;
readonly issues?: undefined;
} | {
readonly issues: ReadonlyArray<StandardIssue>;
};
interface StandardIssue {
readonly message: string;
readonly path?: ReadonlyArray<PropertyKey | {
readonly key: PropertyKey;
}>;
}
type InferOutput<T extends StandardSchema> = NonNullable<T["~standard"]["types"]>["output"];
type ValidatedRequest<TParams extends StandardSchema | undefined, TQuery extends StandardSchema | undefined, TBody extends StandardSchema | undefined> = Omit<Request, "params" | "query" | "body"> & {
params: TParams extends StandardSchema ? InferOutput<TParams> : Record<string, string> | undefined;
query: TQuery extends StandardSchema ? InferOutput<TQuery> : Record<string, string> | undefined;
body: TBody extends StandardSchema ? InferOutput<TBody> : () => Promise<Buffer>;
};
type ResponsesMap = Record<number, StandardSchema>;
type ResponseSink<T> = Pick<Response, "setHeader" | "cookies" | "end"> & {
json(data: T): void;
send(data: T): void;
};
type TypedResponse<R extends ResponsesMap> = Omit<Response, "status" | "json" | "send"> & {
status<S extends keyof R & number>(code: S): ResponseSink<InferOutput<R[S]>>;
json(data: InferOutput<R[keyof R & number]>): void;
send(data: InferOutput<R[keyof R & number]>): void;
raw: Response;
};
type UseMiddleware = (req: Request, res: Response) => unknown;
type LocalsOf<M> = M extends (...args: any[]) => infer R ? Extract<Awaited<R>, object> extends infer C ? [C] extends [never] ? {} : C : {} : {};
type MergedLocals<T extends readonly unknown[]> = T extends readonly [infer Head, ...infer Tail] ? LocalsOf<Head> & MergedLocals<Tail> : {};
interface HandlerMeta {
summary?: string;
description?: string;
tags?: string[];
deprecated?: boolean;
operationId?: string;
}
interface HandlerCacheOptions {
ttl: number;
maxSize?: number;
key?: (req: Request) => string;
}
interface DefineHandlerConfig<TParams extends StandardSchema | undefined = undefined, TQuery extends StandardSchema | undefined = undefined, TBody extends StandardSchema | undefined = undefined, TResponses extends ResponsesMap | undefined = undefined, TUse extends readonly UseMiddleware[] = readonly []> {
params?: TParams;
query?: TQuery;
body?: TBody;
responses?: TResponses;
validateResponses?: boolean;
use?: readonly [...TUse];
meta?: HandlerMeta;
cache?: HandlerCacheOptions;
handler: (req: ValidatedRequest<TParams, TQuery, TBody> & {
locals: Locals & MergedLocals<TUse>;
}, res: TResponses extends ResponsesMap ? TypedResponse<TResponses> : Response) => void | Promise<void>;
}
type DefinedHandler = ((req: Request, res: Response) => Promise<void>) & {
_defineHandler: DefineHandlerConfig<any, any, any, any, any>;
};
declare function defineHandler<TParams extends StandardSchema | undefined = undefined, TQuery extends StandardSchema | undefined = undefined, TBody extends StandardSchema | undefined = undefined, TResponses extends ResponsesMap | undefined = undefined, TUse extends readonly UseMiddleware[] = readonly []>(config: DefineHandlerConfig<TParams, TQuery, TBody, TResponses, TUse>): DefinedHandler;
declare function getRoutesDir(customDir?: string): string;
declare function createCorsMiddleware(config: CorsConfig): MiddlewareCallback;
interface RateLimitEntry {
count: number;
resetAt: number;
}
interface RateLimitStore {
get(key: string): RateLimitEntry | undefined | Promise<RateLimitEntry | undefined>;
set(key: string, entry: RateLimitEntry): void | Promise<void>;
delete(key: string): void | Promise<void>;
}
interface RateLimitOptions {
windowMs?: number;
max?: number;
message?: string;
keyGenerator?: (req: Request) => string;
store?: RateLimitStore;
}
declare function createInMemoryRateLimitStore(windowMs: number): RateLimitStore;
declare function createRateLimit(options?: RateLimitOptions): MiddlewareCallback;
interface CacheEntry {
body: any;
status: number;
contentType: string;
expiresAt: number;
}
interface CacheStore {
get(key: string): CacheEntry | undefined | Promise<CacheEntry | undefined>;
set(key: string, entry: CacheEntry): void | Promise<void>;
}
declare function defaultCacheKey(req: Request): string;
interface ResponseCacheOptions {
ttl: number;
methods?: string[];
maxSize?: number;
keyGenerator?: (req: Request) => string;
match?: (req: Request) => boolean;
exclude?: string | string[];
shouldCache?: (req: Request, res: Response) => boolean;
store?: CacheStore;
}
declare function createResponseCache(options: ResponseCacheOptions): MiddlewareCallback;
interface WithCacheOptions {
ttl: number;
maxSize?: number;
key?: (req: Request) => string;
store?: CacheStore;
}
declare function withCache(options: WithCacheOptions, handler: (req: Request, res: Response) => void | Promise<void>): (req: Request, res: Response) => Promise<void>;
declare function parseNDJSON(stream: ReadableStream<Uint8Array>): AsyncIterable<unknown>;
interface ResLike {
readonly writableEnded: boolean;
write(chunk: any): any;
end(data?: any): any;
writeHead(code: number, headers?: Record<string, string>): any;
on(event: string, cb: () => void): any;
}
declare class SSEContext {
private _res;
private _timeoutId;
constructor(_res: ResLike, timeout: number);
send(data: string): boolean;
json(data: any): boolean;
event(event: string, data: any): boolean;
comment(text: string): boolean;
id(id: string): boolean;
retry(ms: number): boolean;
close(comment?: string): void;
error(event: string, message: string, code?: number, details?: string): void;
}
declare function initSSE(res: ServerResponse, options?: SSEOptions): SSEContext;
/**
* Creates a Server-Sent Events (SSE) client that can handle both URL connections and existing SSE streams
* @param urlOrReq - URL to connect to or an existing IncomingMessage
* @param options - Configuration options for the SSE client
* @param handlers - Event handlers for the SSE connection
* @param req - Optional IncomingMessage to inherit headers from
* @returns A Promise resolving to an SSE client for URL connections, or an SSE client directly for existing connections
*/
declare function createSSEClient(urlOrReq: string | IncomingMessage, options?: SSEClientOptions, handlers?: SSEEventHandlers, req?: IncomingMessage): Promise<SSEClient> | SSEClient;
declare const HTTP_STATUS: {
OK: number;
CREATED: number;
NO_CONTENT: number;
BAD_REQUEST: number;
UNAUTHORIZED: number;
FORBIDDEN: number;
NOT_FOUND: number;
METHOD_NOT_ALLOWED: number;
CONFLICT: number;
UNPROCESSABLE_ENTITY: number;
TOO_MANY_REQUESTS: number;
INTERNAL_SERVER_ERROR: number;
SERVICE_UNAVAILABLE: number;
GATEWAY_TIMEOUT: number;
};
interface HttpError {
name: string;
code: number;
message: string;
details?: any;
expose: boolean;
log: boolean;
stack?: string;
}
declare function createHttpError(options: {
name?: string;
code?: number;
message?: string;
details?: any;
expose?: boolean;
log?: boolean;
}): HttpError;
declare function sendError(error: HttpError, res: ServerResponse): void;
declare function createBadRequestError(message?: string, details?: any): HttpError;
declare function createUnauthorizedError(message?: string, details?: any): HttpError;
declare function createForbiddenError(message?: string, details?: any): HttpError;
declare function createNotFoundError(message?: string, details?: any): HttpError;
declare function createMethodNotAllowedError(message?: string, details?: any): HttpError;
declare function createConflictError(message?: string, details?: any): HttpError;
declare function createValidationError(message?: string, details?: any): HttpError;
declare function createRateLimitError(message?: string, details?: any): HttpError;
declare function createInternalServerError(message?: string, details?: any): HttpError;
declare function createServiceUnavailableError(message?: string, details?: any): HttpError;
declare function createGatewayTimeoutError(message?: string, details?: any): HttpError;
declare function isHttpError(error: any): error is HttpError;
export { AdapterRequest, AdapterResponse, type AlarmStatus, type CacheEntry, type CacheStore, CorsConfig, type DefineHandlerConfig, type DefinedHandler, HTTP_STATUS, type HandlerCacheOptions, type HandlerMeta, type InferOutput, Locals, type MetricValue, type Metrics, MiddlewareCallback, type MonitorOptions, type NetlifyContext, type NetlifyEvent, type NetlifyHandler, type NetlifyResponse, type PerformanceData, type PlatformHandler, type RateLimitEntry, type RateLimitOptions, type RateLimitStore, Request, Response, type ResponseCacheOptions, SSEClient, SSEClientOptions, SSEEventHandlers, SSEOptions, ServerConfig, type StandardIssue, type StandardSchema, type ValidatedRequest, type VercelRequest, type VercelResponse, type WithCacheOptions, createBadRequestError, createConflictError, createCorsMiddleware, createForbiddenError, createGatewayTimeoutError, createHttpError, createInMemoryRateLimitStore, createInternalServerError, createMethodNotAllowedError, createNotFoundError, createRateLimit, createRateLimitError, createResponseCache, createSSEClient, createServer, createServiceUnavailableError, createUnauthorizedError, createValidationError, defaultCacheKey, defineHandler, getConfig, getRoutesDir, initSSE, isHttpError, parseNDJSON, sendError, withCache };