vex_storage 1.0.0 copy "vex_storage: ^1.0.0" to clipboard
vex_storage: ^1.0.0 copied to clipboard

The ultimate Flutter/Dart storage solution. Zero external dependencies. Blazing-fast key-value store + full SQL-like query engine + reactive streams + optional AES-256 encryption. Replaces GetStorage, [...]

⚡ VexStorage #

The ultimate Flutter/Dart storage solution.
Zero external dependencies. Blazing fast. SQL-like queries. Reactive streams. AES-256 encryption.
One package to replace them all.

pub version Dart SDK Flutter License: MIT No external deps


Why VexStorage? #

Every existing storage package for Flutter solves part of the puzzle:

Need Package Problem
Simple key-value GetStorage No queries, no types, no encryption
Typed objects Hive Requires code generation, no queries
SQL queries sqflite Platform-specific, verbose API, no encryption
All of the above ❌ Nothing Until now

VexStorage combines the best of all three — and adds features none of them have.


🆚 Package Comparison #

Feature VexStorage GetStorage Hive sqflite
Zero external dependencies ❌ (path_provider) ❌ (native plugins)
No code generation ❌ (build_runner)
Pure Dart (no native code)
Works on all platforms ❌ (no web/desktop)
Simple key-value API
Typed documents / objects
SQL-like query engine
Dot-notation nested fields
Fluent query builder
B-tree indexes
Reactive streams (watch)
Watch a single document
Watch a live query
AES-256 encryption (built-in)
Write-Ahead Log (crash safety)
Atomic batch writes
Automatic compaction
Schema migrations
Aggregation (sum/avg/min/max)
groupBy
DateTime / Uint8List types
Export / Import
In-memory adapter (for tests)
Custom storage adapter
Pagination (page/limit/offset)
Field projection (select)
OR / AND filter groups
Regex / startsWith / endsWith
Null-safe field exists check

What VexStorage fixes from each package #

vs GetStorage

  • ✅ Full query engine — not just key-value
  • ✅ Typed documents with nested field support
  • ✅ AES-256 encryption (GetStorage has none)
  • ✅ Reactive streams — GetStorage has no watch()
  • ✅ Crash-safe WAL (GetStorage can corrupt on crash)

vs Hive

  • No code generation — no build_runner, no @HiveType, no adapters to write
  • ✅ Full SQL-like query engine — Hive can only filter with custom code
  • ✅ Built-in encryption (Hive requires a separate hive_cipher)
  • ✅ Aggregation, groupBy, projections — Hive has none
  • ✅ Native-code-free — Hive uses native binary format

vs sqflite

  • ✅ Works on all platforms including Web and macOS — sqflite doesn't
  • No SQL strings — type-safe fluent query builder, no injection risks
  • Schema-free — no CREATE TABLE, no ALTER TABLE ever needed
  • Built-in encryption — sqflite requires SQLCipher (complex setup)
  • Reactive — sqflite has no watch() or live queries
  • ✅ Simple setup — Vex.init() vs configuring SQLite migrations manually

Installation #

dependencies:
  vex_storage: ^1.0.0
flutter pub get

No other steps. No native setup. No build_runner. No code generation. Just install and use.


Quick Start #

1. Initialise #

import 'package:vex_storage/vex_storage.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final dir = await getApplicationDocumentsDirectory();
  await Vex.init(
    options: VexOptions(directory: dir.path),
  );

  runApp(MyApp());
}

2. Open a collection #

final users = await Vex.collection('users');

3. Store data #

// Insert a document (auto-id)
final doc = await users.put({
  'name': 'Alice',
  'age': 30,
  'address': {'city': 'London', 'zip': 'EC1A'},
});

// Insert with your own id
await users.putWithId('user_001', {'name': 'Bob', 'age': 25});

// Simple key-value (like GetStorage)
await users.write('lastSync', DateTime.now());
final lastSync = users.read<DateTime>('lastSync');

4. Query data #

// Fluent query builder
final results = users
  .query()
  .where('age').gte(18)
  .and('address.city').eq('London')  // ← dot-notation nested fields
  .sortBy('name')
  .limit(20)
  .offset(0)
  .findAll();

