@supabase/server 1.1.0-rc.64 → 1.1.0-rc.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -264,15 +264,58 @@ withSupabase(
264
264
 
265
265
  Adapters wrap `withSupabase` for a specific framework's middleware contract. They ship inside `@supabase/server`, so a single `npm install @supabase/server` covers the framework you're using — no separate package per adapter.
266
266
 
267
- > **Adapters are a community initiative.** Every adapter in this repo originated as a community contribution — Hono and H3 included. The Supabase team reviews PRs, runs security and regression triage, and ships releases; the original contributor is the de-facto domain expert for their adapter and the first responder on framework-version bumps. Want to add a new one? See [`src/adapters/README.md`](src/adapters/README.md) for the contribution requirements (tests, types, docs, build wiring).
267
+ > **Adapters are a community-driven initiative.** They're developed, maintained, and evolved by contributors including responding to upstream framework changes. See [`src/adapters/README.md`](src/adapters/README.md) for the contribution requirements (tests, types, docs, build wiring) if you'd like to add or help maintain one.
268
268
 
269
- | Framework | Import | Framework version | Docs |
270
- | --------- | -------------------------------- | ----------------- | ---------------------------------------------- |
271
- | Hono | `@supabase/server/adapters/hono` | `^4.0.0` | [docs/adapters/hono.md](docs/adapters/hono.md) |
272
- | H3 / Nuxt | `@supabase/server/adapters/h3` | `^2.0.0` | [docs/adapters/h3.md](docs/adapters/h3.md) |
269
+ | Framework | Import | Framework version | Docs |
270
+ | --------- | ---------------------------------- | ----------------- | -------------------------------------------------- |
271
+ | Hono | `@supabase/server/adapters/hono` | `^4.0.0` | [docs/adapters/hono.md](docs/adapters/hono.md) |
272
+ | H3 / Nuxt | `@supabase/server/adapters/h3` | `^2.0.0` | [docs/adapters/h3.md](docs/adapters/h3.md) |
273
+ | Elysia | `@supabase/server/adapters/elysia` | `^1.4.0` | [docs/adapters/elysia.md](docs/adapters/elysia.md) |
273
274
 
274
275
  See the per-adapter docs above for setup, per-route auth, CORS, error handling, and other patterns.
275
276
 
277
+ ### Elysia
278
+
279
+ ```ts
280
+ import { Elysia } from 'elysia'
281
+ import { withSupabase } from '@supabase/server/adapters/elysia'
282
+
283
+ const app = new Elysia()
284
+ // Protected — plugin resolves supabaseContext before handlers run
285
+ .use(withSupabase({ auth: 'user' }))
286
+ .get('/games', async ({ supabaseContext }) => {
287
+ const { data: myGames } = await supabaseContext.supabase
288
+ .from('favorite_games')
289
+ .select()
290
+ return myGames
291
+ })
292
+ // Public — no plugin means no auth
293
+ .get('/health', () => ({ status: 'ok' }))
294
+
295
+ app.listen(3000)
296
+ ```
297
+
298
+ For per-route auth, use scoped groups:
299
+
300
+ ```ts
301
+ import { Elysia } from 'elysia'
302
+ import { withSupabase } from '@supabase/server/adapters/elysia'
303
+
304
+ const app = new Elysia()
305
+ .get('/health', () => ({ status: 'ok' }))
306
+ .group('/api', (app) =>
307
+ app
308
+ .use(withSupabase({ auth: 'user' }))
309
+ .get('/profile', async ({ supabaseContext }) => {
310
+ return supabaseContext.userClaims
311
+ }),
312
+ )
313
+
314
+ app.listen(3000)
315
+ ```
316
+
317
+ The adapter does not handle CORS — use `@elysiajs/cors` for that.
318
+
276
319
  ## Primitives
277
320
 
278
321
  For when you need more control than `withSupabase` provides — multiple routes with different auth, custom response headers, or building your own wrapper.
@@ -407,7 +450,7 @@ For other environments, pass overrides via the `env` config option or `resolveEn
407
450
  | **Deno / Bun** | Works out of the box via `export default { fetch }`. |
408
451
  | **Node.js** | Use a [framework adapter](#framework-adapters) or [core primitives](#primitives) with your framework of choice. |
409
452
 
410
- Using a framework? See [Framework Adapters](#framework-adapters) for Hono and H3 / Nuxt, or [`docs/ssr-frameworks.md`](docs/ssr-frameworks.md) for Next.js / SvelteKit / Remix (compose with [`@supabase/ssr`](https://github.com/supabase/ssr)).
453
+ Using a framework? See [Framework Adapters](#framework-adapters) for Hono, H3 / Nuxt, and Elysia, or [`docs/ssr-frameworks.md`](docs/ssr-frameworks.md) for Next.js / SvelteKit / Remix (compose with [`@supabase/ssr`](https://github.com/supabase/ssr)).
411
454
 
412
455
  ### Does this replace `@supabase/ssr`?
413
456
 
@@ -415,12 +458,13 @@ No. `@supabase/ssr` handles cookie-based session management for frameworks like
415
458
 
416
459
  ## Exports
417
460
 
418
- | Export | What's in it |
419
- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
420
- | `@supabase/server` | `withSupabase`, `createSupabaseContext` |
421
- | `@supabase/server/core` | `verifyAuth`, `verifyCredentials`, `extractCredentials`, `createContextClient`, `createAdminClient`, `resolveEnv` |
422
- | `@supabase/server/adapters/hono` | `withSupabase` (Hono middleware) |
423
- | `@supabase/server/adapters/h3` | `withSupabase` (H3 / Nuxt middleware) |
461
+ | Export | What's in it |
462
+ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
463
+ | `@supabase/server` | `withSupabase`, `createSupabaseContext` |
464
+ | `@supabase/server/core` | `verifyAuth`, `verifyCredentials`, `extractCredentials`, `createContextClient`, `createAdminClient`, `resolveEnv` |
465
+ | `@supabase/server/adapters/hono` | `withSupabase` (Hono middleware) |
466
+ | `@supabase/server/adapters/h3` | `withSupabase` (H3 / Nuxt middleware) |
467
+ | `@supabase/server/adapters/elysia` | `withSupabase` (Elysia plugin) |
424
468
 
425
469
  ## Documentation
426
470
 
@@ -431,6 +475,7 @@ No. `@supabase/ssr` handles cookie-based session management for frameworks like
431
475
  | Which framework adapters exist? How do I contribute one? | [`src/adapters/README.md`](src/adapters/README.md) |
432
476
  | How do I use this with Hono? | [`docs/adapters/hono.md`](docs/adapters/hono.md) |
433
477
  | How do I use this with H3 / Nuxt? | [`docs/adapters/h3.md`](docs/adapters/h3.md) |
478
+ | How do I use this with Elysia? | [`docs/adapters/elysia.md`](docs/adapters/elysia.md) |
434
479
  | How do I use low-level primitives for custom flows? | [`docs/core-primitives.md`](docs/core-primitives.md) |
435
480
  | How do environment variables work across runtimes? | [`docs/environment-variables.md`](docs/environment-variables.md) |
436
481
  | How do I handle errors? What codes exist? | [`docs/error-handling.md`](docs/error-handling.md) |
@@ -0,0 +1,66 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_create_supabase_context = require('../../create-supabase-context-CKv-4AIg.cjs');
3
+ let elysia = require("elysia");
4
+
5
+ //#region src/adapters/elysia/plugin.ts
6
+ var SupabaseError = class extends Error {
7
+ constructor(inner) {
8
+ super(inner.message, { cause: inner });
9
+ this.status = inner.status;
10
+ }
11
+ };
12
+ /**
13
+ * Elysia plugin that creates a {@link SupabaseContext} and makes it available in route handlers.
14
+ *
15
+ * Skips if a previous plugin already set the context, enabling route-level overrides.
16
+ * Throws a `SupabaseError` on auth failure. `.status` is on the error directly; the original
17
+ * `AuthError` is available as the typed `.cause`. Discriminate in `onError` via `code === 'SupabaseError'`.
18
+ *
19
+ * @param config - Auth modes and optional environment overrides. CORS is excluded — use Elysia's CORS utilities.
20
+ * @returns An Elysia plugin that exposes `supabaseContext`.
21
+ *
22
+ * @example App-wide auth via `.use()`
23
+ * ```ts
24
+ * import { Elysia } from 'elysia'
25
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
26
+ *
27
+ * const app = new Elysia()
28
+ * .use(withSupabase({ allow: 'user' }))
29
+ * .get('/games', async ({ supabaseContext }) => {
30
+ * const { data } = await supabaseContext.supabase.from('favorite_games').select()
31
+ * return data
32
+ * })
33
+ *
34
+ * app.listen(3000)
35
+ * ```
36
+ *
37
+ * @example Per-route auth via scoped `.use()`
38
+ * ```ts
39
+ * import { Elysia } from 'elysia'
40
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
41
+ *
42
+ * const app = new Elysia()
43
+ * .get('/health', () => ({ status: 'ok' }))
44
+ * .group('/api', (app) =>
45
+ * app
46
+ * .use(withSupabase({ allow: 'user' }))
47
+ * .get('/profile', async ({ supabaseContext }) => {
48
+ * return supabaseContext.userClaims
49
+ * })
50
+ * )
51
+ *
52
+ * app.listen(3000)
53
+ * ```
54
+ */
55
+ function withSupabase(config) {
56
+ return new elysia.Elysia().error({ SupabaseError }).resolve(async (ctx) => {
57
+ const existing = ctx.supabaseContext;
58
+ if (existing) return { supabaseContext: existing };
59
+ const { data, error } = await require_create_supabase_context.createSupabaseContext(ctx.request, config);
60
+ if (error) throw new SupabaseError(error);
61
+ return { supabaseContext: data };
62
+ }).as("scoped");
63
+ }
64
+
65
+ //#endregion
66
+ exports.withSupabase = withSupabase;
@@ -0,0 +1,90 @@
1
+ import { t as AuthError } from "../../errors-fa-CyugW.cjs";
2
+ import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-CwKZOVIv.cjs";
3
+ import * as elysia from "elysia";
4
+ import { Elysia } from "elysia";
5
+
6
+ //#region src/adapters/elysia/plugin.d.ts
7
+ declare class SupabaseError extends Error {
8
+ status: number;
9
+ cause: AuthError;
10
+ constructor(inner: AuthError);
11
+ }
12
+ /**
13
+ * Elysia plugin that creates a {@link SupabaseContext} and makes it available in route handlers.
14
+ *
15
+ * Skips if a previous plugin already set the context, enabling route-level overrides.
16
+ * Throws a `SupabaseError` on auth failure. `.status` is on the error directly; the original
17
+ * `AuthError` is available as the typed `.cause`. Discriminate in `onError` via `code === 'SupabaseError'`.
18
+ *
19
+ * @param config - Auth modes and optional environment overrides. CORS is excluded — use Elysia's CORS utilities.
20
+ * @returns An Elysia plugin that exposes `supabaseContext`.
21
+ *
22
+ * @example App-wide auth via `.use()`
23
+ * ```ts
24
+ * import { Elysia } from 'elysia'
25
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
26
+ *
27
+ * const app = new Elysia()
28
+ * .use(withSupabase({ allow: 'user' }))
29
+ * .get('/games', async ({ supabaseContext }) => {
30
+ * const { data } = await supabaseContext.supabase.from('favorite_games').select()
31
+ * return data
32
+ * })
33
+ *
34
+ * app.listen(3000)
35
+ * ```
36
+ *
37
+ * @example Per-route auth via scoped `.use()`
38
+ * ```ts
39
+ * import { Elysia } from 'elysia'
40
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
41
+ *
42
+ * const app = new Elysia()
43
+ * .get('/health', () => ({ status: 'ok' }))
44
+ * .group('/api', (app) =>
45
+ * app
46
+ * .use(withSupabase({ allow: 'user' }))
47
+ * .get('/profile', async ({ supabaseContext }) => {
48
+ * return supabaseContext.userClaims
49
+ * })
50
+ * )
51
+ *
52
+ * app.listen(3000)
53
+ * ```
54
+ */
55
+ declare function withSupabase(config?: Omit<WithSupabaseConfig, 'cors'>): Elysia<"", {
56
+ decorator: {};
57
+ store: {};
58
+ derive: {};
59
+ resolve: {};
60
+ }, {
61
+ typebox: {};
62
+ error: {
63
+ readonly SupabaseError: SupabaseError;
64
+ };
65
+ }, {
66
+ schema: {};
67
+ standaloneSchema: {};
68
+ macro: {};
69
+ macroFn: {};
70
+ parser: {};
71
+ response: {};
72
+ }, {}, {
73
+ derive: {};
74
+ resolve: {
75
+ supabaseContext: SupabaseContext;
76
+ };
77
+ schema: {};
78
+ standaloneSchema: {};
79
+ response: elysia.ExtractErrorFromHandle<{
80
+ supabaseContext: SupabaseContext;
81
+ }>;
82
+ }, {
83
+ derive: {};
84
+ resolve: {};
85
+ schema: {};
86
+ standaloneSchema: {};
87
+ response: {};
88
+ }>;
89
+ //#endregion
90
+ export { withSupabase };
@@ -0,0 +1,90 @@
1
+ import { t as AuthError } from "../../errors-C43um2Gg.mjs";
2
+ import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-DbvLfq25.mjs";
3
+ import * as elysia from "elysia";
4
+ import { Elysia } from "elysia";
5
+
6
+ //#region src/adapters/elysia/plugin.d.ts
7
+ declare class SupabaseError extends Error {
8
+ status: number;
9
+ cause: AuthError;
10
+ constructor(inner: AuthError);
11
+ }
12
+ /**
13
+ * Elysia plugin that creates a {@link SupabaseContext} and makes it available in route handlers.
14
+ *
15
+ * Skips if a previous plugin already set the context, enabling route-level overrides.
16
+ * Throws a `SupabaseError` on auth failure. `.status` is on the error directly; the original
17
+ * `AuthError` is available as the typed `.cause`. Discriminate in `onError` via `code === 'SupabaseError'`.
18
+ *
19
+ * @param config - Auth modes and optional environment overrides. CORS is excluded — use Elysia's CORS utilities.
20
+ * @returns An Elysia plugin that exposes `supabaseContext`.
21
+ *
22
+ * @example App-wide auth via `.use()`
23
+ * ```ts
24
+ * import { Elysia } from 'elysia'
25
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
26
+ *
27
+ * const app = new Elysia()
28
+ * .use(withSupabase({ allow: 'user' }))
29
+ * .get('/games', async ({ supabaseContext }) => {
30
+ * const { data } = await supabaseContext.supabase.from('favorite_games').select()
31
+ * return data
32
+ * })
33
+ *
34
+ * app.listen(3000)
35
+ * ```
36
+ *
37
+ * @example Per-route auth via scoped `.use()`
38
+ * ```ts
39
+ * import { Elysia } from 'elysia'
40
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
41
+ *
42
+ * const app = new Elysia()
43
+ * .get('/health', () => ({ status: 'ok' }))
44
+ * .group('/api', (app) =>
45
+ * app
46
+ * .use(withSupabase({ allow: 'user' }))
47
+ * .get('/profile', async ({ supabaseContext }) => {
48
+ * return supabaseContext.userClaims
49
+ * })
50
+ * )
51
+ *
52
+ * app.listen(3000)
53
+ * ```
54
+ */
55
+ declare function withSupabase(config?: Omit<WithSupabaseConfig, 'cors'>): Elysia<"", {
56
+ decorator: {};
57
+ store: {};
58
+ derive: {};
59
+ resolve: {};
60
+ }, {
61
+ typebox: {};
62
+ error: {
63
+ readonly SupabaseError: SupabaseError;
64
+ };
65
+ }, {
66
+ schema: {};
67
+ standaloneSchema: {};
68
+ macro: {};
69
+ macroFn: {};
70
+ parser: {};
71
+ response: {};
72
+ }, {}, {
73
+ derive: {};
74
+ resolve: {
75
+ supabaseContext: SupabaseContext;
76
+ };
77
+ schema: {};
78
+ standaloneSchema: {};
79
+ response: elysia.ExtractErrorFromHandle<{
80
+ supabaseContext: SupabaseContext;
81
+ }>;
82
+ }, {
83
+ derive: {};
84
+ resolve: {};
85
+ schema: {};
86
+ standaloneSchema: {};
87
+ response: {};
88
+ }>;
89
+ //#endregion
90
+ export { withSupabase };
@@ -0,0 +1,65 @@
1
+ import { t as createSupabaseContext } from "../../create-supabase-context-BxSEJN8a.mjs";
2
+ import { Elysia } from "elysia";
3
+
4
+ //#region src/adapters/elysia/plugin.ts
5
+ var SupabaseError = class extends Error {
6
+ constructor(inner) {
7
+ super(inner.message, { cause: inner });
8
+ this.status = inner.status;
9
+ }
10
+ };
11
+ /**
12
+ * Elysia plugin that creates a {@link SupabaseContext} and makes it available in route handlers.
13
+ *
14
+ * Skips if a previous plugin already set the context, enabling route-level overrides.
15
+ * Throws a `SupabaseError` on auth failure. `.status` is on the error directly; the original
16
+ * `AuthError` is available as the typed `.cause`. Discriminate in `onError` via `code === 'SupabaseError'`.
17
+ *
18
+ * @param config - Auth modes and optional environment overrides. CORS is excluded — use Elysia's CORS utilities.
19
+ * @returns An Elysia plugin that exposes `supabaseContext`.
20
+ *
21
+ * @example App-wide auth via `.use()`
22
+ * ```ts
23
+ * import { Elysia } from 'elysia'
24
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
25
+ *
26
+ * const app = new Elysia()
27
+ * .use(withSupabase({ allow: 'user' }))
28
+ * .get('/games', async ({ supabaseContext }) => {
29
+ * const { data } = await supabaseContext.supabase.from('favorite_games').select()
30
+ * return data
31
+ * })
32
+ *
33
+ * app.listen(3000)
34
+ * ```
35
+ *
36
+ * @example Per-route auth via scoped `.use()`
37
+ * ```ts
38
+ * import { Elysia } from 'elysia'
39
+ * import { withSupabase } from '@supabase/server/adapters/elysia'
40
+ *
41
+ * const app = new Elysia()
42
+ * .get('/health', () => ({ status: 'ok' }))
43
+ * .group('/api', (app) =>
44
+ * app
45
+ * .use(withSupabase({ allow: 'user' }))
46
+ * .get('/profile', async ({ supabaseContext }) => {
47
+ * return supabaseContext.userClaims
48
+ * })
49
+ * )
50
+ *
51
+ * app.listen(3000)
52
+ * ```
53
+ */
54
+ function withSupabase(config) {
55
+ return new Elysia().error({ SupabaseError }).resolve(async (ctx) => {
56
+ const existing = ctx.supabaseContext;
57
+ if (existing) return { supabaseContext: existing };
58
+ const { data, error } = await createSupabaseContext(ctx.request, config);
59
+ if (error) throw new SupabaseError(error);
60
+ return { supabaseContext: data };
61
+ }).as("scoped");
62
+ }
63
+
64
+ //#endregion
65
+ export { withSupabase };
@@ -1,4 +1,4 @@
1
- import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-Bjy1j07i.cjs";
1
+ import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-CwKZOVIv.cjs";
2
2
  import { Middleware } from "h3";
3
3
 
4
4
  //#region src/adapters/h3/middleware.d.ts
@@ -1,4 +1,4 @@
1
- import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-DP9l5Cvf.mjs";
1
+ import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-DbvLfq25.mjs";
2
2
  import { Middleware } from "h3";
3
3
 
4
4
  //#region src/adapters/h3/middleware.d.ts
@@ -1,4 +1,4 @@
1
- import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-Bjy1j07i.cjs";
1
+ import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-CwKZOVIv.cjs";
2
2
  import { MiddlewareHandler } from "hono";
3
3
 
4
4
  //#region src/adapters/hono/middleware.d.ts
@@ -1,4 +1,4 @@
1
- import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-DP9l5Cvf.mjs";
1
+ import { d as SupabaseContext, m as WithSupabaseConfig } from "../../types-DbvLfq25.mjs";
2
2
  import { MiddlewareHandler } from "hono";
3
3
 
4
4
  //#region src/adapters/hono/middleware.d.ts
@@ -1,5 +1,5 @@
1
- import { a as AuthResult, c as CreateContextClientOptions, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, o as ClientAuth, s as CreateAdminClientOptions } from "../types-Bjy1j07i.cjs";
2
- import { i as EnvError, t as AuthError } from "../errors-CZFEYnV_.cjs";
1
+ import { i as EnvError, t as AuthError } from "../errors-fa-CyugW.cjs";
2
+ import { a as AuthResult, c as CreateContextClientOptions, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, o as ClientAuth, s as CreateAdminClientOptions } from "../types-CwKZOVIv.cjs";
3
3
  import { SupabaseClient } from "@supabase/supabase-js";
4
4
 
5
5
  //#region src/core/resolve-env.d.ts
@@ -1,5 +1,5 @@
1
- import { a as AuthResult, c as CreateContextClientOptions, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, o as ClientAuth, s as CreateAdminClientOptions } from "../types-DP9l5Cvf.mjs";
2
- import { i as EnvError, t as AuthError } from "../errors-0dbzn5gA.mjs";
1
+ import { i as EnvError, t as AuthError } from "../errors-C43um2Gg.mjs";
2
+ import { a as AuthResult, c as CreateContextClientOptions, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, o as ClientAuth, s as CreateAdminClientOptions } from "../types-DbvLfq25.mjs";
3
3
  import { SupabaseClient } from "@supabase/supabase-js";
4
4
 
5
5
  //#region src/core/resolve-env.d.ts
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as AuthResult, c as CreateContextClientOptions, d as SupabaseContext, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, m as WithSupabaseConfig, n as AllowWithKey, o as ClientAuth, p as UserClaims, r as AuthMode, s as CreateAdminClientOptions, t as Allow, u as JWTClaims } from "./types-Bjy1j07i.cjs";
2
- import { a as EnvGenericError, c as MissingDefaultPublishableKeyError, d as MissingSecretKeyError, f as MissingSupabaseURLError, i as EnvError, l as MissingDefaultSecretKeyError, n as AuthGenericError, o as Errors, r as CreateSupabaseClientError, s as InvalidCredentialsError, t as AuthError, u as MissingPublishableKeyError } from "./errors-CZFEYnV_.cjs";
1
+ import { a as EnvGenericError, c as MissingDefaultPublishableKeyError, d as MissingSecretKeyError, f as MissingSupabaseURLError, i as EnvError, l as MissingDefaultSecretKeyError, n as AuthGenericError, o as Errors, r as CreateSupabaseClientError, s as InvalidCredentialsError, t as AuthError, u as MissingPublishableKeyError } from "./errors-fa-CyugW.cjs";
2
+ import { a as AuthResult, c as CreateContextClientOptions, d as SupabaseContext, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, m as WithSupabaseConfig, n as AllowWithKey, o as ClientAuth, p as UserClaims, r as AuthMode, s as CreateAdminClientOptions, t as Allow, u as JWTClaims } from "./types-CwKZOVIv.cjs";
3
3
 
4
4
  //#region src/with-supabase.d.ts
5
5
  /**
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as AuthResult, c as CreateContextClientOptions, d as SupabaseContext, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, m as WithSupabaseConfig, n as AllowWithKey, o as ClientAuth, p as UserClaims, r as AuthMode, s as CreateAdminClientOptions, t as Allow, u as JWTClaims } from "./types-DP9l5Cvf.mjs";
2
- import { a as EnvGenericError, c as MissingDefaultPublishableKeyError, d as MissingSecretKeyError, f as MissingSupabaseURLError, i as EnvError, l as MissingDefaultSecretKeyError, n as AuthGenericError, o as Errors, r as CreateSupabaseClientError, s as InvalidCredentialsError, t as AuthError, u as MissingPublishableKeyError } from "./errors-0dbzn5gA.mjs";
1
+ import { a as EnvGenericError, c as MissingDefaultPublishableKeyError, d as MissingSecretKeyError, f as MissingSupabaseURLError, i as EnvError, l as MissingDefaultSecretKeyError, n as AuthGenericError, o as Errors, r as CreateSupabaseClientError, s as InvalidCredentialsError, t as AuthError, u as MissingPublishableKeyError } from "./errors-C43um2Gg.mjs";
2
+ import { a as AuthResult, c as CreateContextClientOptions, d as SupabaseContext, f as SupabaseEnv, i as AuthModeWithKey, l as Credentials, m as WithSupabaseConfig, n as AllowWithKey, o as ClientAuth, p as UserClaims, r as AuthMode, s as CreateAdminClientOptions, t as Allow, u as JWTClaims } from "./types-DbvLfq25.mjs";
3
3
 
4
4
  //#region src/with-supabase.d.ts
5
5
  /**
@@ -0,0 +1,140 @@
1
+ # Elysia Adapter
2
+
3
+ ## Setup
4
+
5
+ Install Elysia as a peer dependency:
6
+
7
+ ```bash
8
+ pnpm add elysia
9
+ ```
10
+
11
+ The adapter exports its own `withSupabase` that returns an Elysia plugin instead of a fetch handler.
12
+
13
+ ## Basic app with auth
14
+
15
+ ```ts
16
+ import { Elysia } from 'elysia'
17
+ import { withSupabase } from '@supabase/server/adapters/elysia'
18
+
19
+ const app = new Elysia()
20
+ .use(withSupabase({ auth: 'user' }))
21
+ .get('/todos', async ({ supabaseContext }) => {
22
+ const { data } = await supabaseContext.supabase.from('todos').select()
23
+ return data
24
+ })
25
+
26
+ app.listen(3000)
27
+ ```
28
+
29
+ The context is available as `supabaseContext` in your route handlers and contains the same `SupabaseContext` fields as the main `withSupabase` wrapper: `supabase`, `supabaseAdmin`, `userClaims`, `jwtClaims`, and `authMode`.
30
+
31
+ ## Per-route auth
32
+
33
+ Apply different auth modes to different routes by using the plugin on scoped route groups:
34
+
35
+ ```ts
36
+ import { Elysia } from 'elysia'
37
+ import { withSupabase } from '@supabase/server/adapters/elysia'
38
+
39
+ const app = new Elysia()
40
+ // Public route — no auth
41
+ .get('/health', () => ({ status: 'ok' }))
42
+ // User-authenticated routes
43
+ .group('/api', (app) =>
44
+ app
45
+ .use(withSupabase({ auth: 'user' }))
46
+ .get('/todos', async ({ supabaseContext }) => {
47
+ const { data } = await supabaseContext.supabase.from('todos').select()
48
+ return data
49
+ }),
50
+ )
51
+ // Secret-key-protected admin routes
52
+ .group('/admin', (app) =>
53
+ app
54
+ .use(withSupabase({ auth: 'secret' }))
55
+ .post('/sync', async ({ supabaseContext }) => {
56
+ const { data } = await supabaseContext.supabaseAdmin
57
+ .from('audit_log')
58
+ .insert({ action: 'sync' })
59
+ return data
60
+ }),
61
+ )
62
+
63
+ app.listen(3000)
64
+ ```
65
+
66
+ ## Skip behavior
67
+
68
+ If a previous plugin already resolved `supabaseContext`, subsequent `withSupabase` calls skip auth. This allows chaining plugins without redundant work.
69
+
70
+ **Important:** The plugin calls `.as('scoped')` so its `resolve` hook propagates one level up to the parent app — routes registered after `.use(withSupabase(...))` will see `supabaseContext`. The skip-if-set pattern cannot make a route stricter than an already-resolved context.
71
+
72
+ For routes that need different auth than the rest of the app, use scoped `.group()` with `.use(withSupabase(...))` without an app-wide plugin (see the "Per-route auth" section above).
73
+
74
+ ## CORS
75
+
76
+ The Elysia adapter does not handle CORS — the `cors` option is excluded from its config type. Use Elysia's CORS plugin:
77
+
78
+ ```ts
79
+ import { Elysia } from 'elysia'
80
+ import { cors } from '@elysiajs/cors'
81
+ import { withSupabase } from '@supabase/server/adapters/elysia'
82
+
83
+ const app = new Elysia()
84
+ .use(cors())
85
+ .use(withSupabase({ auth: 'user' }))
86
+ .get('/todos', async ({ supabaseContext }) => {
87
+ const { data } = await supabaseContext.supabase.from('todos').select()
88
+ return data
89
+ })
90
+
91
+ app.listen(3000)
92
+ ```
93
+
94
+ ## Error handling
95
+
96
+ When auth fails, the plugin throws a `SupabaseError`. The HTTP status is on `.status` directly, and the original `AuthError` is available as the typed `.cause`. Discriminate in `onError` via `code === 'SupabaseError'`:
97
+
98
+ ```ts
99
+ import { Elysia } from 'elysia'
100
+ import { withSupabase } from '@supabase/server/adapters/elysia'
101
+
102
+ const app = new Elysia()
103
+ .use(withSupabase({ auth: 'user' }))
104
+ .onError(({ code, error, status }) => {
105
+ if (code !== 'SupabaseError') return
106
+ return status(error.status as 401, {
107
+ error: error.message,
108
+ code: error.cause.code,
109
+ })
110
+ })
111
+ .get('/todos', async ({ supabaseContext }) => {
112
+ const { data } = await supabaseContext.supabase.from('todos').select()
113
+ return data
114
+ })
115
+
116
+ app.listen(3000)
117
+ ```
118
+
119
+ Without a custom `onError`, Elysia uses the `status` property on the thrown `SupabaseError` to set the response status automatically (401 for auth failures, 500 for internal errors).
120
+
121
+ ## Environment overrides
122
+
123
+ Pass `env` to override auto-detected environment variables, same as the main wrapper:
124
+
125
+ ```ts
126
+ app.use(withSupabase({ auth: 'user', env: { url: 'http://localhost:54321' } }))
127
+ ```
128
+
129
+ ## Supabase client options
130
+
131
+ Forward options to the underlying `createClient()` calls:
132
+
133
+ ```ts
134
+ app.use(
135
+ withSupabase({
136
+ auth: 'user',
137
+ supabaseOptions: { db: { schema: 'api' } },
138
+ }),
139
+ )
140
+ ```
@@ -134,6 +134,38 @@ Defaults to `auth: 'user'` when config is omitted.
134
134
 
135
135
  ---
136
136
 
137
+ ## @supabase/server/adapters/h3
138
+
139
+ ### withSupabase (H3)
140
+
141
+ ```ts
142
+ function withSupabase(config?: Omit<WithSupabaseConfig, 'cors'>): Middleware
143
+ ```
144
+
145
+ H3 middleware. Sets `event.context.supabaseContext` on the H3 event. Throws `HTTPError` on auth failure with `cause: AuthError`.
146
+
147
+ Skips if `event.context.supabaseContext` is already set (enables chained middleware).
148
+
149
+ Defaults to `auth: 'user'` when config is omitted.
150
+
151
+ ---
152
+
153
+ ## @supabase/server/adapters/elysia
154
+
155
+ ### withSupabase (Elysia)
156
+
157
+ ```ts
158
+ function withSupabase(config?: Omit<WithSupabaseConfig, 'cors'>): Elysia
159
+ ```
160
+
161
+ Elysia plugin that resolves `supabaseContext` into the request context. Throws an error on auth failure with `cause: AuthError`.
162
+
163
+ Skips if `supabaseContext` is already resolved by a prior plugin.
164
+
165
+ Defaults to `auth: 'user'` when config is omitted.
166
+
167
+ ---
168
+
137
169
  ## Types
138
170
 
139
171
  ### AuthMode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supabase/server",
3
- "version": "1.1.0-rc.64",
3
+ "version": "1.1.0-rc.65",
4
4
  "description": "Server-side utilities for Supabase. Handles auth, client creation, and context injection so you write business logic, not boilerplate.",
5
5
  "keywords": [
6
6
  "edge",
@@ -39,6 +39,11 @@
39
39
  "import": "./dist/adapters/h3/index.mjs",
40
40
  "require": "./dist/adapters/h3/index.cjs"
41
41
  },
42
+ "./adapters/elysia": {
43
+ "types": "./dist/adapters/elysia/index.d.mts",
44
+ "import": "./dist/adapters/elysia/index.mjs",
45
+ "require": "./dist/adapters/elysia/index.cjs"
46
+ },
42
47
  "./package.json": "./package.json"
43
48
  },
44
49
  "main": "./dist/index.cjs",
@@ -72,7 +77,8 @@
72
77
  "peerDependencies": {
73
78
  "@supabase/supabase-js": "^2.0.0",
74
79
  "h3": "^2.0.0",
75
- "hono": "^4.0.0"
80
+ "hono": "^4.0.0",
81
+ "elysia": "^1.4.0"
76
82
  },
77
83
  "peerDependenciesMeta": {
78
84
  "h3": {
@@ -80,6 +86,9 @@
80
86
  },
81
87
  "hono": {
82
88
  "optional": true
89
+ },
90
+ "elysia": {
91
+ "optional": true
83
92
  }
84
93
  },
85
94
  "devDependencies": {
@@ -87,6 +96,7 @@
87
96
  "@commitlint/config-conventional": "^20.4.2",
88
97
  "@supabase/supabase-js": "^2.105.4",
89
98
  "eslint": "^10.0.2",
99
+ "elysia": "^1.4.0",
90
100
  "h3": "2.0.1-rc.20",
91
101
  "hono": "^4.12.5",
92
102
  "prettier": "3.8.1",