UNPKG

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
# 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).