UNPKG

@nestjs/microservices

Version:

Nest - modern, fast, powerful node.js web framework (@microservices)

105 lines (104 loc) 4.6 kB
import { PATTERN_EXTRAS_METADATA, PATTERN_HANDLER_METADATA, PATTERN_METADATA, TRANSPORT_METADATA, } from '../constants.js'; import { Transport } from '../enums/index.js'; import { PatternHandler } from '../enums/pattern-handler.enum.js'; import { InvalidGrpcDecoratorException, } from '../errors/invalid-grpc-message-decorator.exception.js'; import { isNil, isNumber, isObject, isSymbol } from '@nestjs/common/internal'; export var GrpcMethodStreamingType; (function (GrpcMethodStreamingType) { GrpcMethodStreamingType["NO_STREAMING"] = "no_stream"; GrpcMethodStreamingType["RX_STREAMING"] = "rx_stream"; GrpcMethodStreamingType["PT_STREAMING"] = "pt_stream"; })(GrpcMethodStreamingType || (GrpcMethodStreamingType = {})); /** * Subscribes to incoming messages which fulfils chosen pattern. * * @publicApi */ export const MessagePattern = (metadata, transportOrExtras, maybeExtras) => { let transport; let extras; if ((isNumber(transportOrExtras) || isSymbol(transportOrExtras)) && isNil(maybeExtras)) { transport = transportOrExtras; } else if (isObject(transportOrExtras) && isNil(maybeExtras)) { extras = transportOrExtras; } else { transport = transportOrExtras; extras = maybeExtras; } return (target, key, descriptor) => { try { Reflect.defineMetadata(PATTERN_METADATA, [].concat(metadata), descriptor.value); Reflect.defineMetadata(PATTERN_HANDLER_METADATA, PatternHandler.MESSAGE, descriptor.value); Reflect.defineMetadata(TRANSPORT_METADATA, transport, descriptor.value); Reflect.defineMetadata(PATTERN_EXTRAS_METADATA, { ...Reflect.getMetadata(PATTERN_EXTRAS_METADATA, descriptor.value), ...extras, }, descriptor.value); return descriptor; } catch (err) { throw new InvalidGrpcDecoratorException(metadata); } }; }; export function GrpcMethod(service, method) { return (target, key, descriptor) => { const metadata = createGrpcMethodMetadata(target, key, service, method); return MessagePattern(metadata, Transport.GRPC)(target, key, descriptor); }; } export function GrpcStreamMethod(service, method) { return (target, key, descriptor) => { const metadata = createGrpcMethodMetadata(target, key, service, method, GrpcMethodStreamingType.RX_STREAMING); MessagePattern(metadata, Transport.GRPC)(target, key, descriptor); const originalMethod = descriptor.value; // Override original method to call the "drainBuffer" method on the first parameter // This is required to avoid premature message emission descriptor.value = function (observable, ...args) { const result = originalMethod.apply(this, [observable, ...args]); const isPromise = result && typeof result.then === 'function'; if (isPromise) { return result.then((data) => { if (observable && observable.drainBuffer) { observable.drainBuffer(); } return data; }); } if (observable && observable.drainBuffer) { observable.drainBuffer(); } return result; }; // Copy all metadata from the original method to the new one const metadataKeys = Reflect.getMetadataKeys(originalMethod); metadataKeys.forEach(metadataKey => { const metadataValue = Reflect.getMetadata(metadataKey, originalMethod); Reflect.defineMetadata(metadataKey, metadataValue, descriptor.value); }); }; } export function GrpcStreamCall(service, method) { return (target, key, descriptor) => { const metadata = createGrpcMethodMetadata(target, key, service, method, GrpcMethodStreamingType.PT_STREAMING); return MessagePattern(metadata, Transport.GRPC)(target, key, descriptor); }; } export function createGrpcMethodMetadata(target, key, service, method, streaming = GrpcMethodStreamingType.NO_STREAMING) { const capitalizeFirstLetter = (str) => str.charAt(0).toUpperCase() + str.slice(1); if (!service) { const { name } = target.constructor; return { service: name, rpc: capitalizeFirstLetter(key), streaming, }; } if (service && !method) { return { service, rpc: capitalizeFirstLetter(key), streaming }; } return { service, rpc: method, streaming }; }