Menu
CoddyTech

The Same API

Part of the TypeScript and NestJS section of Coddy's Node.js journey. Lesson 17 of 17.

Section 3's clients call /api/v1/tasks and use ?q=, ?sort= and ?limit=. These are the last pieces between your Nest API and that contract.

app.setGlobalPrefix('api/v1') in main.ts moves every route under the prefix, with no controller changed. The query rules are the ones you wrote in section 3, now in findAll.

const byPrice = [...products].sort((a, b) => a.price - b.price);

Sort a copy: sort reorders the array it is called on, and the service's array would stay reordered for every later request. Throw BadRequestException for a field you do not sort by; your filter gives it the error shape.

challenge icon

Challenge

Easy
  • Every route moves under /api/v1.
  • GET /api/v1/tasks: ?q= matches titles containing it, any case; ?sort= takes title or createdAt, - for descending, else 400; ?limit= sets the page size, default PAGE_SIZE, at most 50.
  • Send GET /api/v1/tasks?sort=-title&limit=3, then ?sort=colour.

Try it yourself

import { Body, Controller, Delete, Get, HttpCode, Inject, Param, ParseIntPipe, Post, Query, UseGuards } from '@nestjs/common';
import { ApiKeyGuard } from '../common/api-key.guard';
import { CreateTaskDto } from './dto/create-task.dto';
import { Task, TasksService } from './tasks.service';

@Controller('tasks')
export class TasksController {
    constructor(
        private readonly tasksService: TasksService,
        @Inject('PAGE_SIZE') private readonly pageSize: number,
    ) {}

    @Get()
    findAll(@Query('done') done?: string, @Query('page') page = '1') {
        const tasks = this.tasksService.findAll(done);
        const current = Number(page);
        const start = (current - 1) * this.pageSize;
        return {
            items: tasks.slice(start, start + this.pageSize),
            page: current,
            total: tasks.length,
            pages: Math.ceil(tasks.length / this.pageSize),
        };
    }

    @Get(':id')
    findOne(@Param('id', ParseIntPipe) id: number): Task {
        return this.tasksService.findOne(id);
    }

    @Post()
    @UseGuards(ApiKeyGuard)
    create(@Body() dto: CreateTaskDto): Task {
        return this.tasksService.create(dto);
    }

    @Delete(':id')
    @UseGuards(ApiKeyGuard)
    @HttpCode(204)
    remove(@Param('id', ParseIntPipe) id: number): void {
        this.tasksService.remove(id);
    }
}

All lessons in TypeScript and NestJS