Class extends value undefined is not a constructor or null - circular dependency

When I am triying to generate migrations I get this error

Error during migration generation:
Error: Unable to open file: "/home/angel/Contenedores/nestjs/plantilla/src/database/config/typeorm.config.ts". Class extends value undefined is not a constructor or null
    at Function.loadDataSource (/home/angel/Contenedores/nestjs/plantilla/node_modules/src/commands/CommandUtils.ts:22:19)
    at async Object.handler (/home/angel/Contenedores/nestjs/plantilla/node_modules/src/commands/MigrationGenerateCommand.ts:78:26) 

I know it is because circular dependencies but I don't know how to solve it, I'll show my entities in order to have more context about the issue.

I have this base entity that all entities extends

export class BaseEntity {
  @ApiProperty({
    example: 'd0e2862c-4f46-4017-985c-a8428e58c66e',
    description: 'Id de usuario',
    uniqueItems: true,
  })
  @PrimaryGeneratedColumn('uuid', {
    comment: 'ID de tipo UUID para la entidad',
  })
  id?: string;

  @ApiProperty({
    example: true,
    description: 'Campo que determina si un registro esta activo o no',
  })
  @Column({
    type: 'bool',
    name: 'active',
    default: true,
    comment: 'Campo que determina si un registro esta activo o no',
  })
  active?: boolean;

  @ManyToOne(() => User, () => {}, {
    nullable: true,
    onUpdate: 'NO ACTION',
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'user_created_at_id' })
  userCreatedAtId?: User;

  @ApiProperty({
    example: '2025-02-05 11:11:34.240',
    description: 'Fecha de creación',
  })
  @CreateDateColumn({
    type: 'timestamp',
    name: 'created_at',
    nullable: false,
    comment: 'Campo que guarda la fecha de creación del registro',
  })
  readonly createdAt?: Date;

  @ManyToOne(() => User, () => {}, {
    nullable: true,
    onUpdate: 'NO ACTION',
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'user_updated_at_id' })
  userUpdatedAtId?: User;

  @ApiProperty({
    example: '2025-02-05 11:11:34.240',
    description: 'Fecha de actualización',
  })
  @UpdateDateColumn({
    type: 'timestamp',
    name: 'updated_at',
    nullable: false,
    comment: 'Campo que guarda la fecha de actualización del registro',
  })
  readonly updatedAt?: Date;

  @ManyToOne(() => User, () => {}, {
    nullable: true,
    onUpdate: 'NO ACTION',
    onDelete: 'CASCADE',
  })
  @JoinColumn({ name: 'user_deleted_at_id' })
  userDeletedAtId?: User;

  @ApiProperty({
    example: '2025-02-05 11:11:34.240',
    description: 'Fecha de eliminació/desactivación',
  })
  @DeleteDateColumn({
    type: 'timestamp',
    name: 'deleted_at',
    nullable: false,
    comment: 'Campo que guarda la fecha de eliminacion del registro',
  })
  deletedAt?: Date;
}

The I have a Country entity that look like this

@Entity({
  name: 'countries',
  comment: 'Tabla que guarda el catalogo de paises',
})
export class Country extends BaseEntity {
  @Column({
    type: 'varchar',
    length: 100,
    nullable: false,
    comment: 'Campo que guarda el nombre de cada país',
  })
  name: string;

  @Column({
    type: 'int4',
    name: 'reference_id',
    nullable: true,
    comment: 'ID de tipo entero correlativo para la entidad',
  })
  referenceId?: number;

  @Column({
    type: 'char',
    length: 2,
    nullable: false,
    comment: 'Campo que guarda el código de cada país',
  })
  code: string;
}

And I have a department entity that has a foreign key with country

@Entity({
  name: 'departments',
  comment: 'Tabla que guarda el catalogo de los departamentos',
})
export class Department extends BaseEntity {
  @Column({
    type: 'varchar',
    length: 50,
    nullable: false,
    comment: 'Campo que guarda el nombre del departamento',
  })
  name: string;

