nestjs-custom-injector의 주 버전: 공급자가 설정되지 않은 경우 예외, 기본값 등에서 약속 사용...
99520 단어 nestjsprovidertypescriptinject
설치
npm i --save nestjs-custom-injector
연결
https://github.com/EndyKaufman/nestjs-custom-injector - 라이브러리의 소스 코드
https://nestjs-custom-injector.site15.ru/api - nestjs-custom-injector를 사용한 데모 애플리케이션.
https://github.com/EndyKaufman/nestjs-custom-injector-example - nest cli로 생성된 예.
주요 변경 사항
getProvider
getProviders
@CustomInject(PROVIDER_TOKEN,{ lazy:true })
.다중 공급자로 모든 기능을 테스트합니다.
다중 공급자와 협력
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, { multi: true })
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers.map((o) => o.type)).toEqual(['c1', 'c2']);
await app.close();
다중 일반 및 비동기 공급자와 협력
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, { multi: true })
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [
{
provide: C_PROVIDER,
useFactory: () =>
new Promise((resolve) => setTimeout(() => resolve(new C2()), 1000)),
},
],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers.map((o) => o.type)).toEqual(['c1', 'c2']);
await app.close();
공급자 배열이 설정되지 않은 경우 오류
interface CProvider {
type: string;
}
const C_PROVIDER1 = 'C_PROVIDER1';
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER1, { multi: true })
providers!: CProvider;
}
const module = await Test.createTestingModule({
imports: [CustomInjectorModule.forRoot()],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
try {
await app.init();
expect(true).toEqual(false);
} catch (err) {
expect(err instanceof CustomInjectorError && err.message).toEqual(
`Providers "C_PROVIDER1" not found!`
);
expect(
err instanceof CustomInjectorError &&
err.injectedProvidersStorageItem?.token
).toEqual(C_PROVIDER1);
}
await app.close();
공급자 배열이 설정되지 않은 경우 사용자 지정 오류
interface CProvider {
type: string;
}
class CustomError extends CustomInjectorError<CProvider> {
constructor(public override message: string) {
super(message);
}
}
const C_PROVIDER1 = 'C_PROVIDER1';
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER1, {
multi: true,
errorFactory: (message: string) => new CustomError(message),
})
providers!: CProvider;
}
const module = await Test.createTestingModule({
imports: [CustomInjectorModule.forRoot()],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
try {
await app.init();
expect(true).toEqual(false);
} catch (err) {
expect(err instanceof CustomError && err.message).toEqual(
`Providers "C_PROVIDER1" not found!`
);
expect(
err instanceof CustomError && err.injectedProvidersStorageItem?.token
).toEqual(undefined);
}
await app.close();
});
팩토리로 다중 제공자 생성
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 {
name = 'c1';
}
@Injectable()
class C2 {
name = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
providerFactory: (data) => ({ type: data.name }),
})
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers.map((o) => o.type)).toEqual(['c1', 'c2']);
await app.close();
비동기 팩토리로 다중 제공자 생성
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 {
name = 'c1';
}
@Injectable()
class C2 {
name = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
providerFactory: (data) =>
new Promise((resolve) =>
setTimeout(() => resolve({ type: data.name }), 1000)
),
})
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers.map((o) => o.type)).toEqual(['c1', 'c2']);
await app.close();
응용 프로그램 부트스트랩에서 설정하지 않고 데이터 가져오기에 지연 옵션을 사용하여 다중 공급자를 로드합니다.
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, { multi: true, lazy: true })
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
// we don't need start application, because providers marked with lazy options will be ignored when the application bootstrap
// await app.init();
const p = app.get<P>(P);
expect(p.providers.map((o) => o.type)).toEqual(['c1', 'c2']);
await app.close();
런타임 시 다중 공급자 업데이트
interface CProvider {
type: string;
}
const C_PROVIDER_NEW = Symbol('C_PROVIDER_NEW');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER_NEW, { multi: true })
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER_NEW, useValue: new C1() }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER_NEW, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers.map((o) => o.type)).toEqual(['c1', 'c2']);
p.providers.forEach((o) => {
o.type = `updated ${o.type}`;
});
const p2 = app.get<P>(P);
expect(p2.providers.map((o) => o.type)).toEqual([
'updated c1',
'updated c2',
]);
await app.close();
});
런타임 시 공장에서 만든 다중 공급자 업데이트
interface CProvider {
type: string;
}
const C_PROVIDER_NEW = Symbol('C_PROVIDER_NEW');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER_NEW, {
multi: true,
providerFactory: (data) => ({ ...data, type: `factory ${data.type}` }),
})
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER_NEW, useValue: new C1() }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER_NEW, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const providers = app.get<P>(P).providers;
expect(providers.map((o) => o.type)).toEqual(['factory c1', 'factory c2']);
providers.forEach((o) => {
o.type = `updated ${o.type}`;
});
const currentProviders = [...app.get<P>(P).providers];
expect(currentProviders.map((o) => o.type)).toEqual([
'updated factory c1',
'updated factory c2',
]);
await app.close();
});
토큰 공급자를 찾을 수 없는 경우 기본 공급자 사용
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
defaultProvidersValue: [],
})
providers!: CProvider[];
}
const module = await Test.createTestingModule({
imports: [CustomInjectorModule.forRoot()],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const providers = app.get<P>(P).providers;
expect(providers).toEqual([]);
await app.close();
});
다중 공급자 및 하위 속성으로 모든 기능을 테스트합니다.
다중 공급자와 협력
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
propertyName: 'type',
})
providers!: CProvider['type'][];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers).toEqual(['c1', 'c2']);
await app.close();
});
다중 일반 및 비동기 공급자와 협력
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
propertyName: 'type',
})
providers!: CProvider['type'][];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [
{
provide: C_PROVIDER,
useFactory: () =>
new Promise((resolve) => setTimeout(() => resolve(new C2()), 1000)),
},
],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers).toEqual(['c1', 'c2']);
await app.close();
공급자 배열이 설정되지 않은 경우 오류
interface CProvider {
type: string;
}
const C_PROVIDER1 = 'C_PROVIDER1';
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER1, {
multi: true,
propertyName: 'type',
})
providers!: CProvider['type'];
}
const module = await Test.createTestingModule({
imports: [CustomInjectorModule.forRoot()],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
try {
await app.init();
expect(true).toEqual(false);
} catch (err) {
expect(err instanceof CustomInjectorError && err.message).toEqual(
`Providers "C_PROVIDER1" not found!`
);
expect(
err instanceof CustomInjectorError &&
err.injectedProvidersStorageItem?.token
).toEqual(C_PROVIDER1);
}
await app.close();
공급자 배열이 설정되지 않은 경우 사용자 지정 오류
interface CProvider {
type: string;
}
class CustomError extends CustomInjectorError<CProvider> {
constructor(public override message: string) {
super(message);
}
}
const C_PROVIDER1 = 'C_PROVIDER1';
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER1, {
multi: true,
propertyName: 'type',
errorFactory: (message: string) => new CustomError(message),
})
providers!: CProvider['type'];
}
const module = await Test.createTestingModule({
imports: [CustomInjectorModule.forRoot()],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
try {
await app.init();
expect(true).toEqual(false);
} catch (err) {
expect(err instanceof CustomError && err.message).toEqual(
`Providers "C_PROVIDER1" not found!`
);
expect(
err instanceof CustomError && err.injectedProvidersStorageItem?.token
).toEqual(undefined);
}
await app.close();
팩토리로 다중 제공자 생성
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 {
name = 'c1';
}
@Injectable()
class C2 {
name = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
propertyName: 'type',
providerFactory: (data) => ({ type: data.name }),
})
providers!: CProvider['type'][];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers).toEqual(['c1', 'c2']);
await app.close();
비동기 팩토리로 다중 제공자 생성
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 {
name = 'c1';
}
@Injectable()
class C2 {
name = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
propertyName: 'type',
providerFactory: (data) =>
new Promise((resolve) =>
setTimeout(() => resolve({ type: data.name }), 1000)
),
})
providers!: CProvider['type'][];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const p = app.get<P>(P);
expect(p.providers).toEqual(['c1', 'c2']);
await app.close();
응용 프로그램 부트스트랩에서 설정하지 않고 데이터 가져오기에 지연 옵션을 사용하여 다중 공급자를 로드합니다.
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class C1 implements CProvider {
type = 'c1';
}
@Injectable()
class C2 implements CProvider {
type = 'c2';
}
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
propertyName: 'type',
lazy: true,
})
providers!: CProvider['type'][];
}
const module = await Test.createTestingModule({
imports: [
CustomInjectorModule.forRoot(),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C1 }],
}),
CustomInjectorModule.forFeature({
providers: [{ provide: C_PROVIDER, useClass: C2 }],
}),
],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
// we don't need start application, because providers marked with lazy options will be ignored when the application bootstrap
// await app.init();
const p = app.get<P>(P);
expect(p.providers).toEqual(['c1', 'c2']);
await app.close();
});
토큰 공급자를 찾을 수 없는 경우 기본 공급자 사용
interface CProvider {
type: string;
}
const C_PROVIDER = Symbol('C_PROVIDER');
@Injectable()
class P {
@CustomInject<CProvider>(C_PROVIDER, {
multi: true,
propertyName: 'type',
defaultProvidersValue: [],
})
providers!: CProvider['type'][];
}
const module = await Test.createTestingModule({
imports: [CustomInjectorModule.forRoot()],
providers: [P],
exports: [P],
}).compile();
const app = module.createNestApplication();
await app.init();
const providers = app.get<P>(P).providers;
expect(providers).toEqual([]);
await app.close();
});
Reference
이 문제에 관하여(nestjs-custom-injector의 주 버전: 공급자가 설정되지 않은 경우 예외, 기본값 등에서 약속 사용...), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/endykaufman/major-version-of-nestjs-custom-injector-exception-if-the-provider-is-not-set-use-a-promise-in-the-default-value-and-etc-2jo5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)