Second layer - repository layer

What for?

Repo layer is used for e.g.:

  • fetching list of users

UserRepository.find(userSearchFilter) -> FindUsersDto

  • upload file

FileRepository.upload(file) -> UploadFileDto

👾

REMBER always return DTOs from repository → models are created from DTOs.

Repository

Repository - is a service that handles HTTP request to our persistance layer (database, fileStorage, etc).

Example Repositories: user.repository.ts, file.repository.ts, analitics.repository.ts.

ℹ️

You can omit reactivity and use Promises instead of Observable.

class UserRepository implements UserRepositoryInterface {
    constructor(private readonly http: HttpClient) {}
 
    find(where: FindUsersFilter): Observable<FindUsersDto> {
        return this.http
            .get<FindUserResponse[]>(`${environment.api}/users`, {params: where})
            .pipe(map(FindUsersDTO.fromResponse))
    }
    create(user: CreateUserBody): Observable<CreateUserDto> {...}
    update(user: UpdateUserBody): Observable<UpdateUserDto> {...}
    delete(id: UserID): Observable<void> {...}
}

Types

Types in repository layer are:

  • repository interfaces
  • inner types libe ...Body, ...Filter, ...Params, etc.
ℹ️

Declare repository interface for easy data provider swap.

interface UserRepositoryInterface {
    find(where: FindUsersFilter): Observable<FindUsersDto>
    create(user: CreateUserBody): Observable<CreateUserDto>
    update(user: UpdateUserBody): Observable<UpdateUserDto>
    delete(id: UserID): Observable<void> // UserID from translations layer
}

Example

Example common feature: users

      • user-repository.interface.ts
      • find-users-filter.ts
    • user.repository.ts
  • class UserRepository implements UserRepositoryInterface {
      constructor(private http: HttpClient) {}
     
      findOne(urlSafeID: UserID): Observable<UserDTO> {
        return this.http
          .get<FindUserResponse>(`/api/users/${urlSafeID}`)
          .pipe(map(UserDTO.fromResponse));
      }
     
      find(where: Partial<FindUsersFilter>): Observable<FindUsersDTO> {
        return this.http
          .get<FindUserResponse[]>('/api/users', { params: where })
          .pipe(map(FindUsersDTO.fromResponse));
      }
     
      update(user: UpdateUserBody): Observable<UpdateUserDto> {
        return this.http
          .put<UpdateUserResponse>(`/api/users/${user.id}`, user)
          .pipe(map(response => new UpdateUserDto(response)));
      }
    }