2.6 KiB
services/registry-augmentation
Purpose
Declares the auditService slot on @suaveplan/api-plugin/service-registry's ServiceRegistry interface via TypeScript module augmentation. Importing this module for its side effects (which the package root barrel does automatically) is sufficient — every consumer of @suaveplan/api-plugin-audit gets typed ctx.getService("auditService") access with the return type narrowed to AuditService | undefined, no casts.
The file also cumulatively re-declares the host-side app slot so the audit plugin's onInit(ctx) resolves ctx.getService("app") to Hono even when the consumer has not explicitly imported @suaveplan/api's registry-augmentation. TypeScript merges duplicate declarations across modules, so the cumulative augmentation is safe.
Features
- TypeScript module augmentation — zero runtime cost.
- Cumulative — does not collide with
@suaveplan/api-plugin-auth's or@suaveplan/api's own augmentations. - Side-effect imported by the package barrel so consumers do not need an explicit subpath import.
Usage: Basic
// In your app entry:
import "@suaveplan/api-plugin-audit"; // side-effect: registers ServiceRegistry slot
// In a sibling plugin's onInit:
const audit = ctx.getService("auditService"); // typed as AuditService | undefined
await audit?.log({
type: "user.created",
severity: "info",
actor: { userId: "u1" },
});
Usage: Advanced
// In a custom test harness that constructs PluginContext directly:
import "@suaveplan/api-plugin-audit/services/audit-service"; // also surfaces the augmentation
import { createPluginContext } from "@suaveplan/api-plugin";
const ctx = createPluginContext({
/* ... */
});
const audit = ctx.getService("auditService"); // AuditService | undefined
API Reference
This file has no runtime exports; it contributes a single TypeScript declare module "@suaveplan/api-plugin/service-registry" block adding:
auditService: AuditServiceapp: Hono
Implementation Notes
The augmentation must live in a module that is reachable from the consumer's TypeScript program (either via a direct import or via a transitive dependency that pulls it in). Importing the package barrel of @suaveplan/api-plugin-audit covers the common case. If the augmentation is missing at compile time, ctx.getService("auditService") types as never per the ServiceRegistry defaults and fails the build with Argument of type '"auditService"' is not assignable…. That failure is the intended UX — it tells the operator the plugin barrel was not loaded.