Files
skills/docs/foundation/data/clipboard/src/errors/errors.md
2026-05-29 08:20:56 +01:00

4.0 KiB

errors/errors.ts

(no submodules)

Purpose

Stable error code registry, per-code metadata, and the concrete ClipboardError class for the @suaveplan/clipboard package. Every error path inside the manager, fallback, permissions, and security modules surfaces one of these codes so consumers can match programmatically without inspecting message strings. Codes are namespaced under CLIPBOARD.* and registered via the shared defineCodes helper from @suaveplan/error so the runtime values, the literal union type, and the metadata table stay in lock-step.

Features

  • Eight stable codes: API_UNAVAILABLE, PERMISSION_DENIED, FALLBACK_FAILED, INSECURE_CONTEXT, NO_CONTENT, READ_FAILED, DOCUMENT_UNAVAILABLE, QUEUE_DRAINED.
  • Per-code metadata: httpStatus, retryable, severity, description.
  • ClipboardError extends SuaveplanError<ClipboardErrorCode> — preserves cause chains, supports OTel span events, and integrates with the project's typed-error contract.
  • asClipboardError(code, cause, fallbackMessage) lifts unknown thrown values into the typed hierarchy at every catch site.

Usage: Basic

import {
    CLIPBOARD_CODES,
    ClipboardError,
} from "@suaveplan/clipboard";

try {
    // ...
} catch (cause) {
    throw new ClipboardError(
        CLIPBOARD_CODES.READ_FAILED,
        "Clipboard read rejected",
        { cause: cause instanceof Error ? cause : new Error(String(cause)) },
    );
}

Usage: Advanced

import {
    asClipboardError,
    CLIPBOARD_CODES,
    CLIPBOARD_ERROR_METADATA,
} from "@suaveplan/clipboard";

function decide(err: unknown): { retry: boolean; status: number } {
    if (
        err instanceof Error &&
        "code" in err &&
        typeof (err as { code?: string }).code === "string" &&
        (err as { code: string }).code.startsWith("CLIPBOARD.")
    ) {
        const meta =
            CLIPBOARD_ERROR_METADATA[
                (err as { code: keyof typeof CLIPBOARD_ERROR_METADATA })
                    .code
            ];
        return { retry: meta.retryable, status: meta.httpStatus };
    }
    const lifted = asClipboardError(
        CLIPBOARD_CODES.READ_FAILED,
        err,
        "Unknown clipboard failure.",
    );
    return {
        retry: lifted.metadata.retryable,
        status: lifted.metadata.httpStatus,
    };
}

API Reference

CLIPBOARD_CODES

Readonly<Record<<key>, "CLIPBOARD.<key>">> produced by defineCodes. The runtime values are namespaced strings; the type infers a literal union for exhaustive matching.

CLIPBOARD_ERROR_METADATA

Readonly<Record<ClipboardErrorCode, ClipboardCodeMetadata>> — frozen map from each code to its httpStatus, retryable, severity, and description fields.

ClipboardCodeMetadata

Interface with httpStatus: number, severity: "info" | "warning" | "error", retryable: boolean, description: string.

ClipboardError

Concrete subclass of SuaveplanError<ClipboardErrorCode>. Constructor signature: new ClipboardError(code, message, options?). Exposes a .metadata getter that returns the row from CLIPBOARD_ERROR_METADATA.

asClipboardError(code, cause, fallbackMessage)

Lifts an arbitrary unknown thrown value into a ClipboardError, preserving the cause chain. Uses cause.message when available and fallbackMessage otherwise. Always returns a ClipboardError with the supplied code.

Implementation Notes

The package version of defineCodes is the canonical helper from @suaveplan/error; every package uses the same pattern so cross- cutting tooling (registry validators, retention checks, OpenSpec conformance) can introspect every namespace identically. Codes are intentionally namespaced strings rather than enums so they remain JSON- serialisable and stable across versions. The metadata table is Object.freeze-d so mutation is a typecheck error and a runtime error; reviewers can diff additions in pull requests without worrying about silent rewrites.