Implementing the Entity Service Layer

Introduction: The Role of the Service Layer

Welcome back, API Engineer! In the previous lesson, we created a simple UsersController that returned hardcoded user data. While this works for a small example, controllers shouldn’t handle logic like data storage or retrieval. Their job is to respond to requests, not to “know” how to fetch users. That’s where the service layer comes in.

The service layer is responsible for the business logic of your application. It interacts with data sources (like databases or APIs), applies rules, and returns processed data to the controller. By moving logic to services, we keep controllers lean and make our code modular, testable, and easy to extend.

Quick Recap: Current Setup

Here’s what we currently have in users.controller.ts:

import { Controller, Get } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get('all')
  findAll() {
    return [
      { id: 1, name: 'Alice' },
      { id: 2, name: 'Bob' },
    ];
  }
}

This is fine for a small demo, but as we add features like “find a user by ID,” this logic will get messy. Time to delegate these responsibilities to a UsersService.

Building the UsersService

Let’s build the service layer to handle user data and business logic.

First, create a new file called users.service.ts and add the following code:

import { Injectable, NotFoundException } from '@nestjs/common';

@Injectable()
export class UsersService {
  // Temporary mock data
  private readonly users = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
  ];

  // Return all users
  findAll() {
    return this.users;
  }

  // Find a user by ID
  findOne(id: number) {
    const user = this.users.find(u => u.id === id);
    if (!user) {
      throw new NotFoundException(`User with id ${id} not found`);
    }
    return user;
  }
}

Explanation:

  • @Injectable() marks this class as a service that NestJS can manage. It tells NestJS that this class can be injected as a dependency.
  • The users array holds the user data.
  • findAll() returns the full list of users.
  • findOne(id: number) looks for a user by their ID. If the user is not found, it throws a NotFoundException. This is a built-in NestJS exception that will return a 404 error to the client.

Example Output:

  • Calling findAll() returns:
    [
      { "id": 1, "name": "Alice" },
      { "id": 2, "name": "Bob" }
    ]
  • Calling findOne(1) returns:
    { "id": 1, "name": "Alice" }
  • Calling findOne(99) throws an error:
    Error: User with id 99 not found
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal