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.
- 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:
- For
Users,Articles,Categories, andComments, REST endpoints with separate router paths should be created:
-
Users(/userroute)GET /user— get all users- Server should answer with
status code200 and all user records
- Server should answer with
GET /user/:id— get single user by id- Server should answer with
status code200 and the record withid === userIdif it exists - Server should answer with
status code400 and corresponding message ifuserIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === userIddoesn't exist
- Server should answer with
POST /user— create userCreateUserDto:interface CreateUserDto { login: string; password: string; role?: 'admin' | 'editor' | 'viewer'; // defaults to 'viewer' }
- Server should answer with
status code201 and newly created record if request is valid - Server should answer with
status code400 and corresponding message if requestbodydoes not contain required fields
- Server should answer with
PUT /user/:id— update user's passwordUpdatePasswordDto:interface UpdatePasswordDto { oldPassword: string; newPassword: string; }
- Server should answer with
status code200 and updated record if request is valid - Server should answer with
status code400 and corresponding message ifuserIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === userIddoesn't exist - Server should answer with
status code403 and corresponding message ifoldPasswordis wrong
- Server should answer with
DELETE /user/:id— delete user- Server should answer with
status code204 if the record is found and deleted - Server should answer with
status code400 and corresponding message ifuserIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === userIddoesn't exist
- Server should answer with
-
Articles(/articleroute)GET /article— get all articles- Server should answer with
status code200 and all article records - Supports optional query parameters for filtering:
status,categoryId,tag(e.g.GET /article?status=published&tag=nodejs)
- Server should answer with
GET /article/:id— get single article by id- Server should answer with
status code200 and the record withid === articleIdif it exists - Server should answer with
status code400 and corresponding message ifarticleIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === articleIddoesn't exist
- Server should answer with
POST /article— create new article- Server should answer with
status code201 and newly created record if request is valid - Server should answer with
status code400 and corresponding message if requestbodydoes not contain required fields (title,content)
- Server should answer with
PUT /article/:id— update article info- Server should answer with
status code200 and updated record if request is valid - Server should answer with
status code400 and corresponding message ifarticleIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === articleIddoesn't exist
- Server should answer with
DELETE /article/:id— delete article- Server should answer with
status code204 if the record is found and deleted - Server should answer with
status code400 and corresponding message ifarticleIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === articleIddoesn't exist
- Server should answer with
-
Categories(/categoryroute)GET /category— get all categories- Server should answer with
status code200 and all category records
- Server should answer with
GET /category/:id— get single category by id- Server should answer with
status code200 and the record withid === categoryIdif it exists - Server should answer with
status code400 and corresponding message ifcategoryIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === categoryIddoesn't exist
- Server should answer with
POST /category— create new category- Server should answer with
status code201 and newly created record if request is valid - Server should answer with
status code400 and corresponding message if requestbodydoes not contain required fields (name,description)
- Server should answer with
PUT /category/:id— update category info- Server should answer with
status code200 and updated record if request is valid - Server should answer with
status code400 and corresponding message ifcategoryIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === categoryIddoesn't exist
- Server should answer with
DELETE /category/:id— delete category- Server should answer with
status code204 if the record is found and deleted - Server should answer with
status code400 and corresponding message ifcategoryIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === categoryIddoesn't exist
- Server should answer with
-
Comments(/commentroute)GET /comment?articleId={articleId}— get all comments for an article- Server should answer with
status code200 and all comment records for the given article articleIdquery parameter is required
- Server should answer with
POST /comment— create new comment- Body must contain
contentandarticleId(both required) - Server should answer with
status code201 and newly created record if request is valid - Server should answer with
status code400 if required fields are missing - Server should answer with
status code422 if the referencedarticleIddoesn't exist
- Body must contain
DELETE /comment/:id— delete comment- Server should answer with
status code204 if the record is found and deleted - Server should answer with
status code400 and corresponding message ifcommentIdis invalid (notuuid) - Server should answer with
status code404 and corresponding message if record withid === commentIddoesn't exist
- Server should answer with
-
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.
-
An
application/jsonformat should be used for request and response body. -
Do not put everything in one file. Organize code by domain using Nest modules (for example:
UserModule,ArticleModule,CategoryModule,CommentModule) with controllers and services. -
User's password should be excluded from server response. -
When you delete a
User, theirauthorIdin correspondingArticlesshould becomenull, and theirCommentsshould be deleted. When you delete aCategory, thecategoryIdin correspondingArticlesshould becomenull. When you delete anArticle, itsCommentsshould be deleted. -
All request bodies should be validated with DTO classes and validation decorators (for example, via a global validation pipe).
-
Use Nest middleware, interceptors, or guards for cross-cutting concerns such as request logging and access checks.
-
Integrate
@nestjs/swaggerto provide OpenAPI documentation accessible at/doc. -
To run the service,
npm startcommand should be used. -
Service should listen on PORT
4000by default, PORT value is stored in.envfile. -
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.roleandArticle.status, prefer TypeScript enums oras constobjects 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', }