I have a DatabaseModule
that imports TypeORM and starts the db connections (cf. database.module.ts
).
I use that module on a crud module and everything works fine while registring the modules the classical way.
But when I lazy load that same module, it breaks and I get the "Can't resolve Connection" error.
"ERROR [ExceptionsHandler] Nest can't resolve dependencies of the ProductRepository (?). Please make sure that the argument Connection at index [0] is available in the TypeOrmModule context."
(I'm writing serverless functions, hence the lazy-loading attempt.)
// product.module.ts: the module I lazy-load
@Module({
imports: [
DatabaseModule.register({
entities: [Product],
}),
],
// database.module.ts: the module that creates the db connections
export interface DatabaseOptions {
entities: any[];
}
@Module({})
export class DatabaseModule {
static register(options: DatabaseOptions): DynamicModule {
return {
module: DatabaseModule,
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: '0.0.0.0',
port: 3306,
username: 'root',
password: '****',
database: 'example',
retryAttempts: 5,
synchronize: true,
entities: options.entities,
}),
TypeOrmModule.forFeature(options.entities),
],
providers: [],
exports: [TypeOrmModule],
};
}
}
Here is the lazy loading part.
// app.controller.ts
@Get()
async createProduct(): Promise<Product> {
// Lazy load the module that imports the DatabaseModule to lazy-load the connections.
const { ProductModule } = await import('./product/product.module');
const productModule = await this.lazyModuleLoader.load(() => ProductModule);
const { ProductService } = await import('./product/product.service');
// It breaks here, 'Connection' providers are not registered.
const productService = productModule.get(ProductService);
return productService.create();
}
Once again, it works fine when I register the ProductModule
in the main AppModule
, so I expected the module to work the same way with lazy-loading.
I guess I have to lazy load more stuff for this to work, but I can't understand why the Connection / Repository providers are not available when I lazy-load the product module... 😦
Reproduction repo (There is a docker-compose with a mysql image to debug locally).
I faced the same problem, unfortunately. I've got it working via the ASYNC_CONNECTION
provider:
import { ConnectionOptions, createConnection, getConnection } from 'typeorm';
providers: [{
provide: 'ASYNC_CONNECTION',
inject: [ConfigService],
useFactory: async (configService: ConfigService) => {
const { host, port, username, password, database } = configService.get('db');
const connection: ConnectionOptions = {
type: 'postgres',
host,
port,
username,
password,
database,
name: 'custom',
entities: [...entities],
synchronize: false,
namingStrategy: new SnakeNamingStrategy(),
};
try {
getConnection(connection.name);
} catch (error) {
return await createConnection(connection);
}
}
}]
Then you can inject the ASYNC_CONNECTION
provider wherever you want:
@Inject('ASYNC_CONNECTION')
private connection: Connection,
And use the classic repository approach with the entities you've declared above:
this.connection.getRepository(<Entity>).findOne({})
That's it.