JavaScript SDK Reference
Complete API reference for @naijabase/js.
Installation
npm install @naijabase/js
Initialize
import { createClient } from '@naijabase/js'
const nb = createClient(
'https://api.naijabase.dev', // Your NaijaBase URL
'nb_anon_...' // Your anon key (safe for browser)
)
Database
.from(table)
Returns a query builder for the given table.
nb.from('products')
.select(columns)
Fetch rows. Returns all columns by default.
// All columns
const { data, error } = await nb.from('products').select()
// Specific columns
const { data, error } = await nb.from('products').select('id, name, price')
// Foreign table join
const { data, error } = await nb.from('orders').select('id, total, customers(name, email)')
// Count rows
const { count, error } = await nb.from('products').select('*', { count: 'exact', head: true })
.insert(rows)
Insert one or more rows.
// Single row
const { data, error } = await nb
.from('products')
.insert({ name: 'Puff Puff', price: 200 })
.select()
// Multiple rows
const { data, error } = await nb
.from('products')
.insert([
{ name: 'Jollof Rice', price: 1500 },
{ name: 'Egusi Soup', price: 2000 },
])
.select()
.update(values)
Update rows matching the filter.
const { data, error } = await nb
.from('products')
.update({ price: 250 })
.eq('id', 'uuid-here')
.select()
.upsert(rows)
Insert or update (by primary key).
const { data, error } = await nb
.from('profiles')
.upsert({ user_id: 'uuid', full_name: 'Ada' }, { onConflict: 'user_id' })
.select()
.delete()
Delete rows matching the filter.
const { error } = await nb
.from('products')
.delete()
.eq('id', 'uuid-here')
Filters
Chain these after .select(), .update(), or .delete().
| Method | SQL equivalent | Example |
|---|---|---|
.eq(col, val) | col = val | .eq('status', 'active') |
.neq(col, val) | col != val | .neq('status', 'deleted') |
.gt(col, val) | col > val | .gt('price', 100) |
.gte(col, val) | col >= val | .gte('price', 100) |
.lt(col, val) | col < val | .lt('stock', 10) |
.lte(col, val) | col <= val | .lte('stock', 10) |
.like(col, pat) | col LIKE pat | .like('name', '%rice%') |
.ilike(col, pat) | col ILIKE pat | .ilike('name', '%rice%') |
.in(col, vals) | col IN (vals) | .in('status', ['active', 'pending']) |
.is(col, val) | col IS val | .is('deleted_at', null) |
.contains(col, val) | col @> val | .contains('tags', ['food']) |
.order(col, opts) | ORDER BY col | .order('created_at', { ascending: false }) |
.limit(n) | LIMIT n | .limit(20) |
.range(from, to) | LIMIT/OFFSET | .range(0, 19) |
.single() | Expect 1 row | .single() |
.maybeSingle() | 0 or 1 row | .maybeSingle() |
Combining filters
// AND (chain multiple filters)
const { data } = await nb
.from('products')
.select()
.eq('category', 'food')
.gt('price', 500)
.order('name')
.limit(10)
// OR filter
const { data } = await nb
.from('products')
.select()
.or('price.gt.1000,stock.lt.5')
RPC (Remote Procedure Calls)
Call a PostgreSQL function:
// Function with no arguments
const { data, error } = await nb.rpc('get_stats')
// Function with arguments
const { data, error } = await nb.rpc('search_products', {
search_term: 'rice',
min_price: 500,
})
Auth
Sign up
const { data, error } = await nb.auth.signUp({ email, password })
Sign in
const { data, error } = await nb.auth.signInWithPassword({ email, password })
Sign out
const { error } = await nb.auth.signOut()
Get current user
const { data: { user } } = await nb.auth.getUser()
Get current session
const { data: { session } } = await nb.auth.getSession()
Update user
const { data, error } = await nb.auth.updateUser({
password: 'newpassword',
data: { full_name: 'Ada Okonkwo' },
})
Reset password
await nb.auth.resetPasswordForEmail('user@example.ng', {
redirectTo: 'https://yourapp.com/reset',
})
Listen for auth changes
const { data: { subscription } } = nb.auth.onAuthStateChange((event, session) => {
console.log(event, session)
})
// Cleanup
subscription.unsubscribe()
Storage
Create bucket
const { data, error } = await nb.storage.createBucket('avatars', { public: true })
Upload
const { data, error } = await nb.storage
.from('avatars')
.upload('user-123.jpg', file, { upsert: true, contentType: 'image/jpeg' })
Get public URL
const { data } = nb.storage.from('avatars').getPublicUrl('user-123.jpg')
// data.publicUrl = 'https://...'
Create signed URL
const { data, error } = await nb.storage
.from('documents')
.createSignedUrl('file.pdf', 3600) // expires in 1 hour
Download
const { data, error } = await nb.storage.from('avatars').download('user-123.jpg')
// data is a Blob
List
const { data, error } = await nb.storage
.from('avatars')
.list('public/', { limit: 50, sortBy: { column: 'name', order: 'asc' } })
Remove
const { error } = await nb.storage.from('avatars').remove(['user-123.jpg'])
Realtime
Subscribe to table changes
const channel = nb
.channel('my-channel')
.on('postgres_changes', { event: '*', schema: 'public', table: 'messages' }, (payload) => {
console.log(payload)
})
.subscribe()
Broadcast
// Send
await channel.send({ type: 'broadcast', event: 'my-event', payload: { foo: 'bar' } })
// Receive
channel.on('broadcast', { event: 'my-event' }, ({ payload }) => console.log(payload))
Presence
// Track
await channel.track({ user_id: 'abc', online_at: new Date().toISOString() })
// Listen
channel.on('presence', { event: 'sync' }, () => {
console.log(channel.presenceState())
})
Unsubscribe
await nb.removeChannel(channel)
await nb.removeAllChannels()
Error handling
All methods return { data, error }. Check error before using data:
const { data, error } = await nb.from('products').select()
if (error) {
console.error(error.message, error.code)
return
}
console.log(data)
Common error codes
| Code | Meaning |
|---|---|
PGRST116 | No rows found (when using .single()) |
42501 | Row Level Security violation |
23505 | Unique constraint violation |
23503 | Foreign key constraint violation |
auth/invalid-email | Malformed email address |
auth/email-already-exists | Email already registered |
auth/invalid-password | Wrong password |