跳到主要内容

TypeScript SDK

XLADA 并没有一个以 XLADA 为名单独发布的 SDK。这并不妨碍使用: 该分支的 API 与 Remnawave 的 API 完全一致 —— 相同的路径,相同的请求与 响应结构。因此 Remnawave 的类型和契约是兼容的,HTTP 客户端 只需几行代码就能搭好。

安装​

下面的示例用标准的 fetch 就够了,Node.js 18+ 和 浏览器中都有它。如果你更习惯 axios:

npm install axios

Remnawave 的官方 SDK —— @remnawave/backend-contract —— 只包含类型 和 zod 结构,没有 HTTP 客户端:

npm install @remnawave/backend-contract

在面板的源代码中,同一个契约库位于 apps/backend/libs/contract(前端的副本位于 apps/frontend/vendor/backend-contract),名为 @xlada/backend-contract。 它不会发布到 npm:请把它作为仓库的本地依赖引入 ("@xlada/backend-contract": "file:./vendor/backend-contract")。

版本匹配

请把契约版本与面板版本绑定。契约和面板按不同的周期演进, 因此「最新」的类型版本并不总能描述你实际运行的那台 服务器。

基础客户端​

面板要求 Authorization: Bearer <token>。如果你从内网直接访问 面板,请加上代理请求头 —— 没有 X-Forwarded-For 和 X-Forwarded-Proto: https 时,面板的 middleware 会断开连接。

const PANEL_URL = process.env.XLADA_PANEL_URL ?? 'https://panel.example.com';
const API_TOKEN = process.env.XLADA_API_TOKEN ?? '';

async function api<T>(path: string, init: RequestInit = {}): Promise<T> {
const res = await fetch(`${PANEL_URL}${path}`, {
...init,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${API_TOKEN}`,
'X-Forwarded-For': '127.0.0.1',
'X-Forwarded-Proto': 'https',
...init.headers,
},
});

if (!res.ok) {
throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
}

return (await res.json()) as T;
}

身份验证​

有两种获取令牌的方式。

管理员 JWT —— 有效期有限(JWT_AUTH_LIFETIME,12 到 168 小时),由 POST /api/auth/login 签发:

curl -sX POST https://panel.example.com/api/auth/login \
-H 'Content-Type: application/json' \
-d '{"username": "admin", "password": "password"}'

响应中包含 accessToken:

{
"response": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}

API 令牌 —— 用于脚本和集成。通过 POST /api/tokens 创建(界面中为 Settings → API Tokens),并在同一个 Authorization 请求头中传递:

curl -sX POST https://panel.example.com/api/tokens \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name": "ci", "expiresInDays": 365}'

生成好的令牌位于 response.token 字段,并且只显示一次。可用范围的 列表由 GET /api/tokens/scopes 返回。

用户列表​

分页输出:start —— 偏移量,size —— 每页大小(1 到 1000, 默认为 25)。

interface GetUsersResponse {
response: {
users: Array<{
id: number;
username: string;
status: 'ACTIVE' | 'DISABLED' | 'LIMITED' | 'EXPIRED';
shortUuid: string;
expireAt: string;
}>;
total: number;
};
}

const { response } = await api<GetUsersResponse>('/api/users?start=0&size=25');

for (const user of response.users) {
console.log(user.username, user.status, user.expireAt);
}
console.log(`总计: ${response.total}`);

创建用户​

POST /api/users 接受 username(3–36 个字符,仅限拉丁字母、数字、 _ 和 -)以及必填的、ISO 8601 格式的 expireAt。

const created = await api<{ response: { id: number; shortUuid: string } }>(
'/api/users',
{
method: 'POST',
body: JSON.stringify({
username: 'john_doe',
status: 'ACTIVE',
expireAt: '2026-01-17T15:38:45.065Z',
trafficLimitBytes: 0,
trafficLimitStrategy: 'NO_RESET',
}),
},
);

console.log(created.response.shortUuid);

获取节点​

单个节点 —— 通过它的 uuid;列表 —— 无需参数:

const { response: node } = await api<{
response: { name: string; address: string; port: number | null; isConnected: boolean };
}>(`/api/nodes/${nodeUuid}`);

console.log(node.name, `${node.address}:${node.port}`, node.isConnected);

从哪里获取类型​

完整规范 —— 162 个路径和 29 个标签 —— 位于 API Specification 页面以及面板仓库的 static/openapi.json 文件中。 可以据此生成 .d.ts:

npx openapi-typescript ./openapi.json -o ./src/xlada-api.d.ts
提示

请从你实际部署的那个面板版本的规范生成类型:不同版本之间字段集合会 变化。

接下来​