Рубрики
Без рубрики

API отдыха с Mongodb и Nest.js

Построить API отдыха с NEST.JS и MONGODB

Автор оригинала: Foysal.

Изображение от NEST.JS Официальный сайт

alt.

Nest.js Является рамочной структурой JS, которая построена с помощью Teadercript и делает дополнительную обычную работу, чтобы дать разработчикам стабильную базу для приложения по боковому серверу зданий. Он имеет чрезвычайно модульную архитектуру, которая позволит вам быть гибким, но очень надежным одновременно. Время от времени их рекомендуемый способ написания приложения может показаться немного утомительным, но доверять мне, он окупается в долгосрочной перспективе и читабельности. С учетом того, я надеюсь, что вы будете нести со мной через этот пост и прийти к тому же выводу, когда мы закончим, построение нашего приложения.

Несколько предположений о вас

Если вы читаете этот пост, я собираюсь предположить, что вы знакомы с Node.js, базовым типографическим и JavaScript в целом. Однако, если вы не знакомы с тем или некоторыми вещами, не имеют смысла вам, не стесняйтесь дать ему чтение в любом случае и дайте мне знать, как я могу помочь вам понять это лучше.

Что мы собираемся построить

С этим постом мы находимся в путешествии вместе, чтобы построить полноценное приложение, в котором пользователи могут создавать сообщения, а по мере того, как новые посты пользователи могут видеть сообщения в потоке в реальном времени. Я называю это Parley Но я не женат на нем, так что если у вас есть лучшее имя, дайте мне знать В качестве первого шага мы построим API Server Side Rest с NEST.JS и работаем на пути к приложению клиента и функции в реальном времени.

Инструменты, необходимые для работы вместе с этим постом

Если вы собираетесь работать вместе с учебником и постройте API на локальной машине, вам нужен только Node.js и NPM на вашем локальном компьютере. Если вы хотите использовать локальный MongoDB, убедитесь, что вы также установили его. В противном случае вы можете использовать внешние поставщики, такие как Atlas, MLAB или составляют Отказ

Начиная

NEST.JS предоставляет надежную стартерную базу для вас, поэтому мы начнем оттуда, чтобы избежать начального загрузки. Запустите следующие команды, чтобы получить шаблон стартера:

$ git clone https://github.com/nestjs/typescript-starter.git parley
$ cd parley
$ npm install
$ npm run start:watch

Теперь вы можете увидеть приложение в действии, перейдя на http://localhost: 3000 на вашем браузере. Теперь открыть каталог в вашем любимом редакторе кода (Мой сейчас vscode прямо сейчас) И давайте погрузимся и начать кодирование.

Подключиться к Mongodb

В реальных мировых приложениях нам нужен постоянный слой данных, и я выбираю Mongodb с Mogoose для этого, но вы можете использовать любой слой данных по вашему выбору с NEST.JS. Они имеют отличную документацию для самых популярных, таких как GraphQL, Sequelize и т. Д. Это наша структура каталогов для модуля базы данных:

src
 |--database
      |--database.module.ts
      |--database.providers.ts

Теперь добавьте следующий код в вашем База данных. Проводите.Тс файл:

import * as mongoose from 'mongoose';
import { DB_PROVIDER } from '../constants'; 

export const databaseProviders = [
    {
        provide: DB_PROVIDER,
        useFactory: async () => {
            (mongoose as any).Promise = global.Promise;
            return await mongoose.connect('mongodb://localhost:27017/parley');
        },
    },
];

Вы заметите, как мы импортируем {Db_provider} из файла, который еще не существует, так что давайте создадим Константы Файл в SRC/ каталог и поместить следующий код в нем:

export const DB_PROVIDER = 'DbConnectionToken';

Инъекция зависимостей в NEST.JS использует имена строк, и рекомендуется хранить имена ваших провайдеров в отдельном файле и использовать постоянные переменные вместо волшебные струны Отказ Вы можете прочитать больше об этом на Официальный док Отказ

