feat: add Elysia adapter#46
Conversation
commit: |
396ca1a to
2633af3
Compare
| class SupabaseAuthError extends Error { | ||
| status: number | ||
| constructor(message: string, status: number, cause: unknown) { | ||
| super(message, { cause }) | ||
| this.status = status | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
Good call! Renamed to SupabaseError.
The intent behind a wrapper class rather than throwing AuthError directly is to give Elysia consumers a single, stable discriminant in onError regardless of whether the failure was an auth error or an env misconfiguration.
There was a problem hiding this comment.
Uhmm so what about registering the original error classes instead of wrapping it?
new Elysia()
.error({
EnvError,
AuthError,
})There was a problem hiding this comment.
Good point! I tried throwing AuthError directly with .error({ AuthError }), but Elysia's error registry inside a scoped plugin doesn't propagate to the parent's onError at runtime, so code === 'AuthError' silently fails even though TS infers it correctly.
We could keep a thin SupabaseError wrapper but expose .code and .status directly on it (no .cause indirection). That way code discrimination still works idiomatically. Open to other suggestions!
There was a problem hiding this comment.
So if we pass the AuthError directly, one will check it in the elysia error hook like this:
import { AuthError } from '@supabase/server/errors'
app.onError(({ error, status }) => {
if (!(error instanceof AuthError)) return
return status(error.status as 401, {
error: error.message,
code: error.code,
})
})but if we create a thin wrapper and expose .code and .status:
app.onError(({ code, error, status }) => {
if (code !== 'SupabaseError') return
return status(error.status as 401, {
error: error.message,
code: error.code,
})
})2nd is more idiomatic to Elysia, no extra import, and the code string is the standard discriminant. The first works but bypasses Elysia's custom error system entirely
|
Thanks for contributing, |
|
@kallebysantos thanks for the thorough review. Resolved the comments! ❤️ |
What kind of change does this PR introduce?
Feature
What is the current behavior?
@supabase/serverships framework adapters for Hono and H3 / Nuxt, but not for Elysia. Users building APIs with Elysia have to wire up Supabase auth manually with the core primitives.What is the new behavior?
Adds
@supabase/server/adapters/elysia, a first-class plugin adapter for Elysia. Elysia has been gaining significant traction in the TypeScript ecosystem, particularly in the Bun community, for its end-to-end type safety and expressive plugin API.Usage with a plain Elysia app:
Per-route auth using scoped groups:
Custom error handling via Elysia's
onError:Additional context
.resolve()hook with.as('scoped')so the context propagates to parent app routes.SupabaseAuthError, which integrates with Elysia's standardonErrorflow and preserves the originalAuthErroronerror.cause.Consumers discriminate oncode === 'SupabaseAuthError'inonErrorwithout needing to import the class.