tinybase-sdk
v1.0.1
Published
Official JavaScript SDK for TinyBase - a simple, type-safe client for interacting with the TinyBase API
Maintainers
Readme
tinybase-sdk
Official JavaScript/TypeScript SDK for TinyBase - a simple, type-safe client for interacting with the TinyBase API.
Installation
npm install tinybase-sdk
# or
yarn add tinybase-sdk
# or
pnpm add tinybase-sdkQuick Start
Using Environment Variables (Recommended)
Create a .env file in your project:
TINYBASE_URL=https://your-tinybase-instance.com
TINYBASE_API_KEY=tb_xxxxxxxxxxxxThen just initialize the client - it auto-detects your credentials:
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`);Explicit Configuration
You can also pass configuration directly:
import { TinyBase } from 'tinybase-sdk';
const tb = new TinyBase({
baseUrl: 'https://your-tinybase-instance.com',
apiKey: 'tb_xxxxxxxxxxxx'
});Authentication
API Key (Server-Side)
Use API key authentication for backend applications. Set environment variables:
TINYBASE_URL=https://your-tinybase-instance.com
TINYBASE_API_KEY=tb_xxxxxxxxxxxxconst tb = new TinyBase(); // Auto-detects from env vars
// Or pass explicitly
const tb = new TinyBase({
baseUrl: 'https://your-tinybase-instance.com',
apiKey: 'tb_xxxxxxxxxxxx'
});Session-Based (Browser)
Use session-based authentication for frontend applications:
const tb = new TinyBase({
baseUrl: 'https://your-tinybase-instance.com',
credentials: 'include' // Sends cookies automatically
});
// Sign in
await tb.auth.signIn({
email: '[email protected]',
password: 'password'
});
// Get current session
const session = await tb.auth.getSession();
console.log(session?.user.email);
// Sign out
await tb.auth.signOut();Data Operations
Basic CRUD
// 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: '[email protected]'
});
// 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');Query Builder
Build complex queries with a fluent interface:
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
Bulk Operations
// 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 });Type Safety
Define interfaces for your tables:
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<Customer>('customers').find();
const customer = await tb.table<Customer>('customers').create({
name: 'Jane Doe',
email: '[email protected]',
plan: 'pro'
});Organizations
Manage multi-tenant organizations:
// 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);Members
// 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');Teams
// 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');Roles
// 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');Invitations
// Send invitation
await tb.organizations.invitations('org-id').send({
email: '[email protected]',
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');Permissions
// Check if user has permissions
const hasAccess = await tb.organizations.permissions('org-id').check({
project: ['create', 'update'],
document: ['read']
});Storage
Manage file storage:
// 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();Error Handling
The SDK provides typed error classes:
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);
}
}Configuration Options
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'
}
});Browser Support
The SDK uses the native fetch API and works in:
- Node.js 18+
- All modern browsers
- Edge runtimes (Cloudflare Workers, Vercel Edge, etc.)
TypeScript
Full TypeScript support with exported types:
import type {
TinyBaseConfig,
PaginatedResponse,
Organization,
Member,
Team,
Role,
Invitation,
StorageFile
} from 'tinybase-sdk';License
MIT
