简体   繁体   中英

How to create a factory for a typeorm custom repository in nestjs?

I have a repository:

export class MyRepository 
    extends 
        Repository<MyEntity>
{

constructor(
        protected readonly _clientId: string
    ) {
        super()
    }

 // ... methods
}

I need to pass the client id through which isnt known until request time. As such, the only way I know how to do it would be to create a factory which can create the repo at run time (it's in GRPC metadata).

@Injectable()
export class MyRepositoryFactory {
    create(clientId: string) {
        return new MyRepository(
            clientId,
        );
    }
}

I register this as a provider and then in my controller I call:

const { clientId } = context;
const repository = this.myRepositoryFactory.create(clientId);

However I get the error

"Cannot read property 'findOne' of undefined"

when trying to do a basic typeorm call. I can see this is because instead the repository should be registered in the module imports like:

imports: [
    TypeOrmModule.forFeature([ MyRepository, MyEntity ])
  ],

However this only works when injecting the repository directly, not in a factory. I have no idea how to either overcome this problem, or use a different way of creating the repository at run time with GRPC meta data passed through. Any help would be appreciated, thanks.

you cant call new and have the repository connected to TypeORM.
for that you need to make call to getCustomRepository(MyCustomRepository (or connectio.getCustomRepository ) so it would be connected to the connectiong pool and everything TypeORM hides under the hood.

IMO creating a custom repository per request is not such a great idea, maybe you can create a Provider that has scope REQUEST (so the provider would be created per-request) allowing NestJS to inject the repository the 'standard' way, modify it's client attribute and then use it's methods that uses the internal repository methods.
something like

@Injectable({ scope: Scope.REQUEST })
export class RequestRepositoryHandler {
  client_id: string
  
  constructor(@InjectRepository(MyEntity) private repo: Repository<MyEntity>){}

  // other methods
}

// usage
@Injectable()
export class SomeService {
  constructor(private providerRepo: RequestRepositoryHandler){}

  async method(client_id: string){
    this.providerRepo.client_id = client_id; // the provider is per-request
    // now do some work
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM