import type { VextApp } from "./app.js"; import type { VextRequest } from "./request.js"; import type { VextResponse } from "./response.js"; import type { RouteOptions } from "./app.js"; export type VextHookName = "request:start" | "route:matched" | "route:notFound" | "validation:success" | "validation:error" | "handler:before" | "handler:after" | "handler:error" | "response:before" | "response:after" | "error:beforeResponse" | "error:afterResponse" | "fetch:before" | "fetch:after" | "fetch:error" | "proxy:before" | "proxy:after" | "proxy:error" | "service:loaded" | "service:reloaded" | "service:beforeCall" | "service:afterCall" | "service:error" | "cache:hit" | "cache:miss" | "cache:write" | "cache:error" | "plugin:beforeSetup" | "plugin:afterSetup" | "plugin:error" | "routes:ready" | "openapi:beforeGenerate" | "openapi:afterGenerate" | "server:beforeListen" | "app:ready" | "app:close"; export interface VextRouteHookInfo { method: string; path: string; options?: RouteOptions; sourceFile?: string; } export interface VextValidationLocationResult { location: "param" | "query" | "header" | "body"; data: unknown; } export type VextResponseKind = "json" | "rawJson" | "text" | "stream"; export interface VextResponseBeforePatch { data?: unknown; status?: number; headers?: Record; } export interface VextErrorBeforeResponsePatch { body?: Record; status?: number; } export interface VextOpenAPIAfterGeneratePatch { document?: unknown; } export interface VextHookPayloadMap { "request:start": { req: VextRequest; requestId: string; method: string; path: string; matched?: boolean; }; "route:matched": { req: VextRequest; route: VextRouteHookInfo; params: Record; requestId: string; }; "route:notFound": { req: VextRequest; requestId: string; path: string; }; "validation:success": { req: VextRequest; route: VextRouteHookInfo; locationResults: VextValidationLocationResult[]; requestId: string; }; "validation:error": { req: VextRequest; route: VextRouteHookInfo; errors: Array<{ field: string; message: string; }>; requestId: string; }; "handler:before": { req: VextRequest; res: VextResponse; route: VextRouteHookInfo; requestId: string; }; "handler:after": { req: VextRequest; res: VextResponse; route: VextRouteHookInfo; requestId: string; durationMs: number; }; "handler:error": { req: VextRequest; res: VextResponse; route: VextRouteHookInfo; error: unknown; requestId: string; }; "response:before": { kind: VextResponseKind; data?: unknown; status: number; headers: Record; wrapped: boolean; requestId: string; }; "response:after": { kind: VextResponseKind; status: number; headers: Record; requestId: string; durationMs: number; }; "error:beforeResponse": { error: Error; status: number; body: Record; requestId: string; }; "error:afterResponse": { error: Error; status: number; requestId: string; }; "fetch:before": { url: string; method: string; headers: Headers; requestId?: string; init?: RequestInit & Record; }; "fetch:after": { url: string; method: string; response: Response; durationMs: number; requestId?: string; }; "fetch:error": { url: string; method: string; error: Error; requestId?: string; }; "proxy:before": { req: VextRequest; target?: string; url: string; method: string; headers: Headers; requestId: string; }; "proxy:after": { req: VextRequest; target?: string; status: number; requestId: string; }; "proxy:error": { req: VextRequest; target?: string; error: Error; requestId: string; }; "service:loaded": { name: string; instance: unknown; filePath: string; }; "service:reloaded": { name: string; instance: unknown; filePath: string; }; "service:beforeCall": { service: string; method: string; args: unknown[]; }; "service:afterCall": { service: string; method: string; args: unknown[]; result: unknown; }; "service:error": { service: string; method: string; args: unknown[]; error: unknown; }; "cache:hit": { req: VextRequest; route?: string; key: string; state: "hit" | "deduped"; metadata: unknown; }; "cache:miss": { req: VextRequest; route?: string; key?: string; state: "miss" | "skipped"; metadata?: unknown; }; "cache:write": { req: VextRequest; route?: string; key: string; state: "write"; metadata?: unknown; }; "cache:error": { req: VextRequest; route?: string; key?: string; state: "error"; metadata?: unknown; error: unknown; }; "plugin:beforeSetup": { plugin: string; sourceFile: string; builtin?: boolean; }; "plugin:afterSetup": { plugin: string; sourceFile: string; builtin?: boolean; durationMs: number; }; "plugin:error": { plugin: string; sourceFile: string; builtin?: boolean; durationMs?: number; error: unknown; }; "routes:ready": { count: number; routes: VextRouteHookInfo[]; collector?: unknown; }; "openapi:beforeGenerate": { routes: unknown[]; }; "openapi:afterGenerate": { routes: unknown[]; document: unknown; }; "server:beforeListen": { host: string; port: number; adapter: unknown; }; "app:ready": { app: VextApp; phase: "before" | "after"; }; "app:close": { app: VextApp; phase: "before" | "after"; }; } export type VextHookReturn = K extends "response:before" ? VextResponseBeforePatch | void : K extends "error:beforeResponse" ? VextErrorBeforeResponsePatch | void : K extends "openapi:afterGenerate" ? VextOpenAPIAfterGeneratePatch | unknown | void : void; export type VextHookHandler = (payload: VextHookPayloadMap[K]) => VextHookReturn | Promise>; export interface VextHooks { on(name: K, handler: VextHookHandler): () => void; has(name: VextHookName): boolean; } export interface VextInternalHooks extends VextHooks { emit(name: K, payload: VextHookPayloadMap[K]): Promise | undefined>; emitSafe(name: K, payload: VextHookPayloadMap[K]): Promise | undefined>; emitSync(name: K, payload: VextHookPayloadMap[K]): VextHookReturn | undefined; emitSafeSync(name: K, payload: VextHookPayloadMap[K]): VextHookReturn | undefined; }