Разделение методов создания и обновления элементов, добавление полей author, description, service_name. Исправление бага при котором не удалялось апи. Удаление из ответа лишних полей __v и _id
This commit is contained in:
24
.eslintrc.js
24
.eslintrc.js
@ -1,24 +0,0 @@
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
project: 'tsconfig.json',
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/eslint-recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'prettier',
|
||||
'prettier/@typescript-eslint',
|
||||
],
|
||||
root: true,
|
||||
env: {
|
||||
node: true,
|
||||
jest: true,
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/interface-name-prefix': 'off',
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
},
|
||||
};
|
||||
25
.eslintrc.json
Normal file
25
.eslintrc.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "tsconfig.json",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint/eslint-plugin"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier",
|
||||
"prettier/@typescript-eslint"
|
||||
],
|
||||
"root": true,
|
||||
"env": {
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off"
|
||||
}
|
||||
}
|
||||
@ -1,9 +1,15 @@
|
||||
import { Controller, Get, Post, Body, Param, Options, Header, Delete, HttpCode } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Body, Param, Options, Header, Delete, HttpCode, Put } from '@nestjs/common';
|
||||
import {StoreService} from './store.service';
|
||||
import {Store, StoreResponse, StoreRequest} from './store.schema';
|
||||
import {Store, StoreRequest} from './store.schema';
|
||||
import {ApiResponse} from '@nestjs/swagger';
|
||||
import {ALLOW_ORIGIN_ALL, ALLOW_METHOD, ALLOW_CREDENTIALS, CONTENT_LENGTH, ALLOW_HEADERS} from 'src/consts';
|
||||
|
||||
const prepareStoreToStoreRequest = ({
|
||||
key, value, description, service_name, author
|
||||
}: Store): StoreRequest => ({
|
||||
key, value, description, service_name, author,
|
||||
});
|
||||
|
||||
@Controller('store')
|
||||
export class StoreController {
|
||||
constructor(
|
||||
@ -15,10 +21,11 @@ export class StoreController {
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Список всех пар ключ-значение',
|
||||
type: [StoreResponse],
|
||||
type: [StoreRequest],
|
||||
})
|
||||
async findAll(): Promise<Store[]> {
|
||||
return this.storeService.findAll();
|
||||
async findAll(): Promise<StoreRequest[]> {
|
||||
const storeList = await this.storeService.findAll();
|
||||
return storeList.map(prepareStoreToStoreRequest);
|
||||
}
|
||||
|
||||
@Get(':key')
|
||||
@ -26,21 +33,35 @@ export class StoreController {
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Возвращает пару ключ-значение по ключу',
|
||||
type: StoreResponse,
|
||||
type: StoreRequest,
|
||||
})
|
||||
async findOne(@Param() {key}: {key: string}): Promise<Store> {
|
||||
return this.storeService.findOne(key);
|
||||
async findOne(@Param() {key}: {key: string}): Promise<StoreRequest> {
|
||||
const store = await this.storeService.findOne(key);
|
||||
return prepareStoreToStoreRequest(store);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Header(...ALLOW_ORIGIN_ALL)
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Создает новую пару ключ-значение или заменяет существующую по ключу',
|
||||
type: StoreResponse,
|
||||
description: 'Создает новую пару ключ-значение',
|
||||
type: StoreRequest,
|
||||
})
|
||||
async create(@Body() createStoreClass: StoreRequest): Promise<Store> {
|
||||
return this.storeService.create(createStoreClass);
|
||||
async create(@Body() createStoreClass: StoreRequest): Promise<StoreRequest> {
|
||||
const store = await this.storeService.create(createStoreClass);
|
||||
return prepareStoreToStoreRequest(store);
|
||||
}
|
||||
|
||||
@Put()
|
||||
@Header(...ALLOW_ORIGIN_ALL)
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Обновляет по ключу объект и мета-поля, кроме author',
|
||||
type: StoreRequest,
|
||||
})
|
||||
async update(@Body() updateStoreClass: StoreRequest): Promise<StoreRequest> {
|
||||
const store = await this.storeService.update(updateStoreClass);
|
||||
return prepareStoreToStoreRequest(store);
|
||||
}
|
||||
|
||||
@Delete(':key')
|
||||
@ -48,10 +69,11 @@ export class StoreController {
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'Удаляет пару ключ-значение по ключу',
|
||||
type: String,
|
||||
type: StoreRequest,
|
||||
})
|
||||
async removeOne(@Param() {key}: {key: string}): Promise<string> {
|
||||
return this.storeService.removeOne(key);
|
||||
async removeOne(@Param() {key}: {key: string}): Promise<StoreRequest> {
|
||||
const store = await this.storeService.removeOne(key);
|
||||
return prepareStoreToStoreRequest(store);
|
||||
}
|
||||
|
||||
@Options()
|
||||
|
||||
@ -8,19 +8,15 @@ export class StoreRequest {
|
||||
|
||||
@ApiProperty()
|
||||
value: any;
|
||||
}
|
||||
export class StoreResponse {
|
||||
@ApiProperty()
|
||||
key: string;
|
||||
|
||||
@ApiProperty()
|
||||
value: any;
|
||||
description: string;
|
||||
|
||||
@ApiProperty()
|
||||
_id: string;
|
||||
service_name: string;
|
||||
|
||||
@ApiProperty()
|
||||
__v: number;
|
||||
author: string;
|
||||
}
|
||||
|
||||
@Schema()
|
||||
@ -37,6 +33,24 @@ export class Store extends Document {
|
||||
type: {}
|
||||
})
|
||||
value: any;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: String,
|
||||
})
|
||||
description: string;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: String,
|
||||
})
|
||||
service_name: string;
|
||||
|
||||
@Prop({
|
||||
required: true,
|
||||
type: String,
|
||||
})
|
||||
author: string;
|
||||
}
|
||||
|
||||
export const StoreSchema = SchemaFactory.createForClass(Store);
|
||||
|
||||
@ -1,8 +1,15 @@
|
||||
import {Model} from 'mongoose';
|
||||
import {Injectable, NotFoundException} from '@nestjs/common';
|
||||
import {Injectable, NotFoundException, BadGatewayException} from '@nestjs/common';
|
||||
import {InjectModel} from '@nestjs/mongoose';
|
||||
import {Store, StoreRequest} from './store.schema';
|
||||
|
||||
const validateModel = async (store: Store) => {
|
||||
try {
|
||||
await store.validate();
|
||||
} catch (e) {
|
||||
throw new BadGatewayException(e);
|
||||
}
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class StoreService {
|
||||
@ -16,23 +23,49 @@ export class StoreService {
|
||||
const searchStore = await this.findOne(store.key);
|
||||
|
||||
if (searchStore) {
|
||||
return searchStore.updateOne(store);
|
||||
} else {
|
||||
throw new NotFoundException(`Api key ${store.key} is already taken`);
|
||||
}
|
||||
|
||||
const createdStore = new this.storeModel(store);
|
||||
|
||||
await validateModel(createdStore);
|
||||
|
||||
return createdStore.save();
|
||||
}
|
||||
|
||||
async update({author, ...omitProps}: StoreRequest): Promise<Store> {
|
||||
const searchStore = await this.findOne(omitProps.key);
|
||||
|
||||
if (searchStore) {
|
||||
const store = {
|
||||
...omitProps,
|
||||
author: searchStore.author,
|
||||
};
|
||||
const updateStore = new this.storeModel(store);
|
||||
await validateModel(updateStore);
|
||||
|
||||
await searchStore.updateOne({
|
||||
...store,
|
||||
author: searchStore.author,
|
||||
});
|
||||
|
||||
return updateStore;
|
||||
}
|
||||
|
||||
throw new NotFoundException(`Not Found api key - ${omitProps.key}`);
|
||||
}
|
||||
|
||||
async findOne(key: string): Promise<Store> {
|
||||
return this.storeModel.findOne({key});
|
||||
return this.storeModel.findOne({key})
|
||||
}
|
||||
|
||||
async removeOne(key: string): Promise<string> {
|
||||
async removeOne(key: string): Promise<Store> {
|
||||
const searchStore = await this.findOne(key);
|
||||
|
||||
if (searchStore) {
|
||||
await searchStore.remove();
|
||||
return 'ok';
|
||||
await this.storeModel.deleteOne({key});
|
||||
|
||||
return searchStore;
|
||||
}
|
||||
|
||||
throw new NotFoundException(`Not Found key - ${key}`);
|
||||
|
||||
25
store.http
25
store.http
@ -6,15 +6,34 @@ GET http://localhost:4001/store/testApi HTTP/1.1
|
||||
|
||||
###
|
||||
|
||||
POST http://vigdorov.ru:4001/store HTTP/1.1
|
||||
POST http://localhost:4001/store HTTP/1.1
|
||||
content-type: application/json
|
||||
|
||||
{
|
||||
"key": "testApi",
|
||||
"value": {
|
||||
"name": "ivan",
|
||||
"age": 15
|
||||
}
|
||||
"age": 16
|
||||
},
|
||||
"description": "тестовое апи",
|
||||
"service_name": "test-api",
|
||||
"author": "vigdorov"
|
||||
}
|
||||
|
||||
### Update Request
|
||||
|
||||
PUT http://localhost:4001/store HTTP/1.1
|
||||
content-type: application/json
|
||||
|
||||
{
|
||||
"key": "testApi",
|
||||
"value": {
|
||||
"name": "ivan23",
|
||||
"age": 22
|
||||
},
|
||||
"description": "тестовое апи",
|
||||
"service_name": "test-api",
|
||||
"author": "vigdorov23422"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
Reference in New Issue
Block a user