  @Column({
    type: 'int4',
    name: 'reference_id',
    nullable: true,
    comment: 'ID de tipo entero correlativo para la entidad',
  })
  referenceId?: number;

  @ManyToOne(() => Country, () => {}, { nullable: false })
  @JoinColumn({ name: 'country_id' })
  country: Country | number;
}

And finally I have users entity that has foreign key with country and department

@Entity({ name: 'users', comment: 'Tabla que guarda los usuarios' })
export class User extends BaseEntity {
  @Column({
    type: 'varchar',
    length: 200,
    unique: true,
    name: 'email',
    nullable: false,
    comment: 'Campo que guarda el correo electrónico del usuario',
  })
  email: string;

  @ApiHideProperty()
  @Column({
    type: 'varchar',
    length: 100,
    name: 'password',
    nullable: false,
    comment: 'Campo que guarda la contraseña del usuario',
  })
  password: string;

  @Column({
    type: 'timestamp',
    name: 'password_verification_at',
    nullable: true,
    comment:
      'Campo que sirve para verificar si un usuario ya verifico o modifico su contraseña inicial',
  })
  passwordVerificationAt: Date;

  @ApiHideProperty()
  @Column({
    type: 'timestamp',
    name: 'password_reset_expiration_at',
    nullable: true,
    comment:
      'Campo que sirve para validar que el código de restauración de contraseña no haya expirado',
  })
  passwordResetExpirationAt: Date;

  @ApiHideProperty()
  @Column({
    type: 'timestamp',
    name: 'password_reset_verification_at',
    nullable: true,
    comment:
      'Campo que sirve para validar que el código de restauración de contraseña ya haya sido verificado',
  })
  passwordResetVerificationAt: Date;

  @ApiHideProperty()
  @Column({
    type: 'text',
    name: 'password_reset_code',
    nullable: true,
    comment: 'Campo que guarda el código de recuperación de contraseña',
  })
  passwordResetCode: string;

  @Column({
    name: 'names',
    nullable: false,
    length: 200,
    comment: 'Campo que guarda los nombres del usuario',
  })
  names: string;

  @Column({
    name: 'last_names',
    nullable: false,
    length: 200,
    comment: 'Campo que guarda los apellidos del usuario',
  })
  lastNames: string;

  @Column({
    name: 'document_number',
    nullable: false,
    length: 100,
    comment: 'Campo que guarda el número de documento del usuario',
  })
  documentNumber: string;

  @Column({
    name: 'address',
    type: 'varchar',
    length: 500,
    nullable: true,
    comment: 'Campo que guarda la dirección del paciente',
  })
  address?: string;

  @ManyToOne(() => DocumentType, () => {}, { nullable: true })
  @JoinColumn({ name: 'document_type_id' })
  documentType?: DocumentType;

  @ManyToOne(() => DependencyType, () => {}, { nullable: true })
  @JoinColumn({ name: 'dependency_type_id' })
  dependencyType?: DependencyType;

  @ManyToOne(() => Dependency, () => {}, { nullable: true })
  @JoinColumn({ name: 'dependency_id' })
  dependency?: Dependency;

  @ManyToOne(() => Sex, { nullable: true })
  @JoinColumn({ name: 'sex_id' })
  sex?: Sex;

  @ManyToOne(() => Country, { nullable: true })
  @JoinColumn({ name: 'country_id' })
  country?: Country;

  @ManyToOne(() => Department, { nullable: true })
  @JoinColumn({ name: 'department_id' })
  department?: Department;

  @BeforeInsert()
  beforeInsert?() {
    this.email = this.email.toLowerCase().trim();
  }

  @BeforeUpdate()
  beforeUpdate?() {
    this.email = this.email.toLowerCase().trim();
  }
}

So when removing countryId in department entity it works but when I add it, it shows the message I place in the begining.

Please help me I am new to nest js and I don't know how to solve this relations and make them work

Upvotes: 0

Views: 24

Answers (0)

Related Questions