api.ts
1.69 KB
// 引擎 API 客户端。所有业务 URL 均由后端场景 Schema 给出(commandApi/optionsSource),前端不硬编码业务地址。
// 主体身份经 X-Principal 头传递(演示态;生产应换真实认证)。
const BASE = '/api'
async function get<T = any>(path: string): Promise<T> {
const r = await fetch(BASE + path)
if (!r.ok) throw new Error(`GET ${path} -> ${r.status}`)
return r.json()
}
async function post<T = any>(path: string, body: any, principal?: string): Promise<T> {
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
if (principal) headers['X-Principal'] = principal
const r = await fetch(BASE + path, { method: 'POST', headers, body: JSON.stringify(body) })
if (!r.ok) {
let msg = `POST ${path} -> ${r.status}`
try { const j = await r.json(); if (j?.message) msg = j.message } catch { /* ignore */ }
throw new Error(msg)
}
return r.json()
}
export const api = {
scenes: () => get('/meta/scenes'),
sceneSchema: (sceneId: string) => get(`/meta/scene/${sceneId}`),
aggregate: (aggregateId: string) => get(`/meta/aggregate/${aggregateId}`),
models: () => get('/meta/models'),
model: (code: string) => get(`/meta/model/${code}`),
reload: (principal?: string) => post('/meta/reload', {}, principal),
options: (aggregateId: string) => get(`/data/${aggregateId}`),
list: (aggregateId: string) => get(`/data/${aggregateId}/list`),
events: () => get('/data/events/recent'),
precheck: (sceneId: string, payload: any, principal?: string) => post(`/scene/${sceneId}/precheck`, payload, principal),
execute: (sceneId: string, payload: any, principal?: string) => post(`/scene/${sceneId}/execute`, payload, principal),
}