Modern TypeScript client for JSON-RPC 2.0 over IPC (Unix sockets/Named Pipes). Designed for communication with Go servers, perfect for VSCode extensions and Electron apps.
- ✅ Modern: Built with TypeScript 5+, ESM + CommonJS support
- ✅ Zero Dependencies: Only uses Node.js stdlib
- ✅ Cross-Platform: Works on Windows (Named Pipes), macOS, Linux (Unix Sockets)
- ✅ Type-Safe: Full TypeScript definitions included
- ✅ Promise-Based: Clean async/await API
- ✅ Event-Driven: EventEmitter for notifications and lifecycle events
- ✅ Reliable: Auto-reconnect, timeout handling, comprehensive error handling
- ✅ Well-Tested: Comprehensive test suite with Vitest
- ✅ Actively Maintained: Replaces outdated packages (6-9 years old)
npm install node-ipc-jsonrpcyarn add node-ipc-jsonrpcpnpm add node-ipc-jsonrpcimport { JSONRPCClient } from 'node-ipc-jsonrpc';
// Create client
const client = new JSONRPCClient({
socketPath: '/tmp/myapp.sock', // Unix/Mac
// socketPath: 'myapp', // Windows (auto-converted to \\.\pipe\myapp)
});
// Connect
await client.connect();
// Send request
const result = await client.request('search', {
query: 'hello world',
limit: 10,
});
console.log('Results:', result);
// Listen for server notifications
client.on('notification', (method, params) => {
console.log(`Notification: ${method}`, params);
});
// Disconnect
await client.disconnect();new JSONRPCClient(config: ClientConfig)| Option | Type | Default | Description |
|---|---|---|---|
socketPath |
string |
- | IPC socket path (required) |
connectionTimeout |
number |
10000 | Connection timeout in ms |
requestTimeout |
number |
30000 | Request timeout in ms |
debug |
boolean |
false | Enable debug logging |
autoReconnect |
boolean |
false | Auto-reconnect on connection loss |
maxReconnectAttempts |
number |
3 | Maximum reconnection attempts |
reconnectDelay |
number |
1000 | Delay between reconnection attempts in ms |
Connect to the IPC server.
await client.connect();Disconnect from the IPC server.
await client.disconnect();Send a JSON-RPC request and wait for response.
const result = await client.request('getData', { id: 123 });Send a JSON-RPC notification (no response expected).
client.notify('logMessage', { level: 'info', message: 'Hello' });Get current connection state.
const state = client.getState();
// 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'closed'Check if currently connected.
if (client.isConnected()) {
// do something
}The client extends EventEmitter and emits the following events:
Fired when connected to the server.
client.on('connected', () => {
console.log('Connected!');
});Fired when disconnected from the server.
client.on('disconnected', () => {
console.log('Disconnected');
});Fired when an error occurs.
client.on('error', (error) => {
console.error('Error:', error);
});Fired when a notification is received from the server.
client.on('notification', (method, params) => {
console.log(`Received ${method}:`, params);
});Fired on reconnection attempt (when autoReconnect is enabled).
client.on('reconnecting', (attempt) => {
console.log(`Reconnection attempt ${attempt}`);
});Use absolute paths for Unix sockets:
const client = new JSONRPCClient({
socketPath: '/tmp/myapp.sock',
});Use named pipe names (automatically converted to \\.\pipe\{name}):
const client = new JSONRPCClient({
socketPath: 'myapp', // Becomes \\.\pipe\myapp
});Or use full pipe path:
const client = new JSONRPCClient({
socketPath: '\\\\.\\pipe\\myapp',
});const client = new JSONRPCClient({
socketPath: '/tmp/myapp.sock',
autoReconnect: true,
maxReconnectAttempts: 5,
reconnectDelay: 2000,
});
client.on('reconnecting', (attempt) => {
console.log(`Reconnection attempt ${attempt}/5`);
});
await client.connect();The client throws JSONRPCError for server errors, which includes the JSON-RPC error code and optional data:
import { JSONRPCError } from 'node-ipc-jsonrpc';
try {
const result = await client.request('getData', { id: 123 });
} catch (error) {
if (error instanceof JSONRPCError) {
// JSON-RPC error from server
console.error(`JSON-RPC Error ${error.code}: ${error.message}`);
if (error.data) {
console.error('Additional data:', error.data);
}
// Standard JSON-RPC error codes
if (error.code === -32601) {
console.error('Method not found');
} else if (error.code === -32602) {
console.error('Invalid params');
}
} else if (error instanceof Error) {
// Connection or timeout errors
if (error.message.includes('timeout')) {
console.error('Request timed out');
} else {
console.error('Error:', error.message);
}
}
}Full type safety with generics:
interface SearchParams {
query: string;
limit: number;
}
interface SearchResult {
items: Array<{
id: string;
title: string;
}>;
total: number;
}
const result = await client.request<SearchResult>('search', {
query: 'test',
limit: 10,
} as SearchParams);
// result is fully typed!
console.log(result.items[0].title);Perfect for VSCode extensions that need to communicate with a native server:
import * as vscode from 'vscode';
import { JSONRPCClient } from 'node-ipc-jsonrpc';
export function activate(context: vscode.ExtensionContext) {
const client = new JSONRPCClient({
socketPath: '/tmp/my-language-server.sock',
debug: true,
});
// Connect on activation
client.connect().then(() => {
vscode.window.showInformationMessage('Language server connected');
});
// Handle server notifications
client.on('notification', (method, params) => {
if (method === 'progress') {
vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: params.title,
},
async (progress) => {
progress.report({ increment: params.percentage });
}
);
}
});
// Cleanup on deactivation
context.subscriptions.push({
dispose: () => client.disconnect(),
});
}Communicate between Electron main process and native backend:
import { app } from 'electron';
import { JSONRPCClient } from 'node-ipc-jsonrpc';
const client = new JSONRPCClient({
socketPath: process.platform === 'win32' ? 'myapp' : '/tmp/myapp.sock',
});
app.on('ready', async () => {
await client.connect();
// Use the client throughout your app
const data = await client.request('getData');
});
app.on('quit', () => {
client.disconnect();
});Coordinate between Node.js processes:
// worker.ts
import { JSONRPCClient } from 'node-ipc-jsonrpc';
const client = new JSONRPCClient({
socketPath: '/tmp/coordinator.sock',
});
await client.connect();
// Report progress
client.notify('workerProgress', {
workerId: process.pid,
progress: 50,
});
// Request work
const task = await client.request('getNextTask', {
workerId: process.pid,
});| Feature | node-ipc-jsonrpc | json-ipc (9 years old) | json-ipc-lib (6 years old) |
|---|---|---|---|
| TypeScript | ✅ Native | ❌ | ❌ |
| ESM + CJS | ✅ | ❌ CJS only | ❌ CJS only |
| Cross-Platform | ✅ | ||
| Auto-Reconnect | ✅ | ❌ | ❌ |
| Promise-Based | ✅ | ❌ Callbacks | |
| Active Maintenance | ✅ | ❌ | ❌ |
| Zero Dependencies | ✅ | ✅ | ✅ |
| JSON-RPC 2.0 Compliant | ✅ | ❌ 1.0 | ✅ |
| Notifications Support | ✅ | ❌ | |
| Timeout Handling | ✅ | ❌ | ❌ |
| Last Updated | 2025 | 2015 | 2018 |
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Run tests
npm test
# Watch mode
npm run test:watch
# Coverage
npm run test:coverage# Build the package
npm run build
# Development mode (watch)
npm run devMIT © gnana997
- Go Server:
ipc-jsonrpc- Companion Go server library
This package was created to replace outdated IPC libraries and provide a modern, TypeScript-first solution for JSON-RPC over IPC communication. Special thanks to the open-source community for inspiration and feedback.
Made with ❤️ for the developer community