It is a traditional request-response communication using gRPC, which is similar to REST.

Example

// todo.proto  
syntax = "proto3";  
  
package todo;  
  
message NoParam {}  
  
message TodoItem {  
  int32 id = 1;  
  string text = 2;  
}  
  
message TodoItems {  
  repeated TodoItem items = 1;  
}  
  
service Todo {  
  rpc Create(TodoItem) returns (TodoItem);  
  rpc Read(NoParam) returns (TodoItems);  
}  
import type { ProtoGrpcType } from '../proto/todo';  
import * as grpc from '@grpc/grpc-js';  
import * as protoLoader from '@grpc/proto-loader';  
import type { TodoHandlers } from '../proto/todo/Todo';  
  
// Load and type the proto file  
const packageDefinition = protoLoader.loadSync('todo.proto', {  
	longs: String,  
	enums: String,  
	defaults: true,  
	oneofs: true,  
});  
  
const proto = grpc.loadPackageDefinition(packageDefinition) as unknown as {  
	todo: ProtoGrpcType;  
};  
  
// Define TypeScript types for the gRPC service  
interface TodoItem {  
	id: number;  
	text: string;  
}  
  
interface TodoItems {  
	items: TodoItem[];  
}  
  
// Typed service implementation  
const todos = new Map<number, TodoItem>();  
  
const todoService: TodoHandlers = {  
	create: (call, callback) => {  
		if (!call.request.text) {  
			return callback({  
				code: grpc.status.INVALID_ARGUMENT,  
				details: 'Missing text',  
			});  
		}  
  
		const newTodo: TodoItem = { id: todos.size + 1, text: call.request.text };  
		todos.set(newTodo.id, newTodo);  
  
		console.log(`(server) Added new todo item: ${JSON.stringify(newTodo)}`);  
		callback(null, newTodo);  
	},  
	read: (call, callback) => {  
		const allTodos: TodoItem[] = Array.from(todos.values());  
		console.log({ allTodos });  
  
		callback(null, { items: allTodos });  
	},  
};  
  
// Create and start gRPC server  
const server = new grpc.Server();  
server.addService(proto.todo.todo.Todo.service, todoService);  
server.bindAsync(  
	'0.0.0.0:50051',  
	grpc.ServerCredentials.createInsecure(),  
	() => {  
		console.log('gRPC server running on port 50051');  
	}  
);  
  
// client  
import grpc from '@grpc/grpc-js';  
import protoLoader from '@grpc/proto-loader';  
import type { ProtoGrpcType } from './proto/todo';  
  
const packageDef = protoLoader.loadSync('./proto/todo.proto', {  
	longs: String,  
	enums: String,  
	defaults: true,  
	oneofs: true,  
});  
  
const grpcObject = grpc.loadPackageDefinition(  
	packageDef  
) as unknown as ProtoGrpcType;  
  
const todoPackage = grpcObject.todo_service;  
  
const client = new todoPackage.Todo(  
	'localhost:50051',  
	grpc.credentials.createInsecure()  
);  
  
client.create(  
	{  
		id: -1,  
		text: 'hello',  
	},  
	(err, resp) => {  
		console.log('Server added things successfully');  
	}  
);