3.1 KiB
options — Zod-validated resolver options
(no submodules)
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_OPTIONScode on every failure (Zod, CIDR parse, missing option object). LabelValidatorandTenantRegistryLookupopt-in extension points.
Usage: Basic
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
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).