Кроме того, мы используем Mongoose в качестве нашего ODM, но мы еще не установили его, так что давайте сделаем это реально

$ npm i --save mongoose
$ npm i --save-dev @types/mongoose

Мы используем MongoDB://localhost: 27017/parley Как наш MongoDB-адрес, предполагая, что у вас есть Mongodb, установленные локально и имеют базу данных с именем Parley в вашей БД. Если вы используете внешний поставщик БД, вместо этого используйте этот DB URL.

Давайте определим наш модуль базы данных в База данных. Module.ts файл:

import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';

@Module({
    components: [...databaseProviders],
    exports: [...databaseProviders],
})
export class DatabaseModule { };

Это все. Теперь мы можем вытащить модуль базы данных в любых других модулях и использовать Mongoose для подключения объекта для запуска запросов на нашу БД.

Посты модуля

Мы разработаем наше приложение от модульного подхода на основе сущности. Начнем с создания нашего первого каталога модуля внутри каталога SRC. С поступочкой наша структура каталогов будет выглядеть так:

src
 |--posts
    |--dto
          |--create-post.dto.ts
      |--interfaces
          |--post.interface.ts
      |--posts.controller.ts
      |--posts.module.ts
      |--posts.providers.ts
      |--posts.schema.ts
      |--posts.service.ts

Продолжайте и создайте файлы и папки, показанные выше. Давайте сначала с кодом create-post.dto.ts файл. Этот файл определяет структуру данных, которые ожидают конечных точек API. При создании нового поста мы ожидаем, что корпус HTTP-запроса содержит заголовок, контент и идентификатор пользователя. В идеале клиент не должен быть в состоянии установить UserID поста, и он должен автоматически устанавливаться из зарегистрированного пользователя, но нам придется ждать, пока мы не реализуем функцию аутентификации в нашем приложении. Итак, на данный момент так выглядит:

export class CreatePostDto {
    readonly title: string;
    readonly content: string;
    readonly userId: string;
}

Теперь давайте создадим наш почтовый интерфейс в post.interface.ts Файл, который будет использоваться в качестве модели Post Entity в нашем Tyertcript Code. Каждый пост должен содержать заголовок, контент и идентификатор пользователя:

import { Document } from 'mongoose';

export interface Post extends Document {
    readonly title: string;
    readonly content: string;
    readonly userId: string;
}

С этими двумя файлами созданы, мы теперь готовы написать нашу почтовую службу в posts.service.ts файл:

import { Model } from 'mongoose';
import { Component, Inject } from '@nestjs/common';

import { Post } from './interfaces/post.interface';
import { CreatePostDto } from './dto/create-post.dto';
import { POST_MODEL_PROVIDER } from '../constants';

@Component()
export class PostsService {
    constructor(
        @Inject(POST_MODEL_PROVIDER) private readonly postModel: Model) { }

    async create(createPostDto: CreatePostDto): Promise {
        const createdPost = new this.postModel(createPostDto);
        return await createdPost.save();
    }

    async findAll(): Promise {
        return await this.postModel.find().exec();
    }
}

Давайте рассмотрим этот файл немного ближе. Сначала мы импортируем интерфейс POST и создать Post Do, который мы создали ранее. Тогда мы импортируем Post_model_provider постоян от Константы файл, но мы еще не добавили переменную в этом файле. Так что давайте добавим это:

export const DB_PROVIDER = 'DbConnectionToken';

export const POST_MODEL_PROVIDER = 'PostModelToken';

В нашем Postervice Конструктор класса компонентов, мы вводим модель Post, которая будет введена в инъекцию зависимости NEST.JS. Однако мы еще не создали поставщика для этого. Так что давайте создадим провайдер в posts.providers.ts файл:

import { Connection } from 'mongoose';

import { PostSchema } from './posts.schema';
import { POST_MODEL_PROVIDER, DB_PROVIDER } from '../constants';

