dbx 0.1.0 copy "dbx: ^0.1.0" to clipboard
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.

Logo

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_storage and encrypted with the encrypt library, 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>, and Map<String, dynamic> (JSON).
      • Uint8List for bytes, JSON for custom objects
  • 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.🚀
  • 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']);
  // 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:

  1. Initialize with shared key seed (same on all devices):
await DBX.init(DBXEncryptionConfig(keySeed: 'user-unique-id'));
  1. 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.

If you find this package useful, please consider sponsoring its development to help us continue improving it. You will be mentioned below

Sponsor

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.
5
likes
160
points
133
downloads

Documentation

API reference

Publisher

verified publisherkumpali.com

Weekly Downloads

A Data Storage Solution, created with simplicity in mind. It is a simple, lightweight, and fast database solution for Flutter apps.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

archive, async, crypto, encrypt, fixnum, flutter, flutter_secure_storage, path_provider, protobuf

More

Packages that depend on dbx