dbx 0.1.0
dbx: ^0.1.0 copied to clipboard
A Data Storage Solution, created with simplicity in mind. It is a simple, lightweight, and fast database solution for Flutter apps.
DBX #
dbx is a Dart package designed for secure and efficient local storage using Protocol Buffers instead of JSON.
- A Key-Value Database with Easy API that supports wide range of Data Types.
Features #
- Protocol Buffers: Utilizes Protocol Buffers (protobuf) for data serialization, offering significant performance improvements over JSON.
- Secure Storage: Data is securely stored using
flutter_secure_storageand encrypted with theencryptlibrary, with customizable encryption options. - Comprehensive Data Support: Supports all data types, including their list variants and JSON objects.
-
What we mean
- Supported data types are
int,double,bool,String,Uint8List,List<int>,List<double>,List<bool>,List<String>,List<Uint8List>, andMap<String, dynamic>(JSON). Uint8Listfor bytes, JSON for custom objects
- Supported data types are
-
- Efficient and Compact: Protobuf is more efficient and compact compared to JSON, with built-in data compression (gzip), reducing latency and improving app performance.
- Customizable Encryption: Configure AES modes, key lengths, and IV lengths for enhanced security.
- Generic Operations: Type-agnostic get/set methods for dynamic data handling.
- Batch Operations: Efficient bulk read/write operations for multiple keys.
- Indexing & Search: Fast key lookups, sorted keys, prefix-based searches, and existence checks.
- Synchronization: Export/import functionality for data backup and cross-device sync.
- Schema Versioning: Automatic migrations for schema evolution.
- Utilities: Key count, file size monitoring, and bulk data removal.
- Familiar Api: Same API as of
SharedPreference.- Won't miss
SharedPreference. No headache, easy adaption.🚀
- Won't miss
- Created With Simplicity in mind
- No Object Creation, no overhead of state management solution
- No Object Passing
- All method are static, just call and use.
Benefits of Using Protocol Buffers Over JSON #
- Performance: Protobuf is significantly faster than JSON for serialization and deserialization.
- Compactness: Protobuf messages are smaller in size, which reduces storage space and improves transmission speed.
- Efficiency: Protobuf is more efficient in terms of CPU and memory usage.
Advantages Over Shared Preferences #
- Data Integrity: Protobuf ensures data integrity and consistency, which is crucial for complex data structures.
- Security: Data is encrypted and securely stored, unlike shared preferences which can be more vulnerable to security breaches.
- Scalability: Protobuf's efficient serialization makes it suitable for larger datasets and more complex data structures.
Installation #
Add dbx to your pubspec.yaml:
dependencies:
dbx: ^0.1.0
you can install packages from the command line:
with Flutter:
$ flutter pub get
with Dart:
$ dart pub get
Initialization #
with Flutter:
import 'package:dbx/dbx.dart';
// Basic initialization
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DBX.init();
runApp(MyApp());
}
// Advanced initialization with custom encryption and path
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DBX.init(
DBXEncryptionConfig(mode: encrypt.AESMode.gcm, keyLength: 32, ivLength: 16),
'/custom/path/to/storage.dbx' // optional custom file path
);
runApp(MyApp());
}
// Sync-enabled initialization (same keySeed across devices)
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DBX.init(
DBXEncryptionConfig(
mode: encrypt.AESMode.cbc,
keyLength: 32,
ivLength: 16,
keySeed: 'user-specific-shared-secret' // Derive keys from seed
)
);
runApp(MyApp());
}
with dart:
import 'package:dbx/dbx.dart';
// Example usage
void main() async {
await DBX.init();
}
Usage #
Basic Operations #
- Store Data (Typed)
// Store data
DBX.setString('message', 'Give it a try!');
DBX.setString('username', 'john_doe');
DBX.setInt('age', 30);
DBX.setDouble('height', 5.9);
DBX.setBool('isAdmin', true);
DBX.setBytes(
'profilePicture', File('assets/profile.jpeg').readAsBytesSync());
DBX.setStringList('tags', ['dart', 'flutter']);
DBX.setIntList('scores', [100, 95, 85]);
DBX.setDoubleList('strike_rate', [36.6, 37.0, 36.8]);
DBX.setBoolList('attendence', [true, false, true]);
DBX.setBytesList('files', [
File('assets/file1.jpeg').readAsBytesSync(),
File('assets/logo.jpeg').readAsBytesSync(),
File('assets/file2.jpeg').readAsBytesSync()
]);
- Generic Operations
// Type-agnostic get/set
DBX.set('generic_string', 'Hello Generic!'); // String
DBX.set('generic_int', 42); // int
DBX.set('generic_list', [1, 2, 3]); // List<int>
String? value = DBX.get('generic_string');
int? number = DBX.get('generic_int');
List<int>? list = DBX.get('generic_list');
- JSON Objects (for custom Dart objects)
// Store JSON objects
DBX.setJson('user_profile', {'name': 'John', 'age': 30, 'active': true});
// Retrieve JSON objects
Map<String, dynamic>? profile = DBX.getJson('user_profile');
// Use with custom objects: User.fromJson(profile!)
Batch Operations #
// Bulk set
DBX.setStringBulk({'key1': 'value1', 'key2': 'value2'});
// Bulk get
Map<String, String?> values = DBX.getStringBulk(['key1', 'key2']);
Indexing & Search #
// Check existence
bool exists = DBX.containsKey('someKey');
// Get all keys
List<String> allKeys = DBX.getAllKeys();
// Get sorted keys
List<String> sortedKeys = DBX.getAllKeysSorted();
// Prefix search
List<String> appKeys = DBX.getKeysStartingWith('app');
Synchronization & Backup #
DBX provides export/import functionality for data backup and synchronization across devices.
Basic Backup and Restore
// Create a backup
Uint8List backupData = await DBX.exportData();
// Save to local file or external storage
await File('/path/to/backup.dbx').writeAsBytes(backupData);
// Restore from backup
Uint8List restoredData = await File('/path/to/backup.dbx').readAsBytes();
await DBX.importData(restoredData);
Cross-Device Synchronization
For syncing data between multiple devices:
- Initialize with shared key seed (same on all devices):
await DBX.init(DBXEncryptionConfig(keySeed: 'user-unique-id'));
- Sync workflow:
// On source device - export and upload
Uint8List syncData = await DBX.exportData();
await cloudService.uploadSyncData(syncData);
// On target device - download and import
Uint8List downloadedData = await cloudService.downloadSyncData();
await DBX.importData(downloadedData);
Cloud Storage Integration Example
class DBXCloudSync {
static Future<void> uploadToCloud() async {
final data = await DBX.exportData();
// Upload to Firebase Storage, AWS S3, etc.
await FirebaseStorage.instance
.ref('user-data/${userId}/dbx-sync')
.putData(data);
}
static Future<void> downloadFromCloud() async {
final data = await FirebaseStorage.instance
.ref('user-data/${userId}/dbx-sync')
.getData();
if (data != null) {
await DBX.importData(data);
}
}
}
// Usage
await DBXCloudSync.uploadToCloud(); // Backup current data
await DBXCloudSync.downloadFromCloud(); // Restore on new device
Key Points
- Security: Exported data remains encrypted - safe for cloud storage
- Atomic: Import replaces entire database state
- Migration: Automatic schema updates on import
- Performance: Export/import handles compression internally
- Conflict Resolution: Last imported data wins (no built-in merging)
Use export/import for periodic backups or when switching devices. For real-time sync, combine with cloud storage webhooks.
Note: For cross-device sync, ensure all devices use the same keySeed during initialization to maintain data compatibility.
Utilities #
// Get statistics
int keyCount = DBX.keyCount;
int fileSize = await DBX.fileSize;
// Remove all data
DBX.removeAll();
// Clear and delete file
DBX.clearAll();
- Read Data
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text('DBX Example'),
centerTitle: true,
),
body: Center(
child: FutureBuilder(
future: writeData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final files =DBX.getBytesList('files');
return Column(
children: [
Image.memory(Uint8List.fromList(
DBX.getBytes('profilePicture') ?? [])),
Text("Message: ${DBX.getString('message') ?? 'No data'}"),
Text(
"Username: ${DBX.getString('username') ?? 'No Data'}"), // Output: john_doe
Text("Age: ${DBX.getInt('age')}"), // Output: 30
Text(
"Height: ${DBX.getDouble('height')}"), // Output: 5.9
Text(
"IsAdmin: ${DBX.getBool('isAdmin')}"), // Output: true
Text(
"Tags: ${DBX.getStringList('tags') ?? [].join(',')}"), // Output: [dart, flutter]
Text(
"Scores: ${DBX.getIntList('scores') ?? [].join(',')}"), // Output: [100, 95, 85]
Text(
"Strike Rate: ${DBX.getDoubleList('strike_rate')}"), // Output: [36.6, 37.0, 36.8]
Text(
"Attendence: ${DBX.getBoolList('attendence')}"), // Output: [true, false, true]
if (files != null)
Row(
mainAxisSize: MainAxisSize.min,
children: [
for (final file in files)
Image.memory(Uint8List.fromList(file)),
],
),
],
);
} else {
return CircularProgressIndicator();
}
},
),
),
),
);
}
Contributing #
We welcome contributions from the community! If you have any ideas, suggestions, or bug reports, please open an issue or submit a pull request.
Sponsor #
If you find this package useful, please consider sponsoring its development to help us continue improving it. You will be mentioned below
License #
This project is licensed under the MIT License - see the LICENSE file for details.
TODO #
- Observable Streams: Add reactive streams for real-time data change notifications.
- Advanced Queries: Implement more complex query operations beyond prefix search.
- Cloud Integration: Built-in support for popular cloud storage providers.
- Typed Object Support: Add strongly-typed object serialization with code generation.