5.7 KiB
5.7 KiB
TypeSRPC
TypeSRPC 是一个轻量级、类型安全的 TypeScript RPC(远程过程调用)框架,支持客户端与服务器之间的无缝通信,并提供完整的类型推断和深度嵌套方法支持。
✨ 特性
- 完整的 TypeScript 支持:自动类型推断。
- 深度嵌套 API:支持任意层级嵌套的方法结构(例如
api.math.utils.absolute())。 - 基于 Promise:所有远程调用均返回 Promise,告别回调地狱。
- 可插拔传输层:轻松更换底层 socket 实现(默认使用 Socket.IO)。
- 访问控制:内置访问密钥认证,保障连接安全。
- 轻量且零样板代码:只需定义一次服务提供者,无需手动声明 RPC 接口。
- 双向通信:客户端和服务器均可暴露和调用对方的 API。
📦 安装
npm install typesrpc
# 或
yarn add typesrpc
# 或
pnpm add typesrpc
🚀 快速开始
1. 定义你的服务提供者
// 服务端提供者
type ServerProvider = {
add: (a: number, b: number) => number;
math: {
multiply: (a: number, b: number) => number;
utils: {
absolute: (num: number) => number;
};
};
};
const serverProvider = {
add(a: number, b: number) { return a + b; },
math: {
multiply(a: number, b: number) { return a * b; },
utils: {
absolute(num: number) { return Math.abs(num); }
}
}
};
// 客户端提供者(可选,用于双向 RPC)
type ClientProvider = {
getName: () => string;
sub: {
getName: () => string;
};
};
const clientProvider = {
name: 'Client1',
getName() { return this.name; },
sub: {
name: 'SubClient',
getName() { return this.name; }
}
};
2. 设置服务端与客户端
import { RPCHandler } from 'typesrpc';
// 服务端
const server = new RPCHandler();
server.setProvider(serverProvider);
await server.listen({ port: 3000 });
// 客户端
const client = new RPCHandler();
client.setProvider(clientProvider);
const session = await client.connect({ url: 'http://localhost:3000' });
// 获取带类型的 API 代理
const serverAPI = session.getAPI<ServerProvider>();
const clientAPI = session.getAPI<ClientProvider>(); // 如果服务端也需要调用客户端 API
3. 发起远程调用
// 所有方法均返回 Promise
const sum = await serverAPI.add(2, 3); // 5
const product = await serverAPI.math.multiply(4, 5); // 20
const abs = await serverAPI.math.utils.absolute(-10); // 10
const name = await clientAPI.getName(); // 'Client1'
💡 提示:内部导出的工具类型
ToDeepPromise<T>会自动将你提供者中的所有同步方法转换为异步方法(返回Promise<T>),因此你可以在客户端直接使用await。
🔐 访问密钥认证
通过访问密钥保护你的 RPC 端点:
服务端(要求访问密钥)
const server = new RPCHandler();
server.setAccessKey('my-secret-key');
await server.listen({ port: 3001 });
客户端(提供访问密钥)
const client = new RPCHandler();
await client.connect({
url: 'http://localhost:3001',
accessKey: 'my-secret-key' // 必填!
});
未提供有效访问密钥的连接将被拒绝。
⚙️ 自定义 Socket 实现
TypeSRPC 支持可插拔的传输层。默认使用 Socket.IO,但你可以替换为任意实时通信库(如原生 WebSocket、SignalR 等)。
如何注入自定义实现
-
实现以下接口:
SocketClientSocketServerSocketConnection
-
注入你的实现:
// my-socket-impl/index.ts
import { injectSocketClient, injectSocketServer } from 'typesrpc';
import { MySocketClient } from './MySocketClient';
import { MySocketServer } from './MySocketServer';
export function injectMySocketImpl() {
injectSocketClient(MySocketClient);
injectSocketServer(MySocketServer);
}
- 在创建任何
RPCHandler实例之前调用注入器:
import { injectMySocketImpl } from './my-socket-impl';
injectMySocketImpl(); // 必须在应用启动时调用一次
const handler = new RPCHandler(); // 现在使用你的自定义 socket 层
✅ 内置的 Socket.IO 实现在你导入 typesrpc 时会自动注入。若要覆盖它,请在创建任何
RPCHandler实例之前(但在导入 typesrpc 之后)调用你的自定义注入器。
📁 项目结构
src/
├── core/ # 核心 RPC 逻辑(与传输层无关)
├── implements/ # 传输层实现
│ └── socket.io/ # 默认:Socket.IO 适配器
├── utils/ # 工具函数(如 ToDeepPromise、EventEmitter)
└── index.ts # 公共 API 导出 + 默认 Socket.IO 注入
🧪 测试
项目包含全面的测试:
- 单元测试:
npm run test:unit - 集成测试:
npm run test:integration - 端到端测试:
npm run test:e2e - 覆盖率:
npm run test:coverage
运行全部测试:
npm test
📄 API 参考
RPCHandler
客户端和服务端的主入口。
.setProvider(provider: T)– 注册本地方法。.setAccessKey(key: string)– 设置访问密钥(服务端)。.listen(options?)– 启动服务端。.connect(options?)– 连接服务端;返回Promise<RPCSession>。
RPCSession
表示一个活跃的 RPC 连接。
.getAPI<T>()– 获取远程提供者的类型化代理。
📜 许可证
MIT 许可证 © tonecn
注意:本库适用于开发和内部工具场景。若用于面向公众的生产服务,请在访问密钥机制之上额外实现完善的认证、限流和输入验证措施。