first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
# `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 the `type` field, missing
required parameters per variant, and empty strings.
- `TenantPluginOptionsSchema` — full options object validated as a
unit. Applies defaults for `required` (`false`), `allowSuspended`
(`false`), and `routePrefix` (`"/tenants"`).
- Custom `z.custom` validators for `store`, `logger`, and the optional
rate-limit `store` so duck-typing accepts any conforming object
without the schema needing to know the full implementation surface.
- `routePrefix` regex enforces leading `/`, no trailing `/` (unless
the prefix is exactly `/`), and a conservative character set so the
resulting Hono routes are predictable.
## Usage: Basic Example
```ts
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
```ts
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; `parse` throws `ZodError`, `safeParse` returns 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.