nestjsnomachine-nxmikro-orm

Nestjs with MikroOrm can't inject Entity Manager


I'm using an nx monorepo with NestJS and MikroORM.

I've create a module called PersistanceModule that is defined like this:

    import { Module } from '@nestjs/common';
    import { MikroOrmModule } from '@mikro-orm/nestjs';
    import { UserRepository } from './repositories/user-repository';
    import { userSchema } from './configurations/user.configuration';
    
    @Module({
      imports: [
        MikroOrmModule.forRoot({
          port: 5432,
          user: 'user',
          host: 'localhost',
          dbName: 'vector',
          password: 'password',
          entities: [userSchema],
          discovery: { warnWhenNoEntities: true },
        }),
      ],
      providers: [UserRepository],
      exports: [UserRepository],
    })
    export class PersistanceModule {}

And a repo that is defined like this:

    import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
    import { Injectable } from '@nestjs/common';
    import { IUserRepository, User } from '@vector/domain';
    import { userSchema } from '../configurations/user.configuration';
    import { MikroORM } from '@mikro-orm/core';
    
    Injectable();
    export class UserRepository implements IUserRepository {
      private readonly _repository: EntityRepository<User>;
    
      constructor(
        private readonly orm: MikroORM,
        private readonly em: EntityManager
      ) {
        this._repository = em.getRepository(userSchema);
      }
    
      async findById(id: string): Promise<User | null> {
        const user = await this._repository.findOne({ id });
        return user;
      }
      async findByEmail(email: string): Promise<User | null> {
        const user = await this._repository.findOne({ email });
        return user;
      }
      async add(user: User): Promise<void> {
        let newUser = this._repository.create(user);
        await this._repository.getEntityManager().flush();
      }
    
      async update(user: User): Promise<void> {
        // await this.em.nativeUpdate(User, { id: user.id }, user);
      }
    
      async delete(id: string): Promise<void> {
        // await this.em.nativeDelete(User, { id });
      }
    }

And I've defined my entities via schema to avoid polluting the domain with decorators.

    import { BaseEntity } from '@vector/domain';
    import { User } from '@vector/domain';
    import { EntitySchema } from '@mikro-orm/core';
    import { baseSchema } from './base.configuration';
    
    export const userSchema = new EntitySchema<User, BaseEntity>({
      class: User,
      extends: baseSchema,
      schema: 'vector',
      properties: {
        externalId: { type: 'string', unique: true },
        email: { type: 'string', unique: true },
        password: { type: 'string' },
        active: { type: 'boolean', default: true },
        verificationToken: { type: 'string' },
      },
    });

But when I start the app that is bundled with webpack, I'm getting always this error:

TypeError: Cannot read properties of undefined (reading 'getRepository') at new UserRepository (C:\Work\Vector\vector\dist\vector-client-api\development\webpack:\packages\infrastructure\persistance\src\lib\repositories\user-repository.ts:15:27) at Injector.instantiateClass (C:\Work\Vector\vector\node_modules@nestjs\core\injector\injector.js:365:19) at callback (C:\Work\Vector\vector\node_modules@nestjs\core\injector\injector.js:65:45) at Injector.resolveConstructorParams (C:\Work\Vector\vector\node_modules@nestjs\core\injector\injector.js:144:24) at Injector.loadInstance (C:\Work\Vector\vector\node_modules@nestjs\core\injector\injector.js:70:13) at Injector.loadProvider (C:\Work\Vector\vector\node_modules@nestjs\core\injector\injector.js:97:9) at C:\Work\Vector\vector\node_modules@nestjs\core\injector\instance-loader.js:56:13 at async Promise.all (index 4) at InstanceLoader.createInstancesOfProviders (C:\Work\Vector\vector\node_modules@nestjs\core\injector\instance-loader.js:55:9) at C:\Work\Vector\vector\node_modules@nestjs\core\injector\instance-loader.js:40:13

Does anyone now what this is and how to surpass it?


Solution

  • The Injectable() method should be changed to the @Injectbale() decorator, so that Typescript properly emits the class's metadata so Nest is able to read it