Skip to content

Commit 63644df

Browse files
feat(core) add error message to improve DX (get vs resolve)
1 parent bdb0ede commit 63644df

4 files changed

Lines changed: 39 additions & 1 deletion

File tree

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { InvalidClassScopeException } from '@nestjs/core/errors/exceptions/invalid-class-scope.exception';
12
import { Test, TestingModule } from '@nestjs/testing';
23
import { expect } from 'chai';
34
import { ScopedController } from '../src/scoped/scoped.controller';
@@ -42,4 +43,12 @@ describe('Scoped Instances', () => {
4243
expect(request2).to.be.instanceOf(ScopedController);
4344
expect(request3).to.not.be.equal(request2);
4445
});
46+
47+
it('should throw an exception when "get()" method is used', async () => {
48+
try {
49+
testingModule.get(ScopedController);
50+
} catch (err) {
51+
expect(err).to.be.instanceOf(InvalidClassScopeException);
52+
}
53+
});
4554
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Abstract, Type } from '@nestjs/common/interfaces';
2+
import { isFunction } from '@nestjs/common/utils/shared.utils';
3+
import { INVALID_CLASS_SCOPE_MESSAGE } from '../messages';
4+
import { RuntimeException } from './runtime.exception';
5+
6+
export class InvalidClassScopeException extends RuntimeException {
7+
constructor(metatypeOrToken: Type<any> | Abstract<any> | string | symbol) {
8+
let name = isFunction(metatypeOrToken)
9+
? (metatypeOrToken as Function).name
10+
: metatypeOrToken;
11+
name = name && name.toString();
12+
13+
super(INVALID_CLASS_SCOPE_MESSAGE`${name}`);
14+
}
15+
}

packages/core/errors/messages.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ export const UNKNOWN_EXPORT_MESSAGE = (
8181
export const INVALID_CLASS_MESSAGE = (text: TemplateStringsArray, value: any) =>
8282
`ModuleRef cannot instantiate class (${value} is not constructable).`;
8383

84+
export const INVALID_CLASS_SCOPE_MESSAGE = (
85+
text: TemplateStringsArray,
86+
name: string | undefined,
87+
) =>
88+
`${name ||
89+
'This class'} is marked as a scoped provider. Request and transient-scoped providers can't be used in combination with "get()" method. Please, use "resolve()" instead.`;
90+
8491
export const INVALID_MIDDLEWARE_CONFIGURATION = `An invalid middleware configuration has been passed inside the module 'configure()' method.`;
8592
export const UNKNOWN_REQUEST_MAPPING = `An invalid controller has been detected. Perhaps, one of your controllers is missing @Controller() decorator.`;
8693
export const UNHANDLED_RUNTIME_EXCEPTION = `Unhandled Runtime Exception.`;

packages/core/injector/container-scanner.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Type } from '@nestjs/common';
2-
import { Abstract } from '@nestjs/common/interfaces';
2+
import { Abstract, Scope } from '@nestjs/common/interfaces';
33
import { isFunction } from '@nestjs/common/utils/shared.utils';
4+
import { InvalidClassScopeException } from '../errors/exceptions/invalid-class-scope.exception';
45
import { UnknownElementException } from '../errors/exceptions/unknown-element.exception';
56
import { NestContainer } from './container';
67
import { InstanceWrapper } from './instance-wrapper';
@@ -41,6 +42,12 @@ export class ContainerScanner {
4142
metatypeOrToken,
4243
contextModule,
4344
);
45+
if (
46+
instanceWrapper.scope === Scope.REQUEST ||
47+
instanceWrapper.scope === Scope.TRANSIENT
48+
) {
49+
throw new InvalidClassScopeException(metatypeOrToken);
50+
}
4451
return instanceWrapper.instance;
4552
}
4653

0 commit comments

Comments
 (0)