Veloquent Flutter SDK
A Flutter SDK for Veloquent BaaS, providing a high-level API for authentication, record management, collections, schema management, and real-time updates.
Contents
Features
- Authentication: Login, identity impersonation, logout, and session management.
- Records: CRUD operations on collection records with filtering, sorting, and expansion.
- Collections: Manage collection metadata and truncate data.
- Schema: Health checks and schema transfer (export/import) tools.
- Onboarding: Check initialization status and create initial superusers.
- Real-time: Subscribe to collection changes using WebSockets (via Pusher).
Installation
Getting started
Initialize the SDK by providing an API URL and choosing your storage and HTTP adapters.
import 'package:veloquent_sdk/veloquent_sdk.dart';
final sdk = Veloquent(
apiUrl: 'https://your-api.com',
http: createFetchAdapter(),
storage: await createLocalStorageAdapter(),
);
Usage
Authentication
final loginRes = await sdk.auth.login('users', 'user@example.com', 'password');
print('Token: ${loginRes['token']}');
final profile = await sdk.auth.me('users');
CRUD Operations
// List records with filters
final result = await sdk.records.list('posts',
filter: 'status = "published"',
sort: '-created_at',
perPage: 25,
page: 1,
expand: 'authorId',
);
print(result.data); // List<Record>
print(result.meta); // {current_page: 1, total: 42, ...}
// Get a single record
final post = await sdk.records.get('posts', 'rec-123', expand: 'authorId');
print(post.get('title'));
// Create a record
final newPost = await sdk.records.create('posts', {
'title': 'Hello World',
'content': 'This is my first post',
});
print(newPost.id);
// Update a record
final updated = await sdk.records.update('posts', newPost.id, {'status': 'published'});
// Delete a record
await sdk.records.delete('posts', newPost.id);
File Uploads
For collection fields of type file, pass a FileUpload object anywhere in the data map.
The SDK automatically sends the request as multipart/form-data, no extra setup needed.
FileUpload is exported from the top-level veloquent_sdk package.
Create a record with a file
final upload = FileUpload(
bytes: imageBytes, // List<int>
filename: 'avatar.jpg',
mimeType: 'image/jpeg',
);
final user = await sdk.records.create('users', {
'name': 'Kevin',
'avatar': upload, // SDK detects FileUpload and sends multipart
});
Flutter — using image_picker
import 'package:image_picker/image_picker.dart';
import 'package:mime/mime.dart';
final picked = await ImagePicker().pickImage(source: ImageSource.gallery);
if (picked == null) return;
final upload = FileUpload(
bytes: await picked.readAsBytes(),
filename: picked.name,
mimeType: lookupMimeType(picked.name) ?? 'application/octet-stream',
);
await sdk.records.create('photos', {'title': 'Sunset', 'image': upload});
Create with multiple files
await sdk.records.create('posts', {
'title': 'My Trip',
'gallery': [upload1, upload2], // List<FileUpload>
});
Update / replace a file
await sdk.records.update('users', userId, {
'avatar': FileUpload(bytes: newBytes, filename: 'new.jpg', mimeType: 'image/jpeg'),
});
Update / append files to a multi-file field
Suffix the field name with + to add files without replacing existing ones:
await sdk.records.update('posts', postId, {
'gallery+': [newUpload1, newUpload2],
});
Update / remove specific files
Suffix the field name with - and pass a path or metadata selector:
// The path comes from the file metadata returned by the API
await sdk.records.update('posts', postId, {
'gallery-': [{'path': 'collections/posts/abc123.jpg'}],
});
File field response shape
File fields are returned as a list of metadata maps:
final post = await sdk.records.get('posts', postId);
final gallery = post.get('gallery') as List?; // [{name, path, size, extension, mime}, ...]
// To remove by path:
final path = (gallery?.first as Map)['path'];
await sdk.records.update('posts', postId, {
'gallery-': [{'path': path}],
});
Real-time Subscriptions
Real-time support is provided via pusher_channels_flutter. You must initialize the Pusher client first.
import 'package:pusher_channels_flutter/pusher_channels_flutter.dart';
final pusher = PusherChannelsFlutter.getInstance();
await pusher.init(
apiKey: 'YOUR_KEY',
cluster: 'YOUR_CLUSTER',
authEndpoint: 'https://your-api.com/api/broadcasting/auth',
authParams: {
'headers': {
'Authorization': 'Bearer ${token}'
}
}
);
// Connect the adapter to the SDK
sdk.realtime.adapter = createPusherChannelsAdapter(pusher);
// Subscribe to events
await sdk.realtime.subscribe('posts', (event, payload) {
print('Real-time event: $event');
print('Record: ${payload['id']}');
});
Tests
Run the unit test suite with:
flutter test test/auth_test.dart test/realtime_test.dart test/records_test.dart
Run integration tests against a live Veloquent server with:
export RUN_INTEGRATION_TESTS=true
export VELOQUENT_API_URL=http://localhost:80
flutter test test/integration_test.dart test/integration_realtime_test.dart
Note:
integration_realtime_test.dartcurrently uses a mock realtime adapter to validate SDK orchestration. A full native Flutter realtime end-to-end test should be added later.
Contributing
Contributions are welcome. Please open issues or pull requests for bug fixes, improvements, or new features. When contributing:
- Keep changes small and focused.
- Add tests for new behavior.
- Follow the existing Dart style and naming conventions.
License
This project is licensed under the MIT License. See LICENSE for details.
Additional information
This SDK is designed for Flutter applications. Non-Flutter Dart targets are not officially supported for real-time features.