feat: init project and add user module

This commit is contained in:
2026-02-17 12:29:31 +03:30
commit b9779f7cb6
29 changed files with 11774 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
import { Transform } from 'class-transformer';
import {
IsNotEmpty,
IsString,
Matches,
MaxLength,
MinLength,
} from 'class-validator';
import Utils from '@/common/utils';
import { i18nValidationMessage as t } from 'nestjs-i18n';
import { ApiProperty } from '@nestjs/swagger';
export class CreateUserDTO {
@ApiProperty({
type: 'string',
description: `User's Firstname`,
example: 'Radmehr',
required: true,
})
@IsString()
@IsNotEmpty({
message: t('validation.requiredField', {
field: '$t(users.fields.firstName)',
}),
})
@MinLength(3, {
message: t('validation.minLengthField', {
field: '$t(users.fields.firstName)',
min: 3,
}),
})
@MaxLength(96, {
message: t('validation.maxLengthField', {
field: '$t(users.fields.firstName)',
max: 96,
}),
})
firstName: string;
@ApiProperty({
type: 'string',
description: `User's Lastname`,
example: 'Tarnas',
required: true,
})
@IsString()
@IsNotEmpty({
message: t('validation.requiredField', {
field: '$t(users.fields.lastName)',
}),
})
@MinLength(3, {
message: t('validation.minLengthField', {
field: '$t(users.fields.lastName)',
min: 3,
}),
})
@MaxLength(96, {
message: t('validation.maxLengthField', {
field: '$t(users.fields.lastName)',
min: 3,
}),
})
lastName: string;
@ApiProperty({
type: 'string',
description: `User's Phone Number`,
example: '09121111111',
required: true,
})
@IsString()
@IsNotEmpty({
message: t('validation.requiredField', {
field: '$t(users.fields.phone)',
}),
})
@Matches(/^(?:09|9)[0-9]{9}$/, {
message: t('validation.wrongField', {
field: '$t(users.fields.phone)',
}),
})
@Transform(({ value }) => Utils.StringUtils.normalizePhone(value as string))
phone: string;
@ApiProperty({
type: 'string',
description: 'Password for User Account',
example: 'Password1@',
required: true,
})
@IsString()
@IsNotEmpty({
message: t('validation.requiredField', {
field: '$t(users.fields.password)',
}),
})
@MinLength(8, {
message: t('validation.minLengthField', {
field: '$t(users.fields.password)',
min: 8,
}),
})
@MaxLength(96, {
message: t('validation.maxLengthField', {
field: '$t(users.fields.password)',
min: 96,
}),
})
@Matches(/^(?=.*[A-Za-z])(?=.*\d)(?=.*[^A-Za-z\d]).{8,}$/, {
message: t('users.errors.passwordPattern'),
})
password: string;
}
@@ -0,0 +1,3 @@
GET http://localhost:3000/users
GET http://localhost:3000/users/2
@@ -0,0 +1,10 @@
POST http://localhost:3000/users
Content-Type: application/json
lang: fa
{
"firstName": "Ra",
"lastName": "Tnas",
"phone": "9333026363",
"password": "ra"
}
@@ -0,0 +1,31 @@
import { Injectable, RequestTimeoutException } from '@nestjs/common';
import { Repository } from 'typeorm';
import { User } from '../user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateUserDTO } from '../dto/create-user.dto';
@Injectable()
export class UsersService {
constructor(
/**
* Injecting User Repository
*/
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
public async createOne(createUserDto: CreateUserDTO) {
const newUser = this.userRepository.create(createUserDto);
try {
await this.userRepository.save(newUser);
} catch (err) {
throw new RequestTimeoutException(
'Unable to process your request at the moment. Please try again later.',
{ cause: err, description: 'Error connecting to the database' },
);
}
return newUser;
}
}
+48
View File
@@ -0,0 +1,48 @@
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: 'varchar',
length: 96,
nullable: false,
})
firstName: string;
@Column({
type: 'varchar',
length: 96,
nullable: false,
})
lastName: string;
@Column({
type: 'varchar',
length: 11,
nullable: false,
unique: true,
})
phone: string;
@Column({
type: 'varchar',
length: 96,
nullable: false,
})
password: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
+35
View File
@@ -0,0 +1,35 @@
import {
Body,
Controller,
Get,
Param,
ParseIntPipe,
Post,
} from '@nestjs/common';
import { CreateUserDTO } from './dto/create-user.dto';
import { UsersService } from './providers/users.service';
@Controller('users')
export class UsersController {
constructor(
/**
* Injecting Users Service
*/
private readonly usersService: UsersService,
) {}
@Get()
public getAllUsers() {
return ['user1', 'user2'];
}
@Get(':id')
public getUserById(@Param('id', ParseIntPipe) id: number) {
return `user ${id}`;
}
@Post()
public async createUser(@Body() createUserDto: CreateUserDTO) {
return await this.usersService.createOne(createUserDto);
}
}
+12
View File
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './providers/users.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}