Initial commit
This commit is contained in:
39
src/users/dto/create-user.dto.ts
Normal file
39
src/users/dto/create-user.dto.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import {
|
||||
IsEmail,
|
||||
IsNotEmpty,
|
||||
IsDefined,
|
||||
IsString,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
} from 'class-validator';
|
||||
export class CreateUserDto {
|
||||
// NOTE: Since the id is autoinc, so no id for user creation
|
||||
// @ApiProperty({
|
||||
// type: 'number',
|
||||
// name: 'id',
|
||||
// description: 'id of user',
|
||||
// required: false,
|
||||
// })
|
||||
// id: number;
|
||||
|
||||
@ApiProperty({
|
||||
type: String,
|
||||
name: 'name',
|
||||
description: 'name of user',
|
||||
required: true,
|
||||
})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name: string;
|
||||
|
||||
@ApiProperty({
|
||||
type: Number,
|
||||
name: 'age',
|
||||
description: 'age of user',
|
||||
required: false,
|
||||
})
|
||||
@IsNumber()
|
||||
@IsOptional()
|
||||
age: number;
|
||||
}
|
||||
4
src/users/dto/update-user.dto.ts
Normal file
4
src/users/dto/update-user.dto.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
import { CreateUserDto } from './create-user.dto';
|
||||
|
||||
export class UpdateUserDto extends PartialType(CreateUserDto) {}
|
||||
54
src/users/entities/user.entity.ts
Normal file
54
src/users/entities/user.entity.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { CreateUserDto } from '../dto/create-user.dto';
|
||||
import { UpdateUserDto } from '../dto/update-user.dto';
|
||||
// See: https://cimpleo.com/blog/nestjs-modules-and-swagger-practices/
|
||||
|
||||
// export interface IUser {
|
||||
// id: number;
|
||||
// name: string;
|
||||
// }
|
||||
|
||||
// export class User implements IUser {
|
||||
export class User {
|
||||
@ApiProperty({
|
||||
type: 'number',
|
||||
name: 'id',
|
||||
description: 'id of user',
|
||||
required: false,
|
||||
})
|
||||
id: number;
|
||||
|
||||
@ApiProperty({
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
description: 'name of user',
|
||||
required: false,
|
||||
})
|
||||
name: string;
|
||||
|
||||
protected constructor() {
|
||||
this.id = -1;
|
||||
this.name = '';
|
||||
}
|
||||
|
||||
// Factory methods
|
||||
public static create(id = 0, name = ''): User {
|
||||
const user = new User();
|
||||
user.id = id;
|
||||
user.name = name;
|
||||
return user;
|
||||
}
|
||||
|
||||
public static createFromCreateUserDto(
|
||||
userDto: CreateUserDto | UpdateUserDto,
|
||||
id?: number,
|
||||
): User {
|
||||
const user = new User();
|
||||
if (id) {
|
||||
user.id = id;
|
||||
}
|
||||
user.name = userDto.name;
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
||||
49
src/users/users.controller.ts
Normal file
49
src/users/users.controller.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
Post,
|
||||
Body,
|
||||
Patch,
|
||||
Param,
|
||||
Delete,
|
||||
} from '@nestjs/common';
|
||||
import { ApiResponse } from '@nestjs/swagger';
|
||||
import { UsersService } from './users.service';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { User } from './entities/user.entity';
|
||||
|
||||
@Controller('users')
|
||||
export class UsersController {
|
||||
constructor(private readonly usersService: UsersService) {}
|
||||
|
||||
@Post()
|
||||
create(@Body() createUserDto: CreateUserDto) {
|
||||
return this.usersService.create(createUserDto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
@ApiResponse({ type: [User], status: 200 })
|
||||
async findAll(): Promise<User[]> {
|
||||
return this.usersService.findAll();
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
@ApiResponse({ type: User, status: 200 })
|
||||
async findOne(@Param('id') id: number): Promise<User> {
|
||||
return this.usersService.findOne(+id);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
update(
|
||||
@Param('id') id: number,
|
||||
@Body() updateUserDto: UpdateUserDto,
|
||||
): Promise<User> {
|
||||
return this.usersService.update(+id, updateUserDto);
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove(@Param('id') id: number): Promise<User> {
|
||||
return this.usersService.remove(+id);
|
||||
}
|
||||
}
|
||||
10
src/users/users.module.ts
Normal file
10
src/users/users.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Logger, Module } from '@nestjs/common';
|
||||
import { UsersService } from './users.service';
|
||||
import { UsersController } from './users.controller';
|
||||
import { UserRepository } from './users.repository';
|
||||
|
||||
@Module({
|
||||
controllers: [UsersController],
|
||||
providers: [Logger, UsersService, UserRepository],
|
||||
})
|
||||
export class UsersModule {}
|
||||
72
src/users/users.repository.ts
Normal file
72
src/users/users.repository.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { User } from './entities/user.entity';
|
||||
|
||||
@Injectable()
|
||||
export class UserRepository {
|
||||
constructor(private readonly logger: Logger) {}
|
||||
|
||||
private readonly users = new Map<number, User>();
|
||||
|
||||
public async findAll(): Promise<User[]> {
|
||||
return [...this.users.values()];
|
||||
}
|
||||
|
||||
public async get(id: number): Promise<User> {
|
||||
// const user = this.users.find((user) => user.id === id);
|
||||
if (!this.users.has(id)) {
|
||||
throw new NotFoundException('User not found');
|
||||
}
|
||||
return this.users.get(id);
|
||||
}
|
||||
|
||||
public async add(user: User): Promise<void> {
|
||||
const largestId = Math.max(...Array.from(this.users.keys()));
|
||||
|
||||
// Can get size from map directly but we simulate reading from external service
|
||||
// So calling the method instead
|
||||
// const cnt = await this.count();
|
||||
// await this.get(cnt - 1)
|
||||
// .then((lastuser) => {
|
||||
// id = lastuser.id + 1;
|
||||
// })
|
||||
// .catch(() => {
|
||||
// id = 0;
|
||||
// });
|
||||
|
||||
user.id = largestId < 0 ? 0 : largestId + 1;
|
||||
this.users.set(user.id, user);
|
||||
this.logger.log({ message: 'User added', user });
|
||||
}
|
||||
|
||||
public async update(id: number, user: User): Promise<User> {
|
||||
// Can get size from map directly but we simulate reading from external service
|
||||
// So calling the method instead
|
||||
// It will throw exception if not found.
|
||||
const oldUser = await this.get(id);
|
||||
|
||||
this.users.set(id, user);
|
||||
this.logger.log({ message: 'User updated', from: oldUser, to: user });
|
||||
return oldUser;
|
||||
}
|
||||
|
||||
public async delete(id: number): Promise<User> {
|
||||
let deletedUser: User;
|
||||
await this.get(id)
|
||||
.then((user) => {
|
||||
this.users.delete(id);
|
||||
this.logger.log({ message: 'User deleted', user });
|
||||
deletedUser = user;
|
||||
})
|
||||
.catch(() => {
|
||||
throw new NotFoundException(
|
||||
`User not found, No user deleted, id=${id}`,
|
||||
);
|
||||
});
|
||||
|
||||
return deletedUser;
|
||||
}
|
||||
|
||||
public async count(): Promise<number> {
|
||||
return this.users.size;
|
||||
}
|
||||
}
|
||||
36
src/users/users.service.ts
Normal file
36
src/users/users.service.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { CreateUserDto } from './dto/create-user.dto';
|
||||
import { UpdateUserDto } from './dto/update-user.dto';
|
||||
import { User } from './entities/user.entity';
|
||||
import { UserRepository } from './users.repository';
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly userRepository: UserRepository,
|
||||
) {}
|
||||
|
||||
async create(createUserDto: CreateUserDto): Promise<User> {
|
||||
const user = User.createFromCreateUserDto(createUserDto, -1);
|
||||
await this.userRepository.add(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
async findAll(): Promise<User[]> {
|
||||
return this.userRepository.findAll();
|
||||
}
|
||||
|
||||
async findOne(id: number): Promise<User> {
|
||||
return this.userRepository.get(id);
|
||||
}
|
||||
|
||||
async update(id: number, updateUserDto: UpdateUserDto): Promise<User> {
|
||||
const user = User.createFromCreateUserDto(updateUserDto, id);
|
||||
return this.userRepository.update(id, user);
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<User> {
|
||||
return this.userRepository.delete(id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user