export const postsProviders = [
    {
        provide: POST_MODEL_PROVIDER,
        useFactory: (connection: Connection) => connection.model('Post', PostSchema),
        inject: [DB_PROVIDER],
    },
];

В провайдере мы в основном построены модель мангусты и впрыскивая модель в качестве завода в контейнер на NEST.JS, чтобы позже мы можем вытащить модель из контейнера в любом месте в нашем приложении. Чтобы создать модель, мы должны определить и прикрепить схему. Давайте определим схему в posts.schema.ts файл:

import * as mongoose from 'mongoose';

export const PostSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true,
    },
    content: {
        type: String,
        required: false,
    },
    userId: {
        type: mongoose.SchemaTypes.ObjectId,
        required: true,
    }
});

Хорошо, давайте вернемся к нашему файлу провайдера. Мы вытаскиваем поставщик соединений БД из контейнера и построить модель Mongoose, а затем хранить модель как провайдер в контейнере под Post_model_provider название.

Итак, объясняет, как поставщик моделей для сообщений может быть введен в конструктор службы сообщений. Теперь вернитесь к файлу сервиса постов. Первый метод этого класса является async Создать метод, который принимает один на систему и возвращает обещание. Сам параметр – это объект Post-Create DTO. Поэтому, если мы попытаемся пройти все, что не допускается схемой Dто, он будет отфильтрован. Это делает его поддерживать целостность данных очень простыми и декларативными. Внутри создать Метод мы просто создаем новую модель Post и сохраните ее в базе данных.

Другой метод в этом классе – Findall Это просто запрашивает все посты и возвращает записи из БД.

До сих пор мы обрабатывали слой данных постов. Теперь мы собираемся подключить данные с контроллером NEST.JS, чтобы сделать их доступными через конечные точки API для отдыха. Для этого мы начинаем с контроллера.

Контроллер в Nest.js – это простой класс, который использует декораторы для определения Получить/сообщение/поставить И т. Д. HTTP Конечные точки API приложения. Вот как наш Posts.Controller.ts Файл выглядит как:

import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { CreatePostDto } from './dto/create-post.dto';
import { PostsService } from './posts.service';
import { Post as PostInterface } from './interfaces/post.interface';

@Controller('posts')
export class PostsController {
    constructor(private readonly postsService: PostsService) { }

    @Post()
    async create(@Body() createPostDto: CreatePostDto) {
        this.postsService.create(createPostDto);
    }

    @Get()
    async findAll(): Promise {
        return this.postsService.findAll();
    }
}

@Controller Декоратор принимает один параметр, который определяет конечную точку, с которым контроллер связан. В нашем случае мы проходим «Посты» Итак, мы можем сделать запросы API к http://localhost: 3000/посты Для связи сопутствующих связей. Вы можете пройти что-нибудь, и это будет использоваться в качестве базы конечной точки.

Nest.js имеет Получить и Пост Декораторы для Получить и Пост API конечные точки, но поскольку наши посты также имеют интерфейс, определенный как Пост Нам нужно изменить имя импорта хотя бы одного из переменных. Вот почему я изменил Пост Имя переменной интерфейса в PostInterface при импорте. Конструктор контроллера впрыскивает Созревервис пример.

У нас есть создать Метод украшен @Post Декоратор, который гарантирует, что любой HTTP Пост просьба прийти в наше приложение на Posts Конечная точка будет огорчаться, что создать метод. Первый параметр метода украшен @Body Декоратор, который дает вам доступ к корпусу запроса (это эквивалентно REQ. Те, если вы знакомы с Express). Лучшая часть использования NEST.JS Decorators заключается в том, что они обеспечивают много удобства, такого как разборы тела JSON. Вам не нужно настроить промежуточное программное обеспечение для анализа тела для принятия входа JSON из клиентских вызовов, Nest.js Decorators сделает это для вас. Вот почему мы можем ожидать, что тело соответствует нашему create-post dто Отказ В рамках метода мы просто называем метод создания Созревервис Отказ

