entities, init schema migration
This commit is contained in:
		
							parent
							
								
									51344d2018
								
							
						
					
					
						commit
						968d83e58b
					
				
							
								
								
									
										51
									
								
								migrations/1695130227420-init-schema.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								migrations/1695130227420-init-schema.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | import { MigrationInterface, QueryRunner } from 'typeorm'; | ||||||
|  | 
 | ||||||
|  | export class InitSchema1695130227420 implements MigrationInterface { | ||||||
|  |   public async up(queryRunner: QueryRunner): Promise<void> { | ||||||
|  |     await queryRunner.query(` | ||||||
|  |     CREATE TABLE users ( | ||||||
|  |         id serial4 NOT NULL, | ||||||
|  |         "name" varchar NOT NULL, | ||||||
|  |         "password" varchar NOT NULL, | ||||||
|  |         email varchar NOT NULL, | ||||||
|  |         CONSTRAINT "users_pk" PRIMARY KEY (id), | ||||||
|  |         CONSTRAINT "users_email_unique" UNIQUE (email) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     CREATE TABLE swipes ( | ||||||
|  |         id serial4 NOT NULL, | ||||||
|  |         liked bool NOT NULL, | ||||||
|  |         "createdAt" timestamp NOT NULL DEFAULT now(), | ||||||
|  |         "sourceUserId" int4 NULL, | ||||||
|  |         "targetUserId" int4 NULL, | ||||||
|  |         CONSTRAINT "PK_bb38af5831e2c084a78e3622ff6" PRIMARY KEY (id) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     ALTER TABLE swipes ADD CONSTRAINT "swipes_target_user_fk" FOREIGN KEY ("targetUserId") REFERENCES users(id); | ||||||
|  |     ALTER TABLE swipes ADD CONSTRAINT "swipes_source_user_fk" FOREIGN KEY ("sourceUserId") REFERENCES users(id); | ||||||
|  | 
 | ||||||
|  |     CREATE TABLE pairs ( | ||||||
|  |         id serial4 NOT NULL, | ||||||
|  |         CONSTRAINT "pairs_pk" PRIMARY KEY (id) | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     CREATE TABLE "pair-members" ( | ||||||
|  |         "pairId" int4 NOT NULL, | ||||||
|  |         "userId" int4 NOT NULL, | ||||||
|  |         CONSTRAINT "pair_members_pk" PRIMARY KEY ("pairId", "userId") | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     ALTER TABLE "pair-members" ADD CONSTRAINT "pair_members_user_fk" FOREIGN KEY ("userId") REFERENCES users(id); | ||||||
|  |     ALTER TABLE "pair-members" ADD CONSTRAINT "pair_members_pair_fk" FOREIGN KEY ("pairId") REFERENCES pairs(id); | ||||||
|  |     `);
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   public async down(queryRunner: QueryRunner): Promise<void> { | ||||||
|  |     await queryRunner.query(` | ||||||
|  |     DROP TABLE users; | ||||||
|  |     DROP TABLE swipes; | ||||||
|  |     DROP TABLE pairs; | ||||||
|  |     DROP TABLE "pair-members"; | ||||||
|  |     `);
 | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -17,7 +17,9 @@ | |||||||
|     "test:watch": "jest --watch", |     "test:watch": "jest --watch", | ||||||
|     "test:cov": "jest --coverage", |     "test:cov": "jest --coverage", | ||||||
|     "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", |     "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", | ||||||
|     "test:e2e": "jest --config ./test/jest-e2e.json" |     "test:e2e": "jest --config ./test/jest-e2e.json", | ||||||
|  |     "typeorm": "ts-node ./node_modules/typeorm/cli", | ||||||
|  |     "migrate:run": "npm run typeorm migration:run -- -d ./typeorm.config.ts" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@nestjs/common": "^9.0.0", |     "@nestjs/common": "^9.0.0", | ||||||
| @ -51,6 +53,7 @@ | |||||||
|     "@types/express": "^4.17.13", |     "@types/express": "^4.17.13", | ||||||
|     "@types/jest": "29.5.1", |     "@types/jest": "29.5.1", | ||||||
|     "@types/lodash": "^4.14.198", |     "@types/lodash": "^4.14.198", | ||||||
|  |     "@types/multer": "^1.4.7", | ||||||
|     "@types/node": "18.16.12", |     "@types/node": "18.16.12", | ||||||
|     "@types/passport-jwt": "^3.0.9", |     "@types/passport-jwt": "^3.0.9", | ||||||
|     "@types/passport-local": "^1.0.35", |     "@types/passport-local": "^1.0.35", | ||||||
|  | |||||||
| @ -2,6 +2,8 @@ import { Module } from '@nestjs/common'; | |||||||
| import { ConfigModule } from '@nestjs/config'; | import { ConfigModule } from '@nestjs/config'; | ||||||
| import { AuthModule } from './auth/auth.module'; | import { AuthModule } from './auth/auth.module'; | ||||||
| import { TypeOrmModule } from '@nestjs/typeorm'; | import { TypeOrmModule } from '@nestjs/typeorm'; | ||||||
|  | import { SwipesModule } from './swipes/swipes.module'; | ||||||
|  | import { PairsModule } from './pairs/pairs.module'; | ||||||
| 
 | 
 | ||||||
| @Module({ | @Module({ | ||||||
|   imports: [ |   imports: [ | ||||||
| @ -15,8 +17,11 @@ import { TypeOrmModule } from '@nestjs/typeorm'; | |||||||
|       password: process.env.DB_PASSWORD, |       password: process.env.DB_PASSWORD, | ||||||
|       database: process.env.DB_NAME, |       database: process.env.DB_NAME, | ||||||
|       entities: ['dist/**/*.entity.js'], |       entities: ['dist/**/*.entity.js'], | ||||||
|  |       // synchronize: true,
 | ||||||
|       // logging: ['query']
 |       // logging: ['query']
 | ||||||
|     }), |     }), | ||||||
|  |     SwipesModule, | ||||||
|  |     PairsModule, | ||||||
|   ], |   ], | ||||||
| }) | }) | ||||||
| export class AppModule {} | export class AppModule {} | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { NestFactory } from '@nestjs/core'; | import { NestFactory } from '@nestjs/core'; | ||||||
| import cookieParser from 'cookie-parser'; | import * as cookieParser from 'cookie-parser'; | ||||||
| import helmet from 'helmet'; | import helmet from 'helmet'; | ||||||
| import { AppModule } from './app.module'; | import { AppModule } from './app.module'; | ||||||
| import { ValidationPipe } from '@nestjs/common'; | import { ValidationPipe } from '@nestjs/common'; | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								src/pairs/entities/pair-member.entity.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/pairs/entities/pair-member.entity.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | import { Entity, ManyToOne, PrimaryColumn } from 'typeorm'; | ||||||
|  | import { Pair } from './pair.entity'; | ||||||
|  | import { User } from 'src/users/entities/user.entity'; | ||||||
|  | 
 | ||||||
