From ae5df0e49d8d8edf10772eaf4a72dbccfe976c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adel=20Rodr=C3=ADguez?= Date: Wed, 18 Feb 2026 22:37:30 -0400 Subject: [PATCH] refactor: replace better-result with faultier for error handling --- bun.lock | 12 ++------ packages/error/package.json | 2 +- packages/error/src/auth.ts | 9 ++++-- packages/error/src/email.ts | 10 +++++-- packages/error/src/index.ts | 8 ++++++ packages/error/src/utils.ts | 40 +++++++++++++++------------ packages/utils/src/assert.ts | 4 +-- packages/utils/src/constants/index.ts | 1 - 8 files changed, 49 insertions(+), 37 deletions(-) diff --git a/bun.lock b/bun.lock index 1e452107..b86ee944 100644 --- a/bun.lock +++ b/bun.lock @@ -401,7 +401,7 @@ "packages/error": { "name": "@init/error", "dependencies": { - "better-result": "2.6.0", + "faultier": "2.2.0", }, "devDependencies": { "@tooling/tsconfig": "workspace:*", @@ -2565,8 +2565,6 @@ "better-opn": ["better-opn@3.0.2", "", { "dependencies": { "open": "^8.0.4" } }, "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ=="], - "better-result": ["better-result@2.6.0", "", { "dependencies": { "@clack/prompts": "^0.11.0" }, "bin": { "better-result": "bin/cli.mjs" } }, "sha512-hv31uYHmjFf3zIJgj5V0mT2ZOUg8zDVfd6Pv0iKKGcEAtjukxJofNa0q91cft+YqwHBSQAld5i9zbwgI9alZnA=="], - "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="], "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], @@ -3125,6 +3123,8 @@ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + "faultier": ["faultier@2.2.0", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-7xpHnoewj6kdbLvAYewStw+oKh6a3ZQo5UjSJNMZMoCbxuoGSNZoSVZEDwPjkmOZ1DWl4epEdLNPnNuMxK0eNA=="], + "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="], "fbjs": ["fbjs@3.0.5", "", { "dependencies": { "cross-fetch": "^3.1.5", "fbjs-css-vars": "^1.0.0", "loose-envify": "^1.0.0", "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^1.0.35" } }, "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg=="], @@ -5469,8 +5469,6 @@ "better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], - "better-result/@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], - "bl/readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "boxen/camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="], @@ -6307,10 +6305,6 @@ "better-opn/open/is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], - "better-result/@clack/prompts/@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="], - - "better-result/@clack/prompts/picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "boxen/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "boxen/wrap-ansi/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], diff --git a/packages/error/package.json b/packages/error/package.json index 2cd159aa..7e130aa3 100644 --- a/packages/error/package.json +++ b/packages/error/package.json @@ -16,7 +16,7 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "better-result": "2.6.0" + "faultier": "2.2.0" }, "devDependencies": { "@tooling/tsconfig": "workspace:*", diff --git a/packages/error/src/auth.ts b/packages/error/src/auth.ts index 5a4a099f..1a55cf9e 100644 --- a/packages/error/src/auth.ts +++ b/packages/error/src/auth.ts @@ -1,7 +1,10 @@ -import { TaggedError } from "better-result" +import * as Faultier from "faultier" -export class UnauthenticatedError extends TaggedError("AuthenticationError")() {} +export class UnauthenticatedError extends Faultier.Tagged("UnauthenticatedError")() {} -export class UnauthorizedError extends TaggedError("AuthorizationError")<{ userId: string }>() {} +export class UnauthorizedError extends Faultier.Tagged("UnauthorizedError")<{ + userId: string +}>() {} export type AuthenticationError = UnauthenticatedError | UnauthorizedError +export const AuthFault = Faultier.registry({ UnauthenticatedError, UnauthorizedError }) diff --git a/packages/error/src/email.ts b/packages/error/src/email.ts index 25c984ef..79c014ab 100644 --- a/packages/error/src/email.ts +++ b/packages/error/src/email.ts @@ -1,16 +1,20 @@ -import { TaggedError } from "better-result" +import * as Faultier from "faultier" -export class SendEmailError extends TaggedError("SendEmailError")<{ +export class SendEmailError extends Faultier.Tagged("SendEmailError")<{ emails: string[] subject: string from?: string text: string }>() {} -export class BatchSendEmailError extends TaggedError("BatchSendEmailError")<{ +export class BatchSendEmailError extends Faultier.Tagged("BatchSendEmailError")<{ emails: string[] subject: string from?: string }>() {} +export const EmailFault = Faultier.registry({ + BatchSendEmailError, + SendEmailError, +}) export type EmailError = SendEmailError | BatchSendEmailError diff --git a/packages/error/src/index.ts b/packages/error/src/index.ts index 1017f281..7bac5e8c 100644 --- a/packages/error/src/index.ts +++ b/packages/error/src/index.ts @@ -1,9 +1,17 @@ +import * as Faultier from "faultier" import type { AuthenticationError } from "#auth.ts" import type { EmailError } from "#email.ts" import type { UtilityError } from "#utils.ts" +import { AuthFault } from "#auth.ts" +import { EmailFault } from "#email.ts" +import { UtilityFault } from "#utils.ts" + +export const AppFault = Faultier.merge(AuthFault, EmailFault, UtilityFault) export type AppError = AuthenticationError | EmailError | UtilityError export * from "#auth.ts" export * from "#email.ts" export * from "#utils.ts" + +export { matchTag, matchTags, Fault } from "faultier" diff --git a/packages/error/src/utils.ts b/packages/error/src/utils.ts index 713b2b49..43173842 100644 --- a/packages/error/src/utils.ts +++ b/packages/error/src/utils.ts @@ -1,28 +1,20 @@ -import { TaggedError } from "better-result" +import * as Faultier from "faultier" -export class InvalidDurationParseInputError extends TaggedError("InvalidDurationParseInputError")<{ - message: string +export class InvalidDurationParseInputError extends Faultier.Tagged( + "InvalidDurationParseInputError" +)<{ value: string -}>() { - constructor(props: { value: string }) { - super({ ...props, message: `Unable to parse duration from input: "${props.value}"` }) - } -} +}>() {} -export class InvalidDurationFormatInputError extends TaggedError( +export class InvalidDurationFormatInputError extends Faultier.Tagged( "InvalidDurationFormatInputError" -)<{ message: string }>() { - constructor() { - super({ message: "Invalid duration format provided" }) - } -} +)() {} -export class AssertUnreachableError extends TaggedError("AssertUnreachableError")<{ +export class AssertUnreachableError extends Faultier.Tagged("AssertUnreachableError")<{ value: unknown }>() {} -export class AssertConditionFailedError extends TaggedError("AssertConditionFailedError")<{ - message: string +export class AssertConditionFailedError extends Faultier.Tagged("AssertConditionFailedError")<{ condition: string }>() {} @@ -30,4 +22,16 @@ export type DurationError = InvalidDurationParseInputError | InvalidDurationForm export type AssertError = AssertUnreachableError | AssertConditionFailedError -export type UtilityError = DurationError | AssertError +export class InvalidBaseUrlError extends Faultier.Tagged("InvalidBaseUrlError")<{ + value: string +}>() {} + +export const UtilityFault = Faultier.registry({ + AssertConditionFailedError, + AssertUnreachableError, + InvalidBaseUrlError, + InvalidDurationFormatInputError, + InvalidDurationParseInputError, +}) + +export type UtilityError = DurationError | AssertError | InvalidBaseUrlError diff --git a/packages/utils/src/assert.ts b/packages/utils/src/assert.ts index 05bb6634..5c00f2a8 100644 --- a/packages/utils/src/assert.ts +++ b/packages/utils/src/assert.ts @@ -13,7 +13,7 @@ export function assertUnreachable(x: never): never { */ export function throwUnless(condition: boolean, message: string): asserts condition is true { if (!condition) { - throw new AssertConditionFailedError({ condition: "throwUnless", message }) + throw new AssertConditionFailedError({ condition: "throwUnless" }).withMessage(message) } } @@ -22,6 +22,6 @@ export function throwUnless(condition: boolean, message: string): asserts condit */ export function throwIf(condition: boolean, message: string): asserts condition is false { if (condition) { - throw new AssertConditionFailedError({ condition: "throwIf", message }) + throw new AssertConditionFailedError({ condition: "throwIf" }).withMessage(message) } } diff --git a/packages/utils/src/constants/index.ts b/packages/utils/src/constants/index.ts index c7c29c36..8b8514e1 100644 --- a/packages/utils/src/constants/index.ts +++ b/packages/utils/src/constants/index.ts @@ -1,3 +1,2 @@ export * from "#constants/app.ts" export * from "#constants/asset.ts" -