Следующий метод Findall Определяется в аналогичной форме, которая не принимает никаких параметров и возвращает все сообщения, запрошенные через Созревервис Отказ

Фу! Это много работы для одного модуля, но я надеюсь, что все это имеет смысл, и поскольку наш модуль растет с большим количеством функций, вы заметите, насколько легче посыпать теми на вершину этого макета. Наконец, нам нужно связать все это и определить наши посты модуль в posts.module.ts файл, как указано ниже:

import { Module } from '@nestjs/common';
import { PostsController } from './posts.controller';
import { PostsService } from './posts.service';
import { postsProviders } from './posts.providers';
import { DatabaseModule } from '../database/database.module';

@Module({
    imports: [DatabaseModule],
    controllers: [PostsController],
    components: [
        PostsService,
        ...postsProviders,
    ],
})
export class PostsModule { }

Возможно, вы, вероятно, замечаете, насколько хороши модуль структура Nest.js может быть там, где все так красиво отделено и инкапсулировано. Теперь мы можем просто загрузить этот модуль в нашем app.module.ts файл:

......
import { AppController } from './app.controller';
import { PostsModule } from './posts/posts.module';

@Module({
  imports: [PostsModule],
.....

Все сделано. Пойдем, проверьте это.

Тестирование нашего API отдыха

Я использую почтальон для тестирования конечных точек моей API, но вы можете проверить первую конечную точку, просто отправившись на http://localhost: 3000/посты/ на вашем браузере, и вы должны увидеть [] выход. Поскольку у нас нет записей в коллекции постов нашей базы данных, он возвращает пустой массив. Теперь вы можете создать запись в базе данных вручную или сделать ее через конечную точку API, которую мы только что создали.

Если вы хотите сделать это очень быстро, просто скопируйте вставьте следующую команду CURL и вставьте его на свой терминал:

curl -X POST \
  http://localhost:3000/posts/ \
  -H 'content-type: application/json' \
  -d '{"title": "this is post one", "content": "You'\''ve gotta write clearer so you can be read when you'\''re dead", "userId": "5ab25d50740ce24b63cc9c83"}'

Или если вы хотите использовать почтальон, как я, создайте новый Пост Запрос на http://localhost: 3000/посты Отказ Затем добавьте новый заголовок с именем Content-Type и ценность Приложение/JSON Отказ Теперь перейдите на вкладку «Тело» и установите тип корпуса RAW и вставьте следующий контент:

{"title": "this is post one", "content": "You've gotta write clearer so you can be read when you're dead", "userId": "5ab25d50740ce24b63cc9c83"}

Обратите внимание, как я даю произвольную строковое значение для UserID имущество? Это потому, что у нас нет записей пользователей в БД, но схема Mongoose ожидает UserID быть типа Объект Таким образом, мы собираемся к жесткому коду сейчас. Позже он будет заменен нашим фактическим зарегистрированным идентификатором пользователя. Теперь нажмите Отправить и вернитесь в свой браузер на http://localhost: 3000/посты И вы получите новый ответ напечатаны как:

[
  {
    _id: "5ab2c497b8bfa11f47c4c38a",
    title: "this is post one",
    content: "You've gotta write clearer so you can be read when you're dead",
    userId: "5ab25d50740ce24b63cc9c83",
    __v: 0
  }
]

Поздравляю!! Вы только что создали свой первый API отдыха на NEST.JS и MongoDB. Похлопайте себя на спину или попросите коллегу сделать это для вас, вы его заработали!

Что дальше?

До сих пор мы построили очень надежную, но довольно бесполезную систему. Итак, далее, мы собираемся построить блестящее новое приложение Frontend, чтобы взаимодействовать с нашим API. Я буду обновлять этот пост со ссылками на сообщения, где я прогуливаю процесс построения приложения Frontend.

Тем временем играйте с API, создайте новые посты и увидите их на Posts Конечная точка нашего API.