Files
skills/docs/communication/emails/campaigns/src/error-codes/error-codes.md
2026-05-29 08:20:56 +01:00

2.9 KiB

error-codes

(no submodules)

Purpose

Defines the stable, machine-readable error namespace for @suaveplan/campaigns. Every failure path in the package — from invalid options at construction time, through state-machine violations during a send, to missing records and store contract breaches — produces a CampaignsError whose code is drawn from the CAMPAIGNS_CODES registry.

Centralising the registry here keeps the error namespace decoupled from any one feature module. Downstream consumers can pattern-match on the code constants instead of importing concrete error classes, which keeps deserialised errors (over the wire, across worker boundaries) just as switchable as in-process ones.

Features

  • CAMPAIGNS_CODES literal map produced by defineCodes("CAMPAIGNS", [...]).
  • CampaignsCode discriminating union literal type derived from the registry.
  • CampaignsError extends SuaveplanError<CampaignsCode> with an explicit public constructor so new CampaignsError(...) is allowed at any call site.
  • Eight initial codes covering construction, input validation, state transitions, missing records, store breaches, batch + throttle config validation, and workflow failures.
  • Codes are namespaced under the CAMPAIGNS. prefix so they never clash with codes from sibling packages.

Usage: Basic

import { CAMPAIGNS_CODES, CampaignsError } from "@suaveplan/campaigns";

throw new CampaignsError(
    CAMPAIGNS_CODES.CAMPAIGN_NOT_FOUND,
    "Campaign not found: c-42",
    { context: { id: "c-42" } }
);

Usage: Advanced

Discriminating in consumer code without an instanceof chain:

import { CAMPAIGNS_CODES, CampaignsError } from "@suaveplan/campaigns";

try {
    await engine.send(id);
} catch (err) {
    if (!(err instanceof CampaignsError)) throw err;
    switch (err.code) {
        case CAMPAIGNS_CODES.CAMPAIGN_NOT_FOUND:
            return { kind: "not-found" as const };
        case CAMPAIGNS_CODES.INVALID_TRANSITION:
            return { kind: "conflict" as const };
        default:
            throw err;
    }
}

API Reference

  • CAMPAIGNS_CODES — readonly literal map of KEY -> "CAMPAIGNS.KEY" strings.
  • CampaignsCode — typeof CAMPAIGNS_CODES[keyof typeof CAMPAIGNS_CODES].
  • CampaignsError(code, message, options?) — public constructor delegating to SuaveplanError. options.cause chains an underlying error; options.context attaches a structured payload.

Implementation Notes

SuaveplanError's base constructor is protected, so without the explicit public constructor here, new CampaignsError(...) would fail with TS2674. The constructor sets this.name = "CampaignsError" so stack traces are self-describing. The code field narrows against CampaignsCode, which means consumers get exhaustiveness checking on switch statements with noFallthroughCasesInSwitch enabled.