first commit
This commit is contained in:
99
docs/api-stack/api/api-plugin-tenant/src/schemas/routes.md
Normal file
99
docs/api-stack/api/api-plugin-tenant/src/schemas/routes.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# `routes`
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the Zod request/response schemas the five management routes
|
||||
mount when the plugin is configured with a `TenantStore`. Every body,
|
||||
query, and response shape flows through these schemas so the OpenAPI
|
||||
3.1 document published at `/openapi.json` is in lock-step with the
|
||||
runtime behaviour — operators and SDKs generated from the spec see the
|
||||
same surface the runtime enforces.
|
||||
|
||||
## Features
|
||||
|
||||
- `TenantResponseSchema` — wire-shape projection of the domain
|
||||
`Tenant` (Dates serialised as ISO strings).
|
||||
- `TenantListResponseSchema` — paginated list response (`items` +
|
||||
`total`).
|
||||
- `CreateTenantBodySchema` / `UpdateTenantBodySchema` — strict
|
||||
body schemas; unknown keys are rejected.
|
||||
- `TenantIdParamSchema` / `ListTenantsQuerySchema` — path-param and
|
||||
query schemas with coercion where appropriate (`limit`, `offset`
|
||||
are coerced from query string numerals).
|
||||
- Slug validation regex: lowercase alphanumeric + hyphen, starting with
|
||||
an alphanumeric. Keeps URLs predictable and prevents subtle
|
||||
case-folding bugs in path-prefix resolution.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { CreateTenantBodySchema } from "@suaveplan/api-plugin-tenant";
|
||||
|
||||
const result = CreateTenantBodySchema.safeParse({
|
||||
name: "Acme",
|
||||
slug: "acme",
|
||||
});
|
||||
if (!result.success) throw new Error(result.error.message);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
CreateTenantBodySchema,
|
||||
ListTenantsQuerySchema,
|
||||
TenantResponseSchema,
|
||||
} from "@suaveplan/api-plugin-tenant";
|
||||
|
||||
// Query coercion — limit/offset arrive as strings from the URL.
|
||||
const query = ListTenantsQuerySchema.parse({
|
||||
status: "active",
|
||||
limit: "50",
|
||||
offset: "0",
|
||||
});
|
||||
console.log(query.limit); // number, not string
|
||||
|
||||
// Round-trip a Tenant through the response schema.
|
||||
const wire = TenantResponseSchema.parse({
|
||||
id: "tenant_1",
|
||||
name: "Acme",
|
||||
slug: "acme",
|
||||
status: "active",
|
||||
settings: {},
|
||||
enabledPlugins: ["billing"],
|
||||
domains: [],
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// Reject invalid slug at the boundary.
|
||||
const bad = CreateTenantBodySchema.safeParse({
|
||||
name: "X",
|
||||
slug: "ACME!", // uppercase + punctuation
|
||||
});
|
||||
console.assert(!bad.success);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `TenantResponseSchema` — single-tenant wire shape.
|
||||
- `TenantListResponseSchema` — `{ items: TenantResponse[]; total: number }`.
|
||||
- `CreateTenantBodySchema` — strict object; `name`, `slug` required.
|
||||
- `UpdateTenantBodySchema` — strict object; all fields optional.
|
||||
- `TenantIdParamSchema` — `{ id: string }`.
|
||||
- `ListTenantsQuerySchema` — `{ status?, limit?, offset? }` with
|
||||
numeric coercion on `limit` and `offset`.
|
||||
- `DeleteTenantResponseSchema` — `{ success: true }`.
|
||||
- Type aliases (`CreateTenantBody`, `UpdateTenantBody`, etc.) are
|
||||
exported for handler signatures.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`strict()` is applied to `CreateTenantBodySchema`, `UpdateTenantBodySchema`,
|
||||
and the nested settings shape so unknown keys are rejected instead of
|
||||
silently dropped. This matters because the same shape round-trips
|
||||
through OpenAPI codegen on the client side — unknown keys on a strict
|
||||
schema imply the client has drifted, and the right behaviour is to fail
|
||||
loudly. The slug regex is intentionally conservative so URLs survive
|
||||
percent-encoding, CDN normalisation, and case-insensitive DNS lookups
|
||||
without ambiguity.
|
||||
Reference in New Issue
Block a user