api/lib: custom errors (like Rails) & prisma db handler

Pedro Lucas Porcellis porcellis@eletrotupi.com 3 months ago abfe26d7a95d86ed42914c995418cc1ffcf634ed
Parents: 1092316
4 file(s) changed
  • api/src/lib/errors/AuthErrors.ts +9 -0
  • api/src/lib/errors/UserErrors.ts +28 -0
  • api/src/lib/errors/base.ts +14 -0
  • api/src/lib/prisma.ts +1 -1
api/src/lib/errors/AuthErrors.ts
@@ -0,0 +1,9 @@
1 + import { DomainError } from "./base";
2 +
3 + export class InvalidCredentialsError extends DomainError {
4 + constructor() { super("Invalid email or password", 401); }
5 + }
6 +
7 + export class UnauthorizedError extends DomainError {
8 + constructor() { super("You must be logged in", 401); }
9 + }
api/src/lib/errors/UserErrors.ts
@@ -0,0 +1,28 @@
1 + import { DomainError } from "./base";
2 +
3 + export class MissingFieldsError extends DomainError {
4 + constructor(fields: string[]) {
5 + super(`Missing required fields: ${fields.join(", ")}`, 400);
6 + }
7 + }
8 +
9 + export class ShortPasswordError extends DomainError {
10 + constructor() { super("Password must be at least 8 characters", 400); }
11 + }
12 +
13 + export class DuplicateEmailError extends DomainError {
14 + constructor(email: string) { super(`${email} is already in use`, 409); }
15 + }
16 +
17 + export class InvalidEmailError extends DomainError {
18 + constructor() {
19 + super(`Email is invalid`, 400);
20 + }
21 + }
22 +
23 +
24 + export class UserNotFoundError extends DomainError {
25 + constructor(id?: number) {
26 + super(id ? `User ${id} not found` : "User not found", 404);
27 + }
28 + }
api/src/lib/errors/base.ts
@@ -0,0 +1,14 @@
1 + // The shared shape all domain errors conform to.
2 + // The type guard solves the `unknown` catch problem everywhere.
3 +
4 + export class DomainError extends Error {
5 + constructor(public readonly message: string, public readonly status: number) {
6 + super(message);
7 + this.name = this.constructor.name; // makes logs say "DuplicateEmailError" not "Error"
8 + Object.setPrototypeOf(this, new.target.prototype); // fixes instanceof after transpile
9 + }
10 + }
11 +
12 + export function isDomainError(err: unknown): err is DomainError {
13 + return err instanceof DomainError;
14 + }
api/src/lib/prisma.ts
@@ -1,6 +1,6 @@
1 1 import "dotenv/config"
2 2 import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3';
3 - import { PrismaClient } from '../generated/prisma/client';
3 + import { PrismaClient } from '@prisma/client';
4 4
5 5 const connectionStr = `${process.env.DATABASE_URL}`;
6 6