Backend

Supabase

Explain the fetcher mapping and auth integration in @ginjou/with-supabase.

@ginjou/with-supabase provides a Ginjou fetcher and a Ginjou auth provider for Supabase.

Most apps pass the same Supabase client to both.

It does not change the higher-level Ginjou API. It only connects those hooks to the Supabase JavaScript client.

Installation

Install @supabase/supabase-js together with the adapter.

pnpm add @ginjou/with-supabase @supabase/supabase-js
PackageSupported version
@supabase/supabase-js^2.7.0

Fetcher

Use createFetcher() with a Supabase client.

PropRequiredMeaning
clientYesA Supabase client instance.

Register it through defineFetchersContext().

import { defineFetchersContext } from '@ginjou/vue'
import { createFetcher } from '@ginjou/with-supabase'
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
    'https://your-project.supabase.co',
    'your-anon-key',
)

defineFetchersContext({
    default: createFetcher({ client: supabase }),
})
Support levelMethods
ImplementedgetList, getMany, getOne, createOne, createMany, updateOne, deleteOne
Not implementedcustom, updateMany, deleteMany

Pagination

List pagination uses Supabase range().

Ginjou inputSupabase behavior
pagination.currentUsed to calculate the starting row
pagination.perPageUsed to calculate the ending row

The adapter calls:

Range argumentValue
from(current - 1) * perPage
tocurrent * perPage - 1

For totals, getList() uses Supabase count mode from meta.count and returns count || 0.

Filters

The adapter maps Ginjou filters to Supabase PostgREST filter helpers.

Ginjou operatorSupabase behavior
eqeq(field, value)
neneq(field, value)
inin(field, value)
gtgt(field, value)
gtegte(field, value)
ltlt(field, value)
ltelte(field, value)
containsilike(field, %value%)
containsslike(field, %value%)
nullis(field, null)
startswithilike(field, value%)
endswithilike(field, %value)
oror(...) with joined logical clauses

These operators use the generic filter() fallback.

Ginjou operatorGeneric fallback operator
ninnot.in
ncontainsnot.ilike
ncontainssnot.like
nnullnot.is

These operators are not supported and throw instead of being translated.

OperatorBehavior
andThrows an error
betweenThrows an error
nbetweenThrows an error

Sorters

Sorters are applied through Supabase order().

Normal fields use order(field, { ascending }).

Related table fields can use dot notation.

Ginjou sorterSupabase behavior
{ field: 'title', order: 'asc' }order('title', { ascending: true })
{ field: 'profile.name', order: 'desc' }order('name', { ascending: false, foreignTable: 'profile' })

When dot notation is used, the adapter also expands the select string so Supabase can order through the related table.

Meta

These meta fields are verified in the adapter.

Meta fieldUsed byDefaultPurpose
selectAll fetcher methods'*' where applicablePostgREST select expression
countgetList'exact'Count strategy for pagination total
idColumnNamegetMany, getOne, updateOne, deleteOne'id'Custom primary key column

Use meta.idColumnName when the record key is not stored in an id column.

import { useGetOne } from '@ginjou/vue'

useGetOne({
    resource: 'orders',
    id: 'order-001',
    meta: {
        idColumnName: 'order_id',
    },
})

Use meta.select to control the returned columns and relations.

import { useGetList } from '@ginjou/vue'

useGetList({
    resource: 'posts',
    meta: {
        select: 'id,title,author:users(id,name)',
    },
})

Use meta.count to choose the Supabase count mode for getList().

import { useGetList } from '@ginjou/vue'

useGetList({
    resource: 'posts',
    meta: {
        count: 'planned',
    },
})

Auth

Use createAuth() with the same Supabase client.

Most apps reuse the client they already passed to createFetcher().

Register it through defineAuthContext().

import { defineAuthContext } from '@ginjou/vue'
import { createAuth } from '@ginjou/with-supabase'
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
    'https://your-project.supabase.co',
    'your-anon-key',
)

defineAuthContext(createAuth({ client: supabase }))

Login

login() dispatches to one of the Supabase auth client methods based on type.

Login typeSupabase client call
passwordsignInWithPassword()
oauthsignInWithOAuth()
idtokensignInWithIdToken()
otpsignInWithOtp()
ssosignInWithSSO()
otp-tokenverifyOtp()

Password login:

import { useLogin } from '@ginjou/vue'

const { mutateAsync: login } = useLogin()

await login({
    type: 'password',
    params: {
        email: 'user@example.com',
        password: 'password123',
    },
})

OAuth login:

import { useLogin } from '@ginjou/vue'

const { mutateAsync: login } = useLogin()

await login({
    type: 'oauth',
    params: {
        provider: 'github',
    },
})

Logout

logout() maps to client.auth.signOut().

It forwards the optional logout params to Supabase.

Identity

getIdentity() maps to client.auth.getUser().

It returns the Supabase user object.

Check Authentication

check() maps to client.auth.getSession().

Session stateResult
Valid session{ authenticated: true }
No valid session and no auth error{ authenticated: false, logout: false, error: null }
Auth error{ authenticated: false, logout: true, error }

Auth failures are returned as part of the result instead of being thrown.

Check Error

checkError() uses Supabase isAuthError().

Error kindResult
Auth error{ logout: true, error }
Other error{}
Copyright © 2026