CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nestjs--microservices

Nest microservices framework providing scalable distributed systems with multiple transport layers and communication patterns.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

grpc.mddocs/

gRPC Integration

Specialized support for gRPC protocol with service definitions, streaming methods, and protocol buffer integration, providing high-performance RPC communication with type safety and bidirectional streaming capabilities.

Capabilities

gRPC Method Decorators

Decorators for defining gRPC service methods with support for unary and streaming patterns.

/**
 * Registers gRPC method handler for unary calls
 * @param service - Optional service name from proto definition
 * @returns Method decorator
 */
function GrpcMethod(service?: string): MethodDecorator;
/**
 * Registers gRPC method handler for unary calls
 * @param service - Service name from proto definition
 * @param method - Optional method name, defaults to function name
 * @returns Method decorator
 */
function GrpcMethod(service: string, method?: string): MethodDecorator;

/**
 * Registers gRPC streaming method handler with RxJS observables
 * @param service - Optional service name from proto definition  
 * @param method - Optional method name, defaults to function name
 * @returns Method decorator
 */
function GrpcStreamMethod(service?: string, method?: string): MethodDecorator;

/**
 * Registers gRPC streaming method with pass-through for manual stream handling
 * @param service - Optional service name from proto definition
 * @param method - Optional method name, defaults to function name
 * @returns Method decorator
 */
function GrpcStreamCall(service?: string, method?: string): MethodDecorator;

Usage Examples:

import { Controller } from '@nestjs/common';
import { GrpcMethod, GrpcStreamMethod, GrpcStreamCall } from '@nestjs/microservices';
import { Observable } from 'rxjs';

// Proto definition:
// service HeroService {
//   rpc FindOne (HeroById) returns (Hero);
//   rpc FindMany (Empty) returns (stream Hero);
//   rpc CreateMany (stream CreateHeroRequest) returns (stream Hero);
// }

@Controller()
export class HeroController {
  // Unary method - single request, single response
  @GrpcMethod('HeroService', 'FindOne')
  findOne(data: HeroById): Hero {
    return this.heroService.findById(data.id);
  }

  // Server streaming - single request, stream response
  @GrpcStreamMethod('HeroService', 'FindMany')
  findMany(data: Empty): Observable<Hero> {
    return this.heroService.findAll();
  }

  // Bidirectional streaming with RxJS
  @GrpcStreamMethod('HeroService', 'CreateMany')
  createMany(data: Observable<CreateHeroRequest>): Observable<Hero> {
    return data.pipe(
      map(request => this.heroService.create(request)),
      tap(hero => this.logger.log(`Created hero: ${hero.name}`))
    );
  }

  // Manual stream handling with pass-through
  @GrpcStreamCall('HeroService', 'ProcessStream')
  processStream(call: any): void {
    call.on('data', (data: any) => {
      const result = this.processHeroData(data);
      call.write(result);
    });

    call.on('end', () => {
      call.end();
    });

    call.on('error', (error: any) => {
      this.logger.error('Stream error:', error);
      call.destroy(error);
    });
  }
}

gRPC Service Decorator

Class decorator for defining gRPC service controllers.

/**
 * Class decorator for gRPC service controllers (alias for @Controller)
 * @param service - Optional service name
 * @returns Class decorator
 */
function GrpcService(service?: string): ClassDecorator;

Usage Examples:

import { GrpcService, GrpcMethod } from '@nestjs/microservices';

@GrpcService('UserService')
export class UserService {
  @GrpcMethod()
  getUser(request: GetUserRequest): GetUserResponse {
    return this.userRepository.findById(request.id);
  }

  @GrpcMethod()
  createUser(request: CreateUserRequest): CreateUserResponse {
    const user = this.userRepository.create(request);
    return { user, success: true };
  }
}

gRPC Client Interface

Interface for gRPC client operations providing access to service methods and typed clients.

/**
 * gRPC client interface for service method access
 */
interface ClientGrpc {
  /**
   * Get gRPC service by name with typed interface
   * @param name - Service name from proto definition
   * @returns Typed service interface with methods
   */
  getService<T = any>(name: string): T;
  
  /**
   * Get gRPC client by service name
   * @param name - Service name from proto definition
   * @returns Typed client interface
   */
  getClientByServiceName<T = any>(name: string): T;
}

Usage Examples:

import { Injectable, OnModuleInit } from '@nestjs/common';
import { Client, ClientGrpc, Transport } from '@nestjs/microservices';
import { join } from 'path';

interface HeroService {
  findOne(data: { id: number }): Observable<any>;
  findMany(data: {}): Observable<any>;
}

interface UserService {
  getUser(data: { id: string }): Observable<any>;
  createUser(data: { name: string; email: string }): Observable<any>;
}

@Injectable()
export class AppService implements OnModuleInit {
  @Client({
    transport: Transport.GRPC,
    options: {
      package: ['hero', 'user'],
      protoPath: [
        join(__dirname, 'hero.proto'),
        join(__dirname, 'user.proto')
      ],
      url: 'localhost:5000',
    },
  })
  private client: ClientGrpc;

  private heroService: HeroService;
  private userService: UserService;

