Sikau

NestJS · Day 13 · about 35 min

Data access and repositories

Keep the database behind an interface.

Swap the storage, keep the logic

Services shouldn't care whether data lives in PostgreSQL, MongoDB or memory. The repository pattern puts data access behind a small set of methods (findAll, findById, save). Nest projects do this with TypeORM, Prisma or Mongoose — and you can swap an in-memory version in for tests.

An abstract repository token

export abstract class DishesRepository {
  abstract findAll(): Promise<Dish[]>;
  abstract findById(id: number): Promise<Dish | null>;
  abstract save(dish: Omit<Dish, "id">): Promise<Dish>;
}

@Injectable()
export class InMemoryDishesRepository extends DishesRepository {
  private rows: Dish[] = [];
  async findAll() { return this.rows; }
  async findById(id: number) { return this.rows.find((d) => d.id === id) ?? null; }
  async save(dish: Omit<Dish, "id">) {
    const row = { id: this.rows.length + 1, ...dish };
    this.rows.push(row);
    return row;
  }
}

// app.module.ts
providers: [DishesService, { provide: DishesRepository, useClass: InMemoryDishesRepository }]
// production: { provide: DishesRepository, useClass: PrismaDishesRepository }
  • Prisma (Prisma course): a PrismaService extends PrismaClient; repositories call this.prisma.dish.findMany().
  • TypeORM: @Entity classes and @InjectRepository(Dish).
  • Keep database types out of controllers; return plain objects or DTOs.

The rest of this lesson

  • Prisma behind a repositoryexplain
  • Transactions and boundariesexplain
  • Who decides the storage?predict
  • Which implementation where?match
  • Your turnwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 15 lessons of NestJS