The @betterbase/client package provides a TypeScript SDK for interacting with BetterBase backends.
bun add @betterbase/client
import { createClient } from '@betterbase/client'
const client = createClient({
url: 'http://localhost:3000',
auth: {
persistSession: true,
autoRefreshToken: true
}
})
interface ClientOptions {
url: string
auth?: {
persistSession?: boolean
autoRefreshToken?: boolean
}
storage?: {
type?: 'local' | 'session'
}
}
const { data, error } = await client.auth.signUp({
email: string,
password: string,
name?: string
})
const { data, error } = await client.auth.signInWithPassword({
email: string,
password: string
})
const { data, error } = await client.auth.signInWithOAuth({
provider: 'github' | 'google' | 'discord'
})
await client.auth.signOut()
const { data, error } = await client.auth.getUser()
const { data, error } = await client.auth.getSession()
// Get all records
const { data, error } = await client
.from('users')
.select()
// Select specific columns
const { data, error } = await client
.from('users')
.select('id, name, email')
// With filters
const { data, error } = await client
.from('posts')
.select()
.eq('published', true)
.order('createdAt', { ascending: false })
.limit(10)
const { data, error } = await client
.from('users')
.insert({
name: 'John Doe',
email: 'john@example.com'
})
const { data, error } = await client
.from('users')
.update({ name: 'Jane Doe' })
.eq('id', 'user-123')
const { data, error } = await client
.from('users')
.delete()
.eq('id', 'user-123')
| Method |
Description |
.select(columns?) |
Select columns to return |
.eq(column, value) |
Filter by equality |
.neq(column, value) |
Filter by inequality |
.gt(column, value) |
Greater than |
.gte(column, value) |
Greater or equal |
.lt(column, value) |
Less than |
.lte(column, value) |
Less or equal |
.like(column, pattern) |
Pattern match |
.in(column, array) |
In array |
.order(column, options) |
Sort results |
.limit(count) |
Limit results |
.offset(count) |
Offset results |
.single() |
Return single record |
const channel = client.channel('public:posts')
channel
.on('postgres_changes',
{ event: 'INSERT', table: 'posts' },
(payload) => console.log('New post:', payload.new)
)
.subscribe()
channel.on('status', (status) => {
console.log('Connection status:', status)
})
const { data, error } = await client.storage.upload(
bucket: string,
path: string,
file: File | Blob
)
const { data, error } = await client.storage.download(
bucket: string,
path: string
)
const { data, error } = await client.storage.remove(
bucket: string,
path: string
)
const { data: { url } } = client.storage.getPublicUrl(
bucket: string,
path: string
)
const { data, error } = await client.storage.list(bucket: string)
const { data, error } = await client.graphql.query(`
query GetUsers {
users {
id
name
email
}
}
`)
const { data, error } = await client.graphql.mutation(`
mutation CreateUser($name: String!, $email: String!) {
insert_users_one(object: { name: $name, email: $email }) {
id
name
}
}
`, { name: 'John', email: 'john@example.com' })
const { data, error } = await client.from('users').select()
if (error) {
console.error('Error:', error.message)
console.error('Code:', error.code)
return
}
console.log('Data:', data)
| Error Code |
Description |
PGRST116 |
Record not found |
23505 |
Unique constraint violation |
42501 |
Permission denied |
AUTH_REQUIRED |
Authentication required |
import type {
User,
Session,
Post,
StorageResult,
RealtimeChannel
} from '@betterbase/client'
- Use persistSession - Keep user logged in across page reloads
- Handle errors - Always check error before processing data
- Type your data - Use TypeScript types for better DX
- Clean up subscriptions - Unsubscribe when done