  onModuleInit() {
    this.heroService = this.client.getService<HeroService>('HeroService');
    this.userService = this.client.getService<UserService>('UserService');
  }

  async getHero(id: number) {
    return this.heroService.findOne({ id }).toPromise();
  }

  async createUser(name: string, email: string) {
    return this.userService.createUser({ name, email }).toPromise();
  }
}

gRPC Streaming Types

Enumeration for different gRPC method streaming types.

/**
 * gRPC method streaming type enumeration
 */
enum GrpcMethodStreamingType {
  NO_STREAMING = 'no_stream',
  RX_STREAMING = 'rx_stream',
  PT_STREAMING = 'pt_stream'
}

gRPC Configuration Options

Configuration interfaces for gRPC transport setup.

/**
 * gRPC transport configuration options
 */
interface GrpcOptions {
  /** Protocol buffer package name(s) */
  package: string | string[];
  /** Path to .proto file(s) */
  protoPath: string | string[];
  /** gRPC server URL */
  url?: string;
  /** Proto loader options */
  loader?: {
    keepCase?: boolean;
    longs?: any;
    enums?: any;
    defaults?: boolean;
    oneofs?: boolean;
    includeDirs?: string[];
  };
  /** gRPC credentials for authentication */
  credentials?: any;
  /** Channel options */
  channelOptions?: Record<string, any>;
}

Usage Examples:

import { NestFactory } from '@nestjs/core';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
import { join } from 'path';

// gRPC Server setup
async function bootstrap() {
  const app = await NestFactory.createMicroservice<MicroserviceOptions>(
    AppModule,
    {
      transport: Transport.GRPC,
      options: {
        package: ['hero', 'user'],
        protoPath: [
          join(__dirname, 'proto/hero.proto'),
          join(__dirname, 'proto/user.proto')
        ],
        url: '0.0.0.0:5000',
        loader: {
          keepCase: true,
          longs: String,
          enums: String,
          defaults: true,
          oneofs: true,
          includeDirs: [join(__dirname, 'proto')]
        },
        channelOptions: {
          'grpc.keepalive_time_ms': 30000,
          'grpc.keepalive_timeout_ms': 5000,
          'grpc.keepalive_permit_without_calls': true
        }
      },
    },
  );
  
  await app.listen();
}

// gRPC Client setup
const client = ClientProxyFactory.create({
  transport: Transport.GRPC,
  options: {
    package: 'hero',
    protoPath: join(__dirname, 'hero.proto'),
    url: 'localhost:5000',
    loader: {
      keepCase: true,
      longs: String,
      enums: String
    }
  },
}) as ClientGrpc;

Advanced gRPC Features

Metadata Handling:

import { Metadata } from '@grpc/grpc-js';

@Controller()
export class AdvancedGrpcController {
  @GrpcMethod('UserService', 'GetUserWithMetadata')
  getUserWithMetadata(data: any, metadata: Metadata): any {
    // Access request metadata
    const authToken = metadata.get('authorization')[0];
    const requestId = metadata.get('request-id')[0];
    
    console.log(`Auth token: ${authToken}`);
    console.log(`Request ID: ${requestId}`);
    
    return this.userService.findById(data.id, { authToken, requestId });
  }

  @GrpcStreamMethod('UserService', 'StreamUsers')
  streamUsers(data: Observable<any>, metadata: Metadata): Observable<any> {
    const correlationId = metadata.get('correlation-id')[0];
    
    return data.pipe(
      tap(request => console.log(`Processing request ${correlationId}:`, request)),
      mergeMap(request => this.userService.processStreamRequest(request)),
      tap(response => console.log(`Response for ${correlationId}:`, response))
    );
  }
}

Error Handling:

import { RpcException } from '@nestjs/microservices';
import { status } from '@grpc/grpc-js';

@Controller()
export class GrpcErrorController {
  @GrpcMethod('UserService', 'GetUser')
  getUser(data: { id: string }): any {
    try {
      const user = this.userService.findById(data.id);
      if (!user) {
        throw new RpcException({
          code: status.NOT_FOUND,
          message: `User with ID ${data.id} not found`
        });
      }
      return user;
    } catch (error) {
      if (error instanceof ValidationError) {
        throw new RpcException({
          code: status.INVALID_ARGUMENT,
          message: error.message,
          details: error.details
        });
      }
      
      throw new RpcException({
        code: status.INTERNAL,
        message: 'Internal server error'
      });
    }
  }
}

Interceptors for gRPC:

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class GrpcLoggingInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const rpcContext = context.switchToRpc();
    const data = rpcContext.getData();
    const metadata = rpcContext.getContext();
    
    const serviceName = context.getClass().name;
    const methodName = context.getHandler().name;
    
    console.log(`gRPC call: ${serviceName}.${methodName}`);
    console.log(`Request data:`, data);
    
    const now = Date.now();
    return next.handle().pipe(
      tap(response => {
        const duration = Date.now() - now;
        console.log(`gRPC response (${duration}ms):`, response);
      })
    );
  }
}

docs

client-proxies.md

context-objects.md

exceptions.md

grpc.md

index.md

message-patterns.md

modules.md

transports.md

tile.json