|  | @Entity('pair-members') | ||||||
|  | export class PairMember { | ||||||
|  |   @PrimaryColumn('int', { name: 'pairId' }) | ||||||
|  |   @ManyToOne(() => Pair, (pair) => pair.pairMembers) | ||||||
|  |   pair: Pair; | ||||||
|  | 
 | ||||||
|  |   @PrimaryColumn('int', { name: 'userId' }) | ||||||
|  |   @ManyToOne(() => User) | ||||||
|  |   user: User; | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								src/pairs/entities/pair.entity.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/pairs/entities/pair.entity.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | import { Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; | ||||||
|  | import { PairMember } from './pair-member.entity'; | ||||||
|  | 
 | ||||||
|  | @Entity('pairs') | ||||||
|  | export class Pair { | ||||||
|  |   @PrimaryGeneratedColumn() | ||||||
|  |   id!: number; | ||||||
|  | 
 | ||||||
|  |   @OneToMany(() => PairMember, (pairMember) => pairMember.pair) | ||||||
|  |   pairMembers: PairMember[]; | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/pairs/pairs.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/pairs/pairs.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | |||||||
|  | import { Module } from '@nestjs/common'; | ||||||
|  | import { PairsService } from './pairs.service'; | ||||||
|  | import { TypeOrmModule } from '@nestjs/typeorm'; | ||||||
|  | import { Pair } from './entities/pair.entity'; | ||||||
|  | import { PairMember } from './entities/pair-member.entity'; | ||||||
|  | import { UsersModule } from 'src/users/users.module'; | ||||||
|  | import { Swipe } from 'src/swipes/entities/swipe.entity'; | ||||||
|  | 
 | ||||||
|  | @Module({ | ||||||
|  |   imports: [TypeOrmModule.forFeature([Pair, PairMember, Swipe]), UsersModule], | ||||||
|  |   providers: [PairsService], | ||||||
|  |   exports: [PairsService], | ||||||
|  | }) | ||||||
|  | export class PairsModule {} | ||||||
							
								
								
									
										77
									
								
								src/pairs/pairs.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/pairs/pairs.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | import { Injectable } from '@nestjs/common'; | ||||||
|  | import { Repository } from 'typeorm'; | ||||||
|  | import { Pair } from './entities/pair.entity'; | ||||||
|  | import { InjectRepository } from '@nestjs/typeorm'; | ||||||
|  | import { PairMember } from './entities/pair-member.entity'; | ||||||
|  | import { UsersService } from 'src/users/users.service'; | ||||||
|  | import { | ||||||
|  |   UserIdNotExistsException, | ||||||
|  |   UserNotBelongsToPair, | ||||||
|  | } from 'src/utils/errors'; | ||||||
|  | import { Swipe } from 'src/swipes/entities/swipe.entity'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class PairsService { | ||||||
|  |   constructor( | ||||||
|  |     @InjectRepository(Pair) | ||||||
|  |     private readonly pairsRepository: Repository<Pair>, | ||||||
|  |     @InjectRepository(PairMember) | ||||||
|  |     private readonly pairMembersRepository: Repository<PairMember>, | ||||||
|  |     private readonly usersService: UsersService, | ||||||
|  |   ) {} | ||||||
|  | 
 | ||||||
|  |   async createPair(userIds: [number, number]) { | ||||||
|  |     const users = await this.usersService.getByIds(userIds); | ||||||
|  |     if (users.length !== 2) { | ||||||
|  |       throw new UserIdNotExistsException(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const pair = await this.pairsRepository.manager.transaction( | ||||||
|  |       async (manager) => { | ||||||
|  |         const pair = this.pairsRepository.create(); | ||||||
|  |         await manager.save(pair); | ||||||
|  |         const pairMembers = this.pairMembersRepository.create([ | ||||||
|  |           { | ||||||
|  |             pair, | ||||||
|  |             user: { id: userIds[0] }, | ||||||
|  |           }, | ||||||
|  |           { | ||||||
|  |             pair, | ||||||
|  |             user: { id: userIds[1] }, | ||||||
|  |           }, | ||||||
|  |         ]); | ||||||
|  |         await manager.save(pairMembers); | ||||||
|  |         return pair; | ||||||
|  |       }, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     return pair; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async destroyPair(userId: number, pairId: number) { | ||||||
|  |     const pair = await this.pairsRepository.findOne({ | ||||||
|  |       where: { id: pairId }, | ||||||
|  |       relations: { pairMembers: { user: true } }, | ||||||
|  |     }); | ||||||
|  |     const members = pair.pairMembers; | ||||||
|  |     if (!members.some((member: PairMember) => member.user.id === userId)) { | ||||||
|  |       throw new UserNotBelongsToPair(); | ||||||
|  |     } | ||||||
|  |     const anotherMember = members.find( | ||||||
|  |       (member: PairMember) => member.user.id !== userId, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|  |     await this.pairsRepository.manager.transaction(async (manager) => { | ||||||
|  |       await manager.delete(PairMember, { pair }); | ||||||
|  |       await manager.delete(Pair, { id: pairId }); | ||||||
|  |       await manager.update( | ||||||
|  |         Swipe, | ||||||
|  |         { | ||||||
|  |           sourceUser: { id: userId }, | ||||||
|  |           targetUser: { id: anotherMember.user.id }, | ||||||
|  |         }, | ||||||
|  |         { liked: false }, | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								src/swipes/entities/swipe.entity.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/swipes/entities/swipe.entity.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | |||||||
|  | import { | ||||||
|  |   Column, | ||||||
|  |   CreateDateColumn, | ||||||
|  |   Entity, | ||||||
|  |   ManyToOne, | ||||||
|  |   PrimaryGeneratedColumn, | ||||||
|  | } from 'typeorm'; | ||||||
|  | import { User } from 'src/users/entities/user.entity'; | ||||||
|  | 
 | ||||||
|  | @Entity('swipes') | ||||||
|  | export class Swipe { | ||||||
|  |   @PrimaryGeneratedColumn() | ||||||
|  |   id!: number; | ||||||
|  | 
 | ||||||
|  |   @ManyToOne(() => User, (user) => user.swipes) | ||||||
|  |   sourceUser: User; | ||||||
|  | 
 | ||||||
|  |   @ManyToOne(() => User, (user) => user.swiped) | ||||||
|  |   targetUser: User; | ||||||
|  | 
 | ||||||
|  |   @Column() | ||||||
|  |   liked: boolean; | ||||||
|  | 
 | ||||||
|  |   @CreateDateColumn({ type: 'timestamp' }) | ||||||
|  |   createdAt: Date; | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								src/swipes/swipes.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/swipes/swipes.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | import { Module } from '@nestjs/common'; | ||||||
|  | import { TypeOrmModule } from '@nestjs/typeorm'; | ||||||
|  | import { Swipe } from './entities/swipe.entity'; | ||||||
|  | import { SwipesService } from './swipes.service'; | ||||||
|  | import { UsersModule } from 'src/users/users.module'; | ||||||
|  | import { PairsModule } from 'src/pairs/pairs.module'; | ||||||
|  | 
 | ||||||
|  | @Module({ | ||||||
|  |   imports: [TypeOrmModule.forFeature([Swipe]), UsersModule, PairsModule], | ||||||
|  |   providers: [SwipesService], | ||||||
|  | }) | ||||||
|  | export class SwipesModule {} | ||||||
							
								
								
									
										58
									
								
								src/swipes/swipes.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								src/swipes/swipes.service.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | |||||||
|  | import { Injectable } from '@nestjs/common'; | ||||||
|  | import { Repository } from 'typeorm'; | ||||||
|  | import { Swipe } from './entities/swipe.entity'; | ||||||
|  | import { InjectRepository } from '@nestjs/typeorm'; | ||||||
|  | import { UsersService } from 'src/users/users.service'; | ||||||
|  | import { UserIdNotExistsException } from 'src/utils/errors'; | ||||||
|  | import { PairsService } from 'src/pairs/pairs.service'; | ||||||
|  | 
 | ||||||
|  | @Injectable() | ||||||
|  | export class SwipesService { | ||||||
|  |   constructor( | ||||||
|  |     @InjectRepository(Swipe) | ||||||
|  |     private readonly swipesRepository: Repository<Swipe>, | ||||||
|  |     private readonly usersService: UsersService, | ||||||
|  |     private readonly pairsService: PairsService, | ||||||
|  |   ) {} | ||||||
|  | 
 | ||||||
|  |   async createSwipe( | ||||||
|  |     sourceUserId: number, | ||||||
|  |     targetUserId: number, | ||||||
|  |     liked: boolean, | ||||||
|  |   ) { | ||||||
|  |     const users = await this.usersService.getByIds([ | ||||||
|  |       sourceUserId, | ||||||
|  |       targetUserId, | ||||||
|  |     ]); | ||||||
|  |     if (users.length !== 2) { | ||||||
|  |       throw new UserIdNotExistsException(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const swipe = this.swipesRepository.create({ | ||||||
|  |       sourceUser: { id: sourceUserId }, | ||||||
|  |       targetUser: { id: targetUserId }, | ||||||
|  |       liked, | ||||||
|  |     }); | ||||||
|  |     await this.swipesRepository.save(swipe); | ||||||
|  | 
 | ||||||
|  |     if (liked) { | ||||||
|  |       const answeringLikeSwipe = await this.swipesRepository.findBy({ | ||||||
|  |         sourceUser: { id: targetUserId }, | ||||||
|  |         targetUser: { id: sourceUserId }, | ||||||
|  |       }); | ||||||
|  |       if (answeringLikeSwipe) { | ||||||
|  |         await this.pairsService.createPair([sourceUserId, targetUserId]); // TODO use transaction?
 | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return swipe; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async getSwipesByUser(sourceUserId: number) { | ||||||
|  |     const user = await this.usersService.getById(sourceUserId); | ||||||
|  |     if (!user) { | ||||||
|  |       throw new UserIdNotExistsException(); | ||||||
|  |     } | ||||||
|  |     return this.swipesRepository.findBy({ sourceUser: { id: sourceUserId } }); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,11 +1,7 @@ | |||||||
| import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; | import { Swipe } from 'src/swipes/entities/swipe.entity'; | ||||||
|  | import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; | ||||||
| 
 | 
 | ||||||
| export enum UserRole { | @Entity('users') | ||||||
|   ADMIN = 'admin', |  | ||||||
|   STANDARD = 'standard', |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @Entity('Users') |  | ||||||
| export class User { | export class User { | ||||||
|   @PrimaryGeneratedColumn() |   @PrimaryGeneratedColumn() | ||||||
|   id!: number; |   id!: number; | ||||||
| @ -19,10 +15,9 @@ export class User { | |||||||
|   @Column({ unique: true }) |   @Column({ unique: true }) | ||||||
|   email: string; |   email: string; | ||||||
| 
 | 
 | ||||||
|   @Column({ |   @OneToMany(() => Swipe, (swipe) => swipe.sourceUser) | ||||||
|     type: 'enum', |   swipes: Swipe[]; | ||||||
|     enum: UserRole, | 
 | ||||||
|     default: UserRole.STANDARD, |   @OneToMany(() => Swipe, (swipe) => swipe.targetUser) | ||||||
|   }) |   swiped: Swipe[]; | ||||||
|   role: UserRole; |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,12 +2,16 @@ import { Injectable } from '@nestjs/common'; | |||||||
| import { CreateUserDto } from './dto/create-user.dto'; | import { CreateUserDto } from './dto/create-user.dto'; | ||||||
| import { InjectRepository } from '@nestjs/typeorm'; | import { InjectRepository } from '@nestjs/typeorm'; | ||||||
| import { User } from './entities/user.entity'; | import { User } from './entities/user.entity'; | ||||||
| import { Repository } from 'typeorm'; | import { In, Not, Repository } from 'typeorm'; | ||||||
| import { | import { | ||||||
|   UserEmailNotExistsException, |   UserEmailNotExistsException, | ||||||
|   UserIdNotExistsException, |   UserIdNotExistsException, | ||||||
| } from 'src/utils/errors'; | } from 'src/utils/errors'; | ||||||
| 
 | 
 | ||||||
|  | interface GetOptions { | ||||||
|  |   limit: number; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @Injectable() | @Injectable() | ||||||
| export class UsersService { | export class UsersService { | ||||||
|   constructor( |   constructor( | ||||||
| @ -31,9 +35,38 @@ export class UsersService { | |||||||
|     return user; |     return user; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   async getByIds(ids: number[]) { | ||||||
|  |     return this.usersRepository.findBy({ id: In(ids) }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   async create(userData: CreateUserDto) { |   async create(userData: CreateUserDto) { | ||||||
|     const user = this.usersRepository.create(userData); |     const user = this.usersRepository.create(userData); | ||||||
|     await this.usersRepository.save(user); |     await this.usersRepository.save(user); | ||||||
|     return user; |     return user; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   async get(userId: number, options: GetOptions) { | ||||||
|  |     // TODO get user preferences
 | ||||||
|  | 
 | ||||||
|  |     const user = await this.usersRepository.findBy({ id: userId }); | ||||||
|  |     if (!user) { | ||||||
|  |       throw new UserIdNotExistsException(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const users = await this.usersRepository.find({ | ||||||
|  |       where: { | ||||||
|  |         swiped: { | ||||||
|  |           sourceUser: { | ||||||
|  |             id: Not(userId), | ||||||
|  |           }, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       relations: { | ||||||
|  |         swiped: true, | ||||||
|  |       }, | ||||||
|  |       take: options.limit || 10, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return users; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -29,3 +29,9 @@ export class UserIdNotExistsException extends HttpException { | |||||||
|     super('User with this id does not exist', HttpStatus.NOT_FOUND); |     super('User with this id does not exist', HttpStatus.NOT_FOUND); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export class UserNotBelongsToPair extends HttpException { | ||||||
|  |   constructor() { | ||||||
|  |     super('User do not belongs to this pair', HttpStatus.BAD_REQUEST); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								typeorm.config.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								typeorm.config.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | import { DataSource } from 'typeorm'; | ||||||
|  | import { ConfigService } from '@nestjs/config'; | ||||||
|  | import { config } from 'dotenv'; | ||||||
|  | 
 | ||||||
|  | config(); | ||||||
|  | 
 | ||||||
|  | const configService = new ConfigService(); | ||||||
|  | 
 | ||||||
|  | export default new DataSource({ | ||||||
|  |   type: 'postgres', | ||||||
|  |   host: configService.get('DB_HOST'), | ||||||
|  |   port: +configService.get('DB_PORT'), | ||||||
|  |   username: configService.get('DB_USER'), | ||||||
|  |   password: configService.get('DB_PASSWORD'), | ||||||
|  |   database: configService.get('DB_NAME'), | ||||||
|  |   entities: ['dist/**/*.entity.js'], | ||||||
|  |   migrations: ['migrations/**/*'], | ||||||
|  | }); | ||||||
| @ -1053,6 +1053,13 @@ | |||||||
|   resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" |   resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" | ||||||
|   integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== |   integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== | ||||||
| 
 | 
 | ||||||
|  | "@types/multer@^1.4.7": | ||||||
|  |   version "1.4.7" | ||||||
|  |   resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e" | ||||||
|  |   integrity sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA== | ||||||
|  |   dependencies: | ||||||
|  |     "@types/express" "*" | ||||||
|  | 
 | ||||||
| "@types/node@*": | "@types/node@*": | ||||||
|   version "20.6.0" |   version "20.6.0" | ||||||
|   resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16" |   resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user