A typesafe RPC library for Node.js, TypeScript and React.
npm install typesafe-rpcA modern, type-safe RPC (Remote Procedure Call) library for Node.js, TypeScript, and React applications. Built with full TypeScript support, providing end-to-end type safety between client and server.
- Full TypeScript Support: Complete type safety from server to client
- Modern Architecture: Built for modern web applications with ES modules
- Middleware Support: Extensible middleware system for authentication, logging, and more
- Performance Monitoring: Built-in hooks for performance tracking
- Error Handling: Comprehensive error handling with customizable error responses
- Abort Signal Support: Cancel requests with AbortController
- Zero Dependencies: Minimal runtime dependencies for optimal bundle size
``bash`
npm install typesafe-rpcor
yarn add typesafe-rpcor
pnpm add typesafe-rpcor
bun add typesafe-rpc
`typescript
// api-schema.ts
import type { BaseContext, Handler } from 'typesafe-rpc';
type UserContext = BaseContext & {
user?: { id: string; name: string };
};
type UserParams = { id: string };
type UserResult = { id: string; name: string; email: string };
const getUserHandler: Handler
params,
context,
}) => {
// Your business logic here
return {
id: params.id,
name: 'John Doe',
email: 'john@example.com',
};
};
export const apiSchema = {
users: {
getById: getUserHandler,
},
} as const;
`
`typescript
// server.ts
import { createRpcHandler } from 'typesafe-rpc/server';
import { apiSchema } from './api-schema';
export async function handleRequest(request: Request): Promise
const context = { request };
return createRpcHandler({
context,
operations: apiSchema,
errorHandler: (error) => {
console.error('RPC Error:', error);
return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
},
hooks: {
preCall: (context) => console.log('RPC call started'),
postCall: (context, performance) => console.log(RPC call completed in ${performance}ms),RPC call failed after ${performance}ms:
error: (context, performance, error) =>
console.error(, error),`
},
});
}
`typescript
// client.ts
import { createRpcClient } from 'typesafe-rpc/client';
import type { apiSchema } from './api-schema';
const client = createRpcClient
// Usage with full type safety
const user = await client.users.getById({ id: '123' });
console.log(user.name); // TypeScript knows this exists!
`
`typescript
// React component
import { useState, useEffect } from 'react';
import { client } from './client';
function UserProfile({ userId }: { userId: string }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const controller = new AbortController();
client.users.getById({ id: userId }, controller.signal)
.then(setUser)
.catch(console.error)
.finally(() => setLoading(false));
return () => controller.abort();
}, [userId]);
if (loading) return
return (
{user.email}
🔧 API Reference
$3
####
BaseContext`typescript
type BaseContext = {
request: Request;
};
`####
Handler`typescript
type Handler = (
args: Args,
) => Promise;
`####
RpcSchema`typescript
type RpcSchema = {
[entity: string]: {
[operation: string]: Handler;
};
};
`$3
####
createRpcHandlerCreates an RPC handler for processing requests.
`typescript
function createRpcHandler({
context,
operations,
errorHandler?,
hooks?,
}: {
context: Context;
operations: T;
errorHandler?: (error: any) => Response;
hooks?: {
preCall?: (context: Context) => void;
postCall?: (context: Context, performance: number) => void;
error?: (context: Context, performance: number, error: any) => void;
};
}): Promise
`$3
####
createRpcClientCreates a type-safe RPC client.
`typescript
function createRpcClient(endpoint: string): RpcClient;
`The returned client provides a proxy that matches your schema structure with full type safety.
$3
`typescript
import type { Middleware } from 'typesafe-rpc';// Authentication middleware
const authMiddleware: Middleware = async ({
context,
}) => {
const token = context.request.headers.get('Authorization');
if (!token) throw new Response('Unauthorized', { status: 401 });
// Verify token and return user info
return { user: { id: 'user-123' } };
};
// Usage in handler
const protectedHandler: Handler<
UserParams,
BaseContext,
UserResult,
{ user: { id: string } }
> = async ({ params, context, extraParams }) => {
// extraParams.user is now available with full type safety
return {
/ ... /
};
};
`🛠️ Development
$3
- Node.js 18+
- Bun 1.3.5+
$3
`bash
git clone https://github.com/bacali95/typesafe-rpc.git
cd typesafe-rpc
bun install
`$3
`bash
Build the library
bun run buildRun tests
bun run testLint code
bun run lintFormat code
bun run prettier:fixCheck code formatting
bun run prettier:check
`🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
1. Fork the repository
2. Create a feature branch (
git checkout -b feature/amazing-feature)
3. Commit your changes (git commit -m 'Add amazing feature')
4. Push to the branch (git push origin feature/amazing-feature`)This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Nx for monorepo management
- TypeScript-first design for maximum developer experience
- Modern web standards with ES modules and Fetch API
- 📧 Email: nasreddine.bacali95@gmail.com
- 🐛 Issues: GitHub Issues
- 📖 Documentation: GitHub Pages
---
Made with ❤️ by Nasreddine Bac Ali