typsio - 类型安全的 Socket.IO RPC 框架
typsio (Typed Socket.IO) 是一个轻量级、非侵入式的库,旨在为您的 python-socketio 和 socket.io-client 应用带来端到端的类型安全。它通过同步 Python 后端和 TypeScript 前端之间的函数签名和数据模型,使您能够创建健壮、可维护且不易出错的实时应用。
告别猜测事件负载(payload)结构的时代。有了 typsio,您的代码编辑器将成为您抵御 Bug 的第一道防线。
✨ 特性
- 🚀 端到端类型安全: 在 Python 中共享 Pydantic 模型,并自动生成相应的 TypeScript 接口。在编译时而不是运行时捕获数据类型不匹配的错误。
- ✨ 声明式 API: 使用简单的
@rpc.register装饰器即可定义您的 RPC 方法,无需复杂的样板代码。 - 🔄 双向通信: 完全支持客户端调用的 RPC 和服务器推送的事件,两者都完全类型化。
- 🧩 非侵入式设计:
typsio与您现有的python-socketio服务器和socket.io-client实例集成,无需进行大规模重构。 - 🛠️ 代码生成: 一个简单而强大的命令行工具,可从您的 Python API 定义生成 TypeScript 类型。
- 🔗 健壮的设计: 使用注册表模式来定义 API,从根本上避免了大型 Python 应用中常见的循环导入问题。
📦 安装
后端 (Python)
Python 包将发布到 PyPI。
# 使用 pip 安装
pip install typsio
# 或者,在此 monorepo 中进行本地开发
pip install -e packages/py_typsio
前端 (TypeScript)
客户端包将发布到 npm。
# 使用 npm 安装
npm install typsio-client socket.io-client
# 或者,在此 monorepo 中进行本地开发
npm install file:packages/ts_typsio
🚀 快速入门:运行示例
通过运行附带的示例项目,在 5 分钟内体验 typsio。
先决条件
- Python 3.8+ 和虚拟环境工具 (如
venv)。 - uv (推荐用于运行脚本):
pip install uv - Node.js 和 npm。
json-schema-to-typescript:npm install -g json-schema-to-typescript
1. 启动后端服务器
# 进入后端示例目录
cd examples/backend
# 创建虚拟环境并安装依赖
uv venv
uv pip install -e . # pyproject.toml 已为本地开发配置
# 运行开发服务器
uv run dev
后端服务器现在运行在 http://localhost:8000。
2. 启动前端客户端
在新的终端中:
# 进入前端示例目录
cd examples/frontend
# 安装依赖 (这将链接到本地的 typsio-client 包)
npm install
# 运行开发服务器
npm run dev
前端将在 http://localhost:5173 (如果 5173 端口被占用,可能会是其他端口) 上可用。
3. 查看实际效果!
在浏览器中打开前端 URL。控制台将显示:
- 成功连接到服务器。
get_user(1)RPC 调用的结果。send_messageRPC 调用成功的确认信息。
💻 开发工作流
这是 typsio 项目的核心开发循环。
1. 在 Python 中定义您的 API
使用 Pydantic 定义数据模型,并在一个中心文件中注册您的 RPC 函数。该文件是您 API 形态的唯一真实来源。
examples/backend/src/my_app/api_defs.py
from pydantic import BaseModel, Field
from typsio import RPCRegistry
import datetime
# 1. 定义数据模型
class User(BaseModel):
id: int
name: str
# 2. 创建 RPC 注册表
rpc_registry = RPCRegistry()
# 3. 注册 RPC 函数
@rpc_registry.register
async def get_user(user_id: int) -> User | None:
# ... 实现逻辑 ...
@rpc_registry.register
def send_message(message: Message) -> bool:
# ... 实现逻辑 ...
# 4. (可选) 定义服务器到客户端的事件
class Notification(BaseModel):
message: str
timestamp: datetime.datetime
SERVER_EVENTS = {
"newNotification": Notification
}
2. 生成 TypeScript 类型
运行生成器,创建一个与您的 Python 定义相匹配的 TypeScript 文件。示例项目已将其配置为 npm 脚本。
# 在 examples/frontend/ 目录下
npm run gen-types
此命令执行 examples/backend/pyproject.toml 中定义的脚本:
python ../../../generator/typsio_gen.py src/my_app/api_defs.py ...
它会生成此文件:
examples/frontend/src/generated/api-types.ts
/* eslint-disable */
/**
* This file was automatically generated by typsio-gen.
* DO NOT MODIFY IT BY HAND.
*/
export interface TypsioModels { /* ... */ }
export interface User { /* ... */ }
// ... 其他模型
export interface RPCMethods {
get_user(user_id: number): Promise<User | null>;
send_message(message: Message): Promise<boolean>;
}
export interface ServerToClientEvents {
'newNotification': (payload: Notification) => void;
}
3. 使用类型安全的客户端
现在,您可以在前端代码中导入和使用客户端,并获得完全的类型安全和自动补全功能。
examples/frontend/src/api.ts
import { io } from 'socket.io-client';
import { createTypsioClient } from 'typsio-client';
// 导入生成的类型
import type { RPCMethods, ServerToClientEvents } from './generated/api-types';
const socket = io('http://localhost:8000');
// 创建客户端,将生成的类型作为泛型传入
const client = createTypsioClient<ServerToClientEvents, RPCMethods>(socket);
export const api = client.remote; // 完全类型化的 RPC 方法
export const on = client.on; // 完全类型化的事件监听器
examples/frontend/src/main.ts
import { api, on } from './api';
// 自动补全知道 `get_user` 接受一个数字并返回 Promise<User | null>
const user = await api.get_user(1);
if (user) {
// 自动补全知道 `user` 的结构
console.log(user.name);
// 如果您尝试发送错误的结构,TypeScript 将会报错
await api.send_message({ text: '来自类型化客户端的消息!', user });
}
// `on` 监听器知道 `newNotification` 具有特定的负载类型
on('newNotification', (payload) => {
console.log(payload.message);
});
通过此工作流,您的 Python 后端和 TypeScript 前端将始终保持同步。
🛠️ 开发 (Contributing)
我们非常欢迎社区的贡献!如果您想改进 typsio,请遵循以下指南。
项目结构
本仓库是一个 monorepo,主要包含以下几个部分:
packages/: 包含py_typsio(Python 核心库) 和ts_typsio(TypeScript 客户端) 的源代码。generator/: 包含从 Python 代码生成 TypeScript 类型的核心脚本。examples/: 包含一个完整的示例项目,用于手动测试和演示。
环境设置
-
Fork & Clone: 首先,Fork 本仓库,然后将您的 Fork 克隆到本地。
-
后端 (
py_typsio): 要对 Python 核心库进行更改,请设置以下环境:# cd typsio # with venv uv venv uv pip install -e packages/py_typsio # without venv python -m venv .venv pip install -e packages/py_typsio
-
前端 (
ts_typsio): 要对 TypeScript 客户端进行更改:cd packages/ts_typsio npm install
打包
要发布新版本,使用 scripts/ 目录中的发布脚本:
# For Linux/macOS
./scripts/publish.sh
# For Windows
./scripts/publish.ps1
确保在运行脚本之前更新两个包的版本号:
- Python 包版本在
packages/py_typsio/pyproject.toml中 - TypeScript 包版本在
packages/ts_typsio/package.json中
详细说明请参见 scripts/README.md。
运行测试
在提交代码之前,请确保所有测试都已通过。
- Python:
cd packages/py_typsio && pytest - TypeScript:
cd packages/ts_typsio && npm test
(注意: 测试脚本和依赖可能需要您根据需要进行配置)
提交贡献
- 从
main分支创建一个新的特性分支 (git checkout -b my-awesome-feature)。 - 进行您的修改。
- 确保代码通过了测试和 lint 检查。
- 提交一个 Pull Request,清晰地描述您所做的更改和原因。
感谢您的贡献!
Release files for typsio 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| typsio-0.1.0.tar.gz | 14.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| typsio-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.7 kB
Release files / typsio-0.1.0.tar.gz
| Download URL | typsio-0.1.0.tar.gz |
|---|---|
| Size | 14.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4247ff4ce00c4e59b320e7753b464885b9f6cc159fce204b7f3ec9b2ccf2ed1c
|
|
BLAKE2b-256 checksum How to use checksums |
68651b4d760dfd0368cfad7a42eb27c0e8d58101e1439d7f27a9b5af4233deab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.10.18
|
Release files / typsio-0.1.0-py3-none-any.whl
| Download URL | typsio-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
84363e187a7c69c5c7ac64d6cdf7fec32d82e08593f3606cc47e36b7b9ee0558
|
|
BLAKE2b-256 checksum How to use checksums |
b75b59f3dd88e4fc0941febb98bcbc9624d771d1e8c294f53a9a1f2092e7f7c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.10.18
|