import { RouteTrie } from './trie'; import { type LoadDirOptions } from '../loader'; import type { MiddlewareFunction, RouteHandler, BodyParserType, LifecycleHook } from '../http/types'; /** Describes a single registered route with its method, path, handler, and metadata. */ export interface RouteDefinition { method: string; path: string; handler: RouteHandler; middlewares: MiddlewareFunction[]; name?: string; domain?: string; parse?: BodyParserType | BodyParserType[]; beforeHandle?: LifecycleHook | LifecycleHook[]; afterHandle?: LifecycleHook | LifecycleHook[]; meta: Record; } /** Defines a pattern for validating and optionally casting a route parameter. */ export interface ParamMatcher { match: RegExp; cast?: (value: string) => any; } /** Built-in param matchers for common types (number, uuid, slug). */ export declare const matchers: { number: () => ParamMatcher; uuid: () => ParamMatcher; slug: () => ParamMatcher; }; /** Fluent builder for configuring a single route (name, middleware, param validation, lifecycle hooks). */ export declare class RouteBuilder { private def; private _wheres; constructor(def: RouteDefinition); as(name: string): this; use(middlewares: MiddlewareFunction | MiddlewareFunction[]): this; where(param: string, matcher: ParamMatcher): this; /** Restrict this route to a specific domain/subdomain */ domain(domain: string): this; /** Store arbitrary metadata on this route (used by swagger, etc.) */ meta(key: string, value: unknown): this; parse(type: BodyParserType | BodyParserType[]): this; beforeHandle(hook: LifecycleHook | LifecycleHook[]): this; afterHandle(hook: LifecycleHook | LifecycleHook[]): this; /** @internal */ _getWheres(): Record; } /** Groups multiple routes under a shared prefix, middleware, and domain. */ export declare class RouteGroup { private callback; private _prefix; private _name; private _domain; private _middlewares; private _routes; private _groups; private _router; private _built; constructor(callback: () => void, router: Router); prefix(prefix: string): this; as(name: string): this; /** Restrict this group to a specific domain/subdomain. Supports :param placeholders. */ domain(domain: string): this; use(middlewares: MiddlewareFunction | MiddlewareFunction[]): this; /** @internal */ _addRoute(def: RouteDefinition): void; /** @internal */ _addGroup(group: RouteGroup): void; /** @internal */ _build(): RouteDefinition[]; } /** Registers RESTful CRUD routes for a controller (index, create, store, show, edit, update, destroy). */ export declare class ResourceBuilder { private router; private basePath; private controller; private onlyMethods; private exceptMethods; private _middlewares; constructor(router: Router, basePath: string, controller: any); only(methods: string[]): this; except(methods: string[]): this; apiOnly(): this; use(middlewares: Record): this; /** @internal */ _build(): void; } /** Central router that registers routes, groups, middleware, lifecycle hooks, and compiles them into a trie for fast matching. */ export declare class Router { private trie; private pendingGroups; private pendingRoutes; private pendingResources; private _globalMiddlewares; private _routerMiddlewares; private _globalWheres; private _activeGroup; private _onRequest; private _onBeforeHandle; private _onAfterHandle; private _onAfterResponse; private _onError; matchers: { number: () => ParamMatcher; uuid: () => ParamMatcher; slug: () => ParamMatcher; }; get(path: string, handler: RouteHandler): RouteBuilder; post(path: string, handler: RouteHandler): RouteBuilder; put(path: string, handler: RouteHandler): RouteBuilder; delete(path: string, handler: RouteHandler): RouteBuilder; patch(path: string, handler: RouteHandler): RouteBuilder; any(path: string, handler: RouteHandler): RouteBuilder; route(path: string, methods: string[], handler: RouteHandler): RouteBuilder; /** * Brisk route — render a view or return data directly without a controller. * @example * router.on('/about').render(AboutPage, { title: 'About' }) * router.on('/terms').redirect('/legal') * router.on('/health').json({ status: 'ok' }) */ on(path: string): { render(component: any, props?: any): RouteBuilder; redirect(to: string, status?: number): RouteBuilder; redirectToPath(destination: string, status?: number): RouteBuilder; redirectToRoute(routeName: string, params?: Record, options?: { qs?: Record; status?: number; }): RouteBuilder; json(data: any): RouteBuilder; }; register(...controllers: any[]): this; /** * Load every file in a directory and register whatever each module * exports against this router. Auto-detects three common patterns: * * 1. **Decorator controller** (a class with `@Controller` + `@Get/@Post/...`): * the class is passed to {@link Router.register}. * 2. **Functional registrar** (`export default (router) => { ... }`): * the function is invoked with this router so it can call * `router.get(...)` etc. directly. * 3. **Class with a `register(router)` method**: a fresh instance is * constructed and its `register` method is invoked. Use this when * you want to attach routes without decorators while keeping the * file's primary export as a class. * * Files whose default export does not match any pattern are skipped * with a `console.warn` so misconfigured exports surface during boot * instead of failing silently at request time. * * @example * ```ts * // Replaces the long `import` + `register(Auth, Projects, ...)` block * await router.registerDir('app/controllers') * ``` * * @param dir Directory. Absolute paths are used as-is. Relative paths * default to the caller's own directory (file-relative, captured via * stack inspection so `await router.registerDir('./controllers')` * from `api/index.ts` resolves to `api/controllers` no matter what * the cwd is). Pass `options.from = import.meta.url` to set the * base explicitly, or `options.from = process.cwd()` to keep the * pre-0.1.15 cwd-relative behavior. * @param options Forwarded to `loadDir`. See `LoadDirOptions`. * @returns This router, for chaining. * * Note: dynamic imports cannot be statically traced by * `bun build --compile`. For single-executable builds keep an * explicit `import` list and pass it to {@link Router.register}. */ registerDir(dir: string, options?: LoadDirOptions): Promise; resource(basePath: string, controller: any): ResourceBuilder; group(callback: () => void): RouteGroup; where(param: string, matcher: ParamMatcher): this; useGlobal(middleware: MiddlewareFunction | MiddlewareFunction[]): this; useRouter(middleware: MiddlewareFunction | MiddlewareFunction[]): this; onRequest(hook: LifecycleHook): this; onBeforeHandle(hook: LifecycleHook): this; onAfterHandle(hook: LifecycleHook): this; onAfterResponse(hook: LifecycleHook): this; onError(hook: (error: Error, ctx: any) => any): this; makeUrl(name: string, params?: Record, qs?: Record): string; private _addRoute; /** @internal - used by ResourceBuilder */ _registerRoute(method: string, path: string, handler: RouteHandler, middlewares: MiddlewareFunction[], name?: string): void; compile(): void; match(method: string, path: string): import("./trie").MatchResult | null; get globalMiddlewares(): MiddlewareFunction[]; get routerMiddlewares(): MiddlewareFunction[]; get hooks(): { onRequest: LifecycleHook[]; onBeforeHandle: LifecycleHook[]; onAfterHandle: LifecycleHook[]; onAfterResponse: LifecycleHook[]; onError: ((error: Error, ctx: any) => any)[]; }; getTrie(): RouteTrie; }