一句话:访问后端有两条路。JavaScript SDK(从 https://lingcode.dev/sdk/lingcode-v1.js 加载)是主接口——data、auth、storage、functions、vector、push、telemetry、config 全都挂在同一个客户端上。它底下是一套朴素的 REST API,位于 https://lingcode.dev/api/cloud/be/<backend-id>/…,SDK 正是调用它——这里把它记录下来,供非 JS 客户端使用。
本页是扁平的速查参考。要理解「为什么」和看完整示例,请跟随各产品指南——每一节都在这里给出了链接。下面每一条签名都取自已发布的 SDK 类型定义;每一个端点都来自线上路由。
SDK 是单个零依赖文件。加载它,再用你后端的数据 URL 和公开的 anon key(匿名密钥)创建客户端(两者都在 lingcode.dev/backends → 你的后端 里获取)。在 /try 和 Mac 预览里,客户端已预先注入为 window.lingcode。
<script src="https://lingcode.dev/sdk/lingcode-v1.js"></script>
<script>
const lingcode = LingCode.createClient(url, anonKey, options?);
</script>
url: string —— 后端数据 URL,https://lingcode.dev/api/cloud/be/<backend-id>。anonKey: string —— 公开的 anon key(可以安全地放进浏览器里)。options.detectSessionInUrl?: boolean —— 默认 true;设为 false 可在构造时跳过从 URL 读取 ?lc_session/?lc_magic。返回一个 LingCodeClient:
| 成员 | 类型 | 说明 |
|---|---|---|
url | string | 后端数据 URL。 |
anonKey | string | 当前使用的 anon key。 |
backendId | string | 从 URL 解析出的后端 id。 |
ready | Promise<LingCodeClient> | 在 URL 中的任何认证跳转被消费后 resolve。加载时 await 一次。 |
from(table) | QueryBuilder | 开始一次数据查询。 |
auth · storage · functions · vector · push · telemetry · config | 命名空间 | 见下文。 |
每个异步的 data/auth/storage 调用都 resolve 为 { data, error } —— 在使用 data 之前先检查 error。失败时,error 是一个 LingCodeError,带 code: string | null(服务端错误码,如 "where_required" 或 "object_not_found")和 status: number(HTTP 状态码,客户端错误为 0)。
from(table) → QueryBuilder链式调用过滤器和修饰符,最后接一个终结操作。update() 和 delete() 必须带过滤器。完整指南:数据库。
| 方法 | 签名 | 说明 |
|---|---|---|
| eq · neq · gt · gte · lt · lte | (column, value) => this | 比较过滤器;多个之间为 AND。 |
| like · ilike | (column, value: string) => this | 子串匹配;ilike 不区分大小写。 |
| in | (column, values: any[]) => this | 成员归属。 |
| is | (column, null | "not_null") => this | IS NULL / IS NOT NULL。 |
| match | (filters: Record<string,any>) => this | 一次设置多个相等过滤器。 |
| order | (column, { ascending? }) => this | 排序。 |
| limit | (n: number) => this | 限制行数(每页 ≤ 200)。 |
| range | (from: number, to: number) => this | 按索引分页。 |
| select | () => Promise<Result<T[]>> | 读取。 |
| insert | (row | row[]) => Promise<Result<T[]>> | 创建。 |
| update | (patch) => Promise<Result<T[]>> | 必须带过滤器。 |
| delete | () => Promise<Result<T[]>> | 必须带过滤器。 |
| subscribe | (onChange, onError?) => Unsubscribe | 实时 INSERT/UPDATE/DELETE,按 RLS 过滤。参见 实时。 |
client.auth完整指南:认证。Session = { user: { id, email } | null, token }。
| 方法 | 签名 |
|---|---|
| signUp | ({ email, password }) => Promise<Result<Session>> |
| signIn · signInWithPassword | ({ email, password }) => Promise<Result<Session>> |
| signInWithOAuth | (provider: "google"|"github"|"apple"|string, { redirectTo? }) => void —— 顶层导航跳转;返回时自动存储 session。 |
| getProviders | () => Promise<Record<string, { available, source? }>> |
| sendMagicLink | ({ email, redirectTo? }) => Promise<Result<{ sent }>> |
| verifyMagicLink | (token) => Promise<Result<Session>> |
| sendOtp | ({ email }) => Promise<Result<{ sent }>> |
| verifyOtp | ({ email, code }) => Promise<Result<Session>> |
| getUser | () => User | null |
| getToken | () => string | null |
| lastError | () => string | null —— 上一次跳转返回的 OAuth 错误码。 |
| signOut | () => Promise<{ error: null }> |
client.storage.from(bucket)bucket 为 "public" 或 "private"。完整指南:存储。
| 方法 | 签名 |
|---|---|
| upload | (path, file: Blob|File|ArrayBuffer|string, { contentType? }) => Promise<Result<{ bucket, path, bytes, url }>> |
| download | (path) => Promise<Result<Blob>> |
| getPublicUrl | (path) => string |
| remove | (path) => Promise<Result<{ removed }>> |
client.functions完整指南:函数。
| 方法 | 签名 |
|---|---|
| invoke | <T>(slug: string, body?: any) => Promise<Result<T>> |
client.vector完整指南:向量检索。
| 方法 | 签名 |
|---|---|
| search | ({ table, column, embedding: number[], limit?, metric?: "cosine"|"l2"|"ip" }) => Promise<Result<T[]>> |
| embed | (input: string | string[]) => Promise<Result<{ embedding, embeddings, model, dimensions }>> |
client.push| 方法 | 签名 |
|---|---|
| isSupported | () => boolean |
| subscribe | ({ serviceWorker? }) => Promise<Result<any>> —— 注册 service worker + PushManager 订阅,然后将其存储。 |
client.telemetry| 方法 | 签名 |
|---|---|
| logEvent | (name, params?: Record<string, string|number|boolean>) => void |
| logScreen | (name) => void |
| trace | (name, ms: number) => void |
| recordError | (err: Error | { message?, stack? } | string) => void |
| setUserId | (id: string | null) => void |
| setUserProperties | (props) => void |
| flush | () => Promise<Result> |
client.config远程配置 + 实验变体。
| 成员 | 签名 |
|---|---|
| ready | Promise<ConfigApi> —— 在配置加载完成后 resolve。 |
| get | <T>(key, def?: T) => T |
| all | () => Record<string, any> |
SDK 调用的就是这些。你可以从任何非 JS 客户端直接使用它们。面向应用的数据平面,基础 URL 是 https://lingcode.dev/api/cloud/be/<backend-id>。
以 Authorization: Bearer <anon-key>(或 ?apikey=<anon-key>)发送 anon key,即可进行匿名、RLS-public 的访问。用户登录后,以 Authorization: Bearer <user-token> 发送其会话令牌,请求便以该用户身份运行。MFA、令牌刷新和登出端点需要用户令牌。
| 方法 | 路径 | 封装 |
|---|---|---|
| POST | /select | from().select() |
| POST | /insert | from().insert() |
| POST | /update | from().update()(必须带过滤器) |
| POST | /delete | from().delete()(必须带过滤器) |
请求体携带表名、过滤器以及行/补丁数据。运行时数据平面是表级 CRUD —— 不支持 JOIN,不支持 upsert,每页 ≤ 200 行(参见数据库)。
| 方法 | 路径 | 请求体 / 说明 |
|---|---|---|
| POST | /auth/signup | { email, password } |
| POST | /auth/signin | { email, password } |
| POST | /auth/magiclink/request | { email, redirect_url } |
| POST | /auth/magiclink/verify | { token } |
| POST | /auth/otp/request | { email } |
| POST | /auth/otp/verify | { email, code } |
| POST | /auth/apple/native | { identity_token } —— 原生 Apple 登录 |
| POST | /auth/token/refresh | { refresh_token } |
| POST | /auth/signout | { refresh_token } 或 { all: true } · 用户令牌 |
| POST | /auth/mfa/enroll | → { secret, qr_code } · 用户令牌 |
| POST | /auth/mfa/verify | { code } → AAL2 级别的 session · 用户令牌 |
| POST | /auth/mfa/challenge | 用户令牌 |
| GET | /auth/mfa/factors | 用户令牌 |
| DELETE | /auth/mfa/factors/:factorId | 用户令牌 |
| GET | /auth/providers | → { google, github, apple: { available, source } } |
| GET | /auth/oauth/:provider/start?redirect_url=… | 302 → provider 授权页 |
OAuth 在 GET/POST /api/cloud/auth/oauth/:provider/callback 完成,它会跳转回你的 redirect_url:成功时带 ?lc_session=<jwt>,失败时带 ?lc_error=<code>。
| 方法 | 路径 | 请求体 / 说明 |
|---|---|---|
| POST | /storage/upload | { bucket?, path, content_type?, data_b64 } → { bucket, path, bytes, url } |
| GET | /storage/object?bucket=…&path=… | 文件本身(公开对象会 302 跳转到 CDN) |
| POST | /storage/remove | { bucket?, path } |
| POST | /storage/create-upload-url | { bucket?, path, content_type? } → { uploadUrl, method:"PUT", headers, bucket, path } |
| POST | /storage/finalize | { bucket?, path } → { bucket, path, bytes, url } |
| 方法 | 路径 | 请求体 |
|---|---|---|
| POST | /vector/embed | { input } → { embedding, embeddings, model, dimensions } |
| POST | /vector/search | { table, column, embedding, limit?, metric? } |
| POST | /search/text | { table, column, query, is_tsvector?, limit? } |
| POST | /search/hybrid | { table, text_column, vector_column, query, embedding, … } |
| 方法 | 路径 | 请求体 |
|---|---|---|
| POST | /functions/:slug | { input? } → { ok, data } · 内置 + 自定义 |
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /realtime?table=foo,bar | SSE(text/event-stream);发出 event: change / data: { table, type, row };约 25s 一次心跳。参见实时。 |
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /push/vapid-public | → { key }(VAPID 公钥) |
| POST | /push/subscribe | { subscription } |
| POST | /telemetry | { events: [...] } |
| GET | /config?client_id=… | → 远程配置值 |
后端管理——密钥、函数源码、provider 配置、schema 迁移、用量——活在一棵单独的、由 owner 鉴权的路径树下(/api/cloud/account/backends/<backend-id>/…),由 lingcode.dev/backends 上的控制台驱动,而不是用公开的 anon key。上面那套面向应用的接口才是你从代码里调用的。