跳转到内容

API 客户端

Framedash API 客户端(@framedash/api-client)是用于操作 Framedash 开发者平台 REST API 的带类型 TypeScript / JavaScript 客户端。它与 @framedash/cli@framedash/mcp-server 内部使用的客户端相同,并以独立包的形式发布,便于你将 Framedash 遥测数据直接集成到自有的内部工具、仪表盘和自动化流程中。

它内置了认证、项目作用域路径生成、响应解包和结构化错误处理,以及若干安全防护(仅限 HTTPS 的基础 URL、拒绝会泄露凭据的重定向、请求超时),让你专注于数据本身。

  • Node.js 18 或更高版本(使用全局 fetchAbortSignal.timeoutnode:net
  • 用于访问 Web API 的管理员 API 密钥(fd_admin_ 前缀)
Terminal window
npm install @framedash/api-client
import { ApiClient, ApiError } from "@framedash/api-client";
const client = new ApiClient({
baseUrl: "https://app.framedash.dev",
apiKey: process.env.FRAMEDASH_API_KEY ?? "",
projectId: process.env.FRAMEDASH_PROJECT_ID ?? "",
onError: (err: ApiError) => {
// onError 在任何非成功响应时被调用,必须 throw(或退出)。
// 其返回类型为 `never`。抛出的值会传播到你的 await。
throw err;
},
});
// 项目作用域 GET -> /api/v1/projects/{projectId}/dashboard?days=30
const dashboard = await client.get(client.projectPath("dashboard?days=30"));
console.log(dashboard);

客户端会自动解包 API 信封:成功的 { "success": true, "data": ... } 响应仅解析为 data

ApiClient 构造函数接收一个选项对象:

选项类型说明
baseUrlstring应用主机 URL(例如 https://app.framedash.dev)。必须为 HTTPS(仅 localhost / 回环允许 HTTP)。
apiKeystring管理员 API 密钥,每次请求都通过 X-API-Key 头发送。
projectIdstring默认项目 UUID。projectPath() 必需;对于非项目路径还会作为 X-Project-Id 头发送。
onError(error: ApiError) => never在任何非成功响应时调用。必须 throw 或退出进程。

基础 URL 在客户端构造时会被校验,不安全或格式错误的 URL 会立即 throw。你也可以使用导出的 assertSafeBaseUrl(baseUrl) 自行执行同样的检查。

四个 HTTP 辅助方法覆盖 Web API。每个都返回解包后的 data 负载,并可通过泛型参数指定类型:

const data = await client.get<MyType>("/api/v1/...");
await client.post("/api/v1/...", body);
await client.patch("/api/v1/...", body);
await client.delete("/api/v1/...");

大多数端点都按项目划分。projectPath(suffix) 使用客户端配置的 projectId 构建 /api/v1/projects/{projectId}/{suffix}:

// GET /api/v1/projects/{projectId}/status
const status = await client.get(client.projectPath("status"));
// GET /api/v1/projects/{projectId}/retention?days=30
const retention = await client.get(client.projectPath("retention?days=30"));
// GET /api/v1/projects/{projectId}/maps
const maps = await client.get(client.projectPath("maps"));

在未配置 projectId 的情况下调用 projectPath() 会 throw。

withProject(projectId) 返回绑定到另一个项目的新客户端,复用相同的基础 URL、API 密钥和错误处理器。原客户端保持不变:

const other = client.withProject("another-project-uuid");
const otherStatus = await other.get(other.projectPath("status"));
// 当前绑定的项目 ID:
console.log(client.currentProjectId);
const rows = await client.post("/api/v1/query", {
sql: "SELECT event_name, count() FROM events GROUP BY event_name",
project_id: client.currentProjectId,
limit: 100,
});
// 列出告警规则
const alerts = await client.get(client.projectPath("alerts"));
// 创建告警规则
const created = await client.post(client.projectPath("alerts"), {
name: "FPS Alert",
// ...其余规则字段
});
// 停用告警规则
await client.delete(client.projectPath(`alerts/${alertId}`));
// content 端点在路径上不是项目作用域;
// 客户端会根据配置的 projectId 自动添加 X-Project-Id 头。
// 批量 upsert 的请求体将数组包装在 entries 属性中(每次请求最多 500 条)。
await client.post("/api/v1/content", { entries });
const content = await client.get("/api/v1/content");

端点、查询参数和负载结构的完整列表请参阅 API 概览

任何非成功响应(网络错误、非 2xx 状态,或缺少 success: true 的响应体)都会被转换为 ApiError 并传给你的 onError 回调。ApiError 携带解析后的 RFC 9457 Problem Details:

成员类型说明
statusnumberHTTP 状态码。
headersHeaders响应头(例如 X-RateLimit-Reset)。
messagestring人类可读的错误信息。
retryablebooleanAPI 是否将该错误标记为可重试。
retryAfternumber | undefined建议的重试间隔(秒)。
errorCategorystring | undefinedAPI 错误类别。
problemProblemDetails解析后的原始 Problem Details 对象。

一个考虑限流的处理器:

const client = new ApiClient({
baseUrl: "https://app.framedash.dev",
apiKey: process.env.FRAMEDASH_API_KEY ?? "",
projectId: process.env.FRAMEDASH_PROJECT_ID ?? "",
onError: (err: ApiError): never => {
if (err.status === 429) {
const retryAfter = err.retryAfter ?? err.headers.get("X-RateLimit-Reset");
throw new Error(`Rate limited; retry after ${retryAfter}`);
}
throw err;
},
});

为避免管理员密钥泄露,客户端强制执行若干安全措施:

  • 仅限 HTTPS 的基础 URL。除 localhost / 回环开发端点外,普通 HTTP 会被拒绝;嵌入凭据的 URL(https://...@host)也会被拒绝。
  • 不允许重定向。API 不会重定向程序化的 JSON 请求,因此任何 3xx 都被视为错误;客户端不会向重定向目标重新发送 X-API-Key 头。
  • 每次调用 30 秒请求超时(通过 AbortSignal.timeout)。