import { Container, ContainerModule } from 'inversify'; import { RouteBuilderImpl } from './RouteBuilderImpl'; import { ClassType } from './ApiRoutingFactory'; import { FilterDefinition } from './WebAppMeta'; import { WebpiecesConfig } from './WebpiecesConfig'; import { ApiClientFactory } from './ApiClientFactory'; import { ApiFactory } from './ApiFactory'; import { ApiClient } from './ApiClient'; /** * Options for {@link WebpiecesRouterFactory.create} — one object (config lives inside it). * * appBindings - DI ContainerModules to load (framework + app). Loaded after the * @provideSingleton auto-scan so they can add/override bindings. * appOverrides - A single ContainerModule loaded LAST so tests can rebind real * controllers/clients to mocks (see @webpieces/core-mock createMock()). * config - Optional {@link WebpiecesConfig} (recording flags, etc.); defaults to a fresh one. */ export interface WebpiecesRouterOptions { appBindings: ContainerModule[]; appOverrides?: ContainerModule; config?: WebpiecesConfig; } /** * WebpiecesRouter - the node-only heart of a webpieces app: a DI container + a filter * chain + an in-process API client. It has NO express dependency, so it runs anywhere * node runs and is fully testable with zero HTTP. * * DI-resolved from the platform container (like the old WebpiecesServerImpl): * `@provideSingleton @injectable`, RouteBuilderImpl injected, and the two containers set in * initialize(). Built by {@link WebpiecesRouterFactory.create} — never `new`ed by callers. * * Two-container pattern (mirrors Java WebPieces): * - webpiecesContainer : framework bindings (config token, @DocumentDesign design roots) * - appContainer : your controllers/filters/modules (a child of the framework one) * * Usage: * ```typescript * const router = await WebpiecesRouterFactory.create({ appBindings: [AppModule] }); * router.addRoutes(SaveApi, SaveController); * router.addFilter(new FilterDefinition(1800, MyFilter, '*')); // your own filters * // (LogApiFilter + AuthFilter are auto-installed above yours; auth is AuthMode-driven. * // LogApiFilter logs request+response for EVERY call — do NOT install it yourself.) * * // test (no express): runs the SAME filter chain (incl. auth) -> controller * const api = router.createApiClient(SaveApi); * await api.save(new SaveRequest(...)); * ``` * * To serve real HTTP, hand this router to the express adapter in @webpieces/http-server * (bindExpress / bindAndStartExpress) — express lifecycle lives THERE, never here. * * @DocumentDesign marks it a design root so it appears in http-routing's designed-lib graph. */ export declare class WebpiecesRouter implements ApiFactory { private readonly routeBuilder; private readonly apiClientFactory; private webpiecesContainer; private appContainer; constructor(routeBuilder: RouteBuilderImpl, apiClientFactory: ApiClientFactory); /** * Build the app container (child of the framework container), load the @provideSingleton * auto-scan + appBindings + appOverrides, and point the RouteBuilder at it. Called once by * the factory after this router is resolved from the framework container. */ initialize(webpiecesContainer: Container, options: WebpiecesRouterOptions): Promise; /** * Auto-install the two fixed framework filters on every route (apps add only their own * filters below these): LogApiFilter outermost (logs request + response/failure for every * call and stamps [Controller.method], then re-throws for the transport to translate), then * AuthFilter (enforces the endpoint's AuthMode off the HttpRequest). Both run over HTTP AND * in-process — there is no transport tier. Because LogApiFilter is outermost, requests that * AuthFilter rejects (401) are still logged with their body + controller identity. */ private installFixedFilters; private loadDIModules; /** * Wire an API prototype (with @ApiPath/@Endpoint decorators) to its controller. * The controller is resolved from the container at request time. */ addRoutes(api: ClassType, controller: ClassType): this; /** * Register a user filter (runs in-process AND over HTTP, below the auto-installed fixed * LogApiFilter + AuthFilter). */ addFilter(filter: FilterDefinition): this; /** * Create an in-process API client that runs the api-tier filter chain + controller * with NO express/HTTP. The primary path for tests and node-only callers. */ createApiClient(apiPrototype: abstract new (...args: any[]) => T): T; /** * Reify the registered APIs as {@link ApiClient}s (contract + the createApiClient proxy) via * the shared {@link ApiClientFactory}. This is the ONLY handoff to the express layer — the * internal RouteBuilder never leaves. */ apiClients(): ApiClient[]; /** The application DI container (child of the framework container). */ getContainer(): Container; } /** * Builds a {@link WebpiecesRouter}: constructs the platform container (mirrors * WebpiecesServerFactory.create), RESOLVES the router from DI, then initializes its app child * container with the @provideSingleton auto-scan + appBindings + optional test overrides. */ export declare class WebpiecesRouterFactory { static create(options: WebpiecesRouterOptions): Promise; }