4.5 KiB
error-codes — CURRENCY_CODES + CurrencyError
(no submodules)
Purpose
@suaveplan/currency raises only typed errors. This module owns the stable
CURRENCY_CODES registry (built with defineCodes("CURRENCY", [...]) from
@suaveplan/error) and the CurrencyError subclass that every public failure
path constructs. Consumers programmatically dispatch on the namespaced strings
("CURRENCY.PROVIDER_UNAVAILABLE", "CURRENCY.RATE_UNAVAILABLE", ...) and
inspect the from / to / providerName discriminants to recover from or
report on failures.
The class extends SuaveplanError<CurrencyErrorCode>, so
instanceof CurrencyError narrows err.code to the literal union, and
instanceof SuaveplanError carries the full project contract: .code,
.cause, .context, .timestamp, .traceId. Seven codes are declared:
INVALID_CONFIG, INVALID_OPTIONS, PROVIDER_UNAVAILABLE,
UNSUPPORTED_CURRENCY, RATE_UNAVAILABLE, TRIANGULATION_IMPOSSIBLE,
ABORTED. Every code is reachable from a real production call site —
registry pollution is banned by repo policy.
Features
- Stable namespaced codes via
defineCodes("CURRENCY", [...] as const)— the registry is frozen, the namespace is encoded into each value. CurrencyError extends SuaveplanError<CurrencyErrorCode>—instanceofnarrows.codeto the literal-string union;causechains arbitrary throwables.from/to/providerNamediscriminants on every error instance for programmatic diagnostics (err.from === "USD",err.providerName === "ecb").- Co-located test pins every code to a real call site so the registry never drifts ahead of the implementation.
Usage: Basic Example
import { CurrencyConverter, CurrencyError, CURRENCY_CODES } from "@suaveplan/currency";
try {
await converter.convert(money, "XYZ");
} catch (err) {
if (err instanceof CurrencyError && err.code === CURRENCY_CODES.RATE_UNAVAILABLE) {
console.error(`No rate for ${err.from} → ${err.to}`);
} else {
throw err;
}
}
Usage: Advanced Example
Wrap an upstream provider failure while keeping the original throwable on
cause so downstream loggers can still report it, and annotate the typed
error with the provider that triggered the fallback chain failure:
import { CurrencyError, CURRENCY_CODES } from "@suaveplan/currency";
async function safeFetch(provider) {
try {
return await provider.fetchRates({ base: "USD" });
} catch (err) {
throw new CurrencyError(
CURRENCY_CODES.PROVIDER_UNAVAILABLE,
`provider ${provider.name} failed`,
{ cause: err, providerName: provider.name, from: "USD" }
);
}
}
API Reference
| Export | Kind | Description |
|---|---|---|
CURRENCY_CODES |
const (frozen) |
Registry of seven namespaced codes built via defineCodes. |
CurrencyErrorCode |
type |
Literal-string union of every registry value. |
CurrencyErrorOptions |
interface |
Extends SuaveplanErrorOptions with optional from, to, providerName. |
CurrencyError |
class |
extends SuaveplanError<CurrencyErrorCode> — constructor takes (code, message, options?). |
CurrencyError properties
code: CurrencyErrorCode— the namespaced error code (e.g."CURRENCY.PROVIDER_UNAVAILABLE").from?: CurrencyCode— the source currency the operation was attempted against.to?: CurrencyCode— the target currency the operation was attempted against.providerName?: string— the provider whose call produced the error.cause?: unknown— chained underlying throwable.timestamp: number— captured at construction time via the injected clock.context?: ErrorContext— bag of structured fields propagated to the formatter.traceId?: string— propagated W3C trace identifier when supplied.
Implementation Notes
The constructor is public so any module in the package can throw it; the
optional discriminants are assigned only when set so JSON.stringify does not
emit "from": undefined. CurrencyError is instanceof SuaveplanError and
instanceof Error; tests pin both. The registry is created with as const
so TypeScript infers literal types — CURRENCY_CODES.PROVIDER_UNAVAILABLE is
"CURRENCY.PROVIDER_UNAVAILABLE", not string. Adding a new code requires
appending to the array in error-codes.ts, wiring it into a real production
raise site, and updating the registry test to assert the literal value.