OSDK TypeScript 前端集成指南
coomia-dip 不仅提供强大的后端数据处理和决策能力,还通过 OSDK(Ontology SDK)为前端应用提供类型安全的 Ontology 访问接口。OSDK TypeScript 版本让前端开发者可以像操作本地对象一样操作 Ontology 中的实体,享受完整的 TypeScript 类型推导和 IDE 自动补全。
Coomia发布于 2026年1月27日7 分钟阅读
分享本文Twitter / X
“系列:S12 开发者教程 · 第 17 篇 | 难度:中级 | 阅读时间:15 分钟
OSDK TypeScript 前端集成指南
#引言
coomia-dip 不仅提供强大的后端数据处理和决策能力,还通过 OSDK(Ontology SDK)为前端应用提供类型安全的 Ontology 访问接口。OSDK TypeScript 版本让前端开发者可以像操作本地对象一样操作 Ontology 中的实体,享受完整的 TypeScript 类型推导和 IDE 自动补全。
本教程将带你从代码生成开始,在 React 应用中集成 OSDK,实现对象查询、Action 调用、实时订阅等核心功能。
#1. OSDK 架构概览
#1.1 代码生成流程
OSDK 采用代码生成(Code Generation)方式,从 Ontology Schema 自动生成强类型的 TypeScript 客户端代码:
Code
Ontology Schema (Platform)
|
v
osdk-cli generate
|
v
Generated TypeScript Code
|
+-- types/ # 对象类型定义
+-- objects/ # 对象操作客户端
+-- actions/ # Action 调用客户端
+-- queries/ # OQL 查询客户端
+-- links/ # 关联关系导航
#1.2 为什么选择代码生成而非运行时
- 编译时类型安全:属性名拼写错误在编译时就能发现
- IDE 自动补全:开发体验与操作本地 TypeScript 对象一致
- Tree-shaking:打包时只包含实际使用的对象类型
- 零运行时开销:没有反射、没有动态代理
#2. 环境准备
#2.1 安装 OSDK CLI
Bash
npm install -g @coomia-dip/osdk-cli
# 验证
osdk --version
#2.2 生成客户端代码
Bash
# 登录到 coomia-dip 实例
osdk auth login --url http://localhost:8080 --token your-api-token
# 生成 TypeScript 代码
osdk generate typescript \
--output ./src/generated/ontology \
--package-name @app/ontology
# 生成的目录结构
src/generated/ontology/
+-- index.ts
+-- types/
| +-- Order.ts
| +-- Customer.ts
| +-- Ticket.ts
+-- objects/
| +-- OrderClient.ts
| +-- CustomerClient.ts
+-- actions/
| +-- CreateOrderAction.ts
| +-- ApproveTicketAction.ts
+-- client.ts
#2.3 初始化客户端
TypeScript
// src/ontology/client.ts
import { OntoPlatformClient } from '@app/ontology/client';
export const ontologyClient = new OntoPlatformClient({
baseUrl: import.meta.env.VITE_coomia-dip_URL || 'http://localhost:8080',
token: import.meta.env.VITE_coomia-dip_TOKEN,
// 或使用 OAuth2
auth: {
type: 'oauth2',
clientId: import.meta.env.VITE_OAUTH_CLIENT_ID,
redirectUri: window.location.origin + '/callback',
},
});
#3. 对象查询
#3.1 基础查询
TypeScript
import { ontologyClient } from './ontology/client';
import { Order, Customer } from '@app/ontology/types';
// 获取单个对象
const order = await ontologyClient.objects.Order.get('order-123');
console.log(order.productName); // TypeScript 自动补全
console.log(order.totalAmount); // number 类型
// 列表查询
const orders = await ontologyClient.objects.Order
.where(o => o.status.eq('ACTIVE'))
.where(o => o.totalAmount.gt(1000))
.orderBy('createdAt', 'desc')
.limit(20)
.list();
for (const order of orders.data) {
console.log(`${order.orderId}: ${order.productName} - $${order.totalAmount}`);
}
#3.2 关联导航
TypeScript
// 获取订单关联的客户
const order = await ontologyClient.objects.Order.get('order-123');
const customer = await order.links.orderedBy.get();
console.log(`Customer: ${customer.name}`);
// 获取客户的所有订单
const customer = await ontologyClient.objects.Customer.get('cust-456');
const customerOrders = await customer.links.orders
.where(o => o.status.eq('COMPLETED'))
.list();
#3.3 聚合查询
TypeScript
const stats = await ontologyClient.objects.Order
.where(o => o.createdAt.gte('2025-01-01'))
.aggregate({
totalRevenue: agg.sum('totalAmount'),
avgOrderValue: agg.avg('totalAmount'),
orderCount: agg.count(),
})
.groupBy('status')
.execute();
for (const group of stats) {
console.log(`${group.status}: ${group.orderCount} orders, $${group.totalRevenue}`);
}
#4. 在 React 中使用
#4.1 React Query 集成
TypeScript
import { useQuery, useMutation } from '@tanstack/react-query';
import { ontologyClient } from './ontology/client';
function useOrders(status: string) {
return useQuery({
queryKey: ['orders', status],
queryFn: () => ontologyClient.objects.Order
.where(o => o.status.eq(status))
.orderBy('createdAt', 'desc')
.limit(50)
.list(),
});
}
function OrderList() {
const { data, isLoading, error } = useOrders('ACTIVE');
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<table>
<thead>
<tr>
<th>Order ID</th>
<th>Product</th>
<th>Amount</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{data.data.map(order => (
<tr key={order.orderId}>
<td>{order.orderId}</td>
<td>{order.productName}</td>
<td>${order.totalAmount.toFixed(2)}</td>
<td>{order.status}</td>
</tr>
))}
</tbody>
</table>
);
}
#4.2 执行 Action
TypeScript
function useCreateOrder() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (params: {
customerId: string;
productName: string;
quantity: number;
unitPrice: number;
}) => ontologyClient.actions.CreateOrder.execute(params),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['orders'] });
},
});
}
function CreateOrderForm() {
const createOrder = useCreateOrder();
const [form, setForm] = useState({ customerId: '', productName: '', quantity: 1, unitPrice: 0 });
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
await createOrder.mutateAsync(form);
};
return (
<form onSubmit={handleSubmit}>
<input value={form.productName}
onChange={e => setForm(f => ({ ...f, productName: e.target.value }))}
placeholder="Product name" />
<input type="number" value={form.quantity}
onChange={e => setForm(f => ({ ...f, quantity: Number(e.target.value) }))} />
<input type="number" value={form.unitPrice}
onChange={e => setForm(f => ({ ...f, unitPrice: Number(e.target.value) }))} />
<button type="submit" disabled={createOrder.isPending}>
{createOrder.isPending ? 'Creating...' : 'Create Order'}
</button>
</form>
);
}
#4.3 实时订阅
TypeScript
import { useEffect, useState } from 'react';
function useRealtimeOrders() {
const [orders, setOrders] = useState<Order[]>([]);
useEffect(() => {
const subscription = ontologyClient.objects.Order
.where(o => o.status.eq('ACTIVE'))
.subscribe({
onData: (event) => {
if (event.type === 'CREATED') {
setOrders(prev => [event.object, ...prev]);
} else if (event.type === 'UPDATED') {
setOrders(prev => prev.map(o =>
o.orderId === event.object.orderId ? event.object : o));
} else if (event.type === 'DELETED') {
setOrders(prev => prev.filter(o => o.orderId !== event.object.orderId));
}
},
onError: (err) => console.error('Subscription error:', err),
});
return () => subscription.unsubscribe();
}, []);
return orders;
}
#5. 高级功能
#5.1 批量操作
TypeScript
const batch = ontologyClient.batch();
batch.objects.Order.update('order-1', { status: 'SHIPPED' });
batch.objects.Order.update('order-2', { status: 'SHIPPED' });
batch.objects.Order.update('order-3', { status: 'SHIPPED' });
const results = await batch.execute();
#5.2 乐观更新
TypeScript
const updateOrder = useMutation({
mutationFn: ({ orderId, status }) =>
ontologyClient.objects.Order.update(orderId, { status }),
onMutate: async ({ orderId, status }) => {
await queryClient.cancelQueries({ queryKey: ['orders'] });
const prev = queryClient.getQueryData(['orders']);
queryClient.setQueryData(['orders'], (old) =>
old.map(o => o.orderId === orderId ? { ...o, status } : o));
return { prev };
},
onError: (err, vars, context) => {
queryClient.setQueryData(['orders'], context.prev);
},
});
#5.3 OQL 自定义查询
TypeScript
const result = await ontologyClient.oql.execute<{
orderId: string;
customerName: string;
totalAmount: number;
}>(`
SELECT o.orderId, c.name AS customerName, o.totalAmount
FROM Order o
JOIN o.orderedBy c
WHERE o.totalAmount > $1
ORDER BY o.totalAmount DESC
LIMIT 10
`, [5000]);
result.rows.forEach(row => {
console.log(`${row.orderId}: ${row.customerName} - $${row.totalAmount}`);
});
#6. 测试
TypeScript
import { describe, it, expect, vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
vi.mock('./ontology/client', () => ({
ontologyClient: {
objects: {
Order: {
where: vi.fn().mockReturnThis(),
orderBy: vi.fn().mockReturnThis(),
limit: vi.fn().mockReturnThis(),
list: vi.fn().mockResolvedValue({
data: [
{ orderId: 'O-1', productName: 'Widget', totalAmount: 100, status: 'ACTIVE' },
],
}),
},
},
},
}));
describe('OrderList', () => {
it('renders orders', async () => {
const client = new QueryClient();
render(
<QueryClientProvider client={client}>
<OrderList />
</QueryClientProvider>
);
await waitFor(() => {
expect(screen.getByText('Widget')).toBeInTheDocument();
});
});
});
#总结
本教程覆盖了 OSDK TypeScript 在前端应用中的完整使用方法:从代码生成到 React 集成,包括对象查询、关联导航、聚合统计、Action 执行、实时订阅、批量操作和 OQL 自定义查询。OSDK 让前端开发者以类型安全的方式访问 Ontology,大幅提升开发效率和代码质量。
下一篇:[S12-18] 多租户隔离与配置指南 上一篇:[S12-16] Temporal 工作流编排指南