2.8 KiB
validate
(no submodules)
Purpose
Owns the default tenant-id validator regex and the validator / registry
function signatures consumed by createHeaderTenantResolver. Splitting the
validator surface out of resolver.ts keeps the resolver implementation a
pure orchestrator (regex check → registry probe → trust check → return) and
lets hosts substitute alternative validators without monkey-patching the
factory.
The default validator (^[a-z0-9-]{1,64}$) is deliberately conservative —
it admits the shape of a typical slug-style identifier and rejects
everything else. Hosts whose tenant ids are UUIDs, prefixed strings, or
arbitrary unicode must pass an explicit validate option.
Features
DEFAULT_TENANT_ID_PATTERNexported as aRegExpso hosts can extend rather than re-derive (new RegExp(...|extra-form)).defaultTenantIdValidator— boolean function backed by the pattern.TenantIdValidatorandTenantRegistryProbetype aliases so host wiring is explicit.
Usage: Basic
import { defaultTenantIdValidator } from "@suaveplan/api-tenant-resolver-header/validate";
defaultTenantIdValidator("acme"); // true
defaultTenantIdValidator("ACME"); // false (uppercase rejected)
defaultTenantIdValidator(""); // false (zero-length rejected)
Usage: Advanced
import type {
TenantIdValidator,
TenantRegistryProbe,
} from "@suaveplan/api-tenant-resolver-header/validate";
const uuidValidator: TenantIdValidator = (v) =>
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(v);
const registry: TenantRegistryProbe = async (tid) =>
(await tenantProvider.lookup(tid as never)) !== null;
API Reference
const DEFAULT_TENANT_ID_PATTERN: RegExp—^[a-z0-9-]{1,64}$.const defaultTenantIdValidator: TenantIdValidator— applies the default pattern; returns boolean.type TenantIdValidator = (value: string) => boolean— synchronous validator contract.type TenantRegistryProbe = (tenantId: string) => boolean | Promise<boolean>— sync-or-async registry membership probe.
Implementation Notes
The validator is intentionally synchronous: the regex check is the
zero-I/O happy path, and a synchronous boolean lets the resolver avoid an
await micro-task in the common-case good-tenant path. Registry probes can
be async because the host may back them with a real TenantProvider.lookup
that hits a database; the resolver awaits the probe only after the regex
check has already passed so a bad value never leaks into the registry call.
The default pattern's 64-character cap is the same maximum used by
api-tenant-provider's seed schema; widening it here without widening it
there would produce values the resolver accepts but the registry refuses.