Skip to content

动态 Schema

运行时从 RPC 服务器获取 schema 信息,无需预先生成代码。

使用场景

  • 动态语言环境(脚本、REPL)
  • 调试和探索性开发
  • 泛型工具(schema 浏览器、代理)

基本用法

1. 请求 Schema

typescript
import { RpcConnection } from '@naeemo/capnp';

const conn = new RpcConnection(transport);

// 按类型名请求 schema
const schema = await conn.getDynamicSchema({ 
  typeName: "calculator.Calculator" 
});

2. 动态读写

typescript
import { createDynamicWriter, createDynamicReader } from '@naeemo/capnp';

// 构建消息
const writer = createDynamicWriter(schema);
writer.set("name", "Alice");
writer.set("age", 30);
const buffer = writer.toBuffer();

// 读取消息
const reader = createDynamicReader(schema, buffer);
console.log(reader.get("name")); // "Alice"
console.log(reader.get("age"));  // 30

3. 处理列表

typescript
// 初始化列表
const list = writer.initList("items", 3);
list.set(0, { name: "Item 1", price: 100 });
list.set(1, { name: "Item 2", price: 200 });

// 读取列表
for (const item of reader.getList("items")) {
  console.log(item.get("name"));
}

Schema Registry

缓存和管理解析的 schemas:

typescript
import { createSchemaRegistry } from '@naeemo/capnp';

const registry = createSchemaRegistry();

// 注册 schema
registry.registerNode(schemaNode);

// 按 ID 查询
const schema = registry.getNodeById(0x123456789abcdef0n);

// 按名称查询
const schema = registry.getNodeByName("myapp.Person");

完整示例

typescript
import { 
  EzRpcTransport, 
  RpcConnection,
  createDynamicWriter,
  createDynamicReader 
} from '@naeemo/capnp';

async function main() {
  // 连接服务器
  const transport = await EzRpcTransport.connect('localhost', 8080);
  const conn = new RpcConnection(transport);

  // 获取动态 schema
  const personSchema = await conn.getDynamicSchema({ 
    typeName: "addressbook.Person" 
  });

  // 构建消息
  const writer = createDynamicWriter(personSchema);
  writer.set("name", "Bob");
  writer.set("email", "bob@example.com");
  
  const phones = writer.initList("phones", 2);
  phones.get(0).set("number", "555-1234");
  phones.get(0).set("type", "mobile");

  // 序列化
  const buffer = writer.toBuffer();

  // 读取
  const reader = createDynamicReader(personSchema, buffer);
  console.log(reader.get("name"));
  console.log(reader.has("email"));
}

与生成代码对比

特性动态 Schema生成代码
类型安全运行时检查编译时检查
性能稍慢(反射)最优(直接访问)
灵活性
IDE 支持有限完整
适用场景探索、工具生产代码

建议:生产环境使用生成代码,开发调试使用动态 schema。

Released under the MIT License.