@themainstack/communication
v1.2.0
Published
Unified gRPC framework for inter-service communication - auto-generates protos, creates servers, and provides type-safe clients
Readme
@themainstack/communication
A unified gRPC framework for inter-service communication at Mainstack.
Table of Contents
- Overview
- Installation
- Proto Generation
- Creating a gRPC Server
- Creating a gRPC Client
- Error Handling
- Full Example
Overview
The workflow is simple:
Developer writes TypeScript function
↓
Package auto-generates .proto file
↓
Server Factory exposes function as gRPC
↓
Client Factory in another service calls it
↓
Error Handler normalizes any errorsInstallation
npm install @themainstack/communication
# or
yarn add @themainstack/communicationProto Generation
Auto-generate .proto files from your TypeScript types.
import { generateProtoFromMethods } from '@themainstack/communication';
generateProtoFromMethods([
{
name: 'CalculateFee',
requestSample: () => ({ merchantId: '', amount: 0, currency: '' }),
responseSample: () => ({ fee: 0, total: 0 }),
}
], {
packageName: 'fee.v1',
serviceName: 'FeeService',
outputDir: './src/grpc',
});Output: ./src/grpc/feeservice.proto is auto-generated!
Creating a gRPC Server
Expose existing functions as gRPC endpoints.
import { GrpcServerFactory } from '@themainstack/communication';
// Your existing business function
async function calculateFee(request) {
return { fee: request.amount * 0.02, total: request.amount * 1.02 };
}
// Create and start the server
const server = await GrpcServerFactory.createServer({
packageName: 'fee.v1',
serviceName: 'FeeService',
port: 50053,
}, [
{
name: 'CalculateFee',
handler: calculateFee, // Your existing function!
requestSample: () => ({ merchantId: '', amount: 0, currency: '' }),
responseSample: () => ({ fee: 0, total: 0 }),
}
]);
await server.start();
// 🚀 gRPC Server running on 0.0.0.0:50053Quick Expose (One-liner)
import { exposeAsGrpc } from '@themainstack/communication';
const server = await exposeAsGrpc(
'CalculateFee',
calculateFee,
{ requestSample: () => ({...}), responseSample: () => ({...}) },
{ packageName: 'fee.v1', serviceName: 'FeeService', port: 50053 }
);Creating a gRPC Client
Call gRPC services from other services.
import { GrpcClientFactory } from '@themainstack/communication';
const client = GrpcClientFactory.createClient({
serviceName: 'FeeService',
packageName: 'fee.v1',
protoPath: './src/grpc/fee.proto',
url: process.env.FEE_SERVICE_URL || 'localhost:50053',
});
// Make a call
client.CalculateFee(
{ merchantId: 'merchant_123', amount: 1000, currency: 'USD' },
(err, response) => {
if (err) {
handleGrpcError(err);
return;
}
console.log('Fee:', response.fee);
}
);Error Handling
Standardized gRPC error translation.
import { handleGrpcError } from '@themainstack/communication';
client.SomeMethod(request, (err, response) => {
if (err) {
try {
handleGrpcError(err); // Throws normalized error
} catch (normalizedError) {
console.error(normalizedError.message);
// Handle based on error type
}
return;
}
// Process response
});Full Example
See examples/full-grpc-demo.ts in the repository for a complete working example.
Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| GRPC_PORT | Port for gRPC server | 50051 |
| FEE_SERVICE_URL | Fee service gRPC address | localhost:50053 |
API Reference
Proto Generation
generateProtoFromMethods(methods, options)- Generate proto with service definitiongenerateProtoFromFunction(fn, name)- Generate proto for a single messageAnyType- Marker symbol forgoogle.protobuf.Anydynamic fields
Server
GrpcServerFactory.createServer(options, handlers)- Create a gRPC serverexposeAsGrpc(name, handler, samples, options)- Quick one-liner
Client
GrpcClientFactory.createClient(options)- Create a gRPC client
Error Handling
handleGrpcError(err)- Translate gRPC errors to application errors
