I'm having some trouble hitting a POST endpoint that triggers a typeorm repository.save() method to my postgres DB.
Here's my DTO object:
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;
}
}
My controller at 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);
}
}
And my service:
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));
}
}
I get a 500 internal server error with log message stating that my ClientDTO.toEntity is not a function.
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)
I'm confused because this only happens via http request. I have a script that seed my dev database after I launch it fresh in a docker container called seed.ts:
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));
It makes me think I am missing something simple/obvious.
Thanks!