diff --git a/docs/adapters/h3.md b/docs/adapters/h3.md index aba4fc9..c45563c 100644 --- a/docs/adapters/h3.md +++ b/docs/adapters/h3.md @@ -10,6 +10,20 @@ pnpm add h3 The adapter exports its own `withSupabase` that returns H3 middleware instead of a fetch handler. Works with standalone H3 servers and Nuxt server routes (which run on H3 under the hood). +## Typing `event.context.supabaseContext` + +The middleware stores the context on `event.context.supabaseContext`. Add this declaration once in your project (e.g. in `types/h3.d.ts`) for typed access: + +```ts +import type { SupabaseContext } from '@supabase/server' + +declare module 'h3' { + interface H3EventContext { + supabaseContext: SupabaseContext + } +} +``` + ## Basic app with auth ```ts diff --git a/src/adapters/elysia/index.ts b/src/adapters/elysia/index.ts index 9b61794..b1f6e13 100644 --- a/src/adapters/elysia/index.ts +++ b/src/adapters/elysia/index.ts @@ -4,4 +4,4 @@ * @packageDocumentation */ -export { withSupabase } from './plugin.js' +export { SupabaseError, withSupabase } from './plugin.js' diff --git a/src/adapters/elysia/plugin.ts b/src/adapters/elysia/plugin.ts index 4c017af..846b59f 100644 --- a/src/adapters/elysia/plugin.ts +++ b/src/adapters/elysia/plugin.ts @@ -1,10 +1,10 @@ -import { Elysia } from 'elysia' +import { Elysia, type ExtractErrorFromHandle } from 'elysia' import { createSupabaseContext } from '../../create-supabase-context.js' import type { AuthError } from '../../errors.js' import type { SupabaseContext, WithSupabaseConfig } from '../../types.js' -class SupabaseError extends Error { +export class SupabaseError extends Error { status: number declare cause: AuthError constructor(inner: AuthError) { @@ -56,7 +56,39 @@ class SupabaseError extends Error { * app.listen(3000) * ``` */ -export function withSupabase(config?: Omit) { +// The explicit return type below mirrors Elysia's own generic defaults, which use +// `{}` literals — switching to `object` or `Record` would not satisfy +// the corresponding generic constraints. +/* eslint-disable @typescript-eslint/no-empty-object-type */ +export function withSupabase(config?: Omit): Elysia< + '', + { decorator: {}; store: {}; derive: {}; resolve: {} }, + { typebox: {}; error: { readonly SupabaseError: SupabaseError } }, + { + schema: {} + standaloneSchema: {} + macro: {} + macroFn: {} + parser: {} + response: {} + }, + {}, + { + derive: {} + resolve: { supabaseContext: SupabaseContext } + schema: {} + standaloneSchema: {} + response: ExtractErrorFromHandle<{ supabaseContext: SupabaseContext }> + }, + { + derive: {} + resolve: {} + schema: {} + standaloneSchema: {} + response: {} + } +> { + /* eslint-enable @typescript-eslint/no-empty-object-type */ return new Elysia() .error({ SupabaseError }) .resolve(async (ctx): Promise<{ supabaseContext: SupabaseContext }> => { diff --git a/src/adapters/h3/middleware.test.ts b/src/adapters/h3/middleware.test.ts index 00eb53c..d5c7e7d 100644 --- a/src/adapters/h3/middleware.test.ts +++ b/src/adapters/h3/middleware.test.ts @@ -1,8 +1,16 @@ import { H3, HTTPError, onError } from 'h3' import { describe, expect, it } from 'vitest' +import type { SupabaseContext } from '../../types.js' + import { withSupabase } from './middleware.js' +declare module 'h3' { + interface H3EventContext { + supabaseContext: SupabaseContext + } +} + describe('h3 supabase middleware', () => { const env = { url: 'https://test.supabase.co', diff --git a/src/adapters/h3/middleware.ts b/src/adapters/h3/middleware.ts index 2aad16e..168a754 100644 --- a/src/adapters/h3/middleware.ts +++ b/src/adapters/h3/middleware.ts @@ -47,18 +47,13 @@ export function withSupabase( config?: Omit, ): Middleware { return defineMiddleware(async (event, next) => { - if (event.context.supabaseContext) return next() + const context = event.context as { supabaseContext?: SupabaseContext } + if (context.supabaseContext) return next() const { data: ctx, error } = await createSupabaseContext(event.req, config) if (error) { throw new HTTPError(error.message, { status: error.status, cause: error }) } - event.context.supabaseContext = ctx + context.supabaseContext = ctx return next() }) } - -declare module 'h3' { - interface H3EventContext { - supabaseContext: SupabaseContext - } -}