Merge branch 'middleware-order' of https://github.com/underfin/nest into underfin-middleware-order

This commit is contained in:
Kamil Myśliwiec
2019-08-26 14:23:40 +02:00
4 changed files with 112 additions and 2 deletions

View File

@@ -0,0 +1,60 @@
import { INestApplication, MiddlewareConsumer, Module } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
const RETURN_VALUE_A = 'test_A';
const RETURN_VALUE_B = 'test_B';
@Module({
imports: [],
})
class TestAModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply((req, res, next) => {
res.send(RETURN_VALUE_A);
})
.forRoutes('hello');
}
}
@Module({
imports: [TestAModule],
})
class TestBModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply((req, res, next) => {
res.send(RETURN_VALUE_B);
})
.forRoutes('hello');
}
}
@Module({
imports: [TestBModule],
})
class TestModule {
}
describe('Middleware Execute Order', () => {
let app: INestApplication;
beforeEach(async () => {
app = (await Test.createTestingModule({
imports: [TestModule],
}).compile()).createNestApplication();
await app.init();
});
it(`Execute middleware of dependent modules first `, () => {
return request(app.getHttpServer())
.get('/hello')
.expect(200, RETURN_VALUE_A);
});
afterEach(async () => {
await app.close();
});
});

View File

@@ -43,6 +43,7 @@ export class Module {
InstanceWrapper<Controller>
>();
private readonly _exports = new Set<string | symbol>();
private _distance: number = 0;
constructor(
private readonly _metatype: Type<any>,
@@ -114,6 +115,17 @@ export class Module {
return this._metatype;
}
get distance(): number {
return this._distance;
}
set distance(distance: number){
this._distance = distance;
Array.from(this._imports)
.filter((module) => !module.imports.has(this))
.forEach((module) => module.distance = distance + 1);
}
public addCoreProviders(container: NestContainer) {
this.addModuleAsProvider();
this.addModuleRef();
@@ -398,8 +410,9 @@ export class Module {
);
}
public addRelatedModule(module: any) {
public addRelatedModule(module: Module) {
this._imports.add(module);
module.distance = this._distance + 1 > module._distance ? this._distance + 1 : module._distance;
}
public replace(toReplace: string | symbol | Type<any>, options: any) {

View File

@@ -110,7 +110,9 @@ export class MiddlewareModule {
});
await Promise.all(
[...configs.entries()].map(async ([module, moduleConfigs]) => {
[...configs.entries()].sort(([moduleA, moduleAConfigs], [moduleB, moduleBConfigs]) => {
return this.container.getModuleByKey(moduleB).distance - this.container.getModuleByKey(moduleA).distance;
}).map(async ([module, moduleConfigs]) => {
await Promise.all(registerAllConfigs(module, [...moduleConfigs]));
}),
);

View File

@@ -481,4 +481,39 @@ describe('Module', () => {
});
});
});
describe('getter "distance"', () => {
@ModuleDecorator({})
class ModuleA {}
@ModuleDecorator({})
class ModuleB {}
@ModuleDecorator({})
class ModuleC {}
let moduleA, moduleB, moduleC;
beforeEach(() => {
moduleA = new Module(ModuleA as any, [], container);
moduleB = new Module(ModuleB as any, [], container);
moduleC = new Module(ModuleC as any, [], container);
});
it('should get "distance" correct', () => {
moduleA.addRelatedModule(moduleB);
moduleC.addRelatedModule(moduleB);
moduleA.addRelatedModule(moduleC);
expect(moduleA.distance).to.be.equal(0);
expect(moduleB.distance).to.be.equal(2);
expect(moduleC.distance).to.be.equal(1);
});
it('should don`t throw exception when circular dependency', () => {
expect(() => {
moduleA.addRelatedModule(moduleB);
moduleB.addRelatedModule(moduleA);
}).to.not.throw;
});
});
});