first commit
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# `TENANT_PROVIDER_CODES` — stable error registry
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`@suaveplan/api-tenant-provider` raises every failure through a single
|
||||
`SuaveplanError` subclass — `TenantProviderError` — and every instance
|
||||
carries a code from the frozen `TENANT_PROVIDER_CODES` registry. The
|
||||
registry exists so consumers can branch on a stable string literal
|
||||
(`error.code === "TENANT_PROVIDER.INVALID_CURSOR"`) without coupling
|
||||
to the package's class hierarchy or sniffing message text.
|
||||
|
||||
Because tenant enumeration is consumed by very different concerns
|
||||
(per-tenant cron fan-out, admin dashboards, background reconciliation,
|
||||
cache warmers), a small set of well-named codes is more useful than a
|
||||
large catalogue: callers either retry on `SOURCE_UNAVAILABLE`, fix
|
||||
caller bugs on `INVALID_CURSOR`, or treat the absent record as expected
|
||||
on `TENANT_NOT_FOUND`.
|
||||
|
||||
## Features
|
||||
|
||||
- `defineCodes("TENANT_PROVIDER", [...])` produces a frozen registry; new entries are an OpenSpec change.
|
||||
- `TenantProviderError extends SuaveplanError<TenantProviderErrorCode>` so `instanceof TenantProviderError` narrows the `code` field.
|
||||
- Three codes: `TENANT_NOT_FOUND`, `SOURCE_UNAVAILABLE`, `INVALID_CURSOR`.
|
||||
- Inherits cause-chain, redaction, OTel span-event adapter from `@suaveplan/error`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
TENANT_PROVIDER_CODES,
|
||||
TenantProviderError,
|
||||
} from "@suaveplan/api-tenant-provider/error-codes";
|
||||
|
||||
throw new TenantProviderError(
|
||||
TENANT_PROVIDER_CODES.TENANT_NOT_FOUND,
|
||||
"tenant t-42 is not registered",
|
||||
);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import {
|
||||
TenantProviderError,
|
||||
TENANT_PROVIDER_CODES,
|
||||
} from "@suaveplan/api-tenant-provider/error-codes";
|
||||
|
||||
try {
|
||||
for await (const t of provider.list({ cursor })) {
|
||||
// ...
|
||||
}
|
||||
} catch (err) {
|
||||
if (
|
||||
err instanceof TenantProviderError &&
|
||||
err.code === TENANT_PROVIDER_CODES.INVALID_CURSOR
|
||||
) {
|
||||
// The caller passed a cursor not produced by `list()` — reset
|
||||
// and start a fresh iteration instead of crashing the job.
|
||||
for await (const t of provider.list()) {
|
||||
// ...
|
||||
}
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `TENANT_PROVIDER_CODES`: `Readonly<{ TENANT_NOT_FOUND: "TENANT_PROVIDER.TENANT_NOT_FOUND"; SOURCE_UNAVAILABLE: "TENANT_PROVIDER.SOURCE_UNAVAILABLE"; INVALID_CURSOR: "TENANT_PROVIDER.INVALID_CURSOR" }>`.
|
||||
- `TenantProviderErrorCode`: the union of those three string literals.
|
||||
- `class TenantProviderError extends SuaveplanError<TenantProviderErrorCode>` with `constructor(code, message, options?)` and public `readonly tenantProviderCode`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The codes are defined via `defineCodes("TENANT_PROVIDER", [...] as const)`
|
||||
so the `TENANT_PROVIDER.` prefix is forwarded by the registry helper —
|
||||
the array entries are bare names. The resulting object is frozen at
|
||||
construction and the type is widened to the union of every namespaced
|
||||
literal. The `tenantProviderCode` field on the error mirrors `code`
|
||||
for ergonomic narrowing in consumer code that already imports the
|
||||
class but not the code union.
|
||||
Reference in New Issue
Block a user