Nest microservices framework providing scalable distributed systems with multiple transport layers and communication patterns.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
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);
});
}
}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 };
}
}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();
}
}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'
}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;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);
})
);
}
}