// OR groups
final adminsOrMods = users.query().or([
  VexFilter.eq('role', 'admin'),
  VexFilter.eq('role', 'moderator'),
]).findAll();

// Pagination
final page2 = users.query().sortBy('name').page(1, pageSize: 20).findAll();

// Count
final londonCount = users.query().where('city').eq('London').count();

// Exists check
final hasAdmin = users.query().where('role').eq('admin').exists();

5. Update & Delete #

// Merge updates (keeps existing fields)
await users.update(doc.id, {'age': 31, 'verified': true});

// Upsert (insert or update)
await users.upsert('user_001', {'name': 'Bob', 'age': 26});

// Delete one
await users.delete(doc.id);

// Delete all
await users.clear();

6. Reactive Streams #

// Watch all changes
users.watch().listen((event) {
  print('Changed: ${event.type}');
});

// Watch a single document
users.watchDocument(doc.id).listen((updatedDoc) {
  setState(() => _doc = updatedDoc);
});

// Watch a live query — re-runs automatically on any change
users
  .watchQuery(() => users.query().where('active').eq(true).sortBy('name'))
  .listen((activeDocs) {
    setState(() => _activeUsers = activeDocs);
  });

7. Aggregation #

final total  = users.sumOf('score');
final avg    = users.avgOf('score');
final oldest = users.maxOf('age');
final youngest = users.minOf('age');

// Group by field
final byCity = users.groupBy('city');
// → {'London': [...], 'Paris': [...]}

8. Indexes (for large datasets) #

// Create once — automatically kept in sync
users.createIndex('email');
users.createIndex('age', order: VexIndexOrder.descending);

// Queries on indexed fields are O(log n) instead of O(n)
final alice = users.query().where('email').eq('alice@example.com').findFirst();

9. Encryption #

await Vex.init(
  options: VexOptions(
    directory: dir.path,
    cipher: VexCipher.fromPassword('my-super-secret'),
    // Or from raw bytes:
    // cipher: VexCipher.fromKey(myKeyBytes),
  ),
);
// Everything stored on disk is now AES-256 encrypted — no extra steps.

10. Schema Migrations #

final migrator = VexMigrator(currentVersion: 3)
  ..addMigration(0, (doc) => doc.merge({'role': 'user'}))
  ..addMigration(1, (doc) => doc.set('settings.theme', 'light'))
  ..addMigration(2, (doc) => doc.merge({'emailVerified': false}));

await users.migrate(migrator);

11. Testing (in-memory) #

setUp(() async {
  await Vex.init(options: const VexOptions(inMemory: true));
  col = await Vex.collection('test');
});

tearDown(() async {
  await Vex.closeAll();
});

No disk I/O. No cleanup. Tests run in microseconds.


API Reference #

Vex (store) #

Method Description
Vex.init({options}) Initialise once at app start
Vex.collection(name) Open / get a collection
Vex.of(name) Get an already-open collection
Vex.closeAll() Flush & close everything
Vex.deleteCollection(name) Delete files for a collection

VexCollection #

Method Description
put(data) Insert with auto-id → VexDocument
putWithId(id, data) Insert / replace by id
update(id, updates) Merge updates into existing doc
upsert(id, data) Insert or update
get(id) Get one document or null
getAll() Get all documents
delete(id) Delete by id → bool
clear() Delete all documents
putMany(list) Batch insert
write(key, value) Key-value write
read<T>(key) Key-value read
remove(key) Key-value delete
hasKey(key) Key-value existence
query() Start a fluent query
executeQuery(query) Run a pre-built VexQuery
watch() Stream of all changes
watchDocument(id) Stream of one document
watchQuery(builder) Live query stream
createIndex(field) Create a field index
sumOf / avgOf / minOf / maxOf Aggregation
groupBy(field) Group documents
migrate(migrator) Run schema migrations
export() / import(data) Backup and restore
compact() Force WAL compaction

VexQueryBuilder #

