gRPC / RPC
Type-safe gRPC services with proto imports - no codegen required
The @justscale/rpc package provides gRPC transport for contract-based controllers. Import contracts directly from .proto files - no code generation step required!
Installation
Bash
pnpm add @justscale/rpc @justscale/protobufKey Features
- Direct proto imports - Import types directly from .proto files
- No codegen - TypeScript compiler plugin generates types at build time
- Contract-based - Define controllers that implement gRPC service contracts
- DI integration - Full dependency injection support for clients and servers
- All streaming modes - Unary, server streaming, client streaming, bidirectional
- Built-in features - Health checks, reflection, interceptors, compression
Quick Example
Define a proto file with your service contract:
protobuf
// greeter.proto
syntax = "proto3";
package greeter;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}Import and implement the contract in a controller:
TypeScript
import { GreeterContract } from './greeter.proto'
import { createController } from '@justscale/core'
const GreeterController = createController
.implements(GreeterContract)
.create({
inject: {},
methods: () => ({
SayHello: async ({ body }) => ({
message: `Hello, ${body.name}!`,
}),
}),
})Serve via cluster:
TypeScript
import JustScale from '@justscale/core'
import '@justscale/rpc' // Auto-registers transport
const app = JustScale()
.add(GreeterController)
.build()
await app.serve({
rpc: { port: 50051, enableReflection: true },
})Streaming RPCs
All gRPC streaming modes are supported. Use async generators for streaming responses:
TypeScript
// Server streaming
async *StreamGreetings({ body }) {
for (let i = 0; i < body.count; i++) {
yield { message: `Hello #${i + 1}, ${body.name}!` }
await delay(1000)
}
}
// Bidirectional streaming
async *Chat({ body: messages }) {
for await (const msg of messages) {
yield { reply: `Echo: ${msg.text}` }
}
}Type-Safe Clients
Create DI-integrated clients with defineRpcClient:
TypeScript
import { defineRpcClient } from '@justscale/rpc'
import { GreeterContract } from './greeter.proto'
const GreeterClient = defineRpcClient({
contract: GreeterContract,
inject: { settings: GreeterSettings },
})
// Use in services
class MyService extends defineService({
inject: { greeter: GreeterClient },
factory: ({ greeter }) => ({
async greet(name: string) {
const reply = await greeter.SayHello({ name })
return reply.message
},
}),
}) {}