gRPC для TypeScript: библиотеки, настройка и примеры кода

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

gRPC для TypeScript: библиотеки и примеры

gRPC — это современный высокопроизводительный фреймворк для удалённого вызова процедур (RPC), разработанный Google. Он использует Protocol Buffers (protobuf) в качестве языка определения интерфейсов и формата сериализации данных. В TypeScript gRPC реализуется через пакеты @grpc/grpc-js (для серверной и клиентской логики) и protobufjs (для работы с .proto файлами). В этой статье мы разберём ключевые библиотеки, настройку окружения и напишем рабочий пример на TypeScript.

Ключевые библиотеки для gRPC в TypeScript

  • @grpc/grpc-js — чистая JavaScript-реализация gRPC (без C++ аддонов). Поддерживает все основные функции: унарные вызовы, серверную и клиентскую стриминг, двунаправленный стриминг.
  • protobufjs — библиотека для загрузки, парсинга и генерации классов из .proto файлов. Позволяет динамически создавать сообщения и сервисы.
  • @grpc/proto-loader — вспомогательный пакет, который упрощает загрузку proto-файлов и автоматически генерирует TypeScript-типы на основе определений.
  • ts-protoc-gen — генератор кода для компилятора protoc. Позволяет сгенерировать строго типизированные классы и интерфейсы из .proto файлов.

Для большинства проектов достаточно связки @grpc/grpc-js + @grpc/proto-loader. Если требуется максимальная типобезопасность, используют ts-protoc-gen или protobufjs с генерацией статических типов.

Установка зависимостей

Создайте новый проект и установите необходимые пакеты:

mkdir grpc-typescript-example
cd grpc-typescript-example
npm init -y
npm install @grpc/grpc-js @grpc/proto-loader
npm install -D typescript @types/node
npx tsc --init

Создание proto-файла

Определим простой сервис для работы с пользователями. Создайте файл user.proto:

syntax = "proto3";

package user;

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc ListUsers (ListUsersRequest) returns (stream User);
}

message GetUserRequest {
  int32 id = 1;
}

message ListUsersRequest {
  int32 page = 1;
  int32 limit = 2;
}

message User {
  int32 id = 1;
  string name = 2;
  string email = 3;
}

Реализация gRPC-сервера на TypeScript

Создадим файл server.ts:

import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import path from 'path';

const PROTO_PATH = path.join(__dirname, 'user.proto');

const packageDefinition = protoLoader.loadSync(PROTO_PATH, {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
});

const userProto = grpc.loadPackageDefinition(packageDefinition) as any;

// Имитация базы данных
const users = [
  { id: 1, name: 'Alice', email: 'alice@example.com' },
  { id: 2, name: 'Bob', email: 'bob@example.com' },
];

function getUser(
  call: grpc.ServerUnaryCall<{ id: number }, any>,
  callback: grpc.sendUnaryData<any>
) {
  const user = users.find(u => u.id === call.request.id);
  if (!user) {
    return callback({
      code: grpc.status.NOT_FOUND,
      message: 'User not found',
    });
  }
  callback(null, user);
}

function listUsers(call: grpc.ServerWritableStream<{ page: number; limit: number }, any>) {
  const page = call.request.page || 1;
  const limit = call.request.limit || 10;
  const start = (page - 1) * limit;
  const end = start + limit;
  const paginatedUsers = users.slice(start, end);
  paginatedUsers.forEach(user => call.write(user));
  call.end();
}

function main() {
  const server = new grpc.Server();
  server.addService(userProto.UserService.service, {
    GetUser: getUser,
    ListUsers: listUsers,
  });

  const address = '0.0.0.0:50051';
  server.bindAsync(
    address,
    grpc.ServerCredentials.createInsecure(),
    (error, port) => {
      if (error) {
        console.error(error);
        return;
      }
      console.log(`gRPC server running on ${address}`);
      server.start();
    }
  );
}

main();

Рекомендаций