error.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import { z, type ZodSchema } from "zod"
  2. import { Log } from "./log"
  3. const log = Log.create()
  4. export abstract class NamedError extends Error {
  5. abstract schema(): ZodSchema
  6. abstract toObject(): { name: string; data: any }
  7. static create<Name extends string, Data extends ZodSchema>(
  8. name: Name,
  9. data: Data,
  10. ) {
  11. const result = class extends NamedError {
  12. public static readonly Schema = z
  13. .object({
  14. name: z.literal(name),
  15. data: data,
  16. })
  17. .openapi({
  18. ref: name,
  19. })
  20. public readonly name = name as Name
  21. constructor(
  22. public readonly data: z.input<Data>,
  23. options?: ErrorOptions,
  24. ) {
  25. super(name, options)
  26. this.name = name
  27. log.error(name, {
  28. ...this.data,
  29. cause: options?.cause?.toString(),
  30. })
  31. }
  32. static isInstance(input: any): input is InstanceType<typeof result> {
  33. return "name" in input && input.name === name
  34. }
  35. schema() {
  36. return result.Schema
  37. }
  38. toObject() {
  39. return {
  40. name: name,
  41. data: this.data,
  42. }
  43. }
  44. }
  45. Object.defineProperty(result, "name", { value: name })
  46. return result
  47. }
  48. public static readonly Unknown = NamedError.create(
  49. "UnknownError",
  50. z.object({
  51. message: z.string(),
  52. }),
  53. )
  54. }