Files
supabase__server/docs/api-reference.md
T
Tomás Pozo 18818e0b5d Pre-v1 API cleanup: rename allow/authType/claims, narrow authKeyName, refresh adapter docs (#48)
* feat: rename `allow` config option to `auth`

Aligns the SDK with Supabase CLI terminology — `auth: 'user'` reads
more naturally than `allow: 'user'`. The legacy `allow` key still
works (with a one-time `console.warn` per process) and will be
removed in a future major release; when both `auth` and `allow` are
provided, `auth` wins. Also exports new `AuthMode` / `AuthModeWithKey`
types alongside deprecated `Allow` / `AllowWithKey` aliases.

* feat!: rename auth mode values `'always'` → `'none'` and `'public'` → `'publishable'`

Aligns auth-mode values with Supabase CLI terminology. `'none'` reads more
directly than `'always'` for "no authentication required", and
`'publishable'` matches the `SUPABASE_PUBLISHABLE_KEY(S)` env var names.
`'secret'` and `'user'` are unchanged.

BREAKING CHANGE: the `'always'` and `'public'` mode values no longer work.
Replace `auth: 'always'` with `auth: 'none'`, `auth: 'public'` with
`auth: 'publishable'`, and `auth: 'public:<name>'` with
`auth: 'publishable:<name>'`. Runtime checks like
`ctx.authType === 'public'` must be updated to
`ctx.authType === 'publishable'`.

* feat!: rename `authType` field to `authMode` on `AuthResult` and `SupabaseContext`

Lines the field name up with its type — `authMode: AuthMode`. Reads more
naturally for both humans and AI agents working with the API.

BREAKING CHANGE: the `authType` field was renamed to `authMode` on
`AuthResult` (returned by `verifyAuth` / `verifyCredentials`) and on
`SupabaseContext` (passed to handlers). Find-and-replace
`ctx.authType` → `ctx.authMode` and `auth.authType` → `auth.authMode`
across your codebase.

* feat!: rename `claims` field to `jwtClaims` on `AuthResult` and `SupabaseContext`

Pairs naturally with `userClaims` and makes the snake_case JWT payload
distinct from the normalized identity view at a glance.

* refactor!: narrow `SupabaseContext.authKeyName` to `string | undefined`

The field used to be `string | null | undefined` (optional + explicitly
nullable), forcing consumers to handle two absence values. Collapse to a
single representation by dropping `null`: the property is simply omitted
for `'user'` and `'none'` modes, which don't match a named key.

`AuthResult.keyName` keeps its `string | null` shape — it's the
low-level type where the field is always present and `null` actively
signals "no named key for this mode."

* docs: add publishable-key example to README quick start

The auth-modes table documented the publishable mode but the quick start
only showed user, none, secret, dual, and server-to-server examples,
leaving readers without a concrete shape for publishable. Slot it
between the "no auth" and "secret" examples so the progression reads
no key → publishable (anon, key-gated) → secret (admin, key-gated).

The example clarifies the resulting client behavior — `supabase` is
anonymous, RLS still applies, and the publishable key is a client gate
rather than a user identity — which is the most common point of
confusion vs. `auth: 'secret'`.

* docs: update skill description

* docs: update ssr references accross docs and skill

* docs(adapters): add ecosystem index + community contribution guide

Adds src/adapters/README.md (index, maintenance model, contribution
checklist) and docs/adapters/h3.md. Moves docs/hono-adapter.md into
docs/adapters/. Slims the top-level README Framework Adapters section
to a canonical adapter table + brief examples. Updates CONTRIBUTING.md,
docs/getting-started.md, and the supabase-server skill to reference the
new paths.

* docs: sweep adapter and SSR docs to use renamed API

The cherry-picked docs commits were authored before the API renames in
this branch, so the new content arrived using `allow:`, `'always'`,
`'public'`, `claims`, `authType`, and `AllowWithKey`. Update the
newly-arrived files in line with the renamed API:

- docs/adapters/h3.md — `allow:` → `auth:`, `claims, authType` →
  `jwtClaims, authMode` throughout
- docs/ssr-frameworks.md — composed Next.js adapter example now uses
  `auth:` / `AuthModeWithKey` / `jwtClaims` / `authMode`
- src/adapters/README.md — adapter-test checklist mentions the four
  current modes (`'user'`, `'publishable'`, `'secret'`, `'none'`)
- CONTRIBUTING.md — same wording fix in the adapter-PR section
- skills/supabase-server/SKILL.md — top-level skill description points
  at `auth:` and the new mode values; legacy patterns folded into the
  existing migration trigger
- src/adapters/hono/middleware.ts — inline comment example uses `auth:`
  in both halves rather than mixing legacy and current option names
- README.md — collapsed Hono and H3 quick-start snippets use `auth:`

Migration prose (`README.md` callout, `docs/auth-modes.md` callout,
`docs/api-reference.md` deprecated-aliases section, `SKILL.md`
migration callouts) intentionally still references the old names; they
document the migration itself.

* docs: reframe Beta disclaimer for v1 launch + extract MIGRATION.md

The Beta callout ("APIs and documentation may change") directly
contradicts the SemVer commitment that v1 makes. For launch material
that pins to v1, the contradiction undermines the stability message
the version number is meant to carry.

Replace it with a v1.0 callout that leads with stability under SemVer
and follows with honest "active development continues" framing — new
adapters and ergonomic improvements in minor releases, breaking
changes only ever in a major bump.

Move the v0 → v1 rename map out of the README and into a dedicated
MIGRATION.md. The README quick start was buried under 20+ lines of
migration tables that only matter to upgraders, not first-time
readers — exactly the wrong tradeoff at launch. New short callout
points upgraders at MIGRATION.md.

SKILL.md gets the same Beta → v1.0 swap. The agent-operational
migration rules (lines 12-14: "always emit `auth:` in new code", "the
new mode values are `'none'` / `'publishable'`") are kept inline —
they're rules the agent applies every time it writes code, not
user-facing migration steps, so they don't belong in MIGRATION.md.

* docs: reframe v1.0 callout as "Public Beta" to match Supabase house style

The previous "Stable under SemVer; active development continues" framing
mixed two distinct axes — code stability (SemVer) and product
lifecycle stage (Public Beta / GA) — into the SemVer line. Several
Supabase docs run those independently: a release can be v1+ in SemVer
terms and still labeled Public Beta in lifecycle terms.

Lead with both signals in the headline: "v1.0 — Public Beta." Keep the
SemVer commitment ("breaking changes only ship as a major bump") so
launch copy can pin to v1, and pair it with the Public Beta lifecycle
stage so readers know the product line is still early. Same swap in
the SKILL.md mirror.
2026-05-06 12:16:14 +03:00

8.4 KiB

API Reference

Complete reference for every export, organized by entry point.


@supabase/server

withSupabase

function withSupabase<Database = unknown>(
  config: WithSupabaseConfig,
  handler: (req: Request, ctx: SupabaseContext<Database>) => Promise<Response>,
): (req: Request) => Promise<Response>

Wraps a fetch handler with auth, CORS, and client creation. Returns a (req: Request) => Promise<Response> function suitable for export default { fetch }.

  • Handles OPTIONS preflight when CORS is enabled
  • Verifies credentials per config.auth
  • Returns JSON error response on auth failure
  • Adds CORS headers to all responses

createSupabaseContext

function createSupabaseContext<Database = unknown>(
  request: Request,
  options?: WithSupabaseConfig,
): Promise<
  | { data: SupabaseContext<Database>; error: null }
  | { data: null; error: AuthError }
>

Creates a SupabaseContext from a request. Returns a result tuple. The cors option is ignored.

Defaults to auth: 'user' when options is omitted.


@supabase/server/core

verifyAuth

function verifyAuth(
  request: Request,
  options: {
    auth?: AuthModeWithKey | AuthModeWithKey[]
    env?: Partial<SupabaseEnv>
  },
): Promise<{ data: AuthResult; error: null } | { data: null; error: AuthError }>

Extracts credentials from a request and verifies them. Convenience wrapper over extractCredentials + verifyCredentials.

verifyCredentials

function verifyCredentials(
  credentials: Credentials,
  options: {
    auth?: AuthModeWithKey | AuthModeWithKey[]
    env?: Partial<SupabaseEnv>
  },
): Promise<{ data: AuthResult; error: null } | { data: null; error: AuthError }>

Verifies pre-extracted credentials against allowed auth modes. Tries each mode in order — first match wins.

extractCredentials

function extractCredentials(request: Request): Credentials

Reads Authorization: Bearer <token> and apikey headers from a request. Pure extraction, no validation. Synchronous.

resolveEnv

function resolveEnv(
  overrides?: Partial<SupabaseEnv>,
): { data: SupabaseEnv; error: null } | { data: null; error: EnvError }

Resolves Supabase environment configuration from runtime variables. SUPABASE_URL is the only hard requirement.

createContextClient

function createContextClient<Database = unknown>(
  options?: CreateContextClientOptions,
): SupabaseClient<Database>

Creates a user-scoped Supabase client. RLS applies. Throws EnvError if URL or publishable key is missing.

Configured with:

  • Publishable key (named or default) as apikey header
  • User's JWT as Authorization: Bearer header (when auth.token is provided)
  • persistSession: false, autoRefreshToken: false, detectSessionInUrl: false

createAdminClient

function createAdminClient<Database = unknown>(
  options?: CreateAdminClientOptions,
): SupabaseClient<Database>

Creates an admin Supabase client that bypasses RLS. Throws EnvError if URL or secret key is missing.


@supabase/server/adapters/hono

withSupabase (Hono)

function withSupabase(
  config?: Omit<WithSupabaseConfig, 'cors'>,
): MiddlewareHandler

Hono middleware. Sets c.var.supabaseContext on the Hono context. Throws HTTPException on auth failure with cause: AuthError.

Skips if c.var.supabaseContext is already set (enables route-level overrides).

Defaults to auth: 'user' when config is omitted.


Types

AuthMode

type AuthMode = 'none' | 'publishable' | 'secret' | 'user'

AuthModeWithKey

type AuthModeWithKey = AuthMode | `publishable:${string}` | `secret:${string}`

Extended auth mode with named key support. Examples: 'publishable:web', 'secret:*', 'secret:internal'.

Allow / AllowWithKey (deprecated aliases)

Allow and AllowWithKey are kept as deprecated aliases for AuthMode and AuthModeWithKey. Prefer the Auth* names — the legacy ones will be removed in a future major release.

SupabaseContext<Database>

interface SupabaseContext<Database = unknown> {
  supabase: SupabaseClient<Database>
  supabaseAdmin: SupabaseClient<Database>
  userClaims: UserClaims | null
  jwtClaims: JWTClaims | null
  authMode: AuthMode
  authKeyName?: string
}

WithSupabaseConfig

interface WithSupabaseConfig {
  auth?: AuthModeWithKey | AuthModeWithKey[] // default: 'user'
  /** @deprecated use `auth` instead — will be removed in a future major release */
  allow?: AuthModeWithKey | AuthModeWithKey[]
  env?: Partial<SupabaseEnv>
  cors?: boolean | Record<string, string> // default: true
  supabaseOptions?: SupabaseClientOptions<string>
}

SupabaseEnv

interface SupabaseEnv {
  url: string
  publishableKeys: Record<string, string>
  secretKeys: Record<string, string>
  jwks: JsonWebKeySet | null
}

Credentials

interface Credentials {
  token: string | null
  apikey: string | null
}

AuthResult

interface AuthResult {
  authMode: AuthMode
  token: string | null
  userClaims: UserClaims | null
  jwtClaims: JWTClaims | null
  keyName?: string | null
}

JWTClaims

interface JWTClaims {
  sub: string
  iss?: string
  aud?: string | string[]
  exp?: number
  iat?: number
  role?: string
  email?: string
  app_metadata?: Record<string, unknown>
  user_metadata?: Record<string, unknown>
  [key: string]: unknown
}

UserClaims

interface UserClaims {
  id: string
  role?: string
  email?: string
  appMetadata?: Record<string, unknown>
  userMetadata?: Record<string, unknown>
}

ClientAuth

interface ClientAuth {
  token?: string | null
  keyName?: string | null
}

CreateContextClientOptions

interface CreateContextClientOptions {
  auth?: ClientAuth
  env?: Partial<SupabaseEnv>
  supabaseOptions?: SupabaseClientOptions<string>
}

CreateAdminClientOptions

interface CreateAdminClientOptions {
  auth?: Pick<ClientAuth, 'keyName'>
  env?: Partial<SupabaseEnv>
  supabaseOptions?: SupabaseClientOptions<string>
}

JsonWebKeySet

interface JsonWebKeySet {
  keys: JsonWebKey[]
}

Error Classes

EnvError

class EnvError extends Error {
  readonly status: 500
  readonly code: string
}

AuthError

class AuthError extends Error {
  readonly status: number // 401 or 500
  readonly code: string
}

Error Code Constants

Constant Value Class Meaning
EnvGenericError 'ENV_ERROR' EnvError Generic environment error
MissingSupabaseURLError 'MISSING_SUPABASE_URL' EnvError SUPABASE_URL not set
MissingPublishableKeyError 'MISSING_PUBLISHABLE_KEY' EnvError Named publishable key not found
MissingDefaultPublishableKeyError 'MISSING_DEFAULT_PUBLISHABLE_KEY' EnvError No default publishable key
MissingSecretKeyError 'MISSING_SECRET_KEY' EnvError Named secret key not found
MissingDefaultSecretKeyError 'MISSING_DEFAULT_SECRET_KEY' EnvError No default secret key
AuthGenericError 'AUTH_ERROR' AuthError Generic auth error
InvalidCredentialsError 'INVALID_CREDENTIALS' AuthError No credential matched, or JWT failed verification
CreateSupabaseClientError 'CREATE_SUPABASE_CLIENT_ERROR' AuthError Client creation failed after auth

Errors Factory Map

const Errors: {
  [MissingSupabaseURLError]: () => EnvError
  [MissingPublishableKeyError]: (name: string) => EnvError
  [MissingDefaultPublishableKeyError]: () => EnvError
  [MissingSecretKeyError]: (name: string) => EnvError
  [MissingDefaultSecretKeyError]: () => EnvError
  [InvalidCredentialsError]: () => AuthError
  [CreateSupabaseClientError]: () => AuthError
}

Keyed by error code constant. Each entry returns a pre-configured error instance.