101

NestJS项目创建及配置

准备工作

安装nestjs脚手架

npm i -g @nestjs/cli

创建nest项目

1、创建项目并跳过安装依赖

nest new <project_name> --skip-install

2、如果不需要eslint和prettier可以删除相应配置文件以及依赖项,再进行依赖安装

cd <project_name>

npm install

3、配置静态文件目录

npm install @nestjs/serve-static
//app.module.ts

import { Module } from '@nestjs/common';
import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';

@Module({
  imports: [
    ServeStaticModule.forRoot({
      rootPath: join(__dirname, '..', 'public')
    }),
  ],
  controllers: []
})
export class AppModule {}

配置prisma

1、安装依赖

npm install --save-dev prisma

2、初始化数据模型

npx prisma init

编辑prisma/schema.prisma文件,创建数据模型

3、通过数据模型生成数据库表

npx prisma db push

该步骤会自动生成 @prisma/client,如果需要手动生成,可执行该命令

npx prisma generate

配置swagger

1、安装依赖

npm install @nestjs/swagger

2、启用swagger

//main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';

async function bootstrap() {
    const app = await NestFactory.create(AppModule);
    //设置OPENAPI接口文档
    const config = new DocumentBuilder()
        .setTitle('项目名称')
        .setDescription('接口描述')
        .setVersion('1.0')
        .build();
    const document = SwaggerModule.createDocument(app, config);
    SwaggerModule.setup('api', app, document);

    await app.listen(3000);
}

bootstrap().catch((err) => {
    console.log('bootstrap error:', err);
});

配置websocket

1、安装依赖

npm install ws @nestjs/websockets @nestjs/platform-socket.io
npm install --save-dev @types/ws

2、创建websocket适配器
由于nest默认使用socket.io作为websocket适配器,使用原生websocket需要自己创建适配器

//ws.adapter.ts

import { INestApplicationContext, Logger, WebSocketAdapter } from '@nestjs/common';
import { filter, fromEvent, mergeMap, Observable, EMPTY } from 'rxjs';
import { MessageMappingProperties } from '@nestjs/websockets';
import { CloseEvent, WebSocket } from 'ws';

/**
 * 原生Websocket适配器
 */
export class WsAdapter implements WebSocketAdapter {
  private name: string;

  constructor(private app: INestApplicationContext) {}

  create(port: number, options?: any): any {
    this.name = options.name || 'None';
    Logger.log(`\x1b[0mWebsocket Server Listened On ::${port}`, this.name);
    return new WebSocket.Server({ port, ...options });
  }

  bindClientConnect(server: any, callback: (...args: any[]) => any): any {
    server.on('connection', callback);
  }

  bindMessageHandlers(client: WebSocket, handlers: MessageMappingProperties[], transform: (data: any) => Observable<any>): any {
    Logger.log(`\x1b[0mWebsocket Client Connected`, this.name);
    fromEvent(client, 'message')
      .pipe(
        mergeMap((data) => this.bindMessageHandler(client, data, handlers, transform)),
        filter((result) => result)
      )
      .subscribe((response) => client.send(JSON.stringify(response)));

    fromEvent(client, 'close')
      .pipe(
        mergeMap((data: CloseEvent) => this.bindCloseHandler(client, data)),
        filter((result) => result)
      )
      .subscribe((response) => client.send(JSON.stringify(response)));

    fromEvent(client, 'error')
      .pipe(
        mergeMap((data: CloseEvent) => this.bindErrorHandler(client, data)),
        filter((result) => result)
      )
      .subscribe((response) => client.send(JSON.stringify(response)));
  }

  /**
   * 定义关闭事件处理方法
   */
  bindCloseHandler(client: WebSocket, event: CloseEvent): Observable<any> {
    console.log(event.type, event.code, event.reason);
    return EMPTY;
  }

  /**
   * 定义错误事件处理方法
   */
  bindErrorHandler(client: WebSocket, event: CloseEvent): Observable<any> {
    console.log(event);
    console.log(event.type, event.code, event.reason);
    return EMPTY;
  }

  /**
   * 定义消息事件处理方法
   */
  bindMessageHandler(client: WebSocket, buffer: any, handlers: MessageMappingProperties[], transform: (data: any) => Observable<any>): Observable<any> {
    let message = null;
    try {
      message = JSON.parse(buffer.data);
    } catch (error) {
      Logger.error(`Websocket Client Message Parse Error \x1b[0m${buffer.data}`, this.name);
      Logger.error(error, this.name);
      return EMPTY;
    }

    //此处使用`type`值作为消息事件名称
    const messageHandler = handlers.find((handler) => handler.message === message.type);
    if (!messageHandler) {
      return EMPTY;
    }
    return transform(messageHandler.callback(message));
  }

  close(server: WebSocket) {
    Logger.log(`\x1b[0mWebsocket Server Closed`, this.name);
    server.close();
  }
}

3、使用适配器

//main.ts

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from './utils/ws.adapter';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  //设置websocket适配器
  app.useWebSocketAdapter(new WsAdapter(app));

  await app.listen(3000);
}

bootstrap().catch((err) => {
  console.log('bootstrap error:', err);
});
文章作者:DOTATONG
发布日期:2024-04-01
# nodejs

评论

暂无

添加新评论