Skip to content

Commit 822c676

Browse files
fix(core): fix typings, transient scope through resolve
1 parent ec29271 commit 822c676

12 files changed

Lines changed: 109 additions & 9 deletions

File tree

integration/injector/e2e/scoped-instances.spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { createContextId } from '@nestjs/core';
12
import { InvalidClassScopeException } from '@nestjs/core/errors/exceptions/invalid-class-scope.exception';
23
import { Test, TestingModule } from '@nestjs/testing';
34
import { expect } from 'chai';
@@ -16,8 +17,9 @@ describe('Scoped Instances', () => {
1617
});
1718

1819
it('should dynamically resolve transient provider', async () => {
19-
const transient1 = await testingModule.resolve(TransientService);
20-
const transient2 = await testingModule.resolve(TransientService);
20+
const contextId = createContextId();
21+
const transient1 = await testingModule.resolve(TransientService, contextId);
22+
const transient2 = await testingModule.resolve(TransientService, contextId);
2123

2224
expect(transient1).to.be.instanceOf(TransientService);
2325
expect(transient2).to.be.instanceOf(TransientService);

integration/injector/src/scoped/scoped.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
22
import { ScopedController } from './scoped.controller';
33
import { ScopedService } from './scoped.service';
44
import { TransientService } from './transient.service';
5+
import { Transient2Service } from './transient2.service';
56

67
@Module({
78
controllers: [ScopedController],
8-
providers: [ScopedService, TransientService],
9+
providers: [ScopedService, TransientService, Transient2Service],
910
})
1011
export class ScopedModule {}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { Injectable, Scope } from '@nestjs/common';
2+
import { Transient2Service } from './transient2.service';
23

34
@Injectable({ scope: Scope.TRANSIENT })
4-
export class TransientService {}
5+
export class TransientService {
6+
constructor(private readonly svc: Transient2Service) {}
7+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { Injectable, Scope } from '@nestjs/common';
2+
3+
@Injectable({ scope: Scope.TRANSIENT })
4+
export class Transient2Service {}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { INestApplication } from '@nestjs/common';
2+
import { Test } from '@nestjs/testing';
3+
import { expect } from 'chai';
4+
import { loggerProvider } from '../src/resolve-scoped/logger.provider';
5+
import { LoggerService } from '../src/resolve-scoped/logger.service';
6+
import { RequestLoggerService } from '../src/resolve-scoped/request-logger.service';
7+
8+
describe('Resolve method', () => {
9+
let app: INestApplication;
10+
11+
beforeEach(async () => {
12+
const module = await Test.createTestingModule({
13+
providers: [LoggerService, loggerProvider, RequestLoggerService],
14+
}).compile();
15+
16+
app = module.createNestApplication();
17+
await app.init();
18+
});
19+
20+
it('should resolve transient logger', async () => {
21+
const transientLogger = await app.resolve(LoggerService);
22+
expect(transientLogger.logger).to.be.eql({
23+
logger: true,
24+
});
25+
});
26+
27+
it('should resolve request-scoped logger', async () => {
28+
const requestScoped = await app.resolve(RequestLoggerService);
29+
30+
expect(requestScoped.loggerService).to.be.instanceOf(LoggerService);
31+
expect(requestScoped.loggerService.logger).to.be.eql({
32+
logger: true,
33+
});
34+
});
35+
36+
after(async () => {
37+
await app.close();
38+
});
39+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { FactoryProvider } from '@nestjs/common/interfaces';
2+
3+
export const LOGGER_PROVIDER = 'LOGGER_PROVIDER';
4+
export const loggerProvider: FactoryProvider = {
5+
provide: LOGGER_PROVIDER,
6+
useFactory: () => {
7+
return { logger: true };
8+
},
9+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Inject, Injectable, Scope } from '@nestjs/common';
2+
import { LOGGER_PROVIDER } from './logger.provider';
3+
4+
@Injectable({ scope: Scope.TRANSIENT })
5+
export class LoggerService {
6+
constructor(@Inject(LOGGER_PROVIDER) public logger) {}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Injectable, Scope } from '@nestjs/common';
2+
import { LoggerService } from './logger.service';
3+
4+
@Injectable({ scope: Scope.REQUEST })
5+
export class RequestLoggerService {
6+
constructor(public loggerService: LoggerService) {}
7+
}

packages/core/helpers/http-adapter-host.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { AbstractHttpAdapter } from '../adapters/http-adapter';
1515
export class HttpAdapterHost<
1616
T extends AbstractHttpAdapter = AbstractHttpAdapter
1717
> {
18-
private _httpAdapter: T;
18+
private _httpAdapter?: T;
1919

2020
/**
2121
* Accessor for the underlying `HttpAdapter`
@@ -32,7 +32,7 @@ export class HttpAdapterHost<
3232
* @example
3333
* `const httpAdapter = adapterHost.httpAdapter;`
3434
*/
35-
get httpAdapter(): T | undefined {
35+
get httpAdapter(): T {
3636
return this._httpAdapter;
3737
}
3838
}

packages/core/injector/injector.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,12 @@ export class Injector {
633633
const isStatic = wrapper.isStatic(contextId, inquirer);
634634
const isInRequestScope = wrapper.isInRequestScope(contextId, inquirer);
635635
const isLazyTransient = wrapper.isLazyTransient(contextId, inquirer);
636-
const isInContext = isStatic || isInRequestScope || isLazyTransient;
636+
const isExplicitlyRequested = wrapper.isExplicitlyRequested(
637+
contextId,
638+
inquirer,
639+
);
640+
const isInContext =
641+
isStatic || isInRequestScope || isLazyTransient || isExplicitlyRequested;
637642

638643
if (isNil(inject) && isInContext) {
639644
instanceHost.instance = wrapper.forwardRef
@@ -664,7 +669,7 @@ export class Injector {
664669
await this.loadInstance(wrapper, collection, module, ctx, wrapper);
665670
await this.loadEnhancersPerContext(wrapper, ctx, wrapper);
666671

667-
const host = wrapper.getInstanceByContextId(ctx);
672+
const host = wrapper.getInstanceByContextId(ctx, wrapper.id);
668673
return host && (host.instance as T);
669674
}
670675

0 commit comments

Comments
 (0)