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.