A robust, type-safe, and transport-agnostic TypeScript library for building JSON-RPC 2.0 clients and servers.
- Type-Safe: Full TypeScript support with strict typing for requests, responses, and errors
- JSON-RPC 2.0 Compliant: Strict adherence to the JSON-RPC 2.0 Specification
- Transport Agnostic: Works with any transport layer (HTTP, WebSocket, etc.)
- Monorepo Architecture: Three focused packages for different use cases
- Comprehensive Error Handling: Standard and custom JSON-RPC errors
- Batch Request Support: Handle multiple requests in a single call
- Notification Support: Fire-and-forget notifications
- Context Support: Pass context data to server method handlers
- Extensive Testing: 63 unit tests with high coverage
- Modern TypeScript: ES modules, strict mode, and latest features
This is a monorepo containing three packages:
Core types and utilities for JSON-RPC 2.0 implementation.
npm install @ts-json-rpc/core
Type-safe JSON-RPC 2.0 client implementation.
npm install @ts-json-rpc/client @ts-json-rpc/core
Type-safe JSON-RPC 2.0 server implementation.
npm install @ts-json-rpc/server @ts-json-rpc/core
import { createJsonRpcClient } from '@ts-json-rpc/client';
// Define your transport function
const transport = async (request) => {
const response = await fetch('/api/jsonrpc', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request),
});
return response.json();
};
// Create client
const client = createJsonRpcClient(transport);
// Make RPC calls
const result = await client.call<number>('add', { a: 1, b: 2 });
console.log(result); // 3
// Send notifications (no response expected)
client.notify('log', { message: 'Hello world' });
import { createJsonRpcServer } from '@ts-json-rpc/server';
// Define your method handlers
const methods = {
add: (params: { a: number; b: number }) => {
return params.a + params.b;
},
subtract: async (params: { a: number; b: number }) => {
return params.a - params.b;
},
greet: (params: { name: string }, context: { userId?: string }) => {
return `Hello, ${params.name}! User ID: ${context.userId || 'anonymous'}`;
},
log: (params: { message: string }) => {
console.log('Received log:', params.message);
},
};
// Create server
const server = createJsonRpcServer(methods, {
strictMethodHandling: true,
logger: console,
});
// Handle incoming requests (Express example)
app.post('/api/jsonrpc', async (req, res) => {
const response = await server.handleJsonRpcRequest(req.body, {
userId: req.user?.id,
});
if (response !== null) {
res.json(response);
} else {
res.status(204).send(); // No response for notifications
}
});
import {
createJsonRpcRequest,
createJsonRpcNotification,
createJsonRpcError,
isJSONRPCRequest,
isJSONRPCResponse,
JSONRPC_ERROR_CODES,
} from '@ts-json-rpc/core';
// Create requests
const request = createJsonRpcRequest('add', 1, { a: 1, b: 2 });
const notification = createJsonRpcNotification('log', { message: 'test' });
// Create errors
const customError = createJsonRpcError(-32001, 'Custom error', { details: 'Something went wrong' });
// Type guards
if (isJSONRPCRequest(someObject)) {
console.log('This is a JSON-RPC request');
}
// Standard error codes
const parseError = JSONRPC_ERROR_CODES.PARSE_ERROR; // -32700
- Node.js >= 20.0.0
- npm
# Clone the repository
git clone <repository-url>
cd ts-json-rpc
# Install dependencies
npm install
# Build all packages
npm run build
# Run tests
npm test
# Run linting
npm run lint
# Format code
npm run format
ts-json-rpc/
βββ packages/
β βββ core/ # Core types and utilities
β βββ client/ # JSON-RPC client
β βββ server/ # JSON-RPC server
βββ .eslintrc.js # ESLint configuration
βββ .prettierrc.js # Prettier configuration
βββ tsconfig.json # Base TypeScript configuration
βββ package.json # Root package configuration
npm run build
- Build all packagesnpm test
- Run tests for all packagesnpm run lint
- Lint all packagesnpm run format
- Format code with Prettier
- Node.js: Version 20.0.0 or higher
- TypeScript: 5.0+ (for development)
- Transport: You provide your own transport implementation
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
This project follows the Git Flow workflow:
- Fork the repository
- Set up Git Flow:
git flow init # Accept defaults
- Start a feature:
git flow feature start your-feature-name # Or manually: git checkout -b feature/your-feature-name develop
- Make your changes
- Test thoroughly:
npm run build npm test npm run lint
- Commit using conventional commits:
feat: add new feature
- Finish feature and create PR:
git flow feature finish your-feature-name # Then create PR from feature/your-feature-name to develop
For detailed Git Flow guidelines, see CONTRIBUTING.md.
MIT - see LICENSE.md for details.
- Built following the JSON-RPC 2.0 Specification
- Inspired by modern TypeScript best practices
- Designed for maximum type safety and developer experience