Official JavaScript/TypeScript SDK for ZendBX with fluent, chainable query API. Works in Node.js, Bun, Deno, Next.js, React, Vue, Svelte, and any modern JavaScript/TypeScript project.
Features
Full TypeScript support with generics
Fluent, chainable query builder API
Authentication & OAuth integration
File storage & management
Real-time subscriptions (coming soon)
Row-level security built-in
PostgREST compatible filtering
Zero external dependencies
Installation
bash
npm install @zendbx/sdk
# or
yarn add @zendbx/sdk
# or
pnpm add @zendbx/sdkRequirements: Node.js 18+ (uses native fetch), TypeScript 5.0+ for type support
Quick Start
typescript
import { createClient } from '@zendbx/sdk'
// Initialize client
const client = createClient({
apiUrl: 'https://api.zendbx.in',
projectSlug: 'my-project',
anonKey: 'eyJ...' // Get from ZendBX dashboard
})
// Query data
const { data, error } = await client.from('users').select('*')
if (error) {
console.error('Error:', error.message)
} else {
console.log('Users:', data)
}Client Initialization
Basic Configuration
typescript
const client = createClient({
apiUrl: 'https://api.zendbx.in',
projectSlug: 'my-project',
anonKey: 'your-anon-key',
accessToken: 'user-jwt-token', // Optional
autoRefreshToken: false, // Optional
})Configuration Options
| Option | Type | Description |
|---|---|---|
| apiUrl | string | ZendBX API URL (required) |
| projectSlug | string | Your project identifier (required) |
| anonKey | string | Anonymous key for client-side access (required) |
| accessToken | string | JWT token for authenticated requests (optional) |
| autoRefreshToken | boolean | Automatically refresh expired tokens (default: false) |
Database Operations
SELECT
typescript
// Select all columns
const { data } = await client.from('users').select('*')
// Select specific columns
const { data } = await client.from('users').select('id, name, email')
// With TypeScript types
interface User {
id: string
name: string
email: string
}
const { data } = await client.from<User>('users').select('*')
// data is User[] | null with full autocompleteINSERT
typescript
// Single row insert
const { data, error } = await client.from('users')
.insert({
name: 'John Doe',
email: 'john@example.com'
})
.select()
// Bulk insert (multiple rows)
const { data } = await client.from('users')
.insert([
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' },
{ name: 'Carol', email: 'carol@example.com' }
])
.select()
console.log(`Inserted ${data.length} users`)UPDATE
typescript
// Update with filter
const { data } = await client.from('users')
.update({ status: 'inactive' })
.eq('id', '123')
.select()
// Update multiple rows
await client.from('users')
.update({ verified: true })
.gt('created_at', '2024-01-01')DELETE
typescript
// Delete with filter
await client.from('users').delete().eq('id', '123')
// Delete multiple rows
await client.from('logs')
.delete()
.lt('created_at', '2024-01-01')Filtering
| Method | SQL | Example |
|---|---|---|
| .eq(col, val) | = | .eq('status', 'active') |
| .neq(col, val) | != | .neq('role', 'admin') |
| .gt(col, val) | > | .gt('age', 18) |
| .gte(col, val) | >= | .gte('score', 90) |
| .lt(col, val) | < | .lt('price', 100) |
| .lte(col, val) | <= | .lte('stock', 10) |
| .like(col, pat) | LIKE | .like('email', '%@gmail.com') |
| .ilike(col, pat) | ILIKE | .ilike('name', '%john%') |
| .in(col, arr) | IN | .in('status', ['active', 'pending']) |
| .is(col, val) | IS | .is('deleted_at', null) |
Chaining Filters
typescript
// Multiple conditions (AND logic)
const { data } = await client.from('users')
.select('*')
.eq('country', 'India')
.gt('age', 18)
.like('email', '%@gmail.com')
.is('verified', true)Ordering & Pagination
Ordering
typescript
// Ascending (default)
const { data } = await client.from('users')
.select('*')
.order('created_at')
// Descending
const { data } = await client.from('users')
.select('*')
.order('created_at', { ascending: false })Pagination
typescript
// Limit
const { data } = await client.from('users')
.select('*')
.limit(20)
// Range (offset + limit)
const { data } = await client.from('users')
.select('*')
.range(0, 19) // First 20 rows
// Pagination with count
const pageSize = 20
const page = 2
const { data, count } = await client.from('users')
.select('*', { count: 'exact' })
.range(page * pageSize, (page + 1) * pageSize - 1)
console.log(`Page ${page + 1} of ${Math.ceil(count / pageSize)}`)Authentication
Sign Up
const { data, error } = await client.auth.signUp({
email: 'user@example.com',
password: 'secure-password-123',
name: 'John Doe'
})Sign In
const { data, error } = await client.auth.signIn({
email: 'user@example.com',
password: 'secure-password-123'
})Get Current User
const user = await client.auth.getUser()
console.log('Current user:', user.email)Sign Out
await client.auth.signOut()
// Token is cleared from the clientStorage
typescript
// Upload file
const file = document.getElementById('file-input').files[0]
const { data, error } = await client.storage
.from('avatars')
.upload('user-123/profile.jpg', file)
// Get public URL
const { data } = client.storage
.from('avatars')
.getPublicUrl('user-123/profile.jpg')
console.log(data.publicUrl)
// Download file
const { data: blob } = await client.storage
.from('avatars')
.download('user-123/profile.jpg')
// Delete file
await client.storage
.from('avatars')
.remove(['user-123/old-avatar.jpg'])Error Handling
Important: All operations return a response object with an error field. The SDK never throws for database errors.
typescript
const { data, error } = await client.from('users').select('*')
if (error) {
console.error('Query failed:', error.message)
console.error('Status:', error.status)
console.error('Details:', error.details)
return
}
// Safe to use data here
console.log('Users:', data)Best Practices
Use TypeScript Generics
interface User {
id: string
email: string
}
const { data } = await client.from<User>('users').select('*')
// Full type safety and autocompleteAlways Check Errors
const { data, error } = await client.from('users').select('*')
if (error) {
// Handle error
return
}
// Safe to use dataUse Environment Variables
const client = createClient({
apiUrl: process.env.ZENDBX_URL!,
projectSlug: process.env.ZENDBX_PROJECT_SLUG!,
anonKey: process.env.ZENDBX_ANON_KEY!
})
