import type { TBindingNamespace } from '../../common/bindings.js'; import type { Binding } from '../../helpers/inversion/index.js'; import { OpenAPIHono } from '@hono/zod-openapi'; import type { IConfigurable, TClass, ValueOrPromise } from '@venizia/ignis-helpers/common'; import { RequestIdGenerator } from '@venizia/ignis-helpers/core'; import type { Env, Schema } from 'hono'; import type { BaseComponent } from '../components/index.js'; import type { BaseConfiguration } from '../configurations/index.js'; import type { IDataSource } from '../datasources/index.js'; import { BaseAppErrorMiddleware } from '../middlewares/app-error/app-error.middleware.js'; import type { TMixinOpts } from '../mixins/common/index.js'; import type { IRepository } from '../repositories/index.js'; import type { IService } from '../services/index.js'; import { AbstractApplication } from './abstract.js'; import type { IBootSequenceStep } from './boot-sequence.js'; import type { IApplicationConfigs, TArtifactIndexInput } from './common/index.js'; interface IRegisterDynamicBindingsOptions { namespace: TBindingNamespace; onBeforeConfigure?: (opts: { binding: Binding; }) => Promise; onAfterConfigure?: (opts: { binding: Binding; instance: T; }) => Promise; } /** Adds the `OpenAPIHono` router surface on top of `AbstractApplication` - no listening server, so this is the layer a browser Worker or gRPC-only host can extend without pulling in `Bun.serve` / `@hono/node-server`. */ export declare abstract class RestApplication extends AbstractApplication { private registeredBindings; private artifactOptions; /** The router, and nothing else. What runtime is underneath and what socket is bound are `ServerApplication`'s to know - a browser Worker has neither, and carrying the union here made `RuntimeModules.detect()` answer `'node'` inside a Worker. */ protected server: { hono: OpenAPIHono; }; protected rootRouter: OpenAPIHono; protected readonly requestIdGenerator: RequestIdGenerator; /** A copy of the `bodyLimit` the default stack installed, absent until `registerDefaultMiddlewares()` ran. */ private installedBodyLimit?; constructor(opts: { scope: string; config: IApplicationConfigs; }); getRootRouter(): OpenAPIHono; getServer(): OpenAPIHono; protected registerCoreBindings(): void; /** The correlation id every host stamps - see {@link RequestIdGenerator} for why `crypto.randomUUID` is refused. */ protected generateRequestId(): string; /** The error handler the default stack installs. `@venizia/ignis` overrides it to swap in the `ErrorPrettier`-backed formatter, which reaches `node:util` and so cannot live here. */ protected buildErrorMiddleware(): BaseAppErrorMiddleware; /** * The three registrations every host needs: request id, error envelope, JSON 404 - without them a * thrown `ApplicationError` is a generic 500, a 404 is `text/plain`, and no response carries a request id. * Registered before `initialize()`, so an application's own handlers still win. */ protected registerDefaultMiddlewares(): ValueOrPromise; /** What a `bodyLimit` config installs: nothing when absent or disabled, else a copy, so a later in-place edit shows. */ private toInstalledBodyLimit; private isSameBodyLimit; /** * `configs.middlewares` is read by `registerDefaultMiddlewares()`, which runs before `staticConfigure()`. * A limit assigned in a boot hook would read back as configured while every request ran unlimited. */ private assertBodyLimitUnchanged; /** * The artifact order, stated once: datasources before the repositories that auto-resolve them, * components before the controllers they may contribute. `BaseApplication` splices its server-only * steps around these by name instead of rewriting the list. */ protected getBootSequence(): IBootSequenceStep[]; initialize(): Promise; /** The application hook currently running, so `registerArtifact` can tell a hand registration inside `preConfigure`/`postConfigure` from one the index step made. */ private runningApplicationHook; private runApplicationHook; /** * Bound keys carrying one of `tags` that nothing has resolved since the counts were last reset. * The counter answers "who was read", never "who is dead" - an unread binding may be an * allow-list entry or a technical floor, and only the application can tell those apart. * * Counting is off by default. Call `startResolutionCounting()` after `initialize()` and run the * traffic that exercises the application, then read this. */ getUnresolvedBindings(opts?: { tags?: string[]; }): string[]; /** `bootChecks.binding.doVerify`: resolve every service and repository once, collect every failure, throw once with the whole list - a made-up `@inject` key or a dependency a `when` excluded then fails the boot, not the first request. */ protected verifyBindings(): void; /** One measured log line per step, and a failure names its step before rethrowing, so a hung or failed boot is attributable without reading the sequence. */ protected runBootSequence(opts: { steps: IBootSequenceStep[]; }): Promise; protected inspectRoutes(): void; /** * `configured` is the drain's state, mutated in place: a fresh `Set` gives a one-shot complete * drain (`RestComponent`); `registerDynamicBindings` passes its persistent per-namespace `Set`, * which is why a second sweep touches only what the first one missed. */ drainByTag(opts: { tag: string; configured: Set; onEach: (opts: { binding: Binding; }) => Promise; }): Promise; protected registerDynamicBindings(opts: IRegisterDynamicBindingsOptions): Promise; /** The same-key guard behind every artifact registration (`component`/`controller`/`service`/`repository`/`dataSource`). `allowOverride` defaults true to match `bind()`'s overwrite behavior; `allowOverride: false` on one registration, or `bootChecks.binding.allowOverride: false` for the whole application, opts into strict mode. */ protected assertNoBindingCollision(opts: { key: string; allowOverride?: boolean; caller: string; }): void; /** Resolution order for every registration: explicit `opts` > the class's `@injectable` defaults > the derived key and the kind's default scope. `order` and `when` are `registerArtifacts`' concern, not this one. */ private registerArtifact; configuration, Options extends object = {}>(target: TClass, opts?: TMixinOpts): Binding; registerConfigurations(): Promise; component, Options extends object = {}>(target: TClass, opts?: TMixinOpts): Binding; registerComponents(): Promise; /** * Second DATASOURCE sweep, for datasources components contributed at any depth. Calls * `registerDynamicBindings` directly: `this.registerDataSources()` is polymorphic and an override * would run twice. Runs after every component, so a component a datasource registers is never configured. */ registerContributedDataSources(): Promise; /** REST only - the kernel has no gRPC (it reaches `node:module`). `BaseApplication` adds the gRPC branch on top. */ registerControllers(): Promise; /** SINGLETON like `component()`: `RestComponent` mounts the one instance it resolves, so a second resolution must be that instance, not an unmounted twin. */ controller(target: TClass, opts?: TMixinOpts): Binding; service(target: TClass, opts?: TMixinOpts): Binding; repository(target: TClass, opts?: TMixinOpts): Binding; dataSource, Options extends object = {}>(target: TClass, opts?: TMixinOpts): Binding; /** The boot step body behind `configs.artifacts`, also callable by hand: registers every kind in dependency order across the given indexes. */ registerArtifacts(index: TArtifactIndexInput): Promise; /** Registers every class a stereotype decorated, with no `configs.artifacts` entry anywhere. `when` and `order` apply exactly as they do to a declared index - which is how one process running several applications keeps them apart. */ registerDiscoveredArtifacts(): Promise; /** * The artifact boot step. `configs.discoverArtifacts` adds every decorated class in the import * graph; `configs.artifacts` adds exactly what it lists. Both together register the union. * * An absent `artifacts` still registers nothing. Reading it as "register everything" would change * what an existing application boots with, silently, and the failure would surface as ten times * the bindings rather than as an error. */ protected registerConfiguredArtifacts(): Promise; /** Each `@provide` method becomes a lazy provider: the component is resolved (SINGLETON) and the method called on first `get`, so a provided value may depend on datasources or secrets that do not exist yet at registration time. */ private bindProvidedKeys; registerDataSources(): Promise; /** * Closes every datasource the boot configured, so a stopped application holds no pool, socket or * WASM instance. A failure, or a `close()` still pending after `dataSourceCloseTimeoutMs`, is logged * and never stops the rest. A datasource configured by hand is closed by whoever configured it. */ protected closeDataSources(): Promise; } export {}; //# sourceMappingURL=rest.d.ts.map