Method Description
.where(field).eq(v) Equality filter
.where(field).neq(v) Inequality
.where(field).gt/gte/lt/lte(v) Numeric/string comparison
.where(field).between(a, b) Range filter
.where(field).inList([...]) Membership test
.where(field).contains(s) Substring match
.where(field).startsWith(s) Prefix match
.where(field).endsWith(s) Suffix match
.where(field).matches(regex) Regex match
.where(field).exists() Null check
.or([filters]) OR filter group
.sortBy(field) Sort ascending
.sortByDesc(field) Sort descending
.limit(n) Take first n results
.offset(n) Skip first n results
.page(n, pageSize: 20) Page-based pagination
.select([fields]) Field projection
.findAll() Execute → List
.findFirst() Execute → first or null
.count() Execute → int
.exists() Execute → bool

Architecture #

┌──────────────────────────────────────────────────────────────────┐
│                          VexStorage                               │
│                                                                    │
│  ┌─────────────┐  ┌─────────────────────────────────────────┐    │
│  │    Vex      │  │            VexCollection                 │    │
│  │ (singleton) │──│  CRUD · KV · Query · Aggregation · Watch│    │
│  └─────────────┘  └───────────────────┬─────────────────────┘    │
│                                        │                          │
│                            ┌───────────▼──────────┐              │
│                            │      VexEngine        │              │
│                            │  ┌─────────────────┐  │              │
│                            │  │  In-Memory Map  │  │              │
│                            │  │  (O(1) reads)   │  │              │
│                            │  └────────┬────────┘  │              │
│                            │  ┌────────▼────────┐  │              │
│                            │  │  VexIndex(es)   │  │              │
│                            │  │  (O(log n))     │  │              │
│                            │  └────────┬────────┘  │              │
│                            │  ┌────────▼────────┐  │              │
│                            │  │   WAL Buffer    │  │              │
│                            │  │ (50ms debounce) │  │              │
│                            │  └────────┬────────┘  │              │
│                            └───────────┼───────────┘              │
│                                        │                          │
│          ┌─────────────────────────────▼─────────────────────┐   │
│          │                  VexAdapter                         │   │
│          │   VexFileAdapter            VexMemoryAdapter        │   │
│          │   (snapshot + WAL)          (tests / cache)        │   │
│          └────────────────────────────────────────────────────┘   │
│                                                                    │
│          ┌─────────────────────────────────────────────────────┐  │
│          │   VexCipher (AES-256 CTR, pure Dart, optional)      │  │
│          └─────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘

Performance characteristics #

Operation Complexity Notes
get(id) O(1) HashMap lookup in memory
put(doc) O(1) amortised Write batched to WAL
delete(id) O(1) In-memory remove + WAL
Query (no index) O(n) Full in-memory scan — very fast
Query (with index, eq) O(log n) Binary search on sorted index
putMany(n docs) O(n) Single atomic batch
Compaction O(n) Runs off the main thread trigger

Platform Support #

Platform Supported Notes
Android Provide directory via path_provider
iOS Provide directory via path_provider
macOS Auto-creates .vex_data/ in CWD
Windows Auto-creates .vex_data/ in CWD
Linux Auto-creates .vex_data/ in CWD
Web Use inMemory: true

FAQ #

Q: Do I need to run build_runner?
No. VexStorage requires zero code generation. No annotations, no generated files.

Q: Does it work on Flutter Web?
Yes — use VexOptions(inMemory: true) for web. Persistent web storage via IndexedDB is on the roadmap.

Q: Is it safe to call put() from multiple isolates?
The engine is single-isolate by design (like Hive). For multi-isolate use, open separate collections.

Q: How does encryption affect performance?
AES-256 in CTR mode is very fast in pure Dart. For large datasets, benchmarks show < 5% overhead vs unencrypted.

Q: Can I store custom model classes?
Yes — use VexSerializer.objectToMap(model) to convert any class that implements toJson().


License #

MIT © 2025 Mysterious Coder

1
likes
150
points
11
downloads

Documentation

Documentation
API reference

Publisher

verified publishermysteriouscoder.com

Weekly Downloads

The ultimate Flutter/Dart storage solution. Zero external dependencies. Blazing-fast key-value store + full SQL-like query engine + reactive streams + optional AES-256 encryption. Replaces GetStorage, Hive, and sqflite in one package.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on vex_storage