StoreIT
StoreIT is a high-performance, SQLite-backed caching engine for Flutter, architected with the same philosophy of simplicity and power that defines Redis. It provides a robust key-value store that handles complex data types with native TTL support and background maintenance.
Design Philosophy
StoreIT is built for developers who need more than basic preferences but less than a full relational database.
- Redis-Inspired: Familiar command patterns for Strings, Lists, and Hashes (JSON).
- Predictable Performance: SQLite indexing ensures O(1) or O(log N) lookups even with large datasets.
- Automatic Expiration: Native Time-To-Live (TTL) management at the database level.
- Zero UI Blocking: Maintenance tasks like purging expired keys are offloaded to a background isolate.
Installation
Add the package to your pubspec.yaml:
dependencies:
store_it: ^1.0.0
Introduction to StoreIT
Before executing commands, initialize the store. This establishes the SQLite connection and starts the background maintenance worker.
import 'package:store_it/store_it.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await StoreIT.init();
runApp(MyApp());
}
Data Types
StoreIT supports three primary data types, each with specialized commands:
- Strings: The most basic data type, capable of storing any text data.
- Lists: Ordered collections of strings, supporting append and removal operations.
- JSON (Hashes): Maps of fields and values, allowing for atomic partial updates (merges).
Command Reference
Generic Commands
| Command | Description |
|---|---|
exists(key) |
Returns true if the key exists and has not expired. |
typeOf(key) |
Returns the type of value stored at the key. |
ttl(key) |
Returns the remaining time to live in seconds. |
expire(key, ttl) |
Updates the expiration time for an existing key. |
keys(prefix) |
Returns all keys matching the given prefix. |
delete(key) |
Removes the specified key. |
deleteByPrefix(prefix) |
Removes all keys matching the given prefix. |
flush() |
Removes all keys from the database. |
String Commands
| Command | Description |
|---|---|
set(key, value, {ttl}) |
Sets the string value of a key with optional TTL. |
get(key) |
Returns the string value of a key. |
update(key, value) |
Updates the value of an existing key. |
List Commands
| Command | Description |
|---|---|
listSet(key, list) |
Sets a list of strings at the specified key. |
listGet(key) |
Returns the list of strings at the specified key. |
listAppend(key, items) |
Appends items to the end of the list. |
listRemove(key, items) |
Removes specified items from the list. |
JSON (Hash) Commands
| Command | Description |
|---|---|
jsonSet(key, object) |
Stores a JSON-encodable Map or List. |
jsonGet(key) |
Returns the decoded JSON object. |
jsonMerge(key, patch) |
Merges a Map into an existing JSON object (HSET-like). |
Examples
1. Basic Caching with Expiration
Similar to the Redis SETEX command, you can cache data with an automatic expiration.
// Cache API response for 5 minutes (300 seconds)
await StoreIT.set('api:user:123', jsonResponse, ttlSeconds: 300);
// Later, retrieve the data
String? cachedData = await StoreIT.get('api:user:123');
if (cachedData == null) {
// The data has either expired or never existed
}
2. Activity Logging with Lists
Use Lists to store ordered logs or recent search terms.
// Log user actions
await StoreIT.listAppend('logs:user:42', ['login_success']);
await StoreIT.listAppend('logs:user:42', ['view_dashboard']);
// Retrieve the full activity log
List<String>? logs = await StoreIT.listGet('logs:user:42');
3. Partial Updates for Complex Objects
Atomic merging allows you to update specific fields in a JSON object without fetching and rewriting the entire object.
// Initial state
await StoreIT.jsonSet('config:ui', {
'theme': 'light',
'compact_mode': true,
'font_size': 12
});
// Update only the theme
await StoreIT.jsonMerge('config:ui', {'theme': 'dark'});
4. Bulk Key Management
Manage groups of keys efficiently using prefixes.
// Find all session-related keys
List<String> sessions = await StoreIT.keys(prefix: 'auth:session:');
// Delete all temporary cache entries at once
await StoreIT.deleteByPrefix('temp:');
Persistence and Maintenance
Background Isolate
StoreIT maintains a lean storage footprint by purging expired keys. To ensure this doesn't impact UI frames, the purge logic runs in a separate Dart Isolate.
You can observe background activity through the onPurge hook:
StoreIT.onPurge = (count) {
print('StoreIT Purge: $count keys evicted.');
};
Manual Purging
While the background worker is automatic, you can force a purge of expired records:
int evicted = await StoreIT.purgeExpired();
License
StoreIT is released under the MIT License. See the LICENSE file for details.