mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 15:08:37 +00:00
build: use strict null checks part 1
This commit is contained in:
@@ -128,8 +128,8 @@ export class Module {
|
||||
}
|
||||
|
||||
get entryProviders(): Array<InstanceWrapper<Injectable>> {
|
||||
return Array.from(this._entryProviderKeys).map(token =>
|
||||
this.providers.get(token),
|
||||
return Array.from(this._entryProviderKeys).map(
|
||||
token => this.providers.get(token)!,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ export class Module {
|
||||
new InstanceWrapper({
|
||||
token: providerToken,
|
||||
name: (providerToken as Function)?.name || providerToken,
|
||||
metatype: null,
|
||||
metatype: null!,
|
||||
instance: value,
|
||||
isResolved: true,
|
||||
async: value instanceof Promise,
|
||||
@@ -497,7 +497,7 @@ export class Module {
|
||||
token: controller,
|
||||
name: controller.name,
|
||||
metatype: controller,
|
||||
instance: null,
|
||||
instance: null!,
|
||||
isResolved: false,
|
||||
scope: getClassScope(controller),
|
||||
durable: isDurable(controller),
|
||||
@@ -532,11 +532,11 @@ export class Module {
|
||||
if (options.isProvider && this.hasProvider(toReplace)) {
|
||||
const originalProvider = this._providers.get(toReplace);
|
||||
|
||||
return originalProvider.mergeWith({ provide: toReplace, ...options });
|
||||
return originalProvider!.mergeWith({ provide: toReplace, ...options });
|
||||
} else if (!options.isProvider && this.hasInjectable(toReplace)) {
|
||||
const originalInjectable = this._injectables.get(toReplace);
|
||||
|
||||
return originalInjectable.mergeWith({
|
||||
return originalInjectable!.mergeWith({
|
||||
provide: toReplace,
|
||||
...options,
|
||||
});
|
||||
|
||||
@@ -91,7 +91,7 @@ export class GraphInspector {
|
||||
}
|
||||
|
||||
public insertAttachedEnhancer(wrapper: InstanceWrapper) {
|
||||
const existingNode = this.graph.getNodeById(wrapper.id);
|
||||
const existingNode = this.graph.getNodeById(wrapper.id)!;
|
||||
existingNode.metadata.global = true;
|
||||
|
||||
this.graph.insertAttachedEnhancer(existingNode.id);
|
||||
@@ -123,12 +123,12 @@ export class GraphInspector {
|
||||
sourceModuleName: moduleRef.name,
|
||||
durable: wrapper.isDependencyTreeDurable(),
|
||||
static: wrapper.isDependencyTreeStatic(),
|
||||
scope: wrapper.scope,
|
||||
scope: wrapper.scope!,
|
||||
transient: wrapper.isTransient,
|
||||
exported: moduleRef.exports.has(wrapper.token),
|
||||
token: wrapper.token,
|
||||
subtype: wrapper.subtype,
|
||||
initTime: wrapper.initTime,
|
||||
initTime: wrapper.initTime!,
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -168,7 +168,7 @@ export class GraphInspector {
|
||||
const moduleRef = this.container.getModuleByKey(entry.moduleToken);
|
||||
const sourceInstanceWrapper =
|
||||
moduleRef.controllers.get(entry.classRef) ??
|
||||
moduleRef.providers.get(entry.classRef);
|
||||
moduleRef.providers.get(entry.classRef)!;
|
||||
const existingSourceNode = this.graph.getNodeById(
|
||||
sourceInstanceWrapper.id,
|
||||
) as ClassNode;
|
||||
@@ -190,7 +190,7 @@ export class GraphInspector {
|
||||
});
|
||||
} else {
|
||||
const name =
|
||||
entry.enhancerRef.constructor?.name ??
|
||||
entry.enhancerRef!.constructor?.name ??
|
||||
(entry.enhancerRef as Function).name;
|
||||
|
||||
enhancers.push({
|
||||
@@ -219,7 +219,7 @@ export class GraphInspector {
|
||||
targetClassName: target.name,
|
||||
sourceClassToken: source.token,
|
||||
targetClassToken: target.token,
|
||||
targetModuleName: target.host?.name,
|
||||
targetModuleName: target.host?.name!,
|
||||
keyOrIndex,
|
||||
injectionType,
|
||||
},
|
||||
|
||||
@@ -41,19 +41,19 @@ export class InterceptorsContextCreator extends ContextCreator {
|
||||
inquirerId?: string,
|
||||
): R {
|
||||
if (isEmpty(metadata)) {
|
||||
return [] as R;
|
||||
return [] as any[] as R;
|
||||
}
|
||||
return iterate(metadata)
|
||||
.filter(
|
||||
interceptor =>
|
||||
interceptor && (interceptor.name || interceptor.intercept),
|
||||
)
|
||||
.map(interceptor =>
|
||||
this.getInterceptorInstance(interceptor, contextId, inquirerId),
|
||||
.map(
|
||||
interceptor =>
|
||||
this.getInterceptorInstance(interceptor, contextId, inquirerId)!,
|
||||
)
|
||||
.filter(
|
||||
(interceptor: NestInterceptor) =>
|
||||
interceptor && isFunction(interceptor.intercept),
|
||||
.filter((interceptor: NestInterceptor) =>
|
||||
interceptor ? isFunction(interceptor.intercept) : false,
|
||||
)
|
||||
.toArray() as R;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ export class InterceptorsContextCreator extends ContextCreator {
|
||||
contextId = STATIC_CONTEXT,
|
||||
inquirerId?: string,
|
||||
): NestInterceptor | null {
|
||||
const isObject = (metatype as NestInterceptor).intercept;
|
||||
const isObject = !!(metatype as NestInterceptor).intercept;
|
||||
if (isObject) {
|
||||
return metatype as NestInterceptor;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ export class InterceptorsContextCreator extends ContextCreator {
|
||||
inquirerId?: string,
|
||||
): T {
|
||||
if (!this.config) {
|
||||
return [] as T;
|
||||
return [] as unknown[] as T;
|
||||
}
|
||||
const globalInterceptors = this.config.getGlobalInterceptors() as T;
|
||||
if (contextId === STATIC_CONTEXT && !inquirerId) {
|
||||
|
||||
@@ -34,7 +34,10 @@ export class MetadataScanner {
|
||||
visitedNames.set(property, true);
|
||||
|
||||
// reason: https://github.com/nestjs/nest/pull/10821#issuecomment-1411916533
|
||||
const descriptor = Object.getOwnPropertyDescriptor(prototype, property);
|
||||
const descriptor = Object.getOwnPropertyDescriptor(
|
||||
prototype,
|
||||
property,
|
||||
)!;
|
||||
|
||||
if (
|
||||
descriptor.set ||
|
||||
|
||||
@@ -338,8 +338,8 @@ export class MiddlewareModule<
|
||||
}
|
||||
|
||||
private getContextId(request: unknown, isTreeDurable: boolean): ContextId {
|
||||
const contextId = ContextIdFactory.getByRequest(request);
|
||||
if (!request[REQUEST_CONTEXT_ID]) {
|
||||
const contextId = ContextIdFactory.getByRequest(request!);
|
||||
if (!request![REQUEST_CONTEXT_ID]) {
|
||||
Object.defineProperty(request, REQUEST_CONTEXT_ID, {
|
||||
value: contextId,
|
||||
enumerable: false,
|
||||
|
||||
@@ -112,9 +112,9 @@ export function isMiddlewareRouteExcluded(
|
||||
if (excludedRoutes.length <= 0) {
|
||||
return false;
|
||||
}
|
||||
const reqMethod = httpAdapter.getRequestMethod(req);
|
||||
const originalUrl = httpAdapter.getRequestUrl(req);
|
||||
const queryParamsIndex = originalUrl && originalUrl.indexOf('?');
|
||||
const reqMethod = httpAdapter.getRequestMethod?.(req)!;
|
||||
const originalUrl = httpAdapter.getRequestUrl?.(req)!;
|
||||
const queryParamsIndex = originalUrl ? originalUrl.indexOf('?') : -1;
|
||||
const pathname =
|
||||
queryParamsIndex >= 0
|
||||
? originalUrl.slice(0, queryParamsIndex)
|
||||
|
||||
@@ -26,15 +26,15 @@ import { NestContainer } from '../injector/container';
|
||||
import { Injector } from '../injector/injector';
|
||||
import { ContextId, InstanceWrapper } from '../injector/instance-wrapper';
|
||||
import { Module } from '../injector/module';
|
||||
import {
|
||||
InterceptorsConsumer,
|
||||
InterceptorsContextCreator,
|
||||
} from '../interceptors';
|
||||
import { GraphInspector } from '../inspector/graph-inspector';
|
||||
import {
|
||||
Entrypoint,
|
||||
HttpEntrypointMetadata,
|
||||
} from '../inspector/interfaces/entrypoint.interface';
|
||||
import {
|
||||
InterceptorsConsumer,
|
||||
InterceptorsContextCreator,
|
||||
} from '../interceptors';
|
||||
import { MetadataScanner } from '../metadata-scanner';
|
||||
import { PipesConsumer, PipesContextCreator } from '../pipes';
|
||||
import { ExceptionsFilter } from './interfaces/exceptions-filter.interface';
|
||||
|
||||
@@ -78,7 +78,7 @@ export class RouterModule {
|
||||
private updateTargetModulesCache(moduleCtor: Type<unknown>) {
|
||||
let moduleClassSet: WeakSet<ModuleClass>;
|
||||
if (targetModulesByContainer.has(this.modulesContainer)) {
|
||||
moduleClassSet = targetModulesByContainer.get(this.modulesContainer);
|
||||
moduleClassSet = targetModulesByContainer.get(this.modulesContainer)!;
|
||||
} else {
|
||||
moduleClassSet = new WeakSet<ModuleClass>();
|
||||
targetModulesByContainer.set(this.modulesContainer, moduleClassSet);
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { normalizePath, isString } from '@nestjs/common/utils/shared.utils';
|
||||
import { Type } from '@nestjs/common';
|
||||
import { isString, normalizePath } from '@nestjs/common/utils/shared.utils';
|
||||
import { Routes } from '../interfaces/routes.interface';
|
||||
|
||||
export function flattenRoutePaths(routes: Routes) {
|
||||
const result = [];
|
||||
const result: Array<{
|
||||
module: Type;
|
||||
path: string;
|
||||
}> = [];
|
||||
routes.forEach(item => {
|
||||
if (item.module && item.path) {
|
||||
result.push({ module: item.module, path: item.path });
|
||||
@@ -15,7 +19,7 @@ export function flattenRoutePaths(routes: Routes) {
|
||||
normalizePath(item.path) + normalizePath(child.path),
|
||||
);
|
||||
} else {
|
||||
result.push({ path: item.path, module: child });
|
||||
result.push({ path: item.path, module: child as any as Type });
|
||||
}
|
||||
});
|
||||
result.push(...flattenRoutePaths(childrenRef));
|
||||
|
||||
@@ -138,7 +138,7 @@ export class DependenciesScanner {
|
||||
...((moduleDefinition as DynamicModule).imports || []),
|
||||
];
|
||||
|
||||
let registeredModuleRefs = [];
|
||||
let registeredModuleRefs: Module[] = [];
|
||||
for (const [index, innerModule] of modules.entries()) {
|
||||
// In case of a circular dependency (ES module system), JavaScript will resolve the type to `undefined`.
|
||||
if (innerModule === undefined) {
|
||||
@@ -152,7 +152,7 @@ export class DependenciesScanner {
|
||||
}
|
||||
const moduleRefs = await this.scanForModules({
|
||||
moduleDefinition: innerModule,
|
||||
scope: [].concat(scope, moduleDefinition),
|
||||
scope: ([] as Array<Type>).concat(scope, moduleDefinition as Type),
|
||||
ctxRegistry,
|
||||
overrides,
|
||||
lazy,
|
||||
@@ -215,7 +215,7 @@ export class DependenciesScanner {
|
||||
...this.container.getDynamicMetadataByToken(
|
||||
token,
|
||||
MODULE_METADATA.IMPORTS as 'imports',
|
||||
),
|
||||
)!,
|
||||
];
|
||||
for (const related of modules) {
|
||||
await this.insertImport(related, token, context);
|
||||
@@ -228,7 +228,7 @@ export class DependenciesScanner {
|
||||
...this.container.getDynamicMetadataByToken(
|
||||
token,
|
||||
MODULE_METADATA.PROVIDERS as 'providers',
|
||||
),
|
||||
)!,
|
||||
];
|
||||
providers.forEach(provider => {
|
||||
this.insertProvider(provider, token);
|
||||
@@ -242,7 +242,7 @@ export class DependenciesScanner {
|
||||
...this.container.getDynamicMetadataByToken(
|
||||
token,
|
||||
MODULE_METADATA.CONTROLLERS as 'controllers',
|
||||
),
|
||||
)!,
|
||||
];
|
||||
controllers.forEach(item => {
|
||||
this.insertController(item, token);
|
||||
@@ -267,7 +267,7 @@ export class DependenciesScanner {
|
||||
...this.container.getDynamicMetadataByToken(
|
||||
token,
|
||||
MODULE_METADATA.EXPORTS as 'exports',
|
||||
),
|
||||
)!,
|
||||
];
|
||||
exports.forEach(exportedProvider =>
|
||||
this.insertExportedProvider(exportedProvider, token),
|
||||
@@ -285,19 +285,25 @@ export class DependenciesScanner {
|
||||
);
|
||||
const methodInjectables = this.metadataScanner
|
||||
.getAllMethodNames(component.prototype)
|
||||
.reduce((acc, method) => {
|
||||
const methodInjectable = this.reflectKeyMetadata(
|
||||
component,
|
||||
metadataKey,
|
||||
method,
|
||||
);
|
||||
.reduce(
|
||||
(acc, method) => {
|
||||
const methodInjectable = this.reflectKeyMetadata(
|
||||
component,
|
||||
metadataKey,
|
||||
method,
|
||||
);
|
||||
|
||||
if (methodInjectable) {
|
||||
acc.push(methodInjectable);
|
||||
}
|
||||
if (methodInjectable) {
|
||||
acc.push(methodInjectable);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
return acc;
|
||||
},
|
||||
[] as Array<{
|
||||
methodKey: string;
|
||||
metadata: Type<Injectable>[];
|
||||
}>,
|
||||
);
|
||||
|
||||
controllerInjectables.forEach(injectable =>
|
||||
this.insertInjectable(
|
||||
@@ -308,13 +314,13 @@ export class DependenciesScanner {
|
||||
),
|
||||
);
|
||||
methodInjectables.forEach(methodInjectable => {
|
||||
methodInjectable.metadata.forEach(injectable =>
|
||||
methodInjectable.metadata!.forEach(injectable =>
|
||||
this.insertInjectable(
|
||||
injectable,
|
||||
token,
|
||||
component,
|
||||
ENHANCER_KEY_TO_SUBTYPE_MAP[metadataKey],
|
||||
methodInjectable.methodKey,
|
||||
methodInjectable.methodKey!,
|
||||
),
|
||||
);
|
||||
});
|
||||
@@ -392,7 +398,7 @@ export class DependenciesScanner {
|
||||
const calculateDistance = (
|
||||
moduleRef: Module,
|
||||
distance = 1,
|
||||
modulesStack = [],
|
||||
modulesStack: Module[] = [],
|
||||
) => {
|
||||
const localModulesStack = [...modulesStack];
|
||||
if (!moduleRef || localModulesStack.includes(moduleRef)) {
|
||||
@@ -412,7 +418,7 @@ export class DependenciesScanner {
|
||||
};
|
||||
|
||||
const rootModule = modulesGenerator.next().value;
|
||||
calculateDistance(rootModule);
|
||||
calculateDistance(rootModule!);
|
||||
}
|
||||
|
||||
public async insertImport(related: any, token: string, context: string) {
|
||||
@@ -478,7 +484,7 @@ export class DependenciesScanner {
|
||||
const factoryOrClassProvider = newProvider as
|
||||
| FactoryProvider
|
||||
| ClassProvider;
|
||||
if (this.isRequestOrTransient(factoryOrClassProvider.scope)) {
|
||||
if (this.isRequestOrTransient(factoryOrClassProvider.scope!)) {
|
||||
return this.container.addInjectable(newProvider, token, enhancerSubtype);
|
||||
}
|
||||
this.container.addProvider(newProvider, token, enhancerSubtype);
|
||||
@@ -629,10 +635,10 @@ export class DependenciesScanner {
|
||||
*/
|
||||
public addScopedEnhancersMetadata() {
|
||||
iterate(this.applicationProvidersApplyMap)
|
||||
.filter(wrapper => this.isRequestOrTransient(wrapper.scope))
|
||||
.filter(wrapper => this.isRequestOrTransient(wrapper.scope!))
|
||||
.forEach(({ moduleKey, providerKey }) => {
|
||||
const modulesContainer = this.container.getModules();
|
||||
const { injectables } = modulesContainer.get(moduleKey);
|
||||
const { injectables } = modulesContainer.get(moduleKey)!;
|
||||
const instanceWrapper = injectables.get(providerKey);
|
||||
|
||||
const iterableIterator = modulesContainer.values();
|
||||
@@ -644,7 +650,7 @@ export class DependenciesScanner {
|
||||
)
|
||||
.flatten()
|
||||
.forEach(controllerOrEntryProvider =>
|
||||
controllerOrEntryProvider.addEnhancerMetadata(instanceWrapper),
|
||||
controllerOrEntryProvider.addEnhancerMetadata(instanceWrapper!),
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -659,7 +665,7 @@ export class DependenciesScanner {
|
||||
collectionKey: 'providers' | 'injectables',
|
||||
) => {
|
||||
const modules = this.container.getModules();
|
||||
const collection = modules.get(moduleKey)[collectionKey];
|
||||
const collection = modules.get(moduleKey)![collectionKey];
|
||||
return collection.get(providerKey);
|
||||
};
|
||||
|
||||
@@ -667,12 +673,12 @@ export class DependenciesScanner {
|
||||
this.applicationProvidersApplyMap.forEach(
|
||||
({ moduleKey, providerKey, type, scope }) => {
|
||||
let instanceWrapper: InstanceWrapper;
|
||||
if (this.isRequestOrTransient(scope)) {
|
||||
if (this.isRequestOrTransient(scope!)) {
|
||||
instanceWrapper = getInstanceWrapper(
|
||||
moduleKey,
|
||||
providerKey,
|
||||
'injectables',
|
||||
);
|
||||
)!;
|
||||
|
||||
this.graphInspector.insertAttachedEnhancer(instanceWrapper);
|
||||
return applyRequestProvidersMap[type as string](instanceWrapper);
|
||||
@@ -681,7 +687,7 @@ export class DependenciesScanner {
|
||||
moduleKey,
|
||||
providerKey,
|
||||
'providers',
|
||||
);
|
||||
)!;
|
||||
this.graphInspector.insertAttachedEnhancer(instanceWrapper);
|
||||
applyProvidersMap[type as string](instanceWrapper.instance);
|
||||
},
|
||||
|
||||
@@ -64,7 +64,7 @@ export class Reflector {
|
||||
const value = options.transform
|
||||
? options.transform(metadataValue)
|
||||
: metadataValue;
|
||||
SetMetadata(metadataKey, value ?? {})(target, key, descriptor);
|
||||
SetMetadata(metadataKey, value ?? {})(target, key!, descriptor);
|
||||
};
|
||||
|
||||
decoratorFn.KEY = metadataKey;
|
||||
@@ -256,7 +256,7 @@ export class Reflector {
|
||||
public getAllAndOverride<TResult = any, TKey = any>(
|
||||
metadataKeyOrDecorator: TKey,
|
||||
targets: (Type<any> | Function)[],
|
||||
): TResult {
|
||||
): TResult | undefined {
|
||||
for (const target of targets) {
|
||||
const result = this.get(metadataKeyOrDecorator, target);
|
||||
if (result !== undefined) {
|
||||
|
||||
@@ -43,7 +43,7 @@ export class ClientGrpcProxy
|
||||
);
|
||||
}
|
||||
|
||||
constructor(protected readonly options: GrpcOptions['options']) {
|
||||
constructor(protected readonly options: Required<GrpcOptions>['options']) {
|
||||
super();
|
||||
this.url = this.getOptionsProp(options, 'url') || GRPC_DEFAULT_URL;
|
||||
|
||||
@@ -166,10 +166,10 @@ export class ClientGrpcProxy
|
||||
methodName: string,
|
||||
): (...args: any[]) => Observable<any> {
|
||||
return (...args: any[]) => {
|
||||
const isRequestStream = client[methodName].requestStream;
|
||||
const isRequestStream = client![methodName].requestStream;
|
||||
const stream = new Observable(observer => {
|
||||
let isClientCanceled = false;
|
||||
let upstreamSubscription: Subscription;
|
||||
let upstreamSubscription: Subscription | null = null;
|
||||
|
||||
const upstreamSubjectOrData = args[0];
|
||||
const maybeMetadata = args[1];
|
||||
@@ -179,8 +179,8 @@ export class ClientGrpcProxy
|
||||
|
||||
const call =
|
||||
isRequestStream && isUpstreamSubject
|
||||
? client[methodName](maybeMetadata)
|
||||
: client[methodName](...args);
|
||||
? client
|
||||
: client;
|
||||
|
||||
if (isRequestStream && isUpstreamSubject) {
|
||||
upstreamSubscription = upstreamSubjectOrData.subscribe(
|
||||
@@ -295,7 +295,7 @@ export class ClientGrpcProxy
|
||||
public createClients(): any[] {
|
||||
const grpcContext = this.loadProto();
|
||||
const packageOption = this.getOptionsProp(this.options, 'package');
|
||||
const grpcPackages = [];
|
||||
const grpcPackages: any[] = [];
|
||||
const packageNames = Array.isArray(packageOption)
|
||||
? packageOption
|
||||
: [packageOption];
|
||||
|
||||
@@ -73,15 +73,15 @@ export class ClientKafka
|
||||
}
|
||||
|
||||
get producer(): Producer {
|
||||
if (!this._consumer) {
|
||||
if (!this._producer) {
|
||||
throw new Error(
|
||||
'No producer initialized. Please, call the "connect" method first.',
|
||||
);
|
||||
}
|
||||
return this._producer;
|
||||
return this._producer!;
|
||||
}
|
||||
|
||||
constructor(protected readonly options: KafkaOptions['options']) {
|
||||
constructor(protected readonly options: Required<KafkaOptions>['options']) {
|
||||
super();
|
||||
|
||||
const clientOptions = this.getOptionsProp(
|
||||
@@ -135,7 +135,7 @@ export class ClientKafka
|
||||
|
||||
public async connect(): Promise<Producer> {
|
||||
if (this.initialized) {
|
||||
return this.initialized.then(() => this._producer);
|
||||
return this.initialized.then(() => this._producer!);
|
||||
}
|
||||
/* eslint-disable-next-line no-async-promise-executor */
|
||||
this.initialized = new Promise(async (resolve, reject) => {
|
||||
@@ -160,7 +160,7 @@ export class ClientKafka
|
||||
},
|
||||
);
|
||||
|
||||
this._consumer = this.client.consumer(consumerOptions);
|
||||
this._consumer = this.client!.consumer(consumerOptions);
|
||||
this.registerConsumerEventListeners();
|
||||
|
||||
// Set member assignments on join and rebalance
|
||||
@@ -172,7 +172,7 @@ export class ClientKafka
|
||||
await this.bindTopics();
|
||||
}
|
||||
|
||||
this._producer = this.client.producer(this.options.producer || {});
|
||||
this._producer = this.client!.producer(this.options.producer || {});
|
||||
this.registerProducerEventListeners();
|
||||
await this._producer.connect();
|
||||
|
||||
@@ -181,7 +181,7 @@ export class ClientKafka
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
return this.initialized.then(() => this._producer);
|
||||
return this.initialized.then(() => this._producer!);
|
||||
}
|
||||
|
||||
public async bindTopics(): Promise<void> {
|
||||
@@ -217,13 +217,13 @@ export class ClientKafka
|
||||
|
||||
public createResponseCallback(): (payload: EachMessagePayload) => any {
|
||||
return async (payload: EachMessagePayload) => {
|
||||
const rawMessage = this.parser.parse<KafkaMessage>(
|
||||
const rawMessage = this.parser!.parse<KafkaMessage>(
|
||||
Object.assign(payload.message, {
|
||||
topic: payload.topic,
|
||||
partition: payload.partition,
|
||||
}),
|
||||
);
|
||||
if (isUndefined(rawMessage.headers[KafkaHeaders.CORRELATION_ID])) {
|
||||
if (isUndefined(rawMessage.headers![KafkaHeaders.CORRELATION_ID])) {
|
||||
return;
|
||||
}
|
||||
const { err, response, isDisposed, id } =
|
||||
@@ -270,6 +270,9 @@ export class ClientKafka
|
||||
}
|
||||
|
||||
protected registerConsumerEventListeners() {
|
||||
if (!this._consumer) {
|
||||
return;
|
||||
}
|
||||
this._consumer.on(this._consumer.events.CONNECT, () =>
|
||||
this._status$.next(KafkaStatus.CONNECTED),
|
||||
);
|
||||
@@ -288,6 +291,9 @@ export class ClientKafka
|
||||
}
|
||||
|
||||
protected registerProducerEventListeners() {
|
||||
if (!this._producer) {
|
||||
return;
|
||||
}
|
||||
this._producer.on(this._producer.events.CONNECT, () =>
|
||||
this._status$.next(KafkaStatus.CONNECTED),
|
||||
);
|
||||
@@ -309,7 +315,7 @@ export class ClientKafka
|
||||
this.options.send || {},
|
||||
);
|
||||
|
||||
return this._producer.send(message);
|
||||
return this._producer!.send(message);
|
||||
}
|
||||
|
||||
protected getReplyTopicPartition(topic: string): string {
|
||||
@@ -355,13 +361,14 @@ export class ClientKafka
|
||||
this.options.send || {},
|
||||
);
|
||||
|
||||
return this._producer.send(message);
|
||||
return this._producer!.send(message);
|
||||
})
|
||||
.catch(err => errorCallback(err));
|
||||
|
||||
return cleanup;
|
||||
} catch (err) {
|
||||
errorCallback(err);
|
||||
return () => null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
protected readonly logger = new Logger(ClientProxy.name);
|
||||
protected readonly subscriptionsCount = new Map<string, number>();
|
||||
protected readonly url: string;
|
||||
protected mqttClient: MqttClient;
|
||||
protected connectionPromise: Promise<any>;
|
||||
protected mqttClient: MqttClient | null = null;
|
||||
protected connectionPromise: Promise<any> | null = null;
|
||||
protected isInitialConnection = false;
|
||||
protected isReconnecting = false;
|
||||
protected pendingEventListeners: Array<{
|
||||
@@ -37,7 +37,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
callback: MqttEvents[keyof MqttEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(protected readonly options: MqttOptions['options']) {
|
||||
constructor(protected readonly options: Required<MqttOptions>['options']) {
|
||||
super();
|
||||
this.url = this.getOptionsProp(this.options, 'url') ?? MQTT_DEFAULT_URL;
|
||||
|
||||
@@ -64,7 +64,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
|
||||
public connect(): Promise<any> {
|
||||
if (this.mqttClient) {
|
||||
return this.connectionPromise;
|
||||
return this.connectionPromise!;
|
||||
}
|
||||
this.mqttClient = this.createClient();
|
||||
this.registerErrorListener(this.mqttClient);
|
||||
@@ -75,7 +75,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
this.registerCloseListener(this.mqttClient);
|
||||
|
||||
this.pendingEventListeners.forEach(({ event, callback }) =>
|
||||
this.mqttClient.on(event, callback),
|
||||
this.mqttClient!.on(event, callback),
|
||||
);
|
||||
this.pendingEventListeners = [];
|
||||
|
||||
@@ -233,7 +233,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
const options = serializedPacket.options;
|
||||
delete serializedPacket.options;
|
||||
|
||||
this.mqttClient.publish(
|
||||
this.mqttClient!.publish(
|
||||
this.getRequestPattern(pattern),
|
||||
JSON.stringify(serializedPacket),
|
||||
this.mergePacketOptions(options),
|
||||
@@ -241,7 +241,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
};
|
||||
|
||||
if (subscriptionsCount <= 0) {
|
||||
this.mqttClient.subscribe(
|
||||
this.mqttClient!.subscribe(
|
||||
responseChannel,
|
||||
(err: any) => !err && publishPacket(),
|
||||
);
|
||||
@@ -255,6 +255,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
};
|
||||
} catch (err) {
|
||||
callback({ err });
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,7 +268,7 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
delete serializedPacket.options;
|
||||
|
||||
return new Promise<void>((resolve, reject) =>
|
||||
this.mqttClient.publish(
|
||||
this.mqttClient!.publish(
|
||||
pattern,
|
||||
JSON.stringify(serializedPacket),
|
||||
this.mergePacketOptions(options),
|
||||
@@ -277,11 +278,11 @@ export class ClientMqtt extends ClientProxy<MqttEvents, MqttStatus> {
|
||||
}
|
||||
|
||||
protected unsubscribeFromChannel(channel: string) {
|
||||
const subscriptionCount = this.subscriptionsCount.get(channel);
|
||||
const subscriptionCount = this.subscriptionsCount.get(channel)!;
|
||||
this.subscriptionsCount.set(channel, subscriptionCount - 1);
|
||||
|
||||
if (subscriptionCount - 1 <= 0) {
|
||||
this.mqttClient.unsubscribe(channel);
|
||||
this.mqttClient!.unsubscribe(channel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ type NatsMsg = any;
|
||||
export class ClientNats extends ClientProxy<NatsEvents, NatsStatus> {
|
||||
protected readonly logger = new Logger(ClientNats.name);
|
||||
|
||||
protected natsClient: Client;
|
||||
protected connectionPromise: Promise<Client>;
|
||||
protected natsClient: Client | null = null;
|
||||
protected connectionPromise: Promise<Client> | null = null;
|
||||
protected statusEventEmitter = new EventEmitter<{
|
||||
[key in keyof NatsEvents]: Parameters<NatsEvents[key]>;
|
||||
}>();
|
||||
|
||||
constructor(protected readonly options: NatsOptions['options']) {
|
||||
constructor(protected readonly options: Required<NatsOptions>['options']) {
|
||||
super();
|
||||
natsPackage = loadPackage('nats', ClientNats.name, () => require('nats'));
|
||||
|
||||
@@ -229,6 +229,7 @@ export class ClientNats extends ClientProxy<NatsEvents, NatsStatus> {
|
||||
return () => subscription.unsubscribe();
|
||||
} catch (err) {
|
||||
callback({ err });
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,21 +49,27 @@ export class ClientProxyFactory {
|
||||
switch (transport) {
|
||||
case Transport.REDIS:
|
||||
return new ClientRedis(
|
||||
options as RedisOptions['options'],
|
||||
options as Required<RedisOptions>['options'],
|
||||
) as ClientProxy;
|
||||
case Transport.NATS:
|
||||
return new ClientNats(options as NatsOptions['options']) as ClientProxy;
|
||||
return new ClientNats(
|
||||
options as Required<NatsOptions>['options'],
|
||||
) as ClientProxy;
|
||||
case Transport.MQTT:
|
||||
return new ClientMqtt(options as MqttOptions['options']) as ClientProxy;
|
||||
return new ClientMqtt(
|
||||
options as Required<MqttOptions>['options'],
|
||||
) as ClientProxy;
|
||||
case Transport.GRPC:
|
||||
return new ClientGrpcProxy(options as GrpcOptions['options']);
|
||||
case Transport.RMQ:
|
||||
return new ClientRMQ(options as RmqOptions['options']) as ClientProxy;
|
||||
return new ClientRMQ(
|
||||
options as Required<RmqOptions>['options'],
|
||||
) as ClientProxy;
|
||||
case Transport.KAFKA:
|
||||
return new ClientKafka(options as KafkaOptions['options']);
|
||||
return new ClientKafka(options as Required<KafkaOptions>['options']);
|
||||
default:
|
||||
return new ClientTCP(
|
||||
options as TcpClientOptions['options'],
|
||||
options as Required<TcpClientOptions>['options'],
|
||||
) as ClientProxy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,10 +177,28 @@ export abstract class ClientProxy<
|
||||
}
|
||||
|
||||
protected getOptionsProp<
|
||||
T extends ClientOptions['options'],
|
||||
K extends keyof T,
|
||||
>(obj: T, prop: K, defaultValue: T[K] = undefined) {
|
||||
return obj && prop in obj ? obj[prop] : defaultValue;
|
||||
Options extends ClientOptions['options'],
|
||||
Attribute extends keyof Options,
|
||||
>(obj: Options, prop: Attribute): Options[Attribute];
|
||||
protected getOptionsProp<
|
||||
Options extends ClientOptions['options'],
|
||||
Attribute extends keyof Options,
|
||||
DefaultValue extends Options[Attribute] = Options[Attribute],
|
||||
>(
|
||||
obj: Options,
|
||||
prop: Attribute,
|
||||
defaultValue: DefaultValue,
|
||||
): Required<Options>[Attribute];
|
||||
protected getOptionsProp<
|
||||
Options extends ClientOptions['options'],
|
||||
Attribute extends keyof Options,
|
||||
DefaultValue extends Options[Attribute] = Options[Attribute],
|
||||
>(
|
||||
obj: Options,
|
||||
prop: Attribute,
|
||||
defaultValue: DefaultValue = undefined as DefaultValue,
|
||||
) {
|
||||
return obj && prop in obj ? obj![prop] : defaultValue;
|
||||
}
|
||||
|
||||
protected normalizePattern(pattern: MsPattern): string {
|
||||
@@ -190,30 +208,26 @@ export abstract class ClientProxy<
|
||||
protected initializeSerializer(options: ClientOptions['options']) {
|
||||
this.serializer =
|
||||
(options &&
|
||||
(
|
||||
options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpClientOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options']
|
||||
).serializer) ||
|
||||
(options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpClientOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options'])!.serializer) ||
|
||||
new IdentitySerializer();
|
||||
}
|
||||
|
||||
protected initializeDeserializer(options: ClientOptions['options']) {
|
||||
this.deserializer =
|
||||
(options &&
|
||||
(
|
||||
options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpClientOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options']
|
||||
).deserializer) ||
|
||||
(options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpClientOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options'])!.deserializer) ||
|
||||
new IncomingResponseDeserializer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export class ClientRedis extends ClientProxy<RedisEvents, RedisStatus> {
|
||||
callback: RedisEvents[keyof RedisEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(protected readonly options: RedisOptions['options']) {
|
||||
constructor(protected readonly options: Required<RedisOptions>['options']) {
|
||||
super();
|
||||
|
||||
redisPackage = loadPackage('ioredis', ClientRedis.name, () =>
|
||||
@@ -209,11 +209,11 @@ export class ClientRedis extends ClientProxy<RedisEvents, RedisStatus> {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (times > this.getOptionsProp(this.options, 'retryAttempts')) {
|
||||
if (times > this.getOptionsProp(this.options, 'retryAttempts', 0)) {
|
||||
this.logger.error('Retry time exhausted');
|
||||
return;
|
||||
}
|
||||
return this.getOptionsProp(this.options, 'retryDelay') ?? 5000;
|
||||
return this.getOptionsProp(this.options, 'retryDelay', 5000);
|
||||
}
|
||||
|
||||
public createResponseCallback(): (
|
||||
@@ -280,6 +280,7 @@ export class ClientRedis extends ClientProxy<RedisEvents, RedisStatus> {
|
||||
};
|
||||
} catch (err) {
|
||||
callback({ err });
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +296,7 @@ export class ClientRedis extends ClientProxy<RedisEvents, RedisStatus> {
|
||||
}
|
||||
|
||||
protected unsubscribeFromChannel(channel: string) {
|
||||
const subscriptionCount = this.subscriptionsCount.get(channel);
|
||||
const subscriptionCount = this.subscriptionsCount.get(channel)!;
|
||||
this.subscriptionsCount.set(channel, subscriptionCount - 1);
|
||||
|
||||
if (subscriptionCount - 1 <= 0) {
|
||||
|
||||
@@ -68,15 +68,19 @@ export class ClientRMQ extends ClientProxy<RmqEvents, RmqStatus> {
|
||||
protected replyQueue: string;
|
||||
protected noAssert: boolean;
|
||||
|
||||
constructor(protected readonly options: RmqOptions['options']) {
|
||||
constructor(protected readonly options: Required<RmqOptions>['options']) {
|
||||
super();
|
||||
this.queue =
|
||||
this.getOptionsProp(this.options, 'queue') || RQM_DEFAULT_QUEUE;
|
||||
this.queueOptions =
|
||||
this.getOptionsProp(this.options, 'queueOptions') ||
|
||||
RQM_DEFAULT_QUEUE_OPTIONS;
|
||||
this.replyQueue =
|
||||
this.getOptionsProp(this.options, 'replyQueue') || REPLY_QUEUE;
|
||||
this.queue = this.getOptionsProp(this.options, 'queue', RQM_DEFAULT_QUEUE);
|
||||
this.queueOptions = this.getOptionsProp(
|
||||
this.options,
|
||||
'queueOptions',
|
||||
RQM_DEFAULT_QUEUE_OPTIONS,
|
||||
);
|
||||
this.replyQueue = this.getOptionsProp(
|
||||
this.options,
|
||||
'replyQueue',
|
||||
REPLY_QUEUE,
|
||||
);
|
||||
this.noAssert =
|
||||
this.getOptionsProp(this.options, 'noAssert') ??
|
||||
this.queueOptions.noAssert ??
|
||||
@@ -300,7 +304,10 @@ export class ClientRMQ extends ClientProxy<RmqEvents, RmqStatus> {
|
||||
): Promise<void>;
|
||||
public async handleMessage(
|
||||
packet: unknown,
|
||||
options: Record<string, unknown> | ((packet: WritePacket) => any),
|
||||
options:
|
||||
| Record<string, unknown>
|
||||
| ((packet: WritePacket) => any)
|
||||
| undefined,
|
||||
callback?: (packet: WritePacket) => any,
|
||||
): Promise<void> {
|
||||
if (isFunction(options)) {
|
||||
@@ -313,13 +320,13 @@ export class ClientRMQ extends ClientProxy<RmqEvents, RmqStatus> {
|
||||
options,
|
||||
);
|
||||
if (isDisposed || err) {
|
||||
callback({
|
||||
callback?.({
|
||||
err,
|
||||
response,
|
||||
isDisposed: true,
|
||||
});
|
||||
}
|
||||
callback({
|
||||
callback?.({
|
||||
err,
|
||||
response,
|
||||
});
|
||||
@@ -372,6 +379,7 @@ export class ClientRMQ extends ClientProxy<RmqEvents, RmqStatus> {
|
||||
return () => this.responseEmitter.removeListener(correlationId, listener);
|
||||
} catch (err) {
|
||||
callback({ err });
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,19 +19,18 @@ export class ClientTCP extends ClientProxy<TcpEvents, TcpStatus> {
|
||||
protected readonly host: string;
|
||||
protected readonly socketClass: Type<TcpSocket>;
|
||||
protected readonly tlsOptions?: ConnectionOptions;
|
||||
protected socket: TcpSocket;
|
||||
protected connectionPromise: Promise<any>;
|
||||
protected socket: TcpSocket | null = null;
|
||||
protected connectionPromise: Promise<any> | null = null;
|
||||
protected pendingEventListeners: Array<{
|
||||
event: keyof TcpEvents;
|
||||
callback: TcpEvents[keyof TcpEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(options: TcpClientOptions['options']) {
|
||||
constructor(options: Required<TcpClientOptions>['options']) {
|
||||
super();
|
||||
this.port = this.getOptionsProp(options, 'port') || TCP_DEFAULT_PORT;
|
||||
this.host = this.getOptionsProp(options, 'host') || TCP_DEFAULT_HOST;
|
||||
this.socketClass =
|
||||
this.getOptionsProp(options, 'socketClass') || JsonSocket;
|
||||
this.port = this.getOptionsProp(options, 'port', TCP_DEFAULT_PORT);
|
||||
this.host = this.getOptionsProp(options, 'host', TCP_DEFAULT_HOST);
|
||||
this.socketClass = this.getOptionsProp(options, 'socketClass', JsonSocket);
|
||||
this.tlsOptions = this.getOptionsProp(options, 'tlsOptions');
|
||||
|
||||
this.initializeSerializer(options);
|
||||
@@ -48,13 +47,13 @@ export class ClientTCP extends ClientProxy<TcpEvents, TcpStatus> {
|
||||
this.registerErrorListener(this.socket);
|
||||
|
||||
this.pendingEventListeners.forEach(({ event, callback }) =>
|
||||
this.socket.on(event, callback as any),
|
||||
this.socket!.on(event, callback as any),
|
||||
);
|
||||
this.pendingEventListeners = [];
|
||||
|
||||
const source$ = this.connect$(this.socket.netSocket).pipe(
|
||||
tap(() => {
|
||||
this.socket.on('message', (buffer: WritePacket & PacketId) =>
|
||||
this.socket!.on('message', (buffer: WritePacket & PacketId) =>
|
||||
this.handleResponse(buffer),
|
||||
);
|
||||
}),
|
||||
@@ -105,7 +104,6 @@ export class ClientTCP extends ClientProxy<TcpEvents, TcpStatus> {
|
||||
...this.tlsOptions,
|
||||
port: this.port,
|
||||
host: this.host,
|
||||
socket,
|
||||
});
|
||||
} else {
|
||||
socket = new net.Socket();
|
||||
@@ -148,7 +146,7 @@ export class ClientTCP extends ClientProxy<TcpEvents, TcpStatus> {
|
||||
|
||||
public handleClose() {
|
||||
this.socket = null;
|
||||
this.connectionPromise = undefined;
|
||||
this.connectionPromise = null;
|
||||
|
||||
if (this.routingMap.size > 0) {
|
||||
const err = new Error('Connection closed');
|
||||
@@ -188,11 +186,12 @@ export class ClientTCP extends ClientProxy<TcpEvents, TcpStatus> {
|
||||
const serializedPacket = this.serializer.serialize(packet);
|
||||
|
||||
this.routingMap.set(packet.id, callback);
|
||||
this.socket.sendMessage(serializedPacket);
|
||||
this.socket!.sendMessage(serializedPacket);
|
||||
|
||||
return () => this.routingMap.delete(packet.id);
|
||||
} catch (err) {
|
||||
callback({ err });
|
||||
return () => {};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +201,6 @@ export class ClientTCP extends ClientProxy<TcpEvents, TcpStatus> {
|
||||
...packet,
|
||||
pattern,
|
||||
});
|
||||
return this.socket.sendMessage(serializedPacket);
|
||||
return this.socket!.sendMessage(serializedPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import {
|
||||
isObject,
|
||||
isNumber,
|
||||
isNil,
|
||||
isNumber,
|
||||
isObject,
|
||||
isSymbol,
|
||||
} from '@nestjs/common/utils/shared.utils';
|
||||
import {
|
||||
PATTERN_EXTRAS_METADATA,
|
||||
PATTERN_HANDLER_METADATA,
|
||||
PATTERN_METADATA,
|
||||
TRANSPORT_METADATA,
|
||||
PATTERN_EXTRAS_METADATA,
|
||||
} from '../constants';
|
||||
import { PatternHandler } from '../enums/pattern-handler.enum';
|
||||
import { Transport } from '../enums';
|
||||
import { PatternHandler } from '../enums/pattern-handler.enum';
|
||||
|
||||
/**
|
||||
* Subscribes to incoming events which fulfils chosen pattern.
|
||||
@@ -43,7 +43,7 @@ export const EventPattern: {
|
||||
extras = transportOrExtras;
|
||||
} else {
|
||||
transport = transportOrExtras as Transport | symbol;
|
||||
extras = maybeExtras;
|
||||
extras = maybeExtras!;
|
||||
}
|
||||
return (
|
||||
target: object,
|
||||
@@ -52,7 +52,7 @@ export const EventPattern: {
|
||||
) => {
|
||||
Reflect.defineMetadata(
|
||||
PATTERN_METADATA,
|
||||
[].concat(metadata),
|
||||
([] as any[]).concat(metadata),
|
||||
descriptor.value,
|
||||
);
|
||||
Reflect.defineMetadata(
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import {
|
||||
isObject,
|
||||
isNumber,
|
||||
isNil,
|
||||
isNumber,
|
||||
isObject,
|
||||
isSymbol,
|
||||
} from '@nestjs/common/utils/shared.utils';
|
||||
|
||||
import {
|
||||
PATTERN_EXTRAS_METADATA,
|
||||
PATTERN_HANDLER_METADATA,
|
||||
PATTERN_METADATA,
|
||||
TRANSPORT_METADATA,
|
||||
PATTERN_EXTRAS_METADATA,
|
||||
} from '../constants';
|
||||
import { PatternHandler } from '../enums/pattern-handler.enum';
|
||||
import { PatternMetadata } from '../interfaces/pattern-metadata.interface';
|
||||
import { Transport } from '../enums';
|
||||
import { PatternHandler } from '../enums/pattern-handler.enum';
|
||||
import {
|
||||
InvalidGrpcDecoratorException,
|
||||
RpcDecoratorMetadata,
|
||||
} from '../errors/invalid-grpc-message-decorator.exception';
|
||||
import { PatternMetadata } from '../interfaces/pattern-metadata.interface';
|
||||
|
||||
export enum GrpcMethodStreamingType {
|
||||
NO_STREAMING = 'no_stream',
|
||||
@@ -61,8 +61,9 @@ export const MessagePattern: {
|
||||
extras = transportOrExtras;
|
||||
} else {
|
||||
transport = transportOrExtras as Transport | symbol;
|
||||
extras = maybeExtras;
|
||||
extras = maybeExtras!;
|
||||
}
|
||||
|
||||
return (
|
||||
target: object,
|
||||
key: string | symbol,
|
||||
@@ -71,7 +72,7 @@ export const MessagePattern: {
|
||||
try {
|
||||
Reflect.defineMetadata(
|
||||
PATTERN_METADATA,
|
||||
[].concat(metadata),
|
||||
([] as any[]).concat(metadata),
|
||||
descriptor.value,
|
||||
);
|
||||
Reflect.defineMetadata(
|
||||
@@ -100,7 +101,10 @@ export const MessagePattern: {
|
||||
*/
|
||||
export function GrpcMethod(service?: string): MethodDecorator;
|
||||
export function GrpcMethod(service: string, method?: string): MethodDecorator;
|
||||
export function GrpcMethod(service: string, method?: string): MethodDecorator {
|
||||
export function GrpcMethod(
|
||||
service: string | undefined,
|
||||
method?: string,
|
||||
): MethodDecorator {
|
||||
return (
|
||||
target: object,
|
||||
key: string | symbol,
|
||||
@@ -126,7 +130,7 @@ export function GrpcStreamMethod(
|
||||
method?: string,
|
||||
): MethodDecorator;
|
||||
export function GrpcStreamMethod(
|
||||
service: string,
|
||||
service: string | undefined,
|
||||
method?: string,
|
||||
): MethodDecorator {
|
||||
return (
|
||||
@@ -160,7 +164,7 @@ export function GrpcStreamCall(
|
||||
method?: string,
|
||||
): MethodDecorator;
|
||||
export function GrpcStreamCall(
|
||||
service: string,
|
||||
service: string | undefined,
|
||||
method?: string,
|
||||
): MethodDecorator {
|
||||
return (
|
||||
|
||||
@@ -18,9 +18,8 @@ export class RpcException extends Error {
|
||||
) {
|
||||
this.message = (this.error as Record<string, any>).message;
|
||||
} else if (this.constructor) {
|
||||
this.message = this.constructor.name
|
||||
.match(/[A-Z][a-z]+|[0-9]+/g)
|
||||
.join(' ');
|
||||
this.message =
|
||||
this.constructor!.name!.match(/[A-Z][a-z]+|[0-9]+/g)!.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,9 @@ export class ListenerMetadataExplorer {
|
||||
const instancePrototype = Object.getPrototypeOf(instance);
|
||||
return this.metadataScanner
|
||||
.getAllMethodNames(instancePrototype)
|
||||
.map(method =>
|
||||
this.exploreMethodMetadata(instance, instancePrototype, method),
|
||||
.map(
|
||||
method =>
|
||||
this.exploreMethodMetadata(instance, instancePrototype, method)!,
|
||||
)
|
||||
.filter(metadata => metadata);
|
||||
}
|
||||
@@ -49,7 +50,7 @@ export class ListenerMetadataExplorer {
|
||||
instance: Controller,
|
||||
instancePrototype: object,
|
||||
methodKey: string,
|
||||
): EventOrMessageListenerDefinition {
|
||||
): EventOrMessageListenerDefinition | undefined {
|
||||
const prototypeCallback = instancePrototype[methodKey];
|
||||
const handlerType = Reflect.getMetadata(
|
||||
PATTERN_HANDLER_METADATA,
|
||||
|
||||
@@ -85,7 +85,7 @@ export class ListenersController {
|
||||
acc.push({ ...handler, patterns: [pattern] }),
|
||||
);
|
||||
return acc;
|
||||
}, [])
|
||||
}, [] as EventOrMessageListenerDefinition[])
|
||||
.forEach((definition: EventOrMessageListenerDefinition) => {
|
||||
const {
|
||||
patterns: [pattern],
|
||||
@@ -98,7 +98,7 @@ export class ListenersController {
|
||||
this.insertEntrypointDefinition(
|
||||
instanceWrapper,
|
||||
definition,
|
||||
serverInstance.transportId,
|
||||
serverInstance.transportId!,
|
||||
);
|
||||
|
||||
if (isStatic) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import {
|
||||
DynamicModule,
|
||||
ForwardReference,
|
||||
Module,
|
||||
OnApplicationShutdown,
|
||||
Provider,
|
||||
Type,
|
||||
} from '@nestjs/common';
|
||||
import { ClientProxy, ClientProxyFactory } from '../client';
|
||||
import {
|
||||
@@ -44,7 +46,9 @@ export class ClientsModule {
|
||||
option.imports && !accImports.includes(option.imports)
|
||||
? accImports.concat(option.imports)
|
||||
: accImports,
|
||||
[],
|
||||
[] as Array<
|
||||
DynamicModule | Promise<DynamicModule> | ForwardReference | Type
|
||||
>,
|
||||
);
|
||||
return {
|
||||
module: ClientsModule,
|
||||
@@ -64,8 +68,8 @@ export class ClientsModule {
|
||||
return [
|
||||
this.createAsyncOptionsProvider(options),
|
||||
{
|
||||
provide: options.useClass,
|
||||
useClass: options.useClass,
|
||||
provide: options.useClass!,
|
||||
useClass: options.useClass!,
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -86,7 +90,7 @@ export class ClientsModule {
|
||||
(optionsFactory: ClientsModuleOptionsFactory) =>
|
||||
optionsFactory.createClientOptions(),
|
||||
),
|
||||
inject: [options.useExisting || options.useClass],
|
||||
inject: [options.useExisting || options.useClass!],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -94,7 +98,7 @@ export class ClientsModule {
|
||||
useFactory: ClientsProviderAsyncOptions['useFactory'],
|
||||
) {
|
||||
return async (...args: any[]) => {
|
||||
const clientOptions = await useFactory(...args);
|
||||
const clientOptions = await useFactory!(...args);
|
||||
const clientProxyRef = ClientProxyFactory.create(clientOptions);
|
||||
return this.assignOnAppShutdownHook(clientProxyRef);
|
||||
};
|
||||
|
||||
@@ -64,7 +64,7 @@ export class NestMicroservice
|
||||
) {
|
||||
super(container, config);
|
||||
|
||||
this.injector = new Injector({ preview: config.preview });
|
||||
this.injector = new Injector({ preview: config.preview! });
|
||||
this.microservicesModule.register(
|
||||
container,
|
||||
this.graphInspector,
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import { Transport } from '../enums/transport.enum';
|
||||
import {
|
||||
CustomStrategy,
|
||||
GrpcOptions,
|
||||
KafkaOptions,
|
||||
MicroserviceOptions,
|
||||
MqttOptions,
|
||||
NatsOptions,
|
||||
RedisOptions,
|
||||
RmqOptions,
|
||||
TcpOptions,
|
||||
} from '../interfaces';
|
||||
import { ServerGrpc } from './server-grpc';
|
||||
import { ServerKafka } from './server-kafka';
|
||||
@@ -20,19 +26,19 @@ export class ServerFactory {
|
||||
>;
|
||||
switch (transport) {
|
||||
case Transport.REDIS:
|
||||
return new ServerRedis(options);
|
||||
return new ServerRedis(options as Required<RedisOptions>['options']);
|
||||
case Transport.NATS:
|
||||
return new ServerNats(options);
|
||||
return new ServerNats(options as Required<NatsOptions>['options']);
|
||||
case Transport.MQTT:
|
||||
return new ServerMqtt(options);
|
||||
return new ServerMqtt(options as Required<MqttOptions>['options']);
|
||||
case Transport.GRPC:
|
||||
return new ServerGrpc(options);
|
||||
return new ServerGrpc(options as Required<GrpcOptions>['options']);
|
||||
case Transport.KAFKA:
|
||||
return new ServerKafka(options);
|
||||
return new ServerKafka(options as Required<KafkaOptions>['options']);
|
||||
case Transport.RMQ:
|
||||
return new ServerRMQ(options);
|
||||
return new ServerRMQ(options as Required<RmqOptions>['options']);
|
||||
default:
|
||||
return new ServerTCP(options);
|
||||
return new ServerTCP(options as Required<TcpOptions>['options']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ export class ServerGrpc extends Server<never, never> {
|
||||
);
|
||||
}
|
||||
|
||||
constructor(private readonly options: GrpcOptions['options']) {
|
||||
constructor(private readonly options: Readonly<GrpcOptions>['options']) {
|
||||
super();
|
||||
this.url = this.getOptionsProp(options, 'url') || GRPC_DEFAULT_URL;
|
||||
|
||||
@@ -96,7 +96,7 @@ export class ServerGrpc extends Server<never, never> {
|
||||
|
||||
public async start(callback?: () => void) {
|
||||
await this.bindEvents();
|
||||
callback();
|
||||
callback?.();
|
||||
}
|
||||
|
||||
public async bindEvents() {
|
||||
@@ -136,7 +136,7 @@ export class ServerGrpc extends Server<never, never> {
|
||||
const service = {};
|
||||
|
||||
for (const methodName in grpcService.prototype) {
|
||||
let methodHandler = null;
|
||||
let methodHandler: MessageHandler | null = null;
|
||||
let streamingType = GrpcMethodStreamingType.NO_STREAMING;
|
||||
|
||||
const methodFunction = grpcService.prototype[methodName];
|
||||
@@ -190,13 +190,13 @@ export class ServerGrpc extends Server<never, never> {
|
||||
methodName: string,
|
||||
streaming: GrpcMethodStreamingType,
|
||||
grpcMethod: { path?: string },
|
||||
) {
|
||||
): MessageHandler {
|
||||
let pattern = this.createPattern(serviceName, methodName, streaming);
|
||||
let methodHandler = this.messageHandlers.get(pattern);
|
||||
let methodHandler = this.messageHandlers.get(pattern)!;
|
||||
if (!methodHandler) {
|
||||
const packageServiceName = grpcMethod.path?.split?.('/')[1];
|
||||
pattern = this.createPattern(packageServiceName, methodName, streaming);
|
||||
methodHandler = this.messageHandlers.get(pattern);
|
||||
pattern = this.createPattern(packageServiceName!, methodName, streaming);
|
||||
methodHandler = this.messageHandlers.get(pattern)!;
|
||||
}
|
||||
return methodHandler;
|
||||
}
|
||||
|
||||
@@ -39,23 +39,28 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
public readonly transportId = Transport.KAFKA;
|
||||
|
||||
protected logger = new Logger(ServerKafka.name);
|
||||
protected client: Kafka = null;
|
||||
protected consumer: Consumer = null;
|
||||
protected producer: Producer = null;
|
||||
protected parser: KafkaParser = null;
|
||||
protected client: Kafka | null = null;
|
||||
protected consumer: Consumer | null = null;
|
||||
protected producer: Producer | null = null;
|
||||
protected parser: KafkaParser | null = null;
|
||||
protected brokers: string[] | BrokersFunction;
|
||||
protected clientId: string;
|
||||
protected groupId: string;
|
||||
|
||||
constructor(protected readonly options: KafkaOptions['options']) {
|
||||
constructor(protected readonly options: Required<KafkaOptions>['options']) {
|
||||
super();
|
||||
|
||||
const clientOptions =
|
||||
this.getOptionsProp(this.options, 'client') || ({} as KafkaConfig);
|
||||
const consumerOptions =
|
||||
this.getOptionsProp(this.options, 'consumer') || ({} as ConsumerConfig);
|
||||
const postfixId =
|
||||
this.getOptionsProp(this.options, 'postfixId') ?? '-server';
|
||||
const clientOptions = this.getOptionsProp(
|
||||
this.options,
|
||||
'client',
|
||||
{} as KafkaConfig,
|
||||
);
|
||||
const consumerOptions = this.getOptionsProp(
|
||||
this.options,
|
||||
'consumer',
|
||||
{} as ConsumerConfig,
|
||||
);
|
||||
const postfixId = this.getOptionsProp(this.options, 'postfixId', '-server');
|
||||
|
||||
this.brokers = clientOptions.brokers || [KAFKA_DEFAULT_BROKER];
|
||||
|
||||
@@ -98,8 +103,8 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
const consumerOptions = Object.assign(this.options.consumer || {}, {
|
||||
groupId: this.groupId,
|
||||
});
|
||||
this.consumer = this.client.consumer(consumerOptions);
|
||||
this.producer = this.client.producer(this.options.producer);
|
||||
this.consumer = this.client!.consumer(consumerOptions);
|
||||
this.producer = this.client!.producer(this.options.producer);
|
||||
this.registerConsumerEventListeners();
|
||||
this.registerProducerEventListeners();
|
||||
|
||||
@@ -110,6 +115,9 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
}
|
||||
|
||||
protected registerConsumerEventListeners() {
|
||||
if (!this.consumer) {
|
||||
return;
|
||||
}
|
||||
this.consumer.on(this.consumer.events.CONNECT, () =>
|
||||
this._status$.next(KafkaStatus.CONNECTED),
|
||||
);
|
||||
@@ -128,6 +136,9 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
}
|
||||
|
||||
protected registerProducerEventListeners() {
|
||||
if (!this.producer) {
|
||||
return;
|
||||
}
|
||||
this.producer.on(this.producer.events.CONNECT, () =>
|
||||
this._status$.next(KafkaStatus.CONNECTED),
|
||||
);
|
||||
@@ -151,7 +162,7 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
const consumerSubscribeOptions = this.options.subscribe || {};
|
||||
|
||||
if (registeredPatterns.length > 0) {
|
||||
await this.consumer.subscribe({
|
||||
await this.consumer!.subscribe({
|
||||
...consumerSubscribeOptions,
|
||||
topics: registeredPatterns,
|
||||
});
|
||||
@@ -178,7 +189,7 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
|
||||
public async handleMessage(payload: EachMessagePayload) {
|
||||
const channel = payload.topic;
|
||||
const rawMessage = this.parser.parse<KafkaMessage>(
|
||||
const rawMessage = this.parser!.parse<KafkaMessage>(
|
||||
Object.assign(payload.message, {
|
||||
topic: payload.topic,
|
||||
partition: payload.partition,
|
||||
@@ -194,9 +205,9 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
rawMessage,
|
||||
payload.partition,
|
||||
payload.topic,
|
||||
this.consumer,
|
||||
this.consumer!,
|
||||
payload.heartbeat,
|
||||
this.producer,
|
||||
this.producer!,
|
||||
]);
|
||||
const handler = this.getHandlerByPattern(packet.pattern);
|
||||
// if the correlation id or reply topic is not set
|
||||
@@ -291,7 +302,7 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
},
|
||||
this.options.send || {},
|
||||
);
|
||||
return this.producer.send(replyMessage);
|
||||
return this.producer!.send(replyMessage);
|
||||
}
|
||||
|
||||
public assignIsDisposedHeader(
|
||||
@@ -301,7 +312,7 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
if (!outgoingResponse.isDisposed) {
|
||||
return;
|
||||
}
|
||||
outgoingMessage.headers[KafkaHeaders.NEST_IS_DISPOSED] = Buffer.alloc(1);
|
||||
outgoingMessage.headers![KafkaHeaders.NEST_IS_DISPOSED] = Buffer.alloc(1);
|
||||
}
|
||||
|
||||
public assignErrorHeader(
|
||||
@@ -315,7 +326,7 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
typeof outgoingResponse.err === 'object'
|
||||
? JSON.stringify(outgoingResponse.err)
|
||||
: outgoingResponse.err;
|
||||
outgoingMessage.headers[KafkaHeaders.NEST_ERR] =
|
||||
outgoingMessage.headers![KafkaHeaders.NEST_ERR] =
|
||||
Buffer.from(stringifiedError);
|
||||
}
|
||||
|
||||
@@ -323,7 +334,7 @@ export class ServerKafka extends Server<never, KafkaStatus> {
|
||||
correlationId: string,
|
||||
outgoingMessage: Message,
|
||||
) {
|
||||
outgoingMessage.headers[KafkaHeaders.CORRELATION_ID] =
|
||||
outgoingMessage.headers![KafkaHeaders.CORRELATION_ID] =
|
||||
Buffer.from(correlationId);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ export class ServerMqtt extends Server<MqttEvents, MqttStatus> {
|
||||
callback: MqttEvents[keyof MqttEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(private readonly options: MqttOptions['options']) {
|
||||
constructor(private readonly options: Required<MqttOptions>['options']) {
|
||||
super();
|
||||
this.url = this.getOptionsProp(options, 'url') || MQTT_DEFAULT_URL;
|
||||
this.url = this.getOptionsProp(options, 'url', MQTT_DEFAULT_URL);
|
||||
|
||||
mqttPackage = this.loadPackage('mqtt', ServerMqtt.name, () =>
|
||||
require('mqtt'),
|
||||
@@ -87,7 +87,7 @@ export class ServerMqtt extends Server<MqttEvents, MqttStatus> {
|
||||
|
||||
const registeredPatterns = [...this.messageHandlers.keys()];
|
||||
registeredPatterns.forEach(pattern => {
|
||||
const { isEventHandler } = this.messageHandlers.get(pattern);
|
||||
const { isEventHandler } = this.messageHandlers.get(pattern)!;
|
||||
mqttClient.subscribe(
|
||||
isEventHandler ? pattern : this.getRequestPattern(pattern),
|
||||
this.getOptionsProp(this.options, 'subscribeOptions'),
|
||||
@@ -120,7 +120,7 @@ export class ServerMqtt extends Server<MqttEvents, MqttStatus> {
|
||||
): Promise<any> {
|
||||
const rawPacket = this.parseMessage(buffer.toString());
|
||||
const packet = await this.deserializer.deserialize(rawPacket, { channel });
|
||||
const mqttContext = new MqttContext([channel, originalPacket]);
|
||||
const mqttContext = new MqttContext([channel, originalPacket!]);
|
||||
if (isUndefined((packet as IncomingRequest).id)) {
|
||||
return this.handleEvent(channel, packet, mqttContext);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export class ServerNats<
|
||||
}>();
|
||||
private readonly subscriptions: Subscription[] = [];
|
||||
|
||||
constructor(private readonly options: NatsOptions['options']) {
|
||||
constructor(private readonly options: Required<NatsOptions>['options']) {
|
||||
super();
|
||||
|
||||
natsPackage = this.loadPackage('nats', ServerNats.name, () =>
|
||||
@@ -211,7 +211,7 @@ export class ServerNats<
|
||||
|
||||
case 'pingTimer':
|
||||
if (this.options.debug) {
|
||||
this.logger.debug(
|
||||
this.logger.debug!(
|
||||
`NatsStatus: type: "${status.type}", data: "${data}".`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export class ServerRedis extends Server<RedisEvents, RedisStatus> {
|
||||
callback: RedisEvents[keyof RedisEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(protected readonly options: RedisOptions['options']) {
|
||||
constructor(protected readonly options: Required<RedisOptions>['options']) {
|
||||
super();
|
||||
|
||||
redisPackage = this.loadPackage('ioredis', ServerRedis.name, () =>
|
||||
@@ -78,7 +78,7 @@ export class ServerRedis extends Server<RedisEvents, RedisStatus> {
|
||||
Promise.all([this.subClient.connect(), this.pubClient.connect()])
|
||||
.then(() => {
|
||||
this.bindEvents(this.subClient, this.pubClient);
|
||||
callback();
|
||||
callback?.();
|
||||
})
|
||||
.catch(callback);
|
||||
}
|
||||
@@ -90,7 +90,7 @@ export class ServerRedis extends Server<RedisEvents, RedisStatus> {
|
||||
);
|
||||
const subscribePatterns = [...this.messageHandlers.keys()];
|
||||
subscribePatterns.forEach(pattern => {
|
||||
const { isEventHandler } = this.messageHandlers.get(pattern);
|
||||
const { isEventHandler } = this.messageHandlers.get(pattern)!;
|
||||
|
||||
const channel = isEventHandler
|
||||
? pattern
|
||||
@@ -258,11 +258,11 @@ export class ServerRedis extends Server<RedisEvents, RedisStatus> {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (times > this.getOptionsProp(this.options, 'retryAttempts')) {
|
||||
if (times > this.getOptionsProp(this.options, 'retryAttempts', 0)) {
|
||||
this.logger.error(`Retry time exhausted`);
|
||||
return;
|
||||
}
|
||||
return this.getOptionsProp(this.options, 'retryDelay') ?? 5000;
|
||||
return this.getOptionsProp(this.options, 'retryDelay', 5000);
|
||||
}
|
||||
|
||||
public unwrap<T>(): T {
|
||||
|
||||
@@ -65,7 +65,7 @@ export class ServerRMQ extends Server<RmqEvents, RmqStatus> {
|
||||
callback: RmqEvents[keyof RmqEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(protected readonly options: RmqOptions['options']) {
|
||||
constructor(protected readonly options: Required<RmqOptions>['options']) {
|
||||
super();
|
||||
this.urls = this.getOptionsProp(this.options, 'urls') || [RQM_DEFAULT_URL];
|
||||
this.queue =
|
||||
@@ -113,7 +113,7 @@ export class ServerRMQ extends Server<RmqEvents, RmqStatus> {
|
||||
this._status$.next(RmqStatus.CONNECTED);
|
||||
this.channel = this.server.createChannel({
|
||||
json: false,
|
||||
setup: (channel: any) => this.setupChannel(channel, callback),
|
||||
setup: (channel: any) => this.setupChannel(channel, callback!),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export class ServerTCP extends Server<TcpEvents, TcpStatus> {
|
||||
callback: TcpEvents[keyof TcpEvents];
|
||||
}> = [];
|
||||
|
||||
constructor(private readonly options: TcpOptions['options']) {
|
||||
constructor(private readonly options: Required<TcpOptions>['options']) {
|
||||
super();
|
||||
this.port = this.getOptionsProp(options, 'port', TCP_DEFAULT_PORT);
|
||||
this.host = this.getOptionsProp(options, 'host', TCP_DEFAULT_HOST);
|
||||
@@ -121,14 +121,14 @@ export class ServerTCP extends Server<TcpEvents, TcpStatus> {
|
||||
this.isManuallyTerminated ||
|
||||
!this.getOptionsProp(this.options, 'retryAttempts') ||
|
||||
this.retryAttemptsCount >=
|
||||
this.getOptionsProp(this.options, 'retryAttempts')
|
||||
this.getOptionsProp(this.options, 'retryAttempts', 0)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
++this.retryAttemptsCount;
|
||||
return setTimeout(
|
||||
() => this.server.listen(this.port, this.host),
|
||||
this.getOptionsProp(this.options, 'retryDelay') || 0,
|
||||
this.getOptionsProp(this.options, 'retryDelay', 0),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ export abstract class Server<
|
||||
callback.extras = extras;
|
||||
|
||||
if (this.messageHandlers.has(normalizedPattern) && isEventHandler) {
|
||||
const headRef = this.messageHandlers.get(normalizedPattern);
|
||||
const headRef = this.messageHandlers.get(normalizedPattern)!;
|
||||
const getTail = (handler: MessageHandler) =>
|
||||
handler?.next ? getTail(handler.next) : handler;
|
||||
|
||||
@@ -120,7 +120,7 @@ export abstract class Server<
|
||||
public getHandlerByPattern(pattern: string): MessageHandler | null {
|
||||
const route = this.getRouteFromPattern(pattern);
|
||||
return this.messageHandlers.has(route)
|
||||
? this.messageHandlers.get(route)
|
||||
? this.messageHandlers.get(route)!
|
||||
: null;
|
||||
}
|
||||
|
||||
@@ -128,12 +128,13 @@ export abstract class Server<
|
||||
stream$: Observable<any>,
|
||||
respond: (data: WritePacket) => Promise<unknown> | void,
|
||||
): Subscription {
|
||||
let dataBuffer: WritePacket[] = null;
|
||||
let dataBuffer: WritePacket[] | null = null;
|
||||
|
||||
const scheduleOnNextTick = (data: WritePacket) => {
|
||||
if (!dataBuffer) {
|
||||
dataBuffer = [data];
|
||||
process.nextTick(async () => {
|
||||
for (const item of dataBuffer) {
|
||||
for (const item of dataBuffer!) {
|
||||
await respond(item);
|
||||
}
|
||||
dataBuffer = null;
|
||||
@@ -197,10 +198,28 @@ export abstract class Server<
|
||||
}
|
||||
|
||||
public getOptionsProp<
|
||||
T extends MicroserviceOptions['options'],
|
||||
K extends keyof T,
|
||||
>(obj: T, prop: K, defaultValue: T[K] = undefined) {
|
||||
return obj && prop in obj ? obj[prop] : defaultValue;
|
||||
Options extends MicroserviceOptions['options'],
|
||||
Attribute extends keyof Options,
|
||||
>(obj: Options, prop: Attribute): Options[Attribute];
|
||||
public getOptionsProp<
|
||||
Options extends MicroserviceOptions['options'],
|
||||
Attribute extends keyof Options,
|
||||
DefaultValue extends Options[Attribute] = Options[Attribute],
|
||||
>(
|
||||
obj: Options,
|
||||
prop: Attribute,
|
||||
defaultValue: DefaultValue,
|
||||
): Required<Options>[Attribute];
|
||||
public getOptionsProp<
|
||||
Options extends MicroserviceOptions['options'],
|
||||
Attribute extends keyof Options,
|
||||
DefaultValue extends Options[Attribute] = Options[Attribute],
|
||||
>(
|
||||
obj: Options,
|
||||
prop: Attribute,
|
||||
defaultValue: DefaultValue = undefined as DefaultValue,
|
||||
) {
|
||||
return obj && prop in obj ? obj![prop] : defaultValue;
|
||||
}
|
||||
|
||||
protected handleError(error: string) {
|
||||
@@ -218,30 +237,26 @@ export abstract class Server<
|
||||
protected initializeSerializer(options: ClientOptions['options']) {
|
||||
this.serializer =
|
||||
(options &&
|
||||
(
|
||||
options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options']
|
||||
).serializer) ||
|
||||
(options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options'])!.serializer) ||
|
||||
new IdentitySerializer();
|
||||
}
|
||||
|
||||
protected initializeDeserializer(options: ClientOptions['options']) {
|
||||
this.deserializer =
|
||||
(options &&
|
||||
(
|
||||
options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options']
|
||||
).deserializer) ||
|
||||
(options! &&
|
||||
(options as
|
||||
| RedisOptions['options']
|
||||
| NatsOptions['options']
|
||||
| MqttOptions['options']
|
||||
| TcpOptions['options']
|
||||
| RmqOptions['options']
|
||||
| KafkaOptions['options'])!.deserializer) ||
|
||||
new IncomingRequestDeserializer();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,12 +11,13 @@ export function createRpcParamDecorator(
|
||||
return (...pipes: (Type<PipeTransform> | PipeTransform)[]) =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key!) ||
|
||||
{};
|
||||
Reflect.defineMetadata(
|
||||
PARAM_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, undefined, ...pipes),
|
||||
target.constructor,
|
||||
key,
|
||||
key!,
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -29,7 +30,7 @@ export const createPipesRpcParamDecorator =
|
||||
): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key!) || {};
|
||||
|
||||
const hasParamData = isNil(data) || isString(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
@@ -37,8 +38,8 @@ export const createPipesRpcParamDecorator =
|
||||
|
||||
Reflect.defineMetadata(
|
||||
PARAM_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, paramData, ...paramPipes),
|
||||
assignMetadata(args, paramtype, index, paramData!, ...paramPipes),
|
||||
target.constructor,
|
||||
key,
|
||||
key!,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import type { Server } from 'http';
|
||||
import {
|
||||
HttpStatus,
|
||||
InternalServerErrorException,
|
||||
Logger,
|
||||
RequestMethod,
|
||||
StreamableFile,
|
||||
VERSION_NEUTRAL,
|
||||
VersioningOptions,
|
||||
VersioningType,
|
||||
VERSION_NEUTRAL,
|
||||
} from '@nestjs/common';
|
||||
import { VersionValue } from '@nestjs/common/interfaces';
|
||||
import {
|
||||
@@ -24,13 +23,14 @@ import {
|
||||
} from '@nestjs/common/utils/shared.utils';
|
||||
import { AbstractHttpAdapter } from '@nestjs/core/adapters/http-adapter';
|
||||
import { RouterMethodFactory } from '@nestjs/core/helpers/router-method-factory';
|
||||
import * as bodyparser from 'body-parser';
|
||||
import {
|
||||
json as bodyParserJson,
|
||||
urlencoded as bodyParserUrlencoded,
|
||||
} from 'body-parser';
|
||||
import * as bodyparser from 'body-parser';
|
||||
import * as cors from 'cors';
|
||||
import * as express from 'express';
|
||||
import type { Server } from 'http';
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
import { Duplex, pipeline } from 'stream';
|
||||
@@ -94,7 +94,7 @@ export class ExpressAdapter extends AbstractHttpAdapter<
|
||||
body.errorHandler(err, response);
|
||||
}),
|
||||
response,
|
||||
(err: Error) => {
|
||||
(err: any) => {
|
||||
if (err) {
|
||||
body.errorLogger(err);
|
||||
}
|
||||
@@ -218,7 +218,7 @@ export class ExpressAdapter extends AbstractHttpAdapter<
|
||||
}
|
||||
|
||||
public enableCors(options: CorsOptions | CorsOptionsDelegate<any>) {
|
||||
return this.use(cors(options));
|
||||
return this.use(cors(options as any));
|
||||
}
|
||||
|
||||
public createMiddlewareFactory(
|
||||
@@ -233,7 +233,7 @@ export class ExpressAdapter extends AbstractHttpAdapter<
|
||||
const isHttpsEnabled = options && options.httpsOptions;
|
||||
if (isHttpsEnabled) {
|
||||
this.httpServer = https.createServer(
|
||||
options.httpsOptions,
|
||||
options.httpsOptions!,
|
||||
this.getInstance(),
|
||||
);
|
||||
} else {
|
||||
@@ -246,8 +246,8 @@ export class ExpressAdapter extends AbstractHttpAdapter<
|
||||
}
|
||||
|
||||
public registerParserMiddleware(prefix?: string, rawBody?: boolean) {
|
||||
const bodyParserJsonOptions = getBodyParserOptions(rawBody);
|
||||
const bodyParserUrlencodedOptions = getBodyParserOptions(rawBody, {
|
||||
const bodyParserJsonOptions = getBodyParserOptions(rawBody!);
|
||||
const bodyParserUrlencodedOptions = getBodyParserOptions(rawBody!, {
|
||||
extended: true,
|
||||
});
|
||||
|
||||
@@ -260,13 +260,15 @@ export class ExpressAdapter extends AbstractHttpAdapter<
|
||||
.forEach(parserKey => this.use(parserMiddleware[parserKey]));
|
||||
}
|
||||
|
||||
public useBodyParser<Options = NestExpressBodyParserOptions>(
|
||||
public useBodyParser<
|
||||
Options extends NestExpressBodyParserOptions = NestExpressBodyParserOptions,
|
||||
>(
|
||||
type: NestExpressBodyParserType,
|
||||
rawBody: boolean,
|
||||
options?: Omit<Options, 'verify'>,
|
||||
): this {
|
||||
const parserOptions = getBodyParserOptions<Options>(rawBody, options);
|
||||
const parser = bodyparser[type](parserOptions);
|
||||
const parser = bodyparser[type](parserOptions!);
|
||||
|
||||
this.use(parser);
|
||||
|
||||
@@ -425,6 +427,8 @@ export class ExpressAdapter extends AbstractHttpAdapter<
|
||||
|
||||
return handlerForHeaderVersioning;
|
||||
}
|
||||
|
||||
throw new Error('Unsupported versioning options');
|
||||
}
|
||||
|
||||
private trackOpenConnections() {
|
||||
|
||||
@@ -51,8 +51,8 @@ export class MulterModule {
|
||||
return [
|
||||
this.createAsyncOptionsProvider(options),
|
||||
{
|
||||
provide: options.useClass,
|
||||
useClass: options.useClass,
|
||||
provide: options.useClass!,
|
||||
useClass: options.useClass!,
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export class MulterModule {
|
||||
provide: MULTER_MODULE_OPTIONS,
|
||||
useFactory: async (optionsFactory: MulterOptionsFactory) =>
|
||||
optionsFactory.createMulterOptions(),
|
||||
inject: [options.useExisting || options.useClass],
|
||||
inject: [options.useExisting || options.useClass!],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ export class FastifyAdapter<
|
||||
return {
|
||||
get(version: string | Array<string>) {
|
||||
if (Array.isArray(version)) {
|
||||
return versions.get(version.find(v => versions.has(v))) || null;
|
||||
return versions.get(version.find(v => versions.has(v))!) || null;
|
||||
}
|
||||
return versions.get(version) || null;
|
||||
},
|
||||
@@ -427,11 +427,11 @@ export class FastifyAdapter<
|
||||
response.statusCode = statusCode;
|
||||
return response;
|
||||
}
|
||||
return response.code(statusCode);
|
||||
return (response as TReply).code(statusCode);
|
||||
}
|
||||
|
||||
public end(response: TReply, message?: string) {
|
||||
response.raw.end(message);
|
||||
response.raw.end(message!);
|
||||
}
|
||||
|
||||
public render(
|
||||
@@ -475,7 +475,7 @@ export class FastifyAdapter<
|
||||
public inject(
|
||||
opts?: InjectOptions | string,
|
||||
): LightMyRequestChain | Promise<LightMyRequestResponse> {
|
||||
return this.instance.inject(opts);
|
||||
return this.instance.inject(opts!);
|
||||
}
|
||||
|
||||
public async close() {
|
||||
@@ -539,7 +539,7 @@ export class FastifyAdapter<
|
||||
}
|
||||
|
||||
public getRequestMethod(request: TRequest): string {
|
||||
return request.raw ? request.raw.method : request.method;
|
||||
return request.raw ? request.raw.method! : request.method;
|
||||
}
|
||||
|
||||
public getRequestUrl(request: TRequest): string;
|
||||
@@ -581,7 +581,7 @@ export class FastifyAdapter<
|
||||
type,
|
||||
parserOptions,
|
||||
(
|
||||
req: RawBodyRequest<FastifyRequest<unknown, TServer, TRawRequest>>,
|
||||
req: RawBodyRequest<FastifyRequest<any, TServer, TRawRequest>>,
|
||||
body: Buffer,
|
||||
done,
|
||||
) => {
|
||||
@@ -708,7 +708,7 @@ export class FastifyAdapter<
|
||||
}
|
||||
|
||||
private getRequestOriginalUrl(rawRequest: TRawRequest) {
|
||||
return rawRequest.originalUrl || rawRequest.url;
|
||||
return rawRequest.originalUrl || rawRequest.url!;
|
||||
}
|
||||
|
||||
private injectRouteOptions(
|
||||
|
||||
@@ -70,7 +70,11 @@ export class WsAdapter extends AbstractWsAdapter {
|
||||
path?: string;
|
||||
},
|
||||
) {
|
||||
const { server, path, ...wsOptions } = options;
|
||||
const { server, path, ...wsOptions } = options as {
|
||||
namespace?: string;
|
||||
server?: any;
|
||||
path?: string;
|
||||
};
|
||||
if (wsOptions?.namespace) {
|
||||
const error = new Error(
|
||||
'"WsAdapter" does not support namespaces. If you need namespaces in your project, consider using the "@nestjs/platform-socket.io" package instead.',
|
||||
@@ -88,7 +92,7 @@ export class WsAdapter extends AbstractWsAdapter {
|
||||
}),
|
||||
);
|
||||
|
||||
this.addWsServerToRegistry(wsServer, port, path);
|
||||
this.addWsServerToRegistry(wsServer, port, path!);
|
||||
return wsServer;
|
||||
}
|
||||
|
||||
@@ -157,7 +161,7 @@ export class WsAdapter extends AbstractWsAdapter {
|
||||
if (!message) {
|
||||
return EMPTY;
|
||||
}
|
||||
const messageHandler = handlersMap.get(message.event);
|
||||
const messageHandler = handlersMap.get(message.event)!;
|
||||
const { callback } = messageHandler;
|
||||
return transform(callback(message.data, message.event));
|
||||
} catch {
|
||||
@@ -213,8 +217,8 @@ export class WsAdapter extends AbstractWsAdapter {
|
||||
httpServer.on('upgrade', (request, socket, head) => {
|
||||
try {
|
||||
const baseUrl = 'ws://' + request.headers.host + '/';
|
||||
const pathname = new URL(request.url, baseUrl).pathname;
|
||||
const wsServersCollection = this.wsServersRegistry.get(port);
|
||||
const pathname = new URL(request.url!, baseUrl).pathname;
|
||||
const wsServersCollection = this.wsServersRegistry.get(port)!;
|
||||
|
||||
let isRequestDelegated = false;
|
||||
for (const wsServer of wsServersCollection) {
|
||||
|
||||
@@ -59,6 +59,12 @@ export class TestingInjector extends Injector {
|
||||
metatype: wrapper.metatype,
|
||||
});
|
||||
const internalCoreModule = this.container.getInternalCoreModuleRef();
|
||||
if (!internalCoreModule) {
|
||||
throw new Error(
|
||||
'Expected to have internal core module reference at this point.',
|
||||
);
|
||||
}
|
||||
|
||||
internalCoreModule.addCustomProvider(
|
||||
{
|
||||
provide: name,
|
||||
|
||||
@@ -160,7 +160,7 @@ export class TestingModuleBuilder {
|
||||
|
||||
private getRootModule() {
|
||||
const modules = this.container.getModules().values();
|
||||
return modules.next().value;
|
||||
return modules.next().value!;
|
||||
}
|
||||
|
||||
private async createInstancesOfDependencies(
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
"sourceMap": false,
|
||||
"allowJs": false,
|
||||
"strict": true,
|
||||
"strictNullChecks": false,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,6 @@ export class ExceptionFiltersContext extends BaseExceptionFilterContext {
|
||||
}
|
||||
|
||||
public getGlobalMetadata<T extends any[]>(): T {
|
||||
return [] as T;
|
||||
return [] as any[] as T;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,8 @@ export class WsException extends Error {
|
||||
) {
|
||||
this.message = (this.error as Record<string, any>).message;
|
||||
} else if (this.constructor) {
|
||||
this.message = this.constructor.name
|
||||
.match(/[A-Z][a-z]+|[0-9]+/g)
|
||||
.join(' ');
|
||||
this.message =
|
||||
this.constructor!.name!.match(/[A-Z][a-z]+|[0-9]+/g)!.join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,14 @@ export class GatewayMetadataExplorer {
|
||||
const instancePrototype = Object.getPrototypeOf(instance);
|
||||
return this.metadataScanner
|
||||
.getAllMethodNames(instancePrototype)
|
||||
.map(method => this.exploreMethodMetadata(instancePrototype, method))
|
||||
.map(method => this.exploreMethodMetadata(instancePrototype, method)!)
|
||||
.filter(metadata => metadata);
|
||||
}
|
||||
|
||||
public exploreMethodMetadata(
|
||||
instancePrototype: object,
|
||||
methodName: string,
|
||||
): MessageMappingProperties {
|
||||
): MessageMappingProperties | null {
|
||||
const callback = instancePrototype[methodName];
|
||||
const isMessageMapping = Reflect.getMetadata(
|
||||
MESSAGE_MAPPING_METADATA,
|
||||
|
||||
@@ -15,7 +15,7 @@ export class SocketsContainer {
|
||||
options: T,
|
||||
): ServerAndEventStreamsHost {
|
||||
const uniqueToken = this.generateHashByOptions(options);
|
||||
return this.serverAndEventStreamsHosts.get(uniqueToken);
|
||||
return this.serverAndEventStreamsHosts.get(uniqueToken)!;
|
||||
}
|
||||
|
||||
public addOne<T extends GatewayMetadata = any>(
|
||||
|
||||
@@ -11,12 +11,13 @@ export function createWsParamDecorator(
|
||||
return (...pipes: (Type<PipeTransform> | PipeTransform)[]) =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key!) ||
|
||||
{};
|
||||
Reflect.defineMetadata(
|
||||
PARAM_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, undefined, ...pipes),
|
||||
target.constructor,
|
||||
key,
|
||||
key!,
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -29,15 +30,15 @@ export const createPipesWsParamDecorator =
|
||||
): ParameterDecorator =>
|
||||
(target, key, index) => {
|
||||
const args =
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key) || {};
|
||||
Reflect.getMetadata(PARAM_ARGS_METADATA, target.constructor, key!) || {};
|
||||
const hasParamData = isNil(data) || isString(data);
|
||||
const paramData = hasParamData ? data : undefined;
|
||||
const paramPipes = hasParamData ? pipes : [data, ...pipes];
|
||||
|
||||
Reflect.defineMetadata(
|
||||
PARAM_ARGS_METADATA,
|
||||
assignMetadata(args, paramtype, index, paramData, ...paramPipes),
|
||||
assignMetadata(args, paramtype, index, paramData!, ...paramPipes),
|
||||
target.constructor,
|
||||
key,
|
||||
key!,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -156,7 +156,7 @@ export class WebSocketsController {
|
||||
.pipe(
|
||||
distinctUntilChanged((prev, curr) => compareElementAt(prev, curr, 0)),
|
||||
)
|
||||
.subscribe((args: unknown[]) => instance.handleConnection(...args));
|
||||
.subscribe((args: unknown[]) => instance.handleConnection!(...args));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
"noImplicitAny": false,
|
||||
"noUnusedLocals": false,
|
||||
"removeComments": true,
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": false,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noLib": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
|
||||
Reference in New Issue
Block a user