| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 5 个月前 | ||
| 2 天前 | ||
| 23 小时前 | ||
| 1 个月前 | ||
| 14 天前 | ||
| 7 个月前 | ||
| 1 个月前 |
@supabase/api
Generated Supabase Management API SDK built directly from the Supabase OpenAPI spec.
The package exposes:
@supabase/apifor the runtime-specific Promise client helpers plus generated contracts@supabase/api/effectfor the Effect-native versioned client plus generated contracts@supabase/api/openapi.jsonfor the raw generated OpenAPI documentopenApiOperationIdMapfor tools that need to join raw OpenAPI operation ids to SDK operation ids
Usage
import { createApiClient } from "@supabase/api";
const client = await createApiClient({ accessToken: "<token>" });
try {
const projects = await client.v1.listAllProjects();
const projectConfig = await client.v2.getProjectConfig({ ref: "<project-ref>" });
} finally {
await client.dispose();
}
Call dispose() when the client is no longer needed so its runtime and client-owned HTTP resources are released.
Operations are namespaced by version, derived from the leading path segment (/v1/... or
/v2/...). Same-named operations can coexist under separate namespaces: client.v1.listOrganizationMembers
and client.v2.listOrganizationMembers are distinct operations hitting /v1/... and /v2/...
respectively.
baseUrl defaults to https://api.supabase.com and accessToken can also come from
SUPABASE_ACCESS_TOKEN.
For Effect consumers:
import { Effect } from "effect";
import { makeApiClient } from "@supabase/api/effect";
const program = Effect.gen(function* () {
const client = yield* makeApiClient({ accessToken: "<token>" });
const projects = yield* client.v1.listAllProjects();
const projectConfig = yield* client.v2.getProjectConfig({ ref: "<project-ref>" });
return { projects, projectConfig };
});
If you want the package to resolve both values from the environment, you can omit the config entirely:
const client = await createApiClient();
Supported environment variables:
SUPABASE_API_URL(optional, defaults tohttps://api.supabase.com)SUPABASE_ACCESS_TOKEN(optional ifaccessTokenis passed explicitly)
The only callable client surface is the versioned namespace:
const projects = await client.v1.listAllProjects();
const projectConfig = await client.v2.getProjectConfig({ ref: "<project-ref>" });
For tools that need the raw generated spec:
import openApiSpec from "@supabase/api/openapi.json";
Binary request bodies
The SDK supports binary request inputs for the Management API routes that use raw eszip bodies or multipart file uploads.
The public binary input contract is:
Uint8ArrayArrayBufferBlob
Uint8Array is the canonical byte type. For the full internal contract and encoding rules, see docs/request-body-encoding.md.
Development
Repo-wide quality checks run from the repository root:
pnpm check:all
pnpm fix:all
Package-local checks and development commands run from packages/api:
pnpm types:check
pnpm test # Run tests
pnpm generate # Refresh the OpenAPI spec and regenerate the SDK
pnpm generate:check # Regenerate in place and fail on any resulting diff
Spec pipeline
The spec is built from two upstream OpenAPI documents, {baseUrl}/api/v1-json and
{baseUrl}/api/v2-json. They are fetched and merged into a single document (paths and
components.schemas are unioned, and info.title is normalized to Supabase API), then
overrides from scripts/openapi-overrides.json are applied to the merged document. The result is
validated — operation ids must be unique, and version-prefixed operation ids must match the
path's leading segment — before being written to src/generated/openapi.json. The merged
document keeps only the keys the generator consumes (openapi, info, paths,
components.schemas); upstream extras such as servers, tags, and components.securitySchemes
are dropped so the snapshot never contains keys a regeneration would remove.
The committed snapshot and the generated modules are also checked against each other offline in
ordinary test runs: scripts/generated-output-sync.unit.test.ts re-renders every generated file
from the committed snapshot and requires byte equality, and src/generated-contract-sync.unit.test.ts
asserts the operation-level bijection. Hand edits to src/generated fail both.
The base URL is resolved in this order:
SUPABASE_API_URLenvironment variablescripts/openapi-source.json, a committed sidecar file ({ "baseUrl": ... }) that is rewritten after every successfulpnpm generaterunhttps://api.supabase.com
To refresh from staging instead of production:
SUPABASE_API_URL=https://api.supabase.green pnpm generate
pnpm generate is the single command to regenerate the spec and SDK. pnpm generate:check
regenerates in place, formats, and fails if that produces any diff in src/generated or
scripts/openapi-source.json — useful for verifying the committed snapshot is still current. If a
failed check leaves an unwanted diff, discard it with:
git restore -- src/generated scripts/openapi-source.json
The hourly api-package-sync.yml workflow runs
generate against production and opens a PR against develop whenever it detects drift, acting
as the automated drift detector for the committed snapshot.
Overrides
scripts/openapi-overrides.json is a JSON-Patch-like array applied to the merged document. It
supports:
test— assert a value atpathbefore proceeding (as in RFC 6902)add— add a value atpath; throws if the key already existsreplace— replace the value atpathremove— remove the value atpathif present
remove is deliberately remove-if-present rather than RFC 6902's strict "must exist" semantics,
because the upstream documents differ between environments — staging's v2-json is currently
served by two backend variants that disagree about some paths. Entries may carry a $comment
field to document why an override exists.
deepObject query parameters
Several v2 list operations declare object-valued query parameters with style: deepObject
(page, filter). The client expands each own entry into its own param[key]=value pair, so
{ page: { size: 100, after: cursor } } reaches the wire as page[size]=100&page[after]=…. Every
object-valued query parameter in the spec is deepObject, so the expansion is applied to all of
them rather than driven by a per-parameter style recorded in the generated contract.