import { IncomingMessage, ServerResponse } from 'node:http'; import { RequestHandler, Router, Application } from 'express'; import * as t from '@babel/types'; import { IncomingMessage as IncomingMessage$1, ServerResponse as ServerResponse$1 } from 'http'; /** * 标准化基础路径,确保以 '/' 开头且不包含 trailing slash * @param basePath 原始基础路径 * @returns 标准化后的基础路径 */ declare function normalizeBasePath(basePath: string): string; type PostprocessStats = { replacedUnknown: number; unmatchedUnknown: string[]; patchedDefects: number; replacedTimestamps: number; replacedDefaultNow: number; }; declare function postprocessDrizzleSchema(targetPath: string): PostprocessStats | undefined; interface Options { tsConfigFilePath: string; schemaFilePath: string; moduleOutputDir: string; } declare function parseAndGenerateNestResourceTemplate(options: Options): Promise; /** * Proxy Error Handler 选项 */ interface ProxyErrorOptions { /** 等待服务重启的超时时间(毫秒),默认 5000ms */ retryTimeout?: number; /** 轮询检查服务的间隔时间(毫秒),默认 500ms */ retryInterval?: number; /** 目标服务器地址,用于检查服务是否恢复,格式:http://localhost:3000 */ target?: string; } /** * HTTP Proxy 错误处理器 * * 处理策略: * 1. 连接错误(服务重启中)→ 等待 5s,恢复则 302 重定向,否则 502 * 2. 其他错误 → 直接 502 * * @example * ```typescript * import { createProxyMiddleware } from 'http-proxy-middleware'; * import { handleDevProxyError } from '@lark-apaas/devtool-kits'; * * const proxy = createProxyMiddleware({ * target: 'http://localhost:3000', * onError: (err, req, res) => { * handleDevProxyError(err, req, res, { * retryTimeout: 5000, * retryInterval: 500, * }); * } * }); * ``` */ declare function handleDevProxyError(err: Error, req: IncomingMessage, res: ServerResponse, options?: ProxyErrorOptions): void; /** * Shared context passed to all middlewares */ interface MiddlewareContext { /** Base path for the application (e.g., '/', '/app') */ basePath: string; /** Whether running in development mode */ isDev: boolean; /** Root directory of the project */ rootDir: string; /** Additional custom options */ [key: string]: any; } /** * Express-compatible app (rspack/webpack dev server) */ type ExpressApp = Application; /** * Vite-compatible middleware handler (Connect server) * Using 'any' to avoid dependency on vite types */ type ViteMiddleware = any; /** * Route registration info for better visibility */ interface RouteInfo { /** HTTP method (GET, POST, etc.) or '*' for all methods */ method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'ALL' | '*'; /** Route path (relative to mount point) */ path: string; /** Description of what this route does */ description: string; } /** * Route-based middleware * Mounts a router at a specific path */ interface RouteMiddleware { /** Unique name for this middleware */ name: string; /** * Mount path for this middleware (relative to basePath) * e.g., '/dev/logs', '/openapi.json' * Required for route-based middlewares */ mountPath: string; /** * List of routes provided by this middleware * Useful for debugging and documentation */ routes?: RouteInfo[]; /** * Determine if this middleware should be enabled * @param context - Shared context * @returns true if middleware should be registered */ enabled?: (context: MiddlewareContext) => boolean; /** * Create router for this middleware * @param context - Shared context * @returns Express Router */ createRouter: (context: MiddlewareContext) => Router; /** Explicitly disallow createHandler for route middleware */ createHandler?: never; } /** * Global middleware * Applies to all requests without a specific mount path */ interface GlobalMiddleware { /** Unique name for this middleware */ name: string; /** * Global middlewares should not have a mount path * If you need path-specific behavior, use RouteMiddleware instead */ mountPath?: never; /** * Determine if this middleware should be enabled * @param context - Shared context * @returns true if middleware should be registered */ enabled?: (context: MiddlewareContext) => boolean; /** * Create handler for this middleware * @param context - Shared context * @returns Express request handler */ createHandler: (context: MiddlewareContext) => RequestHandler; /** Explicitly disallow createRouter for global middleware */ createRouter?: never; } /** * Middleware can be either route-based or global */ type Middleware = RouteMiddleware | GlobalMiddleware; /** * Options for OpenAPI middleware */ interface OpenapiMiddlewareOptions { /** Path to the openapi.json file */ openapiFilePath: string; /** Path to the OpenAPI spec source file (when set, serves /openapi/spec with /openapi/* filtered and $refs resolved) */ openapiSpecFilePath?: string; /** Enable source code enhancement */ enableEnhancement?: boolean; /** Server directory for source code scanning (defaults to context.rootDir) */ serverDir?: string; } /** * Scan serverDir for NestJS controller files and extract all parameterized API routes. * Synchronous — safe to call at preset config time (before bundling). */ declare function parseApiRoutes(serverDir: string): Array<{ method: string; path: string; }>; /** * Creates OpenAPI middleware that serves enhanced openapi.json * Supports both rspack/webpack and Vite dev servers */ declare function createOpenapiMiddleware(options: OpenapiMiddlewareOptions): RouteMiddleware; interface DevLogsMiddlewareOptions$1 { /** Directory containing log files */ logDir?: string; } /** * Creates dev logs middleware for viewing application logs * Supports both rspack/webpack and Vite dev servers */ declare function createDevLogsMiddleware(options?: DevLogsMiddlewareOptions$1): RouteMiddleware; interface DevLogsMiddlewareOptions { logDir?: string; fileName?: string; } /** * Creates dev logs middleware for viewing application logs * Supports both rspack/webpack and Vite dev servers */ declare function createCollectLogsMiddleware(options?: DevLogsMiddlewareOptions): RouteMiddleware; /** * Express/Connect 兼容层 * 让 middleware 同时支持 Express 和 Vite/Connect */ type AnyResponse = ServerResponse$1 & { status?: (code: number) => AnyResponse; json?: (data: unknown) => void; send?: (data: unknown) => void; }; type AnyRequest = IncomingMessage$1 & { query?: Record; params?: Record; }; /** * 发送 JSON 响应,兼容 Express 和 Connect */ declare function sendJson(res: AnyResponse, data: unknown, statusCode?: number): void; /** * 发送错误响应 */ declare function sendError(res: AnyResponse, message: string, error?: unknown, statusCode?: number): void; /** * 发送成功响应 */ declare function sendSuccess(res: AnyResponse, data?: Record): void; /** * 获取 query 参数,兼容 Express 和 Connect */ declare function getQuery(req: AnyRequest): Record; /** * 获取单个 query 参数 */ declare function getQueryParam(req: AnyRequest, key: string): string | undefined; /** * Register middlewares for Express-compatible servers or Vite. * * MUST stay synchronous (no async/await). * * Why: when called from webpack/rspack-dev-server's `setupMiddlewares` callback, * any `await` here yields a microtask, allowing dev-server to finish registering * its own built-ins (proxy, historyApiFallback, serveStatic, ...) BEFORE our * later iterations run. The first router lands before historyApiFallback while * subsequent routers land after — causing extensionless GETs (e.g. `/dev/openapi/spec` * with a wildcard Accept header) to be rewritten to `/index.html`. All registered work * (`server.use`, `createRouter`, `createHandler`) is sync, so async/await is also * unnecessary. * * @example * ```typescript * // In rspack/webpack setupMiddlewares * setupMiddlewares: (middlewares, devServer) => { * if (devServer.app) { * registerMiddlewares(devServer.app, [ * createDevLogsMiddleware({ logDir: './logs' }), * createOpenapiMiddleware({ openapiFilePath: './openapi.json' }) * ], { basePath: '/api', isDev: true, rootDir: __dirname }); * } * return middlewares; * } * ``` */ declare function registerMiddlewares(server: ExpressApp | ViteMiddleware, middlewares: Middleware[], options?: Partial): void; interface PageRouteInfo { path?: string; index?: boolean; [key: string]: unknown; } interface ParseRoutesOptions { /** If true, prefix all routes with basePath. Default: true */ applyBasePath?: boolean; } declare function routeParserLog(level: 'log' | 'warn' | 'error' | 'info', message: string, ...args: unknown[]): void; declare function calculateFileHash(filePath: string): string | null; declare function isRouteComponent(openingElement: t.JSXOpeningElement): boolean; declare function evaluateTemplateLiteral(templateLiteral: t.TemplateLiteral): string; declare function extractPageRouteInfo(openingElement: t.JSXOpeningElement): PageRouteInfo; declare function buildFullPath(routeStack: PageRouteInfo[], currentRoute: PageRouteInfo): string | null; /** * Parse routes from the app file at build time. * @param appPath - Path to app.tsx (relative to cwd or absolute) * @param basePath - Normalized base path prefix (e.g., '/my_plugin', or '' for no prefix) * @param options - Parse options * @returns Array of route definitions */ declare function parseRoutesFromFile(appPath: string, basePath: string, options?: ParseRoutesOptions): Array<{ path: string; }>; export { type GlobalMiddleware, type Middleware, type MiddlewareContext, type Options, type PageRouteInfo, type ParseRoutesOptions, type RouteInfo, type RouteMiddleware, buildFullPath, calculateFileHash, createCollectLogsMiddleware, createDevLogsMiddleware, createOpenapiMiddleware, evaluateTemplateLiteral, extractPageRouteInfo, getQuery, getQueryParam, handleDevProxyError, isRouteComponent, normalizeBasePath, parseAndGenerateNestResourceTemplate, parseApiRoutes, parseRoutesFromFile, postprocessDrizzleSchema, registerMiddlewares, routeParserLog, sendError, sendJson, sendSuccess };