javascript - Nest js POST请求无法识别DTO方法

标签 javascript typescript http nest typeorm

我在访问 POST 端点时遇到一些问题,该端点会触发我的 postgres 数据库的 typeorm repository.save() 方法。

这是我的 DTO 对象:

import { ApiProperty } from '@nestjs/swagger/';
import { IsString, IsUUID} from 'class-validator';

import { Client } from '../../../models';
import { User } from '../../../user.decorator';


export class ClientDTO implements Readonly<ClientDTO> {
    @ApiProperty({ required: true })
    @IsUUID()
    id: string;


    @ApiProperty({ required: true })
    @IsString()
    name: string;

    public static from(dto: Partial<ClientDTO>) {
      const cl = new ClientDTO();
      cl.id = dto.id;
      cl.name = dto.name;
      return cl;
    }

    public static fromEntity(entity: Client) {
      return this.from({
        id: entity.id,
        name: entity.name,
      });
    }

    public toEntity = (user: User | null) => {
      const cl = new Client();
      cl.id = this.id;
      cl.name = this.name;
      cl.createDateTime = new Date();
      cl.createdBy = user ? user.id : null;
      cl.lastChangedBy = user ? user.id : null;
      return cl;
    }
  }

我的 Controller 在 POST - /client:

import { 
    Body,
    Controller, 
    Get, Post 
} from '@nestjs/common';

import { ClientDTO } from './dto/client.dto';
import { ClientService } from './client.service';
import { User } from 'src/user.decorator';

@Controller('client')
export class ClientController {
    constructor(
        private clientService: ClientService
    ) { }

    @Get()
    public async getAllClients(): Promise<ClientDTO[]> {
        return this.clientService.getAllClients();
    }

    @Post()
    public async createClient(@User() user: User, @Body() dto: ClientDTO): Promise<ClientDTO> {
        return this.clientService.createClient(dto, user);
    }
}

我的服务:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

import { Client } from '../../models';
import { ClientDTO } from './dto/client.dto';
import { User } from '../../user.decorator';


@Injectable()
export class ClientService {
    constructor(
        @InjectRepository(Client) private readonly clientRepository: Repository<Client>
    ) {}

    public async getAllClients(): Promise<ClientDTO[]> {
        return await this.clientRepository.find()
            .then(clients => clients.map(e => ClientDTO.fromEntity(e)));
    }

    public async createClient(dto: ClientDTO, user: User): Promise<ClientDTO> {
        return this.clientRepository.save(dto.toEntity(user))
            .then(e => ClientDTO.fromEntity(e));
    }
}

我收到 500 内部服务器错误,日志消息表明我的 ClientDTO.toEntity 不是函数。

TypeError: dto.toEntity is not a function
    at ClientService.createClient (C:\...\nest-backend\dist\features\client\client.service.js:29:47)
    at ClientController.createClient (C:\...\nest-backend\dist\features\client\client.controller.js:27:35)
    at C:\...\nest-backend\node_modules\@nestjs\core\router\router-execution-context.js:37:29
    at process._tickCallback (internal/process/next_tick.js:68:7)

我很困惑,因为这只能通过 http 请求发生。我有一个脚本,可以在我的开发数据库在名为 Seed.ts 的 Docker 容器中重新启动后为其提供种子:

import * as _ from 'lodash';

import { Client } from '../models';
import { ClientDTO } from '../features/client/dto/client.dto';
import { ClientService } from '../features/client/client.service';
import { configService } from '../config/config.service';
import { createConnection, ConnectionOptions } from 'typeorm';
import { User } from '../user.decorator';

async function run() {

  const seedUser: User = { id: 'seed-user' };

  const seedId = Date.now()
    .toString()
    .split('')
    .reverse()
    .reduce((s, it, x) => (x > 3 ? s : (s += it)), '');

  const opt = {
    ...configService.getTypeOrmConfig(),
    debug: true
  };

  const connection = await createConnection(opt as ConnectionOptions);
  const clientService = new ClientService(connection.getRepository(Client));

  const work = _.range(1, 10).map(n => ClientDTO.from({
      name: `seed${seedId}-${n}`,
    }))
######################## my service calls ClientDTO.toEntity() without issue ###########################
    .map(dto => clientService.createClient(dto, seedUser) 
      .then(r => (console.log('done ->', r.name), r)))

  return await Promise.all(work);
}

run()
  .then(_ => console.log('...wait for script to exit'))
  .catch(error => console.error('seed error', error));

这让我觉得我错过了一些简单/明显的东西。

谢谢!

最佳答案

看起来您正在使用 ValidationPipe。这里提到了解决方案 https://github.com/nestjs/nest/issues/552

设置验证管道时,您需要告诉它进行转换

app.useGlobalPipes(new ValidationPipe({
  transform: true
}));

关于javascript - Nest js POST请求无法识别DTO方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60768582/

相关文章:

javascript - 从 XMLHttpRequest 中删除 HTTP header

c++ - MFC框架中如何使用XML over HTTP实现双向通信

c# - HttpWebRequest AddRange 方法查询

javascript - 鼠标悬停效果仅在 <a> 中的 <i> 上

typescript - 提取函数的返回类型并按 typescript 中的属性名称进行过滤

angular - 绑定(bind)元素 'index' 隐式具有 'any' 类型

typescript - 在接口(interface)中使用胖箭头和非胖箭头语法声明函数有什么区别?

javascript - Nunjucks 不渲染模板

javascript - 我可以在构建元素时暂时关闭所有 CSS3 过渡/动画吗?

javascript - twemoji 不转换字符串