3.0 KiB
options
Purpose
Defines the Zod schema validated at the createTenantPlugin boundary
plus the strategy-spec discriminated-union schema each strategy is
parsed against. Boundary validation catches configuration mistakes at
plugin-construction time — long before a request hits the resolver
chain — and surfaces them as TenantPluginError(INVALID_INPUT) with
the original ZodError carried as cause for developer feedback.
Features
TenantStrategySpecSchema— discriminated union over the seven strategy variants. Catches typos in thetypefield, missing required parameters per variant, and empty strings.TenantPluginOptionsSchema— full options object validated as a unit. Applies defaults forrequired(false),allowSuspended(false), androutePrefix("/tenants").- Custom
z.customvalidators forstore,logger, and the optional rate-limitstoreso duck-typing accepts any conforming object without the schema needing to know the full implementation surface. routePrefixregex enforces leading/, no trailing/(unless the prefix is exactly/), and a conservative character set so the resulting Hono routes are predictable.
Usage: Basic Example
import { TenantPluginOptionsSchema } from "@suaveplan/api-plugin-tenant";
const parsed = TenantPluginOptionsSchema.parse({
strategies: [{ type: "header", headerName: "x-tenant-id" }],
});
console.log(parsed.routePrefix); // "/tenants" (default)
Usage: Advanced Example
import {
TenantPluginOptionsSchema,
TenantStrategySpecSchema,
} from "@suaveplan/api-plugin-tenant";
const strategyResult = TenantStrategySpecSchema.safeParse({
type: "cookie",
cookieName: "tenant",
});
if (!strategyResult.success) {
console.error(strategyResult.error.message);
}
const optionsResult = TenantPluginOptionsSchema.safeParse({
strategies: [],
});
console.assert(!optionsResult.success); // strategies cannot be empty
API Reference
TenantStrategySpecSchema: z.ZodDiscriminatedUnion— accepts any of the seven strategy specs.TenantPluginOptionsSchema: z.ZodObject— accepts the full options object;parsethrowsZodError,safeParsereturns a discriminated result.type TenantPluginOptionsInput = z.input<typeof TenantPluginOptionsSchema>— pre-default-application input shape.type TenantPluginOptionsResolved = z.output<typeof TenantPluginOptionsSchema>— post-default-application output shape.
Implementation Notes
The betterAuth-style escape hatches present in
@suaveplan/api-plugin-auth's options schema are not needed here
because the plugin owns its full surface. The store, logger, and
rateLimit.store slots use z.custom rather than a full structural
schema so the validator does not need to enumerate every method —
duck-typing on the few methods callers will actually hit is enough.
This keeps the schema small and the error messages targeted: if a
caller passes a partial store missing create, the error names
getById/create/update/delete and points to the call site.