baseflow-local-client
Version:
Official TypeScript/JavaScript client for BaseFlow Local - a local-first BaaS with SQLite database, authentication, file storage, and real-time features
623 lines (472 loc) • 12.8 kB
Markdown
# BaseFlow Local Client
Official TypeScript/JavaScript client for **BaseFlow Local** - a local-first Backend-as-a-Service with SQLite database, authentication, file storage, and real-time features.
## Installation
```bash
npm install @baseflow/local-client
```
## Quick Start
```typescript
import { createClient } from '@baseflow/local-client';
// Create client (connects to local server)
const baseflow = createClient({
url: 'http://localhost:5555', // Optional, defaults to localhost:5555
apiKey: 'your-api-key-here' // Optional: API key for authentication
});
// Query data
const { data, error } = await baseflow
.from('users')
.select('*')
.eq('status', 'active');
// Insert data
await baseflow.from('posts').insert({
title: 'Hello World',
content: 'My first post'
});
// Update data
await baseflow
.from('users')
.update({ name: 'Jane Doe' })
.eq('id', 1);
// Delete data
await baseflow
.from('posts')
.delete()
.eq('id', 123);
```
### API Key Authentication
BaseFlow Local generates an API key for each project. You can find your API key in the `.baseflow/api-keys.json` file or by visiting `http://localhost:5555/api/keys`.
```typescript
const baseflow = createClient({
url: 'http://localhost:5555',
apiKey: 'bf_local_your_api_key_here'
});
```
Alternatively, you can pass the API key in headers:
```typescript
const baseflow = createClient({
url: 'http://localhost:5555',
headers: {
'x-api-key': 'bf_local_your_api_key_here'
}
});
```
## Features
- 🗄️ **Database Operations** - Full CRUD with query builder
- 🔐 **Authentication** - JWT-based auth with signup/login
- 📁 **File Storage** - Upload, download, and manage files
- 🔄 **Real-time** - Subscribe to database changes
- 🚀 **TypeScript** - Full type safety and IntelliSense
- 🌐 **Universal** - Works in Node.js and browsers
## Authentication
```typescript
// Register a new user
const { data, error } = await baseflow.auth.signUp({
email: 'user@example.com',
password: 'SecurePassword123',
name: 'John Doe'
});
// Login
const { data, error } = await baseflow.auth.signInWithPassword({
email: 'user@example.com',
password: 'SecurePassword123'
});
// Get current user
const { data, error } = await baseflow.auth.getUser();
// Logout
await baseflow.auth.signOut();
// Listen to auth state changes
const unsubscribe = baseflow.auth.onAuthStateChange((event) => {
if (event.type === 'SIGNED_IN') {
console.log('User signed in:', event.user);
}
});
```
## File Storage
```typescript
// Upload file (Node.js)
const fs = require('fs');
const fileBuffer = fs.readFileSync('image.jpg');
const { data, error } = await baseflow.storage.upload(fileBuffer, {
filename: 'image.jpg',
folder: 'images',
isPublic: true
});
// Upload file (Browser)
const file = document.getElementById('input').files[0];
const { data, error } = await baseflow.storage.upload(file, {
folder: 'uploads',
isPublic: true
});
// List files
const { data, error } = await baseflow.storage.list('images');
// Get file URL
const url = baseflow.storage.getUrl('images/photo.jpg');
// Delete file
await baseflow.storage.delete(fileId);
```
- 🔍 **Advanced Queries** - Filtering, sorting, pagination
- 📦 **TypeScript Support** - Full type safety
- 🎯 **Supabase-like API** - Familiar developer experience
## Database Operations
### Select
```typescript
// Select all
const { data } = await baseflow.from('users').select('*');
// Select specific columns
const { data } = await baseflow.from('users').select('id, name, email');
// With filters
const { data } = await baseflow
.from('users')
.select('*')
.eq('status', 'active')
.gt('age', 18);
// With sorting
const { data } = await baseflow
.from('posts')
.select('*')
.order('created_at', { ascending: false });
// With pagination
const { data } = await baseflow
.from('users')
.select('*')
.range(0, 9); // First 10 records
// Single record
const { data } = await baseflow
.from('users')
.select('*')
.eq('id', 1)
.single();
```
### Insert
```typescript
// Insert single record
const { data, error } = await baseflow.from('users').insert({
name: 'John Doe',
email: 'john@example.com'
});
// Insert multiple records
const { data, error } = await baseflow.from('users').insert([
{ name: 'Alice', email: 'alice@example.com' },
{ name: 'Bob', email: 'bob@example.com' }
]);
```
### Update
```typescript
// Update with filter
const { data, error } = await baseflow
.from('users')
.update({ status: 'inactive' })
.eq('last_login', null);
// Update single record
const { data, error } = await baseflow
.from('users')
.update({ name: 'Jane Smith' })
.eq('id', 1);
```
### Delete
```typescript
// Delete with filter
const { data, error } = await baseflow
.from('posts')
.delete()
.eq('status', 'draft');
// Delete single record
const { data, error } = await baseflow
.from('users')
.delete()
.eq('id', 123);
```
## Filters
```typescript
// Equals
.eq('column', 'value')
// Not equals
.neq('column', 'value')
// Greater than
.gt('column', 10)
// Greater than or equal
.gte('column', 10)
// Less than
.lt('column', 10)
// Less than or equal
.lte('column', 10)
// Like (pattern matching)
.like('column', '%pattern%')
// Case-insensitive like
.ilike('column', '%pattern%')
// Is null
.is('column', null)
// In array
.in('column', [1, 2, 3])
// Match multiple conditions
.match({ status: 'active', role: 'admin' })
```
## Authentication
### Sign Up
```typescript
const { data, error } = await baseflow.auth.signUp({
email: 'user@example.com',
password: 'securepassword',
name: 'John Doe' // Optional
});
if (data) {
console.log('User:', data.user);
console.log('Token:', data.token);
}
```
### Sign In
```typescript
const { data, error } = await baseflow.auth.signInWithPassword({
email: 'user@example.com',
password: 'securepassword'
});
if (data) {
console.log('Logged in:', data.user);
}
```
### Get Current User
```typescript
const { data, error } = await baseflow.auth.getUser();
if (data) {
console.log('Current user:', data.user);
}
```
### Sign Out
```typescript
await baseflow.auth.signOut();
```
### Auth State Changes
```typescript
const unsubscribe = baseflow.auth.onAuthStateChange((event) => {
if (event.type === 'SIGNED_IN') {
console.log('User signed in:', event.user);
} else if (event.type === 'SIGNED_OUT') {
console.log('User signed out');
}
});
// Unsubscribe when done
unsubscribe();
```
### Manual Session Management
```typescript
// Set session manually (e.g., from localStorage)
baseflow.auth.setSession({
token: 'your-jwt-token',
user: { id: 1, email: 'user@example.com' }
});
// Get current session
const session = baseflow.auth.getSession();
console.log(session.token, session.user);
```
## File Storage
### Upload File
```typescript
// From file input
const fileInput = document.querySelector('input[type="file"]');
const file = fileInput.files[0];
const { data, error } = await baseflow.storage.upload(file, {
folder: 'images',
isPublic: true
});
if (data) {
console.log('File uploaded:', data.filename);
console.log('Public URL:', data.publicUrl);
}
```
### Upload with Node.js
```typescript
import fs from 'fs';
const fileBuffer = fs.readFileSync('./image.jpg');
const { data, error } = await baseflow.storage.upload(fileBuffer, {
folder: 'uploads',
isPublic: false
});
```
### List Files
```typescript
// List all files
const { data, error } = await baseflow.storage.list();
// List files in folder
const { data, error } = await baseflow.storage.list('images');
if (data) {
console.log('Files:', data.files);
console.log('Count:', data.count);
}
```
### Get File URL
```typescript
const url = baseflow.storage.getUrl('path/to/file.jpg');
console.log('File URL:', url);
```
### Download File
```typescript
const { data, error } = await baseflow.storage.download('path/to/file.jpg');
```
### Delete File
```typescript
const { data, error } = await baseflow.storage.delete(fileId);
```
## RPC Functions
Call custom server-side functions:
```typescript
const { data, error } = await baseflow.rpc('myFunction', {
param1: 'value1',
param2: 'value2'
});
```
## Utility Methods
### List Tables
```typescript
const { data, error } = await baseflow.listTables();
console.log('Tables:', data.tables);
```
### Get Schema
```typescript
const { data, error } = await baseflow.getSchema();
console.log('Schema:', data);
```
## TypeScript Support
The client is fully typed for TypeScript:
```typescript
interface User {
id: number;
name: string;
email: string;
created_at: string;
}
// Type-safe queries
const { data, error } = await baseflow
.from<User>('users')
.select('*')
.eq('email', 'user@example.com');
// data is typed as User[] | null
if (data) {
data.forEach(user => {
console.log(user.name); // TypeScript knows this exists
});
}
```
## Error Handling
All methods return a response object with `data` and `error`:
```typescript
const { data, error } = await baseflow.from('users').select('*');
if (error) {
console.error('Error:', error.message);
console.error('Code:', error.code);
console.error('Details:', error.details);
} else {
console.log('Data:', data);
}
```
## Configuration
### Custom URL
```typescript
const baseflow = createClient({
url: 'http://192.168.1.100:5555' // Custom server URL
});
```
### With Authentication Token
```typescript
const baseflow = createClient({
url: 'http://localhost:5555',
token: 'your-jwt-token' // Pre-authenticated
});
```
### Custom Headers
```typescript
const baseflow = createClient({
url: 'http://localhost:5555',
headers: {
'X-Custom-Header': 'value'
}
});
```
### Custom Fetch Implementation
```typescript
import fetch from 'node-fetch';
const baseflow = createClient({
url: 'http://localhost:5555',
fetch: fetch as any
});
```
## Differences from Cloud Client
| Feature | Cloud Client | Local Client |
|---------|--------------|--------------|
| **URL** | `https://api.baseflow.dev` | `http://localhost:5555` |
| **Auth** | API Key + Project ID | JWT tokens |
| **Endpoints** | `/rest/v1/...` | `/api/...` |
| **Real-time** | Cloud WebSocket | Local WebSocket (coming soon) |
| **OAuth** | Supported | Not supported |
## Examples
### Complete CRUD Example
```typescript
import { createClient } from '@baseflow/local-client';
const baseflow = createClient();
// Create
const { data: newUser } = await baseflow.from('users').insert({
name: 'Alice',
email: 'alice@example.com'
});
// Read
const { data: users } = await baseflow
.from('users')
.select('*')
.eq('email', 'alice@example.com');
// Update
await baseflow
.from('users')
.update({ name: 'Alice Smith' })
.eq('id', newUser.id);
// Delete
await baseflow
.from('users')
.delete()
.eq('id', newUser.id);
```
### Authentication Flow
```typescript
// Register
const { data: signUpData } = await baseflow.auth.signUp({
email: 'user@example.com',
password: 'password123',
name: 'John Doe'
});
// Login
const { data: signInData } = await baseflow.auth.signInWithPassword({
email: 'user@example.com',
password: 'password123'
});
// Get user
const { data: userData } = await baseflow.auth.getUser();
// Logout
await baseflow.auth.signOut();
```
### File Upload Example
```typescript
// Browser
const handleUpload = async (event) => {
const file = event.target.files[0];
const { data, error } = await baseflow.storage.upload(file, {
folder: 'avatars',
isPublic: true
});
if (data) {
console.log('Uploaded:', data.publicUrl);
}
};
// Node.js
import fs from 'fs';
const buffer = fs.readFileSync('./document.pdf');
const { data } = await baseflow.storage.upload(buffer, {
folder: 'documents',
isPublic: false
});
```
## License
MIT
## Links
- [BaseFlow Local Documentation](https://baseflow.cloud/docs/local)
- [GitHub Repository](https://github.com/baseflow/baseflow)
- [Issue Tracker](https://github.com/baseflow/baseflow/issues)
## Support
For questions and support, please visit our [GitHub Discussions](https://github.com/baseflow/baseflow/discussions).