Getting Started
前端集成
使用官方 TypeScript SDK 将前端连接到 RaisFast。
官方 SDK(@raisfast/sdk)是一个框架无关的 TypeScript 客户端,用于访问 RaisFast API。
安装
pnpm add @raisfast/sdk
# 或
npm install @raisfast/sdk
# 或
bun add @raisfast/sdk初始化
import { RaisFast } from "@raisfast/sdk";
const client = new RaisFast("http://localhost:9898/api/v1");构造函数接受可选的认证存储(默认使用 localStorage):
import { RaisFast, LocalAuthStore } from "@raisfast/sdk";
const store = new LocalAuthStore("my_auth_key");
const client = new RaisFast("http://localhost:9898/api/v1", { authStore: store });认证
// 登录
const result = await client.auth.login("admin@raisfast.dev", "admin123");
console.log(result.user, result.access_token);
// 注册
await client.auth.register({
email: "user@example.com",
password: "strongpassword",
username: "newuser",
});
// 获取当前用户
const me = await client.auth.getMe();
// 登出
await client.auth.logout();
// 监听认证状态变化
client.authStore.onChange((auth) => {
console.log("已登录:", !!auth?.token);
});收到 401 时自动刷新 Token — 无需手动处理。
查询内容类型
使用 client.collection() 访问任意内容类型:
// 访问 "portfolios" 内容类型
const portfolios = client.collection<Portfolio>("portfolios");
// 分页列表
const page1 = await portfolios.getList(1, 20);
console.log(page1.items); // Portfolio[]
console.log(page1.total); // 总数
// 带筛选、排序和关联填充的列表
const result = await portfolios.getList(1, 20, {
filter: 'status = "published"',
sort: "-created_at",
expand: "category,tags",
});
// 获取单条
const item = await portfolios.getOne("item_id");
// 按条件查询
const item = await portfolios.getFirstListItem('slug = "my-saas"');
// 获取全部(自动翻页)
const all = await portfolios.getFullList();数据操作
// 创建
const created = await portfolios.create({
title: "My SaaS App",
url: "https://mysaas.com",
tech_stack: ["Rust", "React"],
});
// 更新
const updated = await portfolios.update(created.id, {
url: "https://mysaas.app",
});
// 删除
await portfolios.delete(created.id);类型定义
定义与内容类型 Schema 匹配的接口:
interface Portfolio {
id: string;
title: string;
url?: string;
cover?: string;
description?: string;
tech_stack?: string[];
status: string;
created_at: string;
updated_at: string;
}
// 或从 CLI 生成类型
// raisfast ct types portfolio -o types/portfolio.ts在 React 中使用
import { RaisFast } from "@raisfast/sdk";
import { useEffect, useState } from "react";
const client = new RaisFast(import.meta.env.VITE_API_URL!);
function PortfolioList() {
const [items, setItems] = useState<any[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const portfolios = client.collection("portfolios");
portfolios
.getList(1, 20, { expand: "category,tags" })
.then((res) => setItems(res.items))
.finally(() => setLoading(false));
}, []);
if (loading) return <div>加载中...</div>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<h3>{item.title}</h3>
<p>{item.description}</p>
</li>
))}
</ul>
);
}在 Vue 中使用
<script setup>
import { RaisFast } from "@raisfast/sdk";
import { ref, onMounted } from "vue";
const client = new RaisFast(import.meta.env.VITE_API_URL!);
const items = ref([]);
const loading = ref(true);
onMounted(async () => {
const portfolios = client.collection("portfolios");
const res = await portfolios.getList(1, 20, { expand: "category,tags" });
items.value = res.items;
loading.value = false;
});
</script>
<template>
<div v-if="loading">加载中...</div>
<ul v-else>
<li v-for="item in items" :key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
</li>
</ul>
</template>在原生 JS 中使用
<script type="module">
import { RaisFast } from "@raisfast/sdk";
const client = new RaisFast("http://localhost:9898/api/v1");
const portfolios = client.collection("portfolios");
const { items } = await portfolios.getList(1, 20);
document.getElementById("list").innerHTML = items
.map((item) => `<li><h3>${item.title}</h3><p>${item.description}</p></li>`)
.join("");
</script>文件上传
const media = client.collection("portfolios");
// 上传文件
const fileInput = document.querySelector<HTMLInputElement>("#cover")!;
const file = fileInput.files![0];
await media.upload(portfolioId, file, "cover");Admin API
Admin 端点需要管理员认证:
// 列出所有内容类型 Schema
const schemas = await client.admin.contentTypes.list();
// 用户列表
const users = await client.admin.users.list(1, 20);
// 管理插件
const plugins = await client.admin.plugins.list();
await client.admin.plugins.reload("com.example.my-plugin");
// 仪表盘统计
const stats = await client.admin.stats.overview();错误处理
import { SDKError } from "@raisfast/sdk";
try {
await portfolios.getOne("invalid-id");
} catch (e) {
if (e instanceof SDKError) {
console.log(e.status); // 404
console.log(e.code); // 后端错误码
console.log(e.message); // "not found"
}
}实时事件 (SSE)
const es = client.events.subscribe();
es.addEventListener("post.created", (event) => {
console.log("新文章:", JSON.parse(event.data));
});
es.addEventListener("order.paid", (event) => {
console.log("订单已支付:", JSON.parse(event.data));
});
// 清理
es.close();多租户
client.setTenantId("tenant-123"); // 添加 X-Tenant-ID 请求头
client.setTenantId(null); // 重置