Official JavaScript SDK for TinyBase - a simple, type-safe client for interacting with the TinyBase API
npm install tinybase-sdkOfficial JavaScript/TypeScript SDK for TinyBase - a simple, type-safe client for interacting with the TinyBase API.
``bash`
npm install tinybase-sdkor
yarn add tinybase-sdkor
pnpm add tinybase-sdk
Create a .env file in your project:
`env`
TINYBASE_URL=https://your-tinybase-instance.com
TINYBASE_API_KEY=tb_xxxxxxxxxxxx
Then just initialize the client - it auto-detects your credentials:
`typescript
import { TinyBase } from 'tinybase-sdk';
const tb = new TinyBase();
// Get all customers
const { data, total, hasMore } = await tb.table('customers').find();
console.log(Found ${total} customers);`
You can also pass configuration directly:
`typescript
import { TinyBase } from 'tinybase-sdk';
const tb = new TinyBase({
baseUrl: 'https://your-tinybase-instance.com',
apiKey: 'tb_xxxxxxxxxxxx'
});
`
Use API key authentication for backend applications. Set environment variables:
`env`
TINYBASE_URL=https://your-tinybase-instance.com
TINYBASE_API_KEY=tb_xxxxxxxxxxxx
`typescript
const tb = new TinyBase(); // Auto-detects from env vars
// Or pass explicitly
const tb = new TinyBase({
baseUrl: 'https://your-tinybase-instance.com',
apiKey: 'tb_xxxxxxxxxxxx'
});
`
Use session-based authentication for frontend applications:
`typescript
const tb = new TinyBase({
baseUrl: 'https://your-tinybase-instance.com',
credentials: 'include' // Sends cookies automatically
});
// Sign in
await tb.auth.signIn({
email: 'user@example.com',
password: 'password'
});
// Get current session
const session = await tb.auth.getSession();
console.log(session?.user.email);
// Sign out
await tb.auth.signOut();
`
`typescript
// Find all records with pagination
const { data, total, hasMore } = await tb.table('customers').find({
limit: 100,
offset: 0,
sort: 'createdAt',
order: 'desc'
});
// Find a single record by ID
const customer = await tb.table('customers').findOne('record-id-123');
// Create a new record
const newCustomer = await tb.table('customers').create({
name: 'John Doe',
email: 'john@example.com'
});
// Update a record
const updated = await tb.table('customers').update('record-id-123', {
name: 'John Smith'
});
// Delete a record
await tb.table('customers').delete('record-id-123');
`
Build complex queries with a fluent interface:
`typescript`
const results = await tb.table('orders')
.where('status', 'eq', 'pending')
.where('amount', 'gt', 100)
.orderBy('createdAt', 'desc')
.limit(50)
.offset(0)
.include('customer') // Include related records
.execute();
Supported filter operators:
- eq - equalsneq
- - not equalsgt
- - greater thangte
- - greater than or equallt
- - less thanlte
- - less than or equallike
- - SQL LIKE (case-sensitive)ilike
- - SQL ILIKE (case-insensitive)in
- - in arraynin
- - not in arraynull
- - is nullnotnull
- - is not null
`typescript
// Bulk create (1-1000 records)
const { created, failed, errors } = await tb.table('products').bulkCreate([
{ name: 'Product 1', price: 99 },
{ name: 'Product 2', price: 149 },
{ name: 'Product 3', price: 199 }
]);
// Bulk update by ID
await tb.table('products').bulkUpdate([
{ id: 'id-1', price: 89 },
{ id: 'id-2', price: 139 }
]);
// Bulk delete by IDs
await tb.table('products').bulkDelete(['id-1', 'id-2', 'id-3']);
// Bulk delete by conditions
await tb.table('products')
.where('status', 'eq', 'discontinued')
.bulkDelete();
// Bulk update by conditions
await tb.table('products')
.where('category', 'eq', 'electronics')
.bulkUpdate({ discounted: true });
`
Define interfaces for your tables:
`typescript
interface Customer {
id: string;
name: string;
email: string;
plan: 'free' | 'pro' | 'enterprise';
createdAt: string;
}
// All operations are now type-safe
const customers = await tb.table
const customer = await tb.table
name: 'Jane Doe',
email: 'jane@example.com',
plan: 'pro'
});
`
Manage multi-tenant organizations:
`typescript
// List organizations
const orgs = await tb.organizations.list();
// Create organization
const org = await tb.organizations.create({
name: 'My Company',
slug: 'my-company'
});
// Set active organization (scopes all queries to this org)
await tb.organizations.setActive(org.id);
// Update organization
await tb.organizations.update(org.id, { name: 'New Name' });
// Delete organization
await tb.organizations.delete(org.id);
`
`typescript
// List members
const members = await tb.organizations.members('org-id').list();
// Add member
await tb.organizations.members('org-id').add({
userId: 'user-id',
roleId: 'role-id'
});
// Update member role
await tb.organizations.members('org-id').updateRole('member-id', 'admin');
// Remove member
await tb.organizations.members('org-id').remove('member-id');
`
`typescript
// List teams
const teams = await tb.organizations.teams('org-id').list();
// Create team
const team = await tb.organizations.teams('org-id').create({
name: 'Engineering'
});
// Add member to team
await tb.organizations.teams('org-id').addMember('team-id', 'user-id');
// Remove member from team
await tb.organizations.teams('org-id').removeMember('team-id', 'user-id');
`
`typescript
// List roles
const roles = await tb.organizations.roles('org-id').list();
// Create custom role
await tb.organizations.roles('org-id').create({
name: 'editor',
permissions: ['project:read', 'project:update', 'document:*']
});
// Update role permissions
await tb.organizations.roles('org-id').update('editor', {
permissions: ['project:read', 'project:update']
});
// Delete role
await tb.organizations.roles('org-id').delete('editor');
`
`typescript
// Send invitation
await tb.organizations.invitations('org-id').send({
email: 'newuser@example.com',
role: 'member'
});
// List pending invitations
const invitations = await tb.organizations.invitations('org-id').list();
// Cancel invitation
await tb.organizations.invitations('org-id').cancel('invitation-id');
// User: Get pending invitations
const myInvitations = await tb.invitations.pending();
// User: Accept invitation
await tb.invitations.accept('invitation-id');
// User: Reject invitation
await tb.invitations.reject('invitation-id');
`
`typescript`
// Check if user has permissions
const hasAccess = await tb.organizations.permissions('org-id').check({
project: ['create', 'update'],
document: ['read']
});
Manage file storage:
`typescript
// List files
const files = await tb.storage.list({ prefix: 'uploads/' });
// Upload file
const file = await tb.storage.upload(fileBlob, {
key: 'uploads/document.pdf',
contentType: 'application/pdf'
});
// Upload multiple files
const { success, failed } = await tb.storage.uploadMany([
{ file: blob1, key: 'uploads/file1.jpg' },
{ file: blob2, key: 'uploads/file2.jpg' }
]);
// Download file
const blob = await tb.storage.download('uploads/document.pdf');
// Get file URL
const url = tb.storage.getUrl('uploads/document.pdf');
// Delete file
await tb.storage.delete('uploads/document.pdf');
// Copy file
await tb.storage.copy('uploads/original.pdf', 'backups/original.pdf');
// Move/rename file
await tb.storage.move('uploads/old-name.pdf', 'uploads/new-name.pdf');
// Get storage stats
const stats = await tb.storage.stats();
`
The SDK provides typed error classes:
`typescript
import {
TinyBaseError,
AuthenticationError,
ForbiddenError,
NotFoundError,
ValidationError,
RateLimitError,
ServerError
} from 'tinybase-sdk';
try {
const customer = await tb.table('customers').findOne('invalid-id');
} catch (error) {
if (error instanceof NotFoundError) {
console.log('Customer not found');
} else if (error instanceof AuthenticationError) {
console.log('API key invalid or expired');
} else if (error instanceof ValidationError) {
console.log('Validation errors:', error.errors);
} else if (error instanceof TinyBaseError) {
console.log('API error:', error.statusCode, error.message);
}
}
`
`typescript
const tb = new TinyBase({
// Required: Base URL of your TinyBase instance
baseUrl: 'https://api.example.com',
// API key for authentication
apiKey: 'tb_xxxxxxxxxxxx',
// Credentials mode for session-based auth
credentials: 'include',
// Request timeout in milliseconds (default: 30000)
timeout: 60000,
// Number of retry attempts for failed requests (default: 0)
retries: 3,
// Custom headers to include with every request
headers: {
'X-Custom-Header': 'value'
}
});
`
The SDK uses the native fetch API and works in:
- Node.js 18+
- All modern browsers
- Edge runtimes (Cloudflare Workers, Vercel Edge, etc.)
Full TypeScript support with exported types:
`typescript``
import type {
TinyBaseConfig,
PaginatedResponse,
Organization,
Member,
Team,
Role,
Invitation,
StorageFile
} from 'tinybase-sdk';
MIT