Skip to main content

Parameters

With no parameter decorators, the adapter calls the method the way @grpc/grpc-js calls a raw handler: (call, callback) for unary and client-streaming RPCs, and (call) for server-streaming and bidirectional RPCs.

Add a parameter decorator when you want the container to build the argument list. @Call() injects the call. @Callback() injects the sendUnaryData callback. A custom parameter decorator injects a value you compute from the call. After the first parameter decorator, every argument you need has its own decorator. An undecorated parameter is undefined.

@Callback() belongs on unary and client-streaming methods. Server-streaming and bidirectional RPCs have no callback, and build() throws if one of those methods uses @Callback().

When a method uses @Callback(), that callback sends the response. The adapter leaves the return value alone.

Unary callback​

import { type sendUnaryData, type ServerUnaryCall } from '@grpc/grpc-js';
import { Call, Callback, RPC, Service } from '@inversifyjs/grpc-core';

import {
type HeroRequest,
type HeroResponse,
heroServiceDefinition,
} from './loadHeroServiceDefinition.js';

@Service(heroServiceDefinition)
export class CallbackHeroService {
@RPC('GetHero')
public getHero(
@Call() call: ServerUnaryCall<HeroRequest, HeroResponse>,
@Callback() callback: sendUnaryData<HeroResponse>,
): void {
callback(null, {
name: call.request.id,
});
}
}

Client-streaming callback​

import {
type sendUnaryData,
type ServerReadableStream,
status,
} from '@grpc/grpc-js';
import { Call, Callback, RPC, Service } from '@inversifyjs/grpc-core';

import {
heroUploadServiceDefinition,
type UploadRequest,
type UploadResponse,
} from './loadHeroServiceDefinition.js';

@Service(heroUploadServiceDefinition)
export class CallbackHeroUploadService {
@RPC('UploadHeroes')
public uploadHeroes(
@Call() call: ServerReadableStream<UploadRequest, UploadResponse>,
@Callback() callback: sendUnaryData<UploadResponse>,
): void {
const names: string[] = [];

call.on('data', (request: UploadRequest): void => {
names.push(request.name);
});
call.on('end', (): void => {
callback(null, {
names,
});
});
call.on('error', (error: Error): void => {
callback({
code: status.UNKNOWN,
details: error.message,
});
});
}
}

Server streaming​

import { type ServerWritableStream } from '@grpc/grpc-js';
import { Call, RPC, Service } from '@inversifyjs/grpc-core';

import {
heroListServiceDefinition,
type HeroRequest,
type HeroResponse,
} from './loadHeroServiceDefinition.js';

@Service(heroListServiceDefinition)
export class CallHeroListService {
@RPC('ListHeroes')
public listHeroes(
@Call() call: ServerWritableStream<HeroRequest, HeroResponse>,
): void {
const id: string = call.request.id;

call.write({
name: `${id}-a`,
});
call.write({
name: `${id}-b`,
});
call.end();
}
}

Bidirectional streaming​

import { type ServerDuplexStream } from '@grpc/grpc-js';
import { Call, RPC, Service } from '@inversifyjs/grpc-core';

import {
type ChatMessage,
heroChatServiceDefinition,
} from './loadHeroServiceDefinition.js';

@Service(heroChatServiceDefinition)
export class CallHeroChatService {
@RPC('Chat')
public chat(
@Call() call: ServerDuplexStream<ChatMessage, ChatMessage>,
): void {
call.on('data', (message: ChatMessage): void => {
call.write({
text: message.text,
});
});
call.on('end', (): void => {
call.end();
});
}
}

@Call() and @Callback() accept the same pipe list as a custom parameter. See Pipe for global pipes, parameter pipes, and createCustomParameterDecorator().