Skip to content

Latest commit

 

History

History
197 lines (166 loc) · 10.6 KB

File metadata and controls

197 lines (166 loc) · 10.6 KB

Assignment: Nest.js Knowledge Hub API

Description

Your task is to create a REST API for a Knowledge Hub platform using the Nest.js framework. The Knowledge Hub allows users to create, edit, and organize articles by categories and tags.

Technical requirements

  • Task should be implemented in TypeScript
  • Use Nest.js as the application framework
  • Use 24.x.x version (24.10.0 or upper) of Node.js

NB! You must create a new repository from template for this task. Its name must match the current period of the course (for example, for Node.js 2026 Q1 it'll be nodejs-2026q1-knowledge-hub), i.e. full link to the repository must be https://github.com/%your-github-id%/nodejs-2026q1-knowledge-hub.

Create an application that operates with the following resources:

  • User (with attributes):

    interface User {
      id: string; // uuid v4
      login: string;
      password: string;
      role: 'admin' | 'editor' | 'viewer';
      createdAt: number; // timestamp of creation
      updatedAt: number; // timestamp of last update
    }
  • Article (with attributes):

    interface Article {
      id: string; // uuid v4
      title: string;
      content: string;
      status: 'draft' | 'published' | 'archived';
      authorId: string | null; // refers to User
      categoryId: string | null; // refers to Category
      tags: string[]; // array of tag names
      createdAt: number; // timestamp of creation
      updatedAt: number; // timestamp of last update
    }
  • Category (with attributes):

    interface Category {
      id: string; // uuid v4
      name: string;
      description: string;
    }
  • Comment (with attributes):

    interface Comment {
      id: string; // uuid v4
      content: string;
      articleId: string; // refers to Article
      authorId: string | null; // refers to User
      createdAt: number; // timestamp of creation
    }

Details:

  1. For Users, Articles, Categories, and Comments, REST endpoints with separate router paths should be created:
  • Users (/user route)

    • GET /user — get all users
      • Server should answer with status code 200 and all user records
    • GET /user/:id — get single user by id
      • Server should answer with status code 200 and the record with id === userId if it exists
      • Server should answer with status code 400 and corresponding message if userId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === userId doesn't exist
    • POST /user — create user CreateUserDto:
      interface CreateUserDto {
        login: string;
        password: string;
        role?: 'admin' | 'editor' | 'viewer'; // defaults to 'viewer'
      }
      • Server should answer with status code 201 and newly created record if request is valid
      • Server should answer with status code 400 and corresponding message if request body does not contain required fields
    • PUT /user/:id — update user's password UpdatePasswordDto:
      interface UpdatePasswordDto {
        oldPassword: string;
        newPassword: string;
      }
      • Server should answer with status code 200 and updated record if request is valid
      • Server should answer with status code 400 and corresponding message if userId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === userId doesn't exist
      • Server should answer with status code 403 and corresponding message if oldPassword is wrong
    • DELETE /user/:id — delete user
      • Server should answer with status code 204 if the record is found and deleted
      • Server should answer with status code 400 and corresponding message if userId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === userId doesn't exist
  • Articles (/article route)

    • GET /article — get all articles
      • Server should answer with status code 200 and all article records
      • Supports optional query parameters for filtering: status, categoryId, tag (e.g. GET /article?status=published&tag=nodejs)
    • GET /article/:id — get single article by id
      • Server should answer with status code 200 and the record with id === articleId if it exists
      • Server should answer with status code 400 and corresponding message if articleId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === articleId doesn't exist
    • POST /article — create new article
      • Server should answer with status code 201 and newly created record if request is valid
      • Server should answer with status code 400 and corresponding message if request body does not contain required fields (title, content)
    • PUT /article/:id — update article info
      • Server should answer with status code 200 and updated record if request is valid
      • Server should answer with status code 400 and corresponding message if articleId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === articleId doesn't exist
    • DELETE /article/:id — delete article
      • Server should answer with status code 204 if the record is found and deleted
      • Server should answer with status code 400 and corresponding message if articleId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === articleId doesn't exist
  • Categories (/category route)

    • GET /category — get all categories
      • Server should answer with status code 200 and all category records
    • GET /category/:id — get single category by id
      • Server should answer with status code 200 and the record with id === categoryId if it exists
      • Server should answer with status code 400 and corresponding message if categoryId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === categoryId doesn't exist
    • POST /category — create new category
      • Server should answer with status code 201 and newly created record if request is valid
      • Server should answer with status code 400 and corresponding message if request body does not contain required fields (name, description)
    • PUT /category/:id — update category info
      • Server should answer with status code 200 and updated record if request is valid
      • Server should answer with status code 400 and corresponding message if categoryId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === categoryId doesn't exist
    • DELETE /category/:id — delete category
      • Server should answer with status code 204 if the record is found and deleted
      • Server should answer with status code 400 and corresponding message if categoryId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === categoryId doesn't exist
  • Comments (/comment route)

    • GET /comment?articleId={articleId} — get all comments for an article
      • Server should answer with status code 200 and all comment records for the given article
      • articleId query parameter is required
    • POST /comment — create new comment
      • Body must contain content and articleId (both required)
      • Server should answer with status code 201 and newly created record if request is valid
      • Server should answer with status code 400 if required fields are missing
      • Server should answer with status code 422 if the referenced articleId doesn't exist
    • DELETE /comment/:id — delete comment
      • Server should answer with status code 204 if the record is found and deleted
      • Server should answer with status code 400 and corresponding message if commentId is invalid (not uuid)
      • Server should answer with status code 404 and corresponding message if record with id === commentId doesn't exist
  1. For now, these endpoints should operate only with in-memory (hardcoded) data. In the next tasks we will use a database for it. You should organize your modules with the consideration that the data source will be changed soon.

  2. An application/json format should be used for request and response body.

  3. Do not put everything in one file. Organize code by domain using Nest modules (for example: UserModule, ArticleModule, CategoryModule, CommentModule) with controllers and services.

  4. User's password should be excluded from server response.

  5. When you delete a User, their authorId in corresponding Articles should become null, and their Comments should be deleted. When you delete a Category, the categoryId in corresponding Articles should become null. When you delete an Article, its Comments should be deleted.

  6. All request bodies should be validated with DTO classes and validation decorators (for example, via a global validation pipe).

  7. Use Nest middleware, interceptors, or guards for cross-cutting concerns such as request logging and access checks.

  8. Integrate @nestjs/swagger to provide OpenAPI documentation accessible at /doc.

  9. To run the service, npm start command should be used.

  10. Service should listen on PORT 4000 by default, PORT value is stored in .env file.

  11. Incoming requests should be validated.

Hints:

  • To generate all entities ids use Node.js randomUUID.

  • Use Nest module boundaries and dependency injection to keep business logic out of controllers.

  • Use DTOs and validation pipes for request validation.

  • For finite value sets like User.role and Article.status, prefer TypeScript enums or as const objects to avoid magic strings across DTOs, services, and validation schemas.

    export enum UserRole {
      ADMIN = 'admin',
      EDITOR = 'editor',
      VIEWER = 'viewer',
    }
    
    export enum ArticleStatus {
      DRAFT = 'draft',
      PUBLISHED = 'published',
      ARCHIVED = 'archived',
    }