Что такое репозиторий (repository) в контексте ORM для Node.js?

«Что такое репозиторий (repository) в контексте ORM для Node.js?» — вопрос из категории ORM, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В контексте ORM (Object-Relational Mapping) для Node.js, репозиторий — это паттерн проектирования, который абстрагирует логику доступа к данным. Он действует как посредник между бизнес-логикой приложения и слоем данных (например, базой данных), предоставляя коллекцию-подобный интерфейс для работы с сущностями.

Основная цель: инкапсулировать все операции выборки, сохранения и фильтрации данных для конкретной сущности (например, User, Product) в одном месте.

Пример реализации репозитория с TypeORM (популярная ORM для Node.js/TypeScript):

  1. Определение сущности:
    
    // user.entity.ts
    import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity() export class User { @PrimaryGeneratedColumn() id: number;

@Column() email: string;

@Column() isActive: boolean; }


2.  **Создание кастомного репозитория:**
```typescript
// user.repository.ts
import { EntityRepository, Repository } from 'typeorm';
import { User } from './user.entity';

@EntityRepository(User)
export class UserRepository extends Repository<User> {
  // Кастомный метод для поиска активных пользователей
  async findActiveUsers(): Promise<User[]> {
    return this.createQueryBuilder('user')
      .where('user.isActive = :isActive', { isActive: true })
      .getMany();
  }

  // Метод для поиска по email с проверкой существования
  async findByEmailOrFail(email: string): Promise<User> {
    const user = await this.findOne({ where: { email } });
    if (!user) {
      throw new Error(`User with email ${email} not found`);
    }
    return user;
  }
}
  1. Использование в сервисе:
    
    // user.service.ts
    import { UserRepository } from './user.repository';

class UserService { constructor(private userRepository: UserRepository) {}

async getActiveUsers() { // Используем кастомный метод репозитория return await this.userRepository.findActiveUsers(); }

async createUser(userData: Partial) { // Используем стандартный метод save из Repository const user = this.userRepository.create(userData); return await this.userRepository.save(user); } }



**Преимущества использования репозиториев в Node.js:**
*   **Тестируемость:** Легко подменить реальный репозиторий моком в unit-тестах.
*   **Согласованность:** Все запросы к таблице `users` централизованы в одном классе.
*   **Изоляция бизнес-логики:** Сервисы не зависят от конкретной ORM или способа построения запросов.
*   **Повторное использование:** Сложные запросы, используемые в разных частях приложения, пишутся один раз.

В других ORM, таких как Prisma, паттерн репозитория часто реализуется вручную поверх сгенерированного клиента Prisma для достижения тех же целей абстракции и тестируемости.