Skip to content

Commit

Permalink
fix(core): allow importing providers from global modules in lazy modules
Browse files Browse the repository at this point in the history
  • Loading branch information
LeoAnesi committed Jul 31, 2022
1 parent b98e4d2 commit f022a62
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 3 deletions.
29 changes: 29 additions & 0 deletions integration/lazy-modules/e2e/lazy-import-global-modules.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { INestApplication } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as chai from 'chai';
import { expect } from 'chai';
import chaiAsPromised = require('chai-as-promised');
import { AppModule } from '../src/app.module';
chai.use(chaiAsPromised);

describe('Lazy imports', () => {
let server;
let app: INestApplication;

beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();

app = module.createNestApplication();
server = app.getHttpAdapter().getInstance();
});

it(`Should allow imports of global modules`, async () => {
await expect(app.init()).to.eventually.be.fulfilled;
});

afterEach(async () => {
await app.close();
});
});
16 changes: 16 additions & 0 deletions integration/lazy-modules/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Module } from '@nestjs/common';
import { LazyModuleLoader } from '@nestjs/core';
import { EagerModule } from './eager.module';
import { GlobalModule } from './global.module';
import { LazyModule } from './lazy.module';

@Module({
imports: [GlobalModule, EagerModule],
})
export class AppModule {
constructor(public loader: LazyModuleLoader) {}

async onApplicationBootstrap() {
await this.loader.load(() => LazyModule);
}
}
12 changes: 12 additions & 0 deletions integration/lazy-modules/src/eager.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module, Injectable } from '@nestjs/common';
import { GlobalService } from './global.module';

@Injectable()
export class EagerService {
constructor(public globalService: GlobalService) {}
}

@Module({
providers: [EagerService],
})
export class EagerModule {}
13 changes: 13 additions & 0 deletions integration/lazy-modules/src/global.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module, Injectable, Global } from '@nestjs/common';

@Injectable()
export class GlobalService {
constructor() {}
}

@Global()
@Module({
providers: [GlobalService],
exports: [GlobalService],
})
export class GlobalModule {}
12 changes: 12 additions & 0 deletions integration/lazy-modules/src/lazy.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module, Injectable } from '@nestjs/common';
import { GlobalService } from './global.module';

@Injectable()
export class LazyService {
constructor(public globalService: GlobalService) {}
}

@Module({
providers: [LazyService],
})
export class LazyModule {}
8 changes: 8 additions & 0 deletions integration/lazy-modules/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
7 changes: 4 additions & 3 deletions packages/core/injector/lazy-module-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ export class LazyModuleLoader {
| DynamicModule,
): Promise<ModuleRef> {
const moduleClassOrDynamicDefinition = await loaderFn();
const moduleInstances = await this.dependenciesScanner.scanForModules(
moduleClassOrDynamicDefinition,
);
const moduleInstances =
await this.dependenciesScanner.scanForModulesForLazyModules(
moduleClassOrDynamicDefinition,
);
if (moduleInstances.length === 0) {
// The module has been loaded already. In this case, we must
// retrieve a module reference from the existing container.
Expand Down
12 changes: 12 additions & 0 deletions packages/core/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ export class DependenciesScanner {
this.container.bindGlobalScope();
}

public async scanForModulesForLazyModules(
moduleDefinition: Type<unknown> | DynamicModule,
): Promise<Module[]> {
const modules = await this.scanForModules(moduleDefinition);
// We need to bind global scope to the lazy module because the bind phase happens before it was created
// The only one we need to bind is the actual module we are scanning the dependencies for,
// this modules is the first element in the modules list comming from the scan
this.container.bindGlobalsToImports(modules[0]);

return modules;
}

public async scanForModules(
moduleDefinition:
| ForwardReference
Expand Down

0 comments on commit f022a62

Please sign in to comment.