@snackbase/supabase-compat
v0.2.0
Published
Drop-in replacement for @supabase/supabase-js backed by SnackBase
Maintainers
Readme
@snackbase/supabase-compat
A drop-in replacement for @supabase/supabase-js that points to a SnackBase backend.
Swap your imports, keep your code, and migrate from Supabase to self-hosted SnackBase in minutes.
Quick Start
1. Install
npm install @snackbase/supabase-compat2. Swap Import & URL
- import { createClient } from '@supabase/supabase-js'
- const supabase = createClient('https://xyz.supabase.co', 'anon-key')
+ import { createClient } from '@snackbase/supabase-compat'
+ const supabase = createClient('http://localhost:8000', 'your-api-key')3. Use as Normal
const { data, error } = await supabase
.from("posts")
.select("*")
.eq("status", "published");Support Matrix
| Feature | Supabase API | Status | Notes |
| :----------- | :-------------------------------------- | :------------- | :----------------------------------- |
| Auth | auth.signUp(), signInWithPassword() | ✅ Full | |
| | auth.signOut(), auth.getSession() | ✅ Full | |
| | auth.onAuthStateChange() | ✅ Full | |
| | auth.admin.* | ✅ Full | List, Create, Update, Delete, Invite |
| | auth.signInWithOAuth() | ✅ Full | Returns redirect URL |
| | auth.signInAnonymously() | ❌ Unsupported | Use email/password |
| Data | from().select().eq().neq() | ✅ Full | |
| | .order(), .limit(), .range() | ✅ Full | |
| | .insert(), .update(), .delete() | ✅ Full | |
| | .upsert() | ⚠️ Partial | Create + Catch Conflict strategy |
| | .rpc() | ❌ Unsupported | No RPC support yet |
| Storage | storage.from().upload() / download() | ✅ Full | |
| | storage.from().getPublicUrl() | ✅ Full | |
| | storage.from().list() | ❌ Unsupported | |
| Realtime | channel().on('postgres_changes') | ✅ Full | Filter by table and event |
| | presence / broadcast | ❌ Unsupported | |
Key Differences & Migration Tips
1. No "Buckets" in Storage
SnackBase treats storage as a flat file system. When you use supabase.storage.from('avatars'), we simply prefix your file paths with avatars/.
2. Error Handling
Supported compatibility operations return { data, error } and map SnackBase errors to
the Supabase error shape. Explicitly unsupported surfaces such as supabase.rpc() and
supabase.functions throw NotSupportedError (and storage.from().list() returns an
error result).
3. User Metadata
SnackBase doesn't have a native user_metadata field yet. user.user_metadata currently returns an empty object {} to maintain type compatibility.
4. Realtime Payload
Payloads are normalized to match Supabase's postgres_changes format:
{
schema: 'public',
table: 'posts',
eventType: 'INSERT',
new: { ... },
old: {},
commit_timestamp: '...'
}channel().on('postgres_changes', ...) supports table and event filters. Presence and
broadcast channels are not implemented.
Development & Testing
This package is part of the SnackBase-js monorepo and depends on @snackbase/sdk.
# Run tests
pnpm test
# Typecheck
pnpm typecheck
# Build
pnpm buildLicense
MIT
