/** * @license * Copyright 2022-2026 Matter.js Authors * SPDX-License-Identifier: Apache-2.0 */ import { Status } from "#globals/Status.js"; import { MatterError, capitalize, decamelize } from "@matter/general"; const specializationIndex = {} as Record StatusResponseError>; /** * Base class for errors that should produce protocol-facing status codes. */ export class StatusResponseError extends MatterError { public constructor( message: string, public readonly code: Status, public readonly clusterCode?: number, ) { super(message); } get bareMessage() { return this.message.replace(/ \(code .+\)$/, ""); } static is(error: unknown, ...codes: Status[]) { const sre = StatusResponseError.of(error); return !!sre && (!codes.length || codes.includes(sre.code)); } override get id() { const id = super.id; if (id === "status-response") { const code = Status[this.code]; if (code) { return decamelize(code); } } return id; } static create(code: Status, message?: string, clusterCode?: number) { const type = specializationIndex[code]; if (type) { return new type(message, clusterCode); } throw new UnknownStatusResponseError(message ?? "Unknown status response", code, clusterCode); } } /** * Thrown for errors that have an unknown {@link Status} code. */ export class UnknownStatusResponseError extends StatusResponseError {} /** * A specialized {@link StatusResponseError} class for each standard {@link Status} code. */ export const StatusResponse = Object.fromEntries( Object.entries(Status) .map(([name, code]) => { if (typeof code !== "number") { return undefined; } const ct = { [name]: class extends StatusResponseError { constructor(message?: string, clusterCode?: number) { if (message === undefined) { message = capitalize(decamelize(name, " ")); } super(message, code as Status, clusterCode); let codeStr = `code ${code}`; if (clusterCode !== undefined) { codeStr = `${codeStr}; cluster code ${clusterCode}`; } this.message = `${message} (${codeStr})`; } }, } as const; const constructor = ct[name]; Object.defineProperty(constructor, "name", { value: name }); specializationIndex[code] = constructor; return [`${name}Error`, constructor]; }) .filter(e => e) as [string, new (message?: string, clusterCode?: number) => StatusResponseError][], ) as Record<`${keyof typeof Status}Error`, new (message?: string, clusterCode?: number) => StatusResponseError>; /** Error class for Status response errors that were received from the other node. */ export class ReceivedStatusResponseError extends StatusResponseError {}