Files
2026-05-27 23:47:53 +01:00

4.1 KiB

error-codes

(no submodules)

Purpose

The @suaveplan/font-decompress package centralises every failure mode it can produce behind a single registry built with defineCodes("FONT_DECOMPRESS", [...]) from @suaveplan/error. The registry is the stable contract callers depend on: code strings are documented, frozen at module load, and never renamed without an explicit migration. This module exports the FONT_DECOMPRESS_CODES registry, the derived FontDecompressErrorCode literal-union type, and the FontDecompressError class that every public failure path raises.

FontDecompressError extends SuaveplanError<FontDecompressErrorCode> so instanceof FontDecompressError narrows code to the union of FONT_DECOMPRESS.* strings. The class threads cause straight through SuaveplanError, so primitive-layer exceptions (RangeError from DataView, TypeError from TextDecoder, @suaveplan/font-convert errors) remain inspectable through error.cause.

Features

  • Frozen FONT_DECOMPRESS_CODES registry with two namespaced codes
  • FontDecompressErrorCode literal-union type derived from the registry
  • FontDecompressError class extending SuaveplanError<FontDecompressErrorCode>
  • Full cause-chain preservation via SuaveplanError
  • Distinct from FONT_COMPRESS.* codes — different namespace, different class

Usage: Basic

import {
    FONT_DECOMPRESS_CODES,
    FontDecompressError,
} from "@suaveplan/font-decompress";

if (data.byteLength < 1) {
    throw new FontDecompressError(
        FONT_DECOMPRESS_CODES.INVALID_DATA,
        "BTF buffer is empty",
    );
}

Usage: Advanced

import {
    FONT_DECOMPRESS_CODES,
    FontDecompressError,
} from "@suaveplan/font-decompress";

try {
    const font = unpacker.unpack(buffer);
} catch (err) {
    if (err instanceof FontDecompressError) {
        if (err.code === FONT_DECOMPRESS_CODES.UNPACK_FAILED) {
            telemetry.increment("font.unpack.failure", {
                root: err.cause instanceof Error ? err.cause.name : "unknown",
            });
        }
    }
    throw err;
}

API Reference

FONT_DECOMPRESS_CODES

A frozen object literal of two namespaced codes:

Property Value
UNPACK_FAILED "FONT_DECOMPRESS.UNPACK_FAILED"
INVALID_DATA "FONT_DECOMPRESS.INVALID_DATA"

type FontDecompressErrorCode

The literal union of every value in FONT_DECOMPRESS_CODES.

class FontDecompressError extends SuaveplanError<FontDecompressErrorCode>

Member Type
code FontDecompressErrorCode (narrowed)
cause? unknown (inherited)
timestamp number (inherited; Date.now() at construction)
constructor(...) (code, message, options?: SuaveplanErrorOptions)

Implementation Notes

defineCodes returns a Object.freezed record with null prototype, so the registry cannot be mutated, reassigned, or extended at runtime. The literal-type machinery preserves the exact ${Namespace}.${Reason} string template across every consumer, so switch (err.code) enjoys exhaustive narrowing without runtime cost.

The class's constructor passes message through to SuaveplanError's messageKey parameter. The base class resolves the key via the i18n resolver if one has been registered with setMessageResolver, falling back to the raw string otherwise — so this package works without i18n wiring and lights up automatically when @suaveplan/i18n is present.

The split from @suaveplan/font-compress preserves namespace distinctness: an INVALID_DATA raised by the packer is FONT_COMPRESS.INVALID_DATA; an INVALID_DATA raised by the unpacker is FONT_DECOMPRESS.INVALID_DATA. Consumers dispatching on either class plus its code get fully unambiguous error handling.