Skip to content

Commit 5a8e582

Browse files
committed
feat(core): expose defineAdapter via @supabase/server/core/adapters subpath
1 parent d94a774 commit 5a8e582

10 files changed

Lines changed: 26 additions & 15 deletions

File tree

jsr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
".": "./src/index.ts",
66
"./core": "./src/core/index.ts",
77
"./core/gates": "./src/core/gates/index.ts",
8+
"./core/adapters": "./src/core/adapters/index.ts",
89
"./adapters/hono": "./src/adapters/hono/index.ts",
910
"./adapters/h3": "./src/adapters/h3/index.ts",
1011
"./adapters/elysia": "./src/adapters/elysia/index.ts",

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@
3434
"import": "./dist/core/gates/index.mjs",
3535
"require": "./dist/core/gates/index.cjs"
3636
},
37+
"./core/adapters": {
38+
"types": "./dist/core/adapters/index.d.mts",
39+
"import": "./dist/core/adapters/index.mjs",
40+
"require": "./dist/core/adapters/index.cjs"
41+
},
3742
"./adapters/hono": {
3843
"types": "./dist/adapters/hono/index.d.mts",
3944
"import": "./dist/adapters/hono/index.mjs",

src/adapters/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Before you start, **read [`CONTRIBUTING.md`](../../CONTRIBUTING.md) and agree wi
2727
- **Tests for every auth mode.** Cover `'user'`, `'publishable'`, `'secret'`, `'none'`, the array form, and the failure paths (missing token, invalid JWT, missing apikey). The Hono adapter's [`hono/middleware.test.ts`](hono/middleware.test.ts) is the canonical reference — your test file should look structurally similar.
2828
- **Strict TypeScript.** No `any`, no `// @ts-ignore`. Public types must be exported from the adapter's `index.ts` so consumers can extend them.
2929
- **No new runtime dependencies** beyond the framework you're adapting. The framework itself goes in `peerDependencies` (and `peerDependenciesMeta` if optional). Don't pull in a wrapper, polyfill, or utility lib just to make the adapter shorter.
30-
- **Match the existing adapter shape.** Export `withSupabase` with two call forms — `withSupabase(config)` returning the framework's native middleware/plugin, and `withSupabase(config, handler)` returning a dual-mode route handler built via [`defineAdapter`](../core/define-adapter.ts) (see [Designing an adapter](#designing-an-adapter) below). Use `verifyAuth`, `createContextClient`, and `createAdminClient` from `@supabase/server/core` — never re-implement auth or env handling inside an adapter.
30+
- **Match the existing adapter shape.** Export `withSupabase` with two call forms — `withSupabase(config)` returning the framework's native middleware/plugin, and `withSupabase(config, handler)` returning a dual-mode route handler built via [`defineAdapter`](../core/adapters/define-adapter.ts) (see [Designing an adapter](#designing-an-adapter) below). Use `verifyAuth`, `createContextClient`, and `createAdminClient` from `@supabase/server/core` — never re-implement auth or env handling inside an adapter.
3131
- **Wire up the build outputs.** Add the adapter entry to `package.json#exports`, `jsr.json` (if applicable), and `tsdown.config.ts#entry` so it ships in the published artifact.
3232
- **Docs are required.** Add `docs/adapters/<name>.md` mirroring the structure of [`docs/adapters/hono.md`](../../docs/adapters/hono.md) — at minimum: setup, basic example, per-route auth, CORS note.
3333
- **Update both adapter tables.** Add a row to the table in this `src/adapters/README.md` _and_ the mirror table in the top-level [`README.md`](../../README.md). Keep the framework-version column accurate against `package.json#peerDependencies`. PRs that touch an existing adapter must update the version column if the peer-dep range changed.
@@ -58,7 +58,7 @@ Common contract every one-arg implementation must uphold:
5858

5959
`withSupabase(config, handler)` returns a dual-mode route handler that accepts either a `Request` (Web Fetch use) or the framework's native route input (`Context`, `H3Event`, Elysia args), extracts the underlying Request, and runs base `withSupabase` against it. Mountable directly via `app.all(path, withSupabase(config, handler))`.
6060

61-
Don't hand-roll this — [`defineAdapter`](../core/define-adapter.ts) encapsulates the entire dual-mode contract, including:
61+
Don't hand-roll this — [`defineAdapter`](../core/adapters/define-adapter.ts) (exported publicly as `@supabase/server/core/adapters`) encapsulates the entire dual-mode contract, including:
6262

6363
- Request extraction from the framework's native input.
6464
- `cors: false` forced on the base call (the framework owns CORS).
@@ -68,7 +68,11 @@ Don't hand-roll this — [`defineAdapter`](../core/define-adapter.ts) encapsulat
6868
Wire it up at the top of your adapter file:
6969

7070
```ts
71-
import { defineAdapter } from '../../core/define-adapter.js'
71+
// In-tree (bundled adapters in this repo):
72+
import { defineAdapter } from '../../core/adapters/index.js'
73+
74+
// Third-party adapter published as its own npm package:
75+
// import { defineAdapter } from '@supabase/server/core/adapters'
7276

7377
const adapterWithSupabase = defineAdapter<MyFrameworkContext>({
7478
name: 'my-framework',

src/adapters/elysia/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Elysia, type ExtractErrorFromHandle } from 'elysia'
22

33
import { createSupabaseContext } from '../../create-supabase-context.js'
4-
import { defineAdapter } from '../../core/define-adapter.js'
4+
import { defineAdapter } from '../../core/adapters/index.js'
55
import type { AuthError } from '../../errors.js'
66
import type { SupabaseContext, WithSupabaseConfig } from '../../types.js'
77

src/adapters/h3/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineMiddleware, HTTPError } from 'h3'
22
import type { H3Event, Middleware } from 'h3'
33

44
import { createSupabaseContext } from '../../create-supabase-context.js'
5-
import { defineAdapter } from '../../core/define-adapter.js'
5+
import { defineAdapter } from '../../core/adapters/index.js'
66
import type { SupabaseContext, WithSupabaseConfig } from '../../types.js'
77

88
const adapterWithSupabase = defineAdapter<H3Event>({

src/adapters/hono/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { HTTPException } from 'hono/http-exception'
33
import { createMiddleware } from 'hono/factory'
44

55
import { createSupabaseContext } from '../../create-supabase-context.js'
6-
import { defineAdapter } from '../../core/define-adapter.js'
6+
import { defineAdapter } from '../../core/adapters/index.js'
77
import type { SupabaseContext, WithSupabaseConfig } from '../../types.js'
88

99
const adapterWithSupabase = defineAdapter<Context>({
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { describe, expect, it, vi } from 'vitest'
22

3-
import { AuthError } from '../errors.js'
4-
import type { SupabaseContext, WithSupabaseConfig } from '../types.js'
3+
import { AuthError } from '../../errors.js'
4+
import type { SupabaseContext, WithSupabaseConfig } from '../../types.js'
55

66
import { defineAdapter } from './define-adapter.js'
77

88
const baseMock = vi.hoisted(() => ({ withSupabase: vi.fn() }))
9-
vi.mock('../with-supabase.js', () => baseMock)
9+
vi.mock('../../with-supabase.js', () => baseMock)
1010

1111
interface FakeContext {
1212
request: Request
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import type { AuthError } from '../errors.js'
2-
import type { SupabaseContext, WithSupabaseConfig } from '../types.js'
3-
import { withSupabase as baseWithSupabase } from '../with-supabase.js'
1+
import type { AuthError } from '../../errors.js'
2+
import type { SupabaseContext, WithSupabaseConfig } from '../../types.js'
3+
import { withSupabase as baseWithSupabase } from '../../with-supabase.js'
44

55
/**
66
* Spec for {@link defineAdapter}.
@@ -77,12 +77,11 @@ export interface AdapterSpec<NativeContext> {
7777
* adapter's responsibility; `defineAdapter` only covers the two-arg
7878
* form.
7979
*
80-
* @example
80+
* @example Third-party adapter package
8181
* ```ts
82-
* // adapters/hono/middleware.ts
8382
* import type { Context } from 'hono'
8483
* import { HTTPException } from 'hono/http-exception'
85-
* import { defineAdapter } from '../../core/define-adapter.js'
84+
* import { defineAdapter } from '@supabase/server/core/adapters'
8685
*
8786
* const adapterWithSupabase = defineAdapter<Context>({
8887
* name: 'hono',

src/core/adapters/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { defineAdapter, type AdapterSpec } from './define-adapter.js'

tsdown.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default defineConfig({
55
'src/index.ts',
66
'src/core/index.ts',
77
'src/core/gates/index.ts',
8+
'src/core/adapters/index.ts',
89
'src/adapters/hono/index.ts',
910
'src/adapters/h3/index.ts',
1011
'src/gates/feature-flag/index.ts',

0 commit comments

Comments
 (0)