Nestjs Commander error when create instance with TypeORM

37 views Asked by At

I got the error

QueryFailedError: null value in column "id" of relation "workspaces" violates not-null constraint

when trying to run cli: yarn create:workspace wsp_name

here is the cli file:

import { Injectable } from '@nestjs/common';
import { Command, Positional } from 'nestjs-command';

import { WorkspacesCommandService } from '../application/commands/workspaces.command.service';
import { CreateWorkspaceDto } from '../interfaces/dto/create-workspace.dto';

@Injectable()
export class WorkspaceCommandLine {
  constructor(private _workspaceCommandService: WorkspacesCommandService) {}

  @Command({
    command: 'create:workspace <name>',
    describe: 'create a workspace',
  })
  async create(
    @Positional({ alias: 'n', describe: 'Name', name: 'name', type: 'string' }) name: string
    // @Positional({ alias: 'd', describe: 'Domain', name: 'domain', type: 'string' }) domain?: string
  ) {
    const createWorkspaceDto: CreateWorkspaceDto = {
      // domain,
      name,
    };

    try {
      console.info('======================CREATE WORKSPACE ============================');
      const createdWorkspace = await this._workspaceCommandService.create(createWorkspaceDto);
      console.info('Created workspace..', createdWorkspace);
    } catch (err) {
      // console.error(err);
      process.exit(1);
    }

    process.exit(1);
  }
}

and this is the entity file:

import { WorkspaceStatusEnum } from '@shared/interfaces/workspace.enum';
import {
  Column,
  CreateDateColumn,
  Entity,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';

@Entity('workspaces')
export class Workspace {
  @PrimaryGeneratedColumn()
  id: string;

  @Column()
  name: string;

  @Column({ nullable: true })
  domain: string;

  @Column({
    default: WorkspaceStatusEnum.PENDING,
    // enum: WorkspaceStatusEnum,
    // type: 'enum',
  })
  status: WorkspaceStatusEnum;

  @CreateDateColumn({ name: 'created_at' })
  createdAt: Date;

  @UpdateDateColumn({ name: 'updated_at' })
  updatedAt: Date;
}

I did test in jestjs for function create in commandService and it can create normally. here is the command service to test:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Workspace } from '@shared/infrastructures/data-access/ORMs/workspaces';
import { WorkspacesRepository } from '@shared/infrastructures/data-access/repositories/workspaces.repository';
import { plainToClass } from 'class-transformer';

import { CreateWorkspaceDto } from '../../interfaces/dto/create-workspace.dto';
import { DeleteWorkspaceDto } from '../../interfaces/dto/delete-workspace.dto';
import { UpdateWorkspaceDto } from '../../interfaces/dto/update-workspace.dto';

@Injectable()
export class WorkspacesCommandService {
  constructor(
    @InjectRepository(WorkspacesRepository)
    private readonly _workspacesRepository: WorkspacesRepository
  ) {}

  async create({ ...createWorkspaceDto }: CreateWorkspaceDto) {
    try {
      // Check and validate
      this.checkUniqueDomain(createWorkspaceDto.domain);
      this.checkValidateDomain(createWorkspaceDto.domain);

      const workspace = await this._workspacesRepository.save(createWorkspaceDto);

      return plainToClass(Workspace, workspace);
    } catch (error) {
      console.log(error);
      throw new Error('Failed to create workspace');
    }
  }

  async update({ ...updateWorkspaceDto }: UpdateWorkspaceDto) {
    try {
      if (!(await this._workspacesRepository.findOne(updateWorkspaceDto.id))) {
        throw new Error('Workspace not found');
      }

      // Check and validate
      this.checkUniqueDomain(updateWorkspaceDto.domain);
      this.checkValidateDomain(updateWorkspaceDto.domain);

      await this._workspacesRepository.update(updateWorkspaceDto.id, updateWorkspaceDto);

      const workspace = await this._workspacesRepository.findOneOrFail({
        id: updateWorkspaceDto.id,
      });

      return workspace;
    } catch (error) {
      throw new Error('Failed to update workspace');
    }
  }

  async delete({ ...deleteWorkspaceDto }: DeleteWorkspaceDto) {
    try {
      const workspace = await this._workspacesRepository.findOne(deleteWorkspaceDto.id);
      if (!workspace) {
        throw new Error('Workspace not found');
      }

      await this._workspacesRepository.remove(workspace);
    } catch (error) {
      throw new Error('Failed to delete workspace');
    }
  }

  async checkUniqueDomain(domain: string) {
    const existingWorkspace = await this._workspacesRepository.findOne({
      domain: domain,
    });

    if (existingWorkspace) {
      throw new Error('Workspace domain already exists');
    }
  }

  async checkValidateDomain(domain: string) {
    const domainRegex = new RegExp('^((?!-)[A-Za-z0–9-]{1,63}(?<!-).)+[A-Za-z]{2,6}$');
    const isValidDomain = domainRegex.test(domain);

    if (!isValidDomain) {
      throw new Error('Invalid domain');
    }
  }
}

My question is: did I implement something wrong? What are the flow when it runs from the cli to the db (I use postgres)? Where and when it generate the id and other attribute by default?

0

There are 0 answers