Files
suaveplan/packages/api-stack/api/api-tenant/src/error-codes/error-codes.md
2026-05-27 23:29:53 +01:00

3.0 KiB

error-codes

(no submodules)

Purpose

The error-codes module defines the seven stable TENANT.* failure codes shipped by @suaveplan/api-tenant and the concrete TenantError class that carries them. Every public failure path in the package — resolver lookups, middleware status gating, rate-limit enforcement, input validation, and lookup timeouts — raises a TenantError with one of these codes so consumers can switch on the string value without depending on a class-instanceof check.

The registry uses defineCodes("TENANT", [...]) from @suaveplan/error, which freezes the object and produces "TENANT.NOT_FOUND"-style stable identifiers. Each code is sized to a specific operational outcome so log aggregators and on-call dashboards can group incidents accurately rather than collapsing every failure under a single bucket.

Features

  • Exactly seven TENANT.* codes: NOT_FOUND, SUSPENDED, PENDING, RESOLUTION_FAILED, RATE_LIMITED, INVALID_INPUT, LOOKUP_TIMEOUT.
  • Frozen registry — Object.isFrozen(TENANT_CODES) is true.
  • TenantError extends SuaveplanError<TenantErrorCode> — the generic parameter narrows .code from string to the discriminated union.
  • A duplicate .tenantCode field is exposed alongside .code so callers writing structural assertions (error.tenantCode === ...) do not have to widen the parent's type parameter.
  • SuaveplanErrorOptions flows through to support cause, context, redactable payloads, and OTel span-event adapter integration.

Usage: Basic

import { TENANT_CODES, TenantError } from "@suaveplan/api-tenant";

throw new TenantError(TENANT_CODES.NOT_FOUND, "Tenant 'acme' not found");

Usage: Advanced

Threading a cause and structured context for OTel ingestion:

import { TENANT_CODES, TenantError } from "@suaveplan/api-tenant";

try {
    await db.query("SELECT * FROM tenants WHERE slug = $1", ["acme"]);
} catch (cause) {
    throw new TenantError(
        TENANT_CODES.RESOLUTION_FAILED,
        "Tenant lookup failed",
        {
            cause: cause instanceof Error ? cause : new Error(String(cause)),
            context: { resolver: "subdomain", input: "acme" },
        }
    );
}

API Reference

  • TENANT_CODES — frozen Record<string, "TENANT.${string}"> mapping short keys (NOT_FOUND etc.) to dotted identifiers.
  • TenantErrorCode — discriminated string union over (typeof TENANT_CODES)[keyof typeof TENANT_CODES].
  • class TenantError extends SuaveplanError<TenantErrorCode> — constructor (code, message, options?). Public .tenantCode field mirrors .code.

Implementation Notes

The constructor widens visibility to public because SuaveplanError's constructor is protected for the base class only. Every shipped subclass (PluginError, TenantError, etc.) follows the same shape so consumers can swap subclasses without adjusting call sites. The tenantCode mirror field avoids forcing callers to write error.code as TenantErrorCode when narrowing.