├── .prettierrc ├── tsconfig.build.json ├── example.env ├── nest-cli.json ├── src ├── modules │ ├── product │ │ ├── dto │ │ │ ├── index.ts │ │ │ ├── create-product.dto.ts │ │ │ └── update-product.dto.ts │ │ ├── product.module.ts │ │ ├── product.entity.ts │ │ ├── product.service.ts │ │ ├── product.repository.ts │ │ └── product.controller.ts │ ├── category │ │ ├── dto │ │ │ ├── index.ts │ │ │ ├── create-category.dto.ts │ │ │ └── update-category.dto.ts │ │ ├── category.module.ts │ │ ├── category.entity.ts │ │ ├── category.service.ts │ │ ├── category.repository.ts │ │ └── category.controller.ts │ └── market │ │ ├── dto │ │ ├── index.ts │ │ ├── update-market.dto.ts │ │ ├── create-market.dto.ts │ │ └── market-category.dto.ts │ │ ├── market.module.ts │ │ ├── market.entity.ts │ │ ├── market.repository.ts │ │ ├── market.service.ts │ │ └── market.controller.ts ├── config │ ├── config.interface.ts │ └── index.ts ├── main.ts └── app.module.ts ├── test ├── jest-e2e.json └── app.e2e-spec.ts ├── .gitignore ├── tsconfig.json ├── .eslintrc.js ├── package.json └── README.md /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /example.env: -------------------------------------------------------------------------------- 1 | DB_HOST=localhost 2 | DB_TYPE=postgres 3 | DB_PORT=5432 4 | DB_USERNAME=postgres 5 | DB_PASSWORD=db_password 6 | DB_NAME=test -------------------------------------------------------------------------------- /nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src" 5 | } 6 | -------------------------------------------------------------------------------- /src/modules/product/dto/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CreateProductDto } from './create-product.dto'; 2 | export { default as UpdateProductDto } from './update-product.dto'; 3 | -------------------------------------------------------------------------------- /src/modules/category/dto/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CreateCategoryDto } from './create-category.dto'; 2 | export { default as UpdateCategoryDto } from './update-category.dto'; 3 | -------------------------------------------------------------------------------- /src/modules/market/dto/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CreateMarketDto } from './create-market.dto'; 2 | export { default as UpdateMarketDto } from './update-market.dto'; 3 | export { default as MarketCategoryDto } from './market-category.dto'; 4 | -------------------------------------------------------------------------------- /test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/modules/category/dto/create-category.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class CreateCategoryDto { 5 | @ApiProperty({ 6 | description: 'Title', 7 | example: 'foods', 8 | }) 9 | @IsNotEmpty() 10 | @IsString() 11 | readonly title: string; 12 | } 13 | 14 | export default CreateCategoryDto; 15 | -------------------------------------------------------------------------------- /src/modules/category/dto/update-category.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsString } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class UpdateCategoryDto { 5 | @ApiProperty({ 6 | description: 'Title', 7 | example: 'technologies', 8 | }) 9 | @IsOptional() 10 | @IsString() 11 | readonly title: string; 12 | } 13 | 14 | export default UpdateCategoryDto; 15 | -------------------------------------------------------------------------------- /src/modules/market/dto/update-market.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsString } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class UpdateMarketDto { 5 | @ApiProperty({ 6 | description: 'Title', 7 | example: 'Karzinko', 8 | }) 9 | @IsOptional() 10 | @IsString() 11 | readonly title: string; 12 | 13 | @ApiProperty({ 14 | description: 'Address', 15 | example: 'TTZ-4', 16 | }) 17 | @IsOptional() 18 | @IsString() 19 | readonly address: string; 20 | } 21 | 22 | export default UpdateMarketDto; 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | /.env 5 | 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | pnpm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | lerna-debug.log* 14 | 15 | # OS 16 | .DS_Store 17 | 18 | # Tests 19 | /coverage 20 | /.nyc_output 21 | 22 | # IDEs and editors 23 | /.idea 24 | .project 25 | .classpath 26 | .c9/ 27 | *.launch 28 | .settings/ 29 | *.sublime-workspace 30 | 31 | # IDE - VSCode 32 | .vscode/* 33 | !.vscode/settings.json 34 | !.vscode/tasks.json 35 | !.vscode/launch.json 36 | !.vscode/extensions.json -------------------------------------------------------------------------------- /src/modules/market/dto/create-market.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class CreateMarketDto { 5 | @ApiProperty({ 6 | description: 'Title', 7 | example: 'Makro', 8 | }) 9 | @IsNotEmpty() 10 | @IsString() 11 | readonly title: string; 12 | 13 | @ApiProperty({ 14 | description: 'Address', 15 | example: 'Buyuk Ipak yoli metro', 16 | }) 17 | @IsNotEmpty() 18 | @IsString() 19 | readonly address: string; 20 | } 21 | 22 | export default CreateMarketDto; 23 | -------------------------------------------------------------------------------- /src/modules/market/dto/market-category.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class MarketCategoryDto { 5 | @ApiProperty({ 6 | description: 'MarketId', 7 | example: 'uuid', 8 | }) 9 | @IsNotEmpty() 10 | @IsString() 11 | readonly marketId: string; 12 | 13 | @ApiProperty({ 14 | description: 'CategoryId', 15 | example: 'uuid', 16 | }) 17 | @IsNotEmpty() 18 | @IsString() 19 | readonly categoryId: string; 20 | } 21 | 22 | export default MarketCategoryDto; 23 | -------------------------------------------------------------------------------- /src/config/config.interface.ts: -------------------------------------------------------------------------------- 1 | interface IDatabase { 2 | host: string; 3 | type: string; 4 | name: string; 5 | port: number; 6 | username: string; 7 | password: string; 8 | database: string; 9 | entities: string[]; 10 | synchronize: boolean; 11 | 12 | migrationsRun?: boolean; 13 | logging?: boolean; 14 | autoLoadEntities?: boolean; 15 | migrations?: string[]; 16 | cli?: { 17 | migrationsDir?: string; 18 | }; 19 | } 20 | 21 | export interface IConfig { 22 | port: number; 23 | database: IDatabase; 24 | newPasswordBytes: number; 25 | codeBytes: number; 26 | } 27 | -------------------------------------------------------------------------------- /src/modules/product/product.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { ProductService } from './product.service'; 3 | import { ProductController } from './product.controller'; 4 | import { Product } from './product.entity'; 5 | import { ProductRepository } from './product.repository'; 6 | import { TypeOrmModule } from '@nestjs/typeorm'; 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([Product])], 10 | controllers: [ProductController], 11 | providers: [ProductService, ProductRepository], 12 | exports: [ProductService, ProductRepository], 13 | }) 14 | export class ProductModule {} 15 | -------------------------------------------------------------------------------- /src/modules/market/market.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { MarketService } from './market.service'; 4 | import { MarketController } from './market.controller'; 5 | import { Market } from './market.entity'; 6 | import { CategoryModule } from '../category/category.module'; 7 | import { MarketRepository } from './market.repository'; 8 | 9 | @Module({ 10 | imports: [TypeOrmModule.forFeature([Market]), CategoryModule], 11 | providers: [MarketService, MarketRepository], 12 | controllers: [MarketController], 13 | }) 14 | export class MarketModule {} 15 | -------------------------------------------------------------------------------- /src/modules/category/category.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { CategoryService } from './category.service'; 4 | import { CategoryController } from './category.controller'; 5 | import { Category } from './category.entity'; 6 | import { CategoryRepository } from './category.repository'; 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([Category])], 10 | controllers: [CategoryController], 11 | providers: [CategoryService, CategoryRepository], 12 | exports: [CategoryService, CategoryRepository], 13 | }) 14 | export class CategoryModule {} 15 | -------------------------------------------------------------------------------- /src/modules/product/product.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Column, 3 | BaseEntity, 4 | Entity, 5 | PrimaryGeneratedColumn, 6 | JoinTable, 7 | ManyToOne, 8 | } from 'typeorm'; 9 | import { Category } from '../category/category.entity'; 10 | 11 | @Entity({ name: 'product' }) 12 | export class Product extends BaseEntity { 13 | @PrimaryGeneratedColumn('uuid') 14 | id: string; 15 | 16 | @Column() 17 | name: string; 18 | 19 | @Column() 20 | price: string; 21 | 22 | @ManyToOne(() => Category, (category) => category.products, { 23 | onDelete: 'CASCADE', 24 | }) 25 | @JoinTable() 26 | category: Category; 27 | } 28 | -------------------------------------------------------------------------------- /src/modules/market/market.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Column, 3 | BaseEntity, 4 | Entity, 5 | PrimaryGeneratedColumn, 6 | ManyToMany, 7 | JoinTable, 8 | } from 'typeorm'; 9 | import { Category } from '../category/category.entity'; 10 | 11 | @Entity({ name: 'market' }) 12 | export class Market extends BaseEntity { 13 | @PrimaryGeneratedColumn('uuid') 14 | id: string; 15 | 16 | @Column() 17 | title: string; 18 | 19 | @Column() 20 | address: string; 21 | 22 | @ManyToMany(() => Category, (category) => category.markets, { 23 | onDelete: 'CASCADE', 24 | }) 25 | @JoinTable() 26 | categories: Category[]; 27 | } 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; 3 | import { ValidationPipe } from '@nestjs/common'; 4 | import { AppModule } from './app.module'; 5 | 6 | async function bootstrap() { 7 | const app = await NestFactory.create(AppModule); 8 | 9 | app.useGlobalPipes(new ValidationPipe()); 10 | 11 | const config = new DocumentBuilder() 12 | .setTitle('Markets') 13 | .setDescription('nestjs typeorm reletions') 14 | .setVersion('0.1') 15 | .build(); 16 | const document = SwaggerModule.createDocument(app, config); 17 | SwaggerModule.setup('docs', app, document); 18 | 19 | await app.listen(3000); 20 | } 21 | bootstrap(); 22 | -------------------------------------------------------------------------------- /test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | tsconfigRootDir : __dirname, 6 | sourceType: 'module', 7 | }, 8 | plugins: ['@typescript-eslint/eslint-plugin'], 9 | extends: [ 10 | 'plugin:@typescript-eslint/recommended', 11 | 'plugin:prettier/recommended', 12 | ], 13 | root: true, 14 | env: { 15 | node: true, 16 | jest: true, 17 | }, 18 | ignorePatterns: ['.eslintrc.js'], 19 | rules: { 20 | '@typescript-eslint/interface-name-prefix': 'off', 21 | '@typescript-eslint/explicit-function-return-type': 'off', 22 | '@typescript-eslint/explicit-module-boundary-types': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /src/modules/product/dto/create-product.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsString, IsNumber } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class CreateProductDto { 5 | @ApiProperty({ 6 | description: 'Product name', 7 | example: 'Iphone 14', 8 | }) 9 | @IsNotEmpty() 10 | @IsString() 11 | readonly name: string; 12 | 13 | @ApiProperty({ 14 | description: 'Product price', 15 | example: 2000, 16 | }) 17 | @IsNotEmpty() 18 | @IsNumber() 19 | readonly price: number; 20 | 21 | @ApiProperty({ 22 | description: 'CategoryId', 23 | example: '844acc84-aff3-4f45-8608-be5431e00645', 24 | }) 25 | @IsNotEmpty() 26 | @IsString() 27 | readonly category: string; 28 | } 29 | 30 | export default CreateProductDto; 31 | -------------------------------------------------------------------------------- /src/modules/product/dto/update-product.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsOptional, IsString, IsNumber } from 'class-validator'; 2 | import { ApiProperty } from '@nestjs/swagger'; 3 | 4 | class UpdateProductDto { 5 | @ApiProperty({ 6 | description: 'Product name', 7 | example: 'Iphone 13', 8 | }) 9 | @IsOptional() 10 | @IsString() 11 | readonly name: string; 12 | 13 | @ApiProperty({ 14 | description: 'Product price', 15 | example: 1800, 16 | }) 17 | @IsOptional() 18 | @IsNumber() 19 | readonly price: number; 20 | 21 | @ApiProperty({ 22 | description: 'CategoryId', 23 | example: '844acc84-aff3-4f45-8608-be5431e00645', 24 | }) 25 | @IsOptional() 26 | @IsString() 27 | readonly category: string; 28 | } 29 | 30 | export default UpdateProductDto; 31 | -------------------------------------------------------------------------------- /src/modules/category/category.entity.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Entity, 3 | Column, 4 | PrimaryGeneratedColumn, 5 | BaseEntity, 6 | ManyToMany, 7 | OneToMany, 8 | } from 'typeorm'; 9 | import { Market } from '../market/market.entity'; 10 | import { Product } from '../product/product.entity'; 11 | 12 | @Entity({ name: 'category' }) 13 | export class Category extends BaseEntity { 14 | @PrimaryGeneratedColumn('uuid') 15 | id: string; 16 | 17 | @Column({ 18 | type: 'varchar', 19 | name: 'title', 20 | }) 21 | title: string; 22 | 23 | @ManyToMany(() => Market, (market) => market.categories, { 24 | cascade: true, 25 | onDelete: 'CASCADE', 26 | }) 27 | markets: Market[]; 28 | 29 | @OneToMany(() => Product, (product) => product.category) 30 | products: Product[]; 31 | } 32 | -------------------------------------------------------------------------------- /src/config/index.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv'; 2 | 3 | import { IConfig } from './config.interface'; 4 | 5 | dotenv.config(); 6 | 7 | export default (): IConfig => ({ 8 | port: parseInt(process.env.PORT, 10) || 8000, 9 | 10 | database: { 11 | host: process.env.DB_HOST, 12 | type: process.env.DB_TYPE, 13 | name: 'default', 14 | port: parseInt(process.env.DB_PORT, 10) || 5432, 15 | username: process.env.DB_USERNAME, 16 | password: process.env.DB_PASSWORD, 17 | database: process.env.DB_NAME, 18 | 19 | synchronize: true, 20 | 21 | migrationsRun: false, 22 | 23 | logging: false, 24 | autoLoadEntities: true, 25 | entities: ['./dist/**/*.entity.js'], 26 | // migrations: ['dist/migrations/scripts/*.js'], 27 | // cli: { 28 | // migrationsDir: 'src/migrations/scripts', 29 | // }, 30 | }, 31 | 32 | newPasswordBytes: 4, 33 | codeBytes: 2, 34 | }); 35 | -------------------------------------------------------------------------------- /src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { ConfigModule, ConfigService } from '@nestjs/config'; 4 | import { ScheduleModule } from '@nestjs/schedule'; 5 | import configuration from './config'; 6 | 7 | import { ProductModule } from './modules/product/product.module'; 8 | import { CategoryModule } from './modules/category/category.module'; 9 | import { MarketModule } from './modules/market/market.module'; 10 | 11 | @Module({ 12 | imports: [ 13 | ConfigModule.forRoot({ 14 | isGlobal: true, 15 | load: [configuration], 16 | cache: true, 17 | }), 18 | ScheduleModule.forRoot(), 19 | TypeOrmModule.forRootAsync({ 20 | imports: [ConfigModule], 21 | useFactory: (configService: ConfigService) => 22 | configService.get('database'), 23 | inject: [ConfigService], 24 | }), 25 | ProductModule, 26 | CategoryModule, 27 | MarketModule, 28 | ], 29 | }) 30 | export class AppModule {} 31 | -------------------------------------------------------------------------------- /src/modules/product/product.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; 2 | import { ProductRepository } from './product.repository'; 3 | import { CreateProductDto, UpdateProductDto } from './dto'; 4 | 5 | @Injectable() 6 | export class ProductService { 7 | constructor(private readonly productRepository: ProductRepository) {} 8 | 9 | async getAll() { 10 | const [data, count] = await this.productRepository.getAll(); 11 | return { items: data, totalItemsCount: count }; 12 | } 13 | 14 | async getOne(id: string) { 15 | const product = await this.productRepository.getById(id); 16 | 17 | if (!product) { 18 | throw new HttpException('Product not found', HttpStatus.NOT_FOUND); 19 | } 20 | return product; 21 | } 22 | 23 | async deleteOne(id: string) { 24 | const response = await this.productRepository.remove(id); 25 | return response; 26 | } 27 | 28 | async change(value: UpdateProductDto, id: string) { 29 | const response = await this.productRepository.update(value, id); 30 | return response; 31 | } 32 | 33 | async create(value: CreateProductDto) { 34 | const response = await this.productRepository.create(value); 35 | return response; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/modules/category/category.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; 2 | import { CategoryRepository } from './category.repository'; 3 | import { CreateCategoryDto, UpdateCategoryDto } from './dto'; 4 | 5 | @Injectable() 6 | export class CategoryService { 7 | constructor(private readonly categoryRepository: CategoryRepository) {} 8 | 9 | async getAll() { 10 | const [data, count] = await this.categoryRepository.getAll(); 11 | return { items: data, totalItemsCount: count }; 12 | } 13 | 14 | async getOne(id: string) { 15 | const category = await this.categoryRepository.getById(id); 16 | 17 | if (!category) { 18 | throw new HttpException('Category not found', HttpStatus.NOT_FOUND); 19 | } 20 | return category; 21 | } 22 | 23 | async deleteOne(id: string) { 24 | const response = await this.categoryRepository.remove(id); 25 | return response; 26 | } 27 | 28 | async change(value: UpdateCategoryDto, id: string) { 29 | const response = await this.categoryRepository.update(value, id); 30 | return response; 31 | } 32 | 33 | async create(value: CreateCategoryDto) { 34 | const response = await this.categoryRepository.create(value); 35 | return response; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/modules/category/category.repository.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { InjectRepository } from '@nestjs/typeorm'; 3 | import { Repository, DeleteResult, InsertResult, UpdateResult } from 'typeorm'; 4 | 5 | import { Category } from './category.entity'; 6 | import { CreateCategoryDto, UpdateCategoryDto } from './dto'; 7 | 8 | @Injectable() 9 | export class CategoryRepository { 10 | constructor( 11 | @InjectRepository(Category) 12 | private readonly categoryRepository: Repository, 13 | ) {} 14 | 15 | async getAll() { 16 | return this.categoryRepository 17 | .createQueryBuilder('category') 18 | .getManyAndCount(); 19 | } 20 | 21 | async getById(id: string): Promise { 22 | return this.categoryRepository 23 | .createQueryBuilder('category') 24 | .where('id = :id', { id }) 25 | .getOne(); 26 | } 27 | 28 | async remove(id: string): Promise { 29 | return this.categoryRepository 30 | .createQueryBuilder() 31 | .delete() 32 | .where('id = :id', { id }) 33 | .execute(); 34 | } 35 | 36 | async create(values: CreateCategoryDto): Promise { 37 | return this.categoryRepository 38 | .createQueryBuilder() 39 | .insert() 40 | .into(Category) 41 | .values(values as unknown as Category) 42 | .returning('id') 43 | .execute(); 44 | } 45 | 46 | async update(values: UpdateCategoryDto, id: string): Promise { 47 | return this.categoryRepository 48 | .createQueryBuilder() 49 | .update(Category) 50 | .set(values as unknown as Category) 51 | .where('id = :id', { id }) 52 | .returning('id') 53 | .execute(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/modules/product/product.repository.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { InjectRepository } from '@nestjs/typeorm'; 3 | import { Repository, DeleteResult, InsertResult, UpdateResult } from 'typeorm'; 4 | 5 | import { Product } from './product.entity'; 6 | import { CreateProductDto, UpdateProductDto } from './dto'; 7 | 8 | @Injectable() 9 | export class ProductRepository { 10 | constructor( 11 | @InjectRepository(Product) 12 | private readonly productRepository: Repository, 13 | ) {} 14 | 15 | async getAll() { 16 | return this.productRepository 17 | .createQueryBuilder('product') 18 | .leftJoinAndSelect('product.category', 'category') 19 | .getManyAndCount(); 20 | } 21 | 22 | async getById(id: string): Promise { 23 | return this.productRepository 24 | .createQueryBuilder('product') 25 | .where('product.id = :id', { id }) 26 | .leftJoinAndSelect('product.category', 'category') 27 | .getOne(); 28 | } 29 | 30 | async remove(id: string): Promise { 31 | return this.productRepository 32 | .createQueryBuilder() 33 | .delete() 34 | .where('id = :id', { id }) 35 | .execute(); 36 | } 37 | 38 | async create(values: CreateProductDto): Promise { 39 | return this.productRepository 40 | .createQueryBuilder() 41 | .insert() 42 | .into(Product) 43 | .values(values as unknown as Product) 44 | .returning('id') 45 | .execute(); 46 | } 47 | 48 | async update(values: UpdateProductDto, id: string): Promise { 49 | return this.productRepository 50 | .createQueryBuilder() 51 | .update(Product) 52 | .set(values as unknown as Product) 53 | .where('id = :id', { id }) 54 | .returning('id') 55 | .execute(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/modules/market/market.repository.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { InjectRepository } from '@nestjs/typeorm'; 3 | import { Repository, DeleteResult, InsertResult, UpdateResult } from 'typeorm'; 4 | 5 | import { Market } from './market.entity'; 6 | import { CreateMarketDto, UpdateMarketDto } from './dto'; 7 | 8 | @Injectable() 9 | export class MarketRepository { 10 | constructor( 11 | @InjectRepository(Market) 12 | private readonly marketRepository: Repository, 13 | ) {} 14 | 15 | async getAll() { 16 | return this.marketRepository 17 | .createQueryBuilder('market') 18 | .leftJoinAndSelect('market.categories', 'category') 19 | .getManyAndCount(); 20 | } 21 | 22 | async getByCategory(categoryId: string) { 23 | return this.marketRepository 24 | .createQueryBuilder('market') 25 | .leftJoinAndSelect('market.categories', 'category') 26 | .where('category.id = :id', { id: categoryId }) 27 | .getManyAndCount(); 28 | } 29 | 30 | async getById(id: string): Promise { 31 | return this.marketRepository 32 | .createQueryBuilder('market') 33 | .where('market.id = :id', { id }) 34 | .leftJoinAndSelect('market.categories', 'category') 35 | .getOne(); 36 | } 37 | 38 | async remove(id: string): Promise { 39 | return this.marketRepository 40 | .createQueryBuilder() 41 | .delete() 42 | .where('id = :id', { id }) 43 | .execute(); 44 | } 45 | 46 | async create(values: CreateMarketDto): Promise { 47 | return this.marketRepository 48 | .createQueryBuilder() 49 | .insert() 50 | .into(Market) 51 | .values(values as unknown as Market) 52 | .returning('id') 53 | .execute(); 54 | } 55 | 56 | async update(values: UpdateMarketDto, id: string): Promise { 57 | return this.marketRepository 58 | .createQueryBuilder() 59 | .update(Market) 60 | .set(values as unknown as Market) 61 | .where('id = :id', { id }) 62 | .returning('id') 63 | .execute(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/modules/market/market.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, HttpException, HttpStatus } from '@nestjs/common'; 2 | import { DataSource, EntityManager } from 'typeorm'; 3 | 4 | import { MarketRepository } from './market.repository'; 5 | import { CreateMarketDto, MarketCategoryDto, UpdateMarketDto } from './dto'; 6 | import { CategoryRepository } from '../category/category.repository'; 7 | @Injectable() 8 | export class MarketService { 9 | constructor( 10 | private readonly marketRepository: MarketRepository, 11 | private readonly categoryRepository: CategoryRepository, 12 | private readonly connection: DataSource, 13 | ) {} 14 | 15 | async getAll() { 16 | const [data, count] = await this.marketRepository.getAll(); 17 | return { items: data, totalItemsCount: count }; 18 | } 19 | 20 | async getOne(id: string) { 21 | const market = await this.marketRepository.getById(id); 22 | 23 | if (!market) { 24 | throw new HttpException('Market not found', HttpStatus.NOT_FOUND); 25 | } 26 | return market; 27 | } 28 | 29 | async deleteOne(id: string) { 30 | const response = await this.marketRepository.remove(id); 31 | return response; 32 | } 33 | 34 | async change(value: UpdateMarketDto, id: string) { 35 | const response = await this.marketRepository.update(value, id); 36 | return response; 37 | } 38 | 39 | async create(value: CreateMarketDto) { 40 | const response = await this.marketRepository.create(value); 41 | return response; 42 | } 43 | 44 | async addCategory(value: MarketCategoryDto) { 45 | const market = await this.marketRepository.getById(value.marketId); 46 | const category = await this.categoryRepository.getById(value.categoryId); 47 | 48 | market.categories = market.categories || []; 49 | market.categories.push(category); 50 | 51 | await this.connection.transaction(async (manager: EntityManager) => { 52 | await manager.save(market); 53 | }); 54 | 55 | return market; 56 | } 57 | 58 | async deleteCategory(value: MarketCategoryDto) { 59 | const market = await this.marketRepository.getById(value.marketId); 60 | 61 | market.categories = market.categories 62 | ? market.categories.filter((c) => c.id != value.categoryId) 63 | : []; 64 | 65 | await this.connection.transaction(async (manager: EntityManager) => { 66 | await manager.save(market); 67 | }); 68 | 69 | return market; 70 | } 71 | 72 | async getMarketsByCategory(categoryId: string) { 73 | const [data, count] = await this.marketRepository.getByCategory(categoryId); 74 | return { items: data, totalItemsCount: count }; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs-typeorm-reletions", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "prebuild": "rimraf dist", 10 | "build": "nest build", 11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 12 | "start": "nest start", 13 | "start:dev": "nest start --watch", 14 | "start:debug": "nest start --debug --watch", 15 | "start:prod": "node dist/main", 16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 17 | "test": "jest", 18 | "test:watch": "jest --watch", 19 | "test:cov": "jest --coverage", 20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 21 | "test:e2e": "jest --config ./test/jest-e2e.json" 22 | }, 23 | "dependencies": { 24 | "@nestjs/axios": "^1.0.0", 25 | "@nestjs/common": "^9.2.0", 26 | "@nestjs/config": "^2.2.0", 27 | "@nestjs/core": "^8.0.0", 28 | "@nestjs/platform-express": "^8.0.0", 29 | "@nestjs/schedule": "^2.1.0", 30 | "@nestjs/swagger": "^6.1.3", 31 | "@nestjs/typeorm": "^9.0.1", 32 | "class-transformer": "^0.5.1", 33 | "class-validator": "^0.13.2", 34 | "pg": "^8.8.0", 35 | "reflect-metadata": "^0.1.13", 36 | "rimraf": "^3.0.2", 37 | "rxjs": "^7.2.0", 38 | "typeorm": "^0.3.10" 39 | }, 40 | "devDependencies": { 41 | "@nestjs/cli": "^8.0.0", 42 | "@nestjs/schematics": "^8.0.0", 43 | "@nestjs/testing": "^8.0.0", 44 | "@types/express": "^4.17.13", 45 | "@types/jest": "27.4.1", 46 | "@types/node": "^16.0.0", 47 | "@types/supertest": "^2.0.11", 48 | "@types/uuid": "^8.3.4", 49 | "@typescript-eslint/eslint-plugin": "^5.0.0", 50 | "@typescript-eslint/parser": "^5.0.0", 51 | "eslint": "^8.0.1", 52 | "eslint-config-prettier": "^8.3.0", 53 | "eslint-plugin-prettier": "^4.0.0", 54 | "jest": "^27.2.5", 55 | "prettier": "^2.3.2", 56 | "source-map-support": "^0.5.20", 57 | "supertest": "^6.1.3", 58 | "ts-jest": "^27.0.3", 59 | "ts-loader": "^9.2.3", 60 | "ts-node": "^10.0.0", 61 | "tsconfig-paths": "^3.10.1", 62 | "typescript": "^4.3.5" 63 | }, 64 | "jest": { 65 | "moduleFileExtensions": [ 66 | "js", 67 | "json", 68 | "ts" 69 | ], 70 | "rootDir": "src", 71 | "testRegex": ".*\\.spec\\.ts$", 72 | "transform": { 73 | "^.+\\.(t|j)s$": "ts-jest" 74 | }, 75 | "collectCoverageFrom": [ 76 | "**/*.(t|j)s" 77 | ], 78 | "coverageDirectory": "../coverage", 79 | "testEnvironment": "node" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/modules/product/product.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Controller, 3 | Post, 4 | Body, 5 | HttpCode, 6 | HttpStatus, 7 | HttpException, 8 | Delete, 9 | Patch, 10 | Param, 11 | Get, 12 | } from '@nestjs/common'; 13 | 14 | import { DeleteResult, InsertResult, UpdateResult } from 'typeorm'; 15 | 16 | import { 17 | ApiCreatedResponse, 18 | ApiOkResponse, 19 | ApiTags, 20 | ApiOperation, 21 | } from '@nestjs/swagger'; 22 | 23 | import { Product } from './product.entity'; 24 | import { ProductService } from './product.service'; 25 | import { CreateProductDto, UpdateProductDto } from './dto'; 26 | 27 | @ApiTags('Product') 28 | @Controller('product') 29 | export class ProductController { 30 | constructor(private readonly productService: ProductService) {} 31 | 32 | @Get('/') 33 | @ApiOperation({ summary: 'Method: returns all products' }) 34 | @ApiOkResponse({ 35 | description: 'The products were returned successfully', 36 | }) 37 | @HttpCode(HttpStatus.OK) 38 | async getData(): Promise<{ items: Product[]; totalItemsCount: number }> { 39 | try { 40 | return await this.productService.getAll(); 41 | } catch (err) { 42 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 43 | } 44 | } 45 | 46 | @Get('/:id') 47 | @ApiOperation({ summary: 'Method: returns product by id' }) 48 | @ApiOkResponse({ 49 | description: 'The product was returned successfully', 50 | }) 51 | @HttpCode(HttpStatus.OK) 52 | async getOne(@Param('id') id: string): Promise { 53 | return this.productService.getOne(id); 54 | } 55 | 56 | @Post('/') 57 | @ApiOperation({ summary: 'Method: creates new product' }) 58 | @ApiCreatedResponse({ 59 | description: 'The product was created successfully', 60 | }) 61 | @HttpCode(HttpStatus.CREATED) 62 | async saveData( 63 | @Body() categoryData: CreateProductDto, 64 | ): Promise { 65 | try { 66 | return await this.productService.create(categoryData); 67 | } catch (err) { 68 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 69 | } 70 | } 71 | 72 | @Patch('/:id') 73 | @ApiOperation({ summary: 'Method: updates product by id' }) 74 | @ApiOkResponse({ 75 | description: 'Product was changed', 76 | }) 77 | @HttpCode(HttpStatus.OK) 78 | async changeData( 79 | @Body() categoryData: UpdateProductDto, 80 | @Param('id') id: string, 81 | ): Promise { 82 | try { 83 | return await this.productService.change(categoryData, id); 84 | } catch (err) { 85 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 86 | } 87 | } 88 | 89 | @Delete('/:id') 90 | @ApiOperation({ summary: 'Method: deletes product by id' }) 91 | @ApiOkResponse({ 92 | description: 'Product was deleted', 93 | }) 94 | @HttpCode(HttpStatus.NO_CONTENT) 95 | async deleteData(@Param('id') id: string): Promise { 96 | try { 97 | return await this.productService.deleteOne(id); 98 | } catch (err) { 99 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/modules/category/category.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Controller, 3 | Post, 4 | Body, 5 | HttpCode, 6 | HttpStatus, 7 | HttpException, 8 | Delete, 9 | Patch, 10 | Param, 11 | Get, 12 | } from '@nestjs/common'; 13 | 14 | import { DeleteResult, InsertResult, UpdateResult } from 'typeorm'; 15 | 16 | import { 17 | ApiCreatedResponse, 18 | ApiOkResponse, 19 | ApiTags, 20 | ApiOperation, 21 | } from '@nestjs/swagger'; 22 | 23 | import { Category } from './category.entity'; 24 | import { CategoryService } from './category.service'; 25 | import { CreateCategoryDto, UpdateCategoryDto } from './dto'; 26 | 27 | @ApiTags('Category') 28 | @Controller('category') 29 | export class CategoryController { 30 | constructor(private readonly categoryService: CategoryService) {} 31 | 32 | @Get('/') 33 | @ApiOperation({ summary: 'Method: returns all categories' }) 34 | @ApiOkResponse({ 35 | description: 'The categories were returned successfully', 36 | }) 37 | @HttpCode(HttpStatus.OK) 38 | async getData(): Promise<{ items: Category[]; totalItemsCount: number }> { 39 | try { 40 | return await this.categoryService.getAll(); 41 | } catch (err) { 42 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 43 | } 44 | } 45 | 46 | @Get('/:id') 47 | @ApiOperation({ summary: 'Method: returns single category by id' }) 48 | @ApiOkResponse({ 49 | description: 'The category was returned successfully', 50 | }) 51 | @HttpCode(HttpStatus.OK) 52 | async getOne(@Param('id') id: string): Promise { 53 | return this.categoryService.getOne(id); 54 | } 55 | 56 | @Post('/') 57 | @ApiOperation({ summary: 'Method: creates new category' }) 58 | @ApiCreatedResponse({ 59 | description: 'The category was created successfully', 60 | }) 61 | @HttpCode(HttpStatus.CREATED) 62 | async saveData( 63 | @Body() categoryData: CreateCategoryDto, 64 | ): Promise { 65 | try { 66 | return await this.categoryService.create(categoryData); 67 | } catch (err) { 68 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 69 | } 70 | } 71 | 72 | @Patch('/:id') 73 | @ApiOperation({ summary: 'Method: updates category by id' }) 74 | @ApiOkResponse({ 75 | description: 'Category was changed', 76 | }) 77 | @HttpCode(HttpStatus.OK) 78 | async changeData( 79 | @Body() categoryData: UpdateCategoryDto, 80 | @Param('id') id: string, 81 | ): Promise { 82 | try { 83 | return await this.categoryService.change(categoryData, id); 84 | } catch (err) { 85 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 86 | } 87 | } 88 | 89 | @Delete('/:id') 90 | @ApiOperation({ summary: 'Method: deletes category by id' }) 91 | @ApiOkResponse({ 92 | description: 'Category was deleted', 93 | }) 94 | @HttpCode(HttpStatus.NO_CONTENT) 95 | async deleteData(@Param('id') id: string): Promise { 96 | try { 97 | return await this.categoryService.deleteOne(id); 98 | } catch (err) { 99 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Nest Logo 3 |

4 | 5 | [circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 6 | [circleci-url]: https://circleci.com/gh/nestjs/nest 7 | 8 |

A progressive Node.js framework for building efficient and scalable server-side applications.

9 |

10 | NPM Version 11 | Package License 12 | NPM Downloads 13 | CircleCI 14 | Coverage 15 | Discord 16 | Backers on Open Collective 17 | Sponsors on Open Collective 18 | 19 | Support us 20 | 21 |

22 | 24 | 25 | ## Description 26 | 27 | [Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. 28 | 29 | ## Installation 30 | 31 | ```bash 32 | $ npm install 33 | ``` 34 | 35 | ## Running the app 36 | 37 | ```bash 38 | # development 39 | $ npm run start 40 | 41 | # watch mode 42 | $ npm run start:dev 43 | 44 | # production mode 45 | $ npm run start:prod 46 | ``` 47 | 48 | ## Test 49 | 50 | ```bash 51 | # unit tests 52 | $ npm run test 53 | 54 | # e2e tests 55 | $ npm run test:e2e 56 | 57 | # test coverage 58 | $ npm run test:cov 59 | ``` 60 | 61 | ## Support 62 | 63 | Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). 64 | 65 | ## Stay in touch 66 | 67 | - Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) 68 | - Website - [https://nestjs.com](https://nestjs.com/) 69 | - Twitter - [@nestframework](https://twitter.com/nestframework) 70 | 71 | ## License 72 | 73 | Nest is [MIT licensed](LICENSE). 74 | -------------------------------------------------------------------------------- /src/modules/market/market.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Controller, 3 | Post, 4 | Body, 5 | HttpCode, 6 | HttpStatus, 7 | HttpException, 8 | Delete, 9 | Patch, 10 | Param, 11 | Get, 12 | } from '@nestjs/common'; 13 | 14 | import { DeleteResult, InsertResult, UpdateResult } from 'typeorm'; 15 | 16 | import { 17 | ApiCreatedResponse, 18 | ApiOkResponse, 19 | ApiTags, 20 | ApiOperation, 21 | } from '@nestjs/swagger'; 22 | 23 | import { Market } from './market.entity'; 24 | import { MarketService } from './market.service'; 25 | import { CreateMarketDto, MarketCategoryDto, UpdateMarketDto } from './dto'; 26 | 27 | @ApiTags('Market') 28 | @Controller('market') 29 | export class MarketController { 30 | constructor(private readonly marketService: MarketService) {} 31 | 32 | @Get('/') 33 | @ApiOperation({ summary: 'Method: returns all markets' }) 34 | @ApiOkResponse({ 35 | description: 'The markets were returned successfully', 36 | }) 37 | @HttpCode(HttpStatus.OK) 38 | async getData(): Promise<{ items: Market[]; totalItemsCount: number }> { 39 | try { 40 | return await this.marketService.getAll(); 41 | } catch (err) { 42 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 43 | } 44 | } 45 | 46 | @Get('/:id') 47 | @ApiOperation({ summary: 'Method: returns single market by id' }) 48 | @ApiOkResponse({ 49 | description: 'The market was returned successfully', 50 | }) 51 | @HttpCode(HttpStatus.OK) 52 | async getOne(@Param('id') id: string): Promise { 53 | return this.marketService.getOne(id); 54 | } 55 | 56 | @Get('/category/:id') 57 | @ApiOperation({ summary: 'Method: returns markets by category' }) 58 | @ApiOkResponse({ 59 | description: 'The markets was returned by category', 60 | }) 61 | @HttpCode(HttpStatus.OK) 62 | async getByCategory( 63 | @Param('id') id: string, 64 | ): Promise<{ items: Market[]; totalItemsCount: number }> { 65 | return this.marketService.getMarketsByCategory(id); 66 | } 67 | 68 | @Post('/') 69 | @ApiOperation({ summary: 'Method: creates new market' }) 70 | @ApiCreatedResponse({ 71 | description: 'The market was created successfully', 72 | }) 73 | @HttpCode(HttpStatus.CREATED) 74 | async saveData(@Body() categoryData: CreateMarketDto): Promise { 75 | try { 76 | return await this.marketService.create(categoryData); 77 | } catch (err) { 78 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 79 | } 80 | } 81 | 82 | @Post('/category') 83 | @ApiOperation({ summary: 'Method: adds category to market' }) 84 | @ApiCreatedResponse({ 85 | description: 'The category was added to market successfully', 86 | }) 87 | @HttpCode(HttpStatus.CREATED) 88 | async addCategory(@Body() addData: MarketCategoryDto): Promise { 89 | try { 90 | return await this.marketService.addCategory(addData); 91 | } catch (err) { 92 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 93 | } 94 | } 95 | 96 | @Patch('/:id') 97 | @ApiOperation({ summary: 'Method: updates market by id' }) 98 | @ApiOkResponse({ 99 | description: 'Market was changed', 100 | }) 101 | @HttpCode(HttpStatus.OK) 102 | async changeData( 103 | @Body() categoryData: UpdateMarketDto, 104 | @Param('id') id: string, 105 | ): Promise { 106 | try { 107 | return await this.marketService.change(categoryData, id); 108 | } catch (err) { 109 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 110 | } 111 | } 112 | 113 | @Delete('/:id') 114 | @ApiOperation({ summary: 'Method: deletes market by id' }) 115 | @ApiOkResponse({ 116 | description: 'Market was deleted', 117 | }) 118 | @HttpCode(HttpStatus.NO_CONTENT) 119 | async deleteData(@Param('id') id: string): Promise { 120 | try { 121 | return await this.marketService.deleteOne(id); 122 | } catch (err) { 123 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 124 | } 125 | } 126 | 127 | @Delete('/category/delete') 128 | @ApiOperation({ summary: 'Method: delete category from market' }) 129 | @ApiOkResponse({ 130 | description: 'The category was deleted from market', 131 | }) 132 | @HttpCode(HttpStatus.NO_CONTENT) 133 | async deleteCategory(@Body() deleteData: MarketCategoryDto): Promise { 134 | try { 135 | return await this.marketService.deleteCategory(deleteData); 136 | } catch (err) { 137 | throw new HttpException(err.message, HttpStatus.INTERNAL_SERVER_ERROR); 138 | } 139 | } 140 | } 141 | --------------------------------------------------------------------------------