summaryrefslogtreecommitdiffhomepage
path: root/packages/core/src/util/error.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/core/src/util/error.ts')
-rw-r--r--packages/core/src/util/error.ts60
1 files changed, 60 insertions, 0 deletions
diff --git a/packages/core/src/util/error.ts b/packages/core/src/util/error.ts
new file mode 100644
index 000000000..9d3b7c661
--- /dev/null
+++ b/packages/core/src/util/error.ts
@@ -0,0 +1,60 @@
+import z from "zod"
+
+export abstract class NamedError extends Error {
+ abstract schema(): z.core.$ZodType
+ abstract toObject(): { name: string; data: any }
+
+ static hasName(error: unknown, name: string): boolean {
+ return (
+ typeof error === "object" && error !== null && "name" in error && (error as Record<string, unknown>).name === name
+ )
+ }
+
+ static create<Name extends string, Data extends z.core.$ZodType>(name: Name, data: Data) {
+ const schema = z
+ .object({
+ name: z.literal(name),
+ data,
+ })
+ .meta({
+ ref: name,
+ })
+ const result = class extends NamedError {
+ public static readonly Schema = schema
+
+ public override readonly name = name as Name
+
+ constructor(
+ public readonly data: z.input<Data>,
+ options?: ErrorOptions,
+ ) {
+ super(name, options)
+ this.name = name
+ }
+
+ static isInstance(input: any): input is InstanceType<typeof result> {
+ return typeof input === "object" && "name" in input && input.name === name
+ }
+
+ schema() {
+ return schema
+ }
+
+ toObject() {
+ return {
+ name: name,
+ data: this.data,
+ }
+ }
+ }
+ Object.defineProperty(result, "name", { value: name })
+ return result
+ }
+
+ public static readonly Unknown = NamedError.create(
+ "UnknownError",
+ z.object({
+ message: z.string(),
+ }),
+ )
+}