Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
# `options` — Zod-validated resolver options
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Defines and validates the public option bundle accepted by
`createSubdomainTenantResolver`. Every option is bounded by a Zod
schema at construction time so an operator that misspells a key,
supplies an invalid CIDR, or passes a negative `tenantLabelIndex`
discovers the mistake immediately rather than at the first inbound
request. The resolved bundle replaces every `??` ladder so the
resolver body stays small and the hot-path is allocation-free.
The shape mirrors `@suaveplan/api-tenant-resolver-header` /
`-jwt` (id + strict + validator + registry) plus the subdomain-specific
fields (`baseDomain`, `tenantLabelIndex`, `trustForwardedHost`,
`trustedProxyCidrs`) and a `getTransport` extractor so the host can
inject framework-specific request metadata.
## Features
- Strict Zod schema — extra keys fail validation.
- CIDR pre-parsing at construction time so the per-request hot-path is
byte-array prefix comparison only.
- Stable `INVALID_OPTIONS` code on every failure (Zod, CIDR parse,
missing option object).
- `LabelValidator` and `TenantRegistryLookup` opt-in extension points.
## Usage: Basic
```ts
import { parseSubdomainTenantResolverOptions } from "@suaveplan/api-tenant-resolver-subdomain/options";
const resolved = parseSubdomainTenantResolverOptions({
baseDomain: "api.example.com",
});
// → { id: "subdomain", baseDomain: "api.example.com",
// tenantLabelIndex: 0, strict: false, ... }
```
## Usage: Advanced
```ts
import type { TenantId } from "@suaveplan/api-types/tenant";
import { parseSubdomainTenantResolverOptions } from "@suaveplan/api-tenant-resolver-subdomain/options";
const registry = new Map<string, TenantId>([
["acme", "t_acme" as TenantId],
]);
const resolved = parseSubdomainTenantResolverOptions({
id: "primary",
baseDomain: "api.example.com",
tenantLabelIndex: 0,
strict: true,
trustForwardedHost: true,
trustedProxyCidrs: ["10.0.0.0/8", "2001:db8::/32"],
registry: (slug) => registry.get(slug) ?? null,
});
```
## API Reference
- `SubdomainTenantResolverOptions` — public input bundle.
- `ResolvedSubdomainTenantResolverOptions` — internal, every default
applied, CIDRs pre-parsed.
- `parseSubdomainTenantResolverOptions(input): Resolved...`.
- `TenantRegistryLookup` — slug → `TenantId | null` (sync or async).
- `RequestTransport` — `{ host, forwardedHost, remoteAddress }`.
- `TransportExtractor` — `(request: Request) => RequestTransport`.
## Implementation Notes
The schema is `.strict()` so a typo (`requirePrincipal` instead of
`requireTenant`) is a hard error at construction. `validate` and
`registry` are stripped before the Zod parse — `z.function()` is
deprecated and unnecessary here because runtime function calls already
fail loudly if the wrong shape is passed. `trustedProxyCidrs` is
re-parsed through `parseCidr` so every CIDR is normalised to a
`ParsedCidr` once; this is the only allocation per resolver
construction (per-request matching uses the cached array).