集成
两个 SDK 的框架级接线模式。TypeScript 部分涵盖 React、Next.js 和 Node.js;Python 部分涵盖 FastAPI、asyncio、Django 和 Celery。OTP 登录流程为两者均有记录。
凭证策略(api key vs access token、env vars),参阅身份验证和安装指南。
React (TypeScript)
单例客户端
在组件树外创建一次客户端并复用。localStorage 中的 token 来自 OTP 登录流程。
import { ImbraceClient } from "@imbrace/sdk";
export const client = new ImbraceClient({ accessToken: typeof window !== "undefined" ? (localStorage.getItem("imbrace_token") ?? undefined) : undefined,});数据获取 Hook
import { useState, useEffect } from "react";import { client } from "@/lib/imbrace";import type { Product } from "@imbrace/sdk";
export function useProducts(category?: string) { const [products, setProducts] = useState<Product[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null);
useEffect(() => { setLoading(true); client.marketplace .listProducts({ category }) .then((res) => setProducts(res.data)) .catch(setError) .finally(() => setLoading(false)); }, [category]);
return { products, loading, error };}import { useProducts } from "@/hooks/useProducts";
export function ProductList() { const { products, loading, error } = useProducts("electronics"); if (loading) return <p>加载中...</p>; if (error) return <p>错误:{error.message}</p>; return ( <ul> {products.map((p) => ( <li key={p.id}>{p.name} — {p.price} {p.currency}</li> ))} </ul> );}Next.js (TypeScript)
API 路由(App Router)
import { NextResponse } from "next/server";import { ImbraceClient } from "@imbrace/sdk";
const client = new ImbraceClient({ apiKey: process.env.IMBRACE_API_KEY,});
export async function GET(request: Request) { const { searchParams } = new URL(request.url); const category = searchParams.get("category") ?? undefined; const { data } = await client.marketplace.listProducts({ category }); return NextResponse.json(data);}
export async function POST(request: Request) { const body = await request.json(); const product = await client.marketplace.createProduct(body); return NextResponse.json(product, { status: 201 });}process.env.IMBRACE_API_KEY 应按你的部署平台的方式设置。参阅安装指南 → 配置凭证。
服务端组件(App Router)
import { ImbraceClient } from "@imbrace/sdk";
const client = new ImbraceClient({ apiKey: process.env.IMBRACE_API_KEY,});
export default async function ProductsPage() { const { data: products } = await client.marketplace.listProducts({ limit: 20 }); return ( <main> <h1>商品</h1> <ul>{products.map((p) => <li key={p.id}>{p.name}</li>)}</ul> </main> );}Node.js CLI 脚本 (TypeScript)
适用于一次性脚本(数据导出、回填、临时查询):
import { ImbraceClient } from "@imbrace/sdk";import { writeFileSync } from "fs";
const client = new ImbraceClient();
async function exportContacts() { const { data: contacts } = await client.contacts.list({ limit: 1000 }); writeFileSync("contacts.json", JSON.stringify(contacts, null, 2)); console.log(`已导出 ${contacts.length} 个联系人`);}
exportContacts().catch(console.error);npx ts-node scripts/export-contacts.tsFastAPI (Python)
Per-request 依赖注入
最简单的模式 — 每个请求一个 async client,由依赖项管理生命周期:
from fastapi import FastAPI, Dependsfrom imbrace import AsyncImbraceClient
app = FastAPI()
async def get_imbrace() -> AsyncImbraceClient: async with AsyncImbraceClient() as client: yield client
@app.get("/products")async def list_products(client: AsyncImbraceClient = Depends(get_imbrace)): result = await client.marketplace.list_products(limit=20) return result["data"]
@app.get("/products/{product_id}")async def get_product(product_id: str, client: AsyncImbraceClient = Depends(get_imbrace)): return await client.marketplace.get_product(product_id)
@app.post("/ai/chat")async def chat(message: str, client: AsyncImbraceClient = Depends(get_imbrace)): return await client.ai.complete( model="gpt-4o", messages=[{"role": "user", "content": message}], )全局单例(提高连接复用)
对于更高吞吐量,在应用程序生命周期内共享一个 client:
from contextlib import asynccontextmanagerfrom fastapi import FastAPIfrom imbrace import AsyncImbraceClient
imbrace: AsyncImbraceClient = None # type: ignore
@asynccontextmanagerasync def lifespan(app: FastAPI): global imbrace imbrace = AsyncImbraceClient() await imbrace.init() # 启动时健康检查 yield await imbrace.close()
app = FastAPI(lifespan=lifespan)
@app.get("/me")async def get_me(): return await imbrace.platform.get_me()asyncio (Python)
并发请求
import asynciofrom imbrace import AsyncImbraceClient
async def fetch_dashboard_data(): async with AsyncImbraceClient() as client: me, products, channels = await asyncio.gather( client.platform.get_me(), client.marketplace.list_products(limit=5), client.channel.list_channels(type="group"), ) return { "user": me, "products": products["data"], "channels": channels["data"], }
data = asyncio.run(fetch_dashboard_data())流式 AI
import asynciofrom imbrace import AsyncImbraceClient
async def stream_response(): async with AsyncImbraceClient() as client: async for chunk in client.ai.stream( model="gpt-4o", messages=[{"role": "user", "content": "解释 Python 中的 async/await。"}], ): content = chunk["choices"][0]["delta"].get("content", "") print(content, end="", flush=True)
asyncio.run(stream_response())Django (Python)
同步视图
from django.http import JsonResponsefrom imbrace import ImbraceClient, ApiError
def product_list(request): with ImbraceClient() as client: try: result = client.marketplace.list_products( category=request.GET.get("category"), page=int(request.GET.get("page", 1)), ) return JsonResponse(result) except ApiError as e: return JsonResponse({"error": str(e)}, status=e.status_code)Django 设置集成
IMBRACE_API_KEY = env("IMBRACE_API_KEY")IMBRACE_ENV = env("IMBRACE_ENV", default="stable")
# utils/imbrace.pyfrom django.conf import settingsfrom imbrace import ImbraceClient
def get_client() -> ImbraceClient: return ImbraceClient( api_key=settings.IMBRACE_API_KEY, env=settings.IMBRACE_ENV, )Celery (Python)
对于后台任务 workers,在每个 task 内部创建 client — 不要在 worker 之间共享:
from celery import Celeryfrom imbrace import ImbraceClient, NetworkError
app = Celery("tasks")
@app.task(bind=True, max_retries=3)def sync_products(self): try: with ImbraceClient() as client: result = client.marketplace.list_products(limit=100) for product in result["data"]: save_to_db(product) except NetworkError as exc: raise self.retry(exc=exc, countdown=2 ** self.request.retries)OTP 登录流程
OTP 流程在两个 SDK 中概念上相同:为邮箱请求 OTP,然后交换为 access token。参阅身份验证 → OTP 登录流程了解完整的凭证生命周期。
import { useState } from "react";import { ImbraceClient, AuthError } from "@imbrace/sdk";
const client = new ImbraceClient();
export function LoginForm() { const [email, setEmail] = useState(""); const [otp, setOtp] = useState(""); const [step, setStep] = useState<"email" | "otp">("email");
async function requestOtp() { await client.requestOtp(email); setStep("otp"); }
async function verifyOtp() { try { await client.loginWithOtp(email, otp); window.location.href = "/dashboard"; } catch (e) { if (e instanceof AuthError) alert("OTP 不正确"); } }
return step === "email" ? ( <div> <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="邮箱" /> <button onClick={requestOtp}>发送 OTP</button> </div> ) : ( <div> <input value={otp} onChange={(e) => setOtp(e.target.value)} placeholder="输入 OTP" /> <button onClick={verifyOtp}>确认</button> </div> );}from fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModelfrom imbrace import AsyncImbraceClient, AuthError
app = FastAPI()
class OtpRequest(BaseModel): email: str
class OtpVerify(BaseModel): email: str otp: str
@app.post("/auth/request-otp")async def request_otp(body: OtpRequest): async with AsyncImbraceClient() as client: await client.request_otp(body.email) return {"message": "OTP 已发送"}
@app.post("/auth/verify-otp")async def verify_otp(body: OtpVerify): async with AsyncImbraceClient() as client: try: await client.login_with_otp(body.email, body.otp) token = client._token_manager.get_token() return {"access_token": token} except AuthError: raise HTTPException(status_code=401, detail="OTP 不正确")