From 5ff9a31feab05550cbb5fd29adc6c0e067fc7935 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Fri, 14 Aug 2026 14:33:48 +0000 Subject: [PATCH] feat: Implement convenience functions for replacing/clearning component errors --- src/backend/common/AbstractInitializable.ts | 18 ++++++++++- src/core/ErrorUtils.ts | 36 +++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/backend/common/AbstractInitializable.ts b/src/backend/common/AbstractInitializable.ts index ac2513c1..4e744c44 100644 --- a/src/backend/common/AbstractInitializable.ts +++ b/src/backend/common/AbstractInitializable.ts @@ -4,7 +4,7 @@ import { hasNodeNetworkException } from "./errors/NodeErrors.ts"; import { hasUpstreamError } from "./errors/UpstreamError.ts"; import type {WebhookPayload} from "./infrastructure/config/health/webhooks.ts"; import { AuthCheckError, AuthError, BuildDataError, ConnectionCheckError, findAuthIssue, ParseCacheError, PostInitError, StageError, type AuthErrorMap } from "./errors/MSErrors.ts"; -import { messageWithCausesTruncatedDefault } from "../../core/ErrorUtils.ts"; +import { generateErrorTruthyTest, messageWithCausesTruncatedDefault, type TruthyErrorsOpts } from "../../core/ErrorUtils.ts"; import { spawn } from 'abort-controller-x'; import { COMPONENT_AUTH_TYPE, type ComponentAuthType } from "../../core/Atomic.ts"; export default abstract class AbstractInitializable { @@ -386,4 +386,20 @@ export default abstract class AbstractInitializable { public additionalApiData(): Record { return {}; } + + public clearErrors(opts?: TruthyErrorsOpts) { + if (!opts) { this.errors = []; return; } + + const test = generateErrorTruthyTest(opts); + this.errors = this.errors.filter(x => !test(x)); + } + + public replaceErrors(e: Error, opts?: TruthyErrorsOpts) { + if(opts !== undefined) { + this.clearErrors(opts); + } else { + this.clearErrors({instance: e}); + } + this.errors.push(e); + } } diff --git a/src/core/ErrorUtils.ts b/src/core/ErrorUtils.ts index e684e85e..dad67aa2 100644 --- a/src/core/ErrorUtils.ts +++ b/src/core/ErrorUtils.ts @@ -80,3 +80,39 @@ export const getErrorCause = (err: Error | } }; +/** A generic shape for a function (Class) that has a constructor. + * Can be used to determine if the passed function is a (non-instanced) Class */ +type ClassCtor = abstract new (...args: any[]) => unknown; + +export type TruthyErrorsOpts = + | { type: ClassCtor } + | { instance: object } + | { predicate: (e: Error) => boolean }; + +/** + * Generate a function that detects if a given Error... + * + * * passes a truthy function test (predicate) + * * is an instance of a Class (type) + * * is an instance of the Class of a passed instance (instance) + * + * EX, same order as above + * + * generateErrorTruthyTest({ predicate: (e) => e.message === 'x' }) + * generateErrorTruthyTest({ type: MyError) }) + * generateErrorTruthyTest({ instance: new MyError('oops') }) + * + * @returns + */ +export const generateErrorTruthyTest = (opts: TruthyErrorsOpts) => { + + if ('predicate' in opts) { + return (e: Error) => opts.predicate(e); + } + + const ctor = 'type' in opts + ? opts.type + : opts.instance.constructor as ClassCtor; + + return (e: Error) => e instanceof ctor; +} \ No newline at end of file -- 2.51.2