first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# `validate`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## 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_PATTERN` exported as a `RegExp` so hosts can extend
|
||||
rather than re-derive (`new RegExp(...|extra-form)`).
|
||||
- `defaultTenantIdValidator` — boolean function backed by the pattern.
|
||||
- `TenantIdValidator` and `TenantRegistryProbe` type aliases so host wiring
|
||||
is explicit.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { defaultTenantIdValidator } from "@suaveplan/api-tenant-resolver-header/validate";
|
||||
|
||||
defaultTenantIdValidator("acme"); // true
|
||||
defaultTenantIdValidator("ACME"); // false (uppercase rejected)
|
||||
defaultTenantIdValidator(""); // false (zero-length rejected)
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
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.
|
||||
Reference in New Issue
Block a user