3.4 KiB
routes
(no submodules)
Purpose
Builds the five OpenAPI route entries createTenantPlugin mounts when a
TenantStore is configured: GET /, POST /, GET /:id, PATCH /:id,
and DELETE /:id, each paired with a Hono handler that delegates to
the TenantService. Every body, query, and response shape flows
through the Zod schemas from schemas/routes.ts so the unified
OpenAPI 3.1 document the host serves stays in lock-step with the
runtime behaviour.
Features
- Five-route CRUD surface returned as
PluginRouteEntry[]ready fordefinePluginRoutes. - Per-handler Zod validation — bodies, query parameters, and path
params are validated explicitly with
safeParseso the error shape is consistent across all five handlers. - Domain → wire projection via
toResponsesoDatefields serialise as ISO strings and optionalplan/metadatakeys are omitted rather than serialised asnull. TenantPluginErrorinstances are translated to JSON{ success: false, error: { code, message } }with the carriedstatusCodeso callers see 404 / 409 / 500 as appropriate.- Soft-delete success response is
{ success: true }.
Usage: Basic Example
import { buildTenantRoutes, createTenantService, MemoryTenantStore } from "@suaveplan/api-plugin-tenant";
import { headerResolver } from "@suaveplan/api-tenant";
const store = new MemoryTenantStore();
const resolver = headerResolver("x-tenant-id", (id) => store.getById(id));
const service = createTenantService({ resolver, store });
const entries = buildTenantRoutes(service);
console.log(entries.length); // 5
Usage: Advanced Example
import { buildTenantRoutes, createTenantService, MemoryTenantStore } from "@suaveplan/api-plugin-tenant";
import { headerResolver } from "@suaveplan/api-tenant";
import { definePluginRoutes, createOpenAPIRegistry } from "@suaveplan/api-openapi";
import { OpenAPIHono } from "@hono/zod-openapi";
const store = new MemoryTenantStore();
const resolver = headerResolver("x-tenant-id", (id) => store.getById(id));
const service = createTenantService({ resolver, store });
const app = new OpenAPIHono();
const registry = createOpenAPIRegistry({ info: { title: "demo", version: "0.0.1" } });
const entries = buildTenantRoutes(service);
// Caller is responsible for prefixing the paths and applying any RBAC middleware.
const prefixed = entries.map((e) => ({
...e,
route: { ...e.route, path: `/tenants${e.route.path === "/" ? "" : e.route.path}` },
}));
definePluginRoutes(prefixed, { app, registry, pluginName: "tenant" });
API Reference
function buildTenantRoutes(service: TenantService): PluginRouteEntry[]— returns five entries. Path templates use/{id}for the resource routes (OpenAPI style), which Hono accepts via theapp.openapi(route, handler)integration indefinePluginRoutes.
Implementation Notes
The handlers validate inputs even though definePluginRoutes already
wires c.req.valid(...) because we want the same handlers to be
runnable on a Hono-only mount (no OpenAPI registry) without losing
boundary validation. Errors are JSON-formatted with explicit status
codes so consumers using a thin error handler do not need to know
plugin-internal error shapes. The list response shape ({ items, total }) is deliberately minimal; consumers needing cursor-based
pagination wire their own variant or subclass the schema.