3.0 KiB
Service-registry augmentation
Purpose
This module is a type-only side-effect import that augments the
canonical ServiceRegistry interface from
@suaveplan/api-plugin/service-registry to surface the slots the
banking plugin reads and writes: its own bankingService, the
host-supplied app (the OpenAPIHono instance routes are mounted
on), and the upstream-supplied db (the DatabaseAdapter registered
by @suaveplan/api-plugin-database). After the augmentation,
ctx.getService("bankingService") types as BankingService | undefined
in any consumer file that imports the banking package barrel.
Features
- Zero-runtime side effect — the
declare moduleblock compiles to nothing. - Cumulative augmentation: re-declaring
appanddbdoes not conflict with the host packages' own declarations; TypeScript merges duplicate interface members. - Picks up the augmentation automatically when consumers import
@suaveplan/api-plugin-bankingfor any reason (the package root barrel forwards the side effect).
Usage: Basic
import "@suaveplan/api-plugin-banking"; // type-only side effect
function handler(ctx: PluginContext) {
const service = ctx.getService("bankingService");
// service: BankingService | undefined
}
Usage: Advanced
Direct subpath import for code that wants the augmentation without the runtime package — pure-type files such as host scaffolding can reference the slot type:
import "@suaveplan/api-plugin-banking/services/registry-augmentation";
import type { ServiceRegistry } from "@suaveplan/api-plugin/service-registry";
declare const reg: ServiceRegistry;
reg.bankingService.transferFunds(/* ... */);
API Reference
The module exports nothing at runtime. The interface it augments:
declare module "@suaveplan/api-plugin/service-registry" {
interface ServiceRegistry {
bankingService: BankingService;
app: OpenAPIHono;
db: DatabaseAdapter;
}
}
After the augmentation:
ctx.getService("bankingService")→BankingService | undefinedctx.getService("app")→OpenAPIHono | undefinedctx.getService("db")→DatabaseAdapter | undefined
Implementation Notes
The pattern (declare-merge the host slot and the plugin's own
slot inside the plugin's package) follows the genesis convention set
by @suaveplan/api-plugin-search. The host packages (@suaveplan/api
for app, @suaveplan/api-plugin-database for db) declare their
own slots; we re-declare them here so the banking plugin compiles
against a consumer's tsconfig that does not transitively import
those host modules' augmentation files.
Re-declaration is safe because TypeScript merges interface members
across declare module blocks. If two packages declared the same
slot with conflicting types, the build would fail at the
augmentation point rather than silently picking one — this gives a
clear compile-time signal if a future change ever drifts the
bankingService slot's type out of sync.