work_db
A lightweight, cross-platform local database for Dart and Flutter. Simple key-value storage organized in collections, with support for Desktop, Web, and Mobile platforms.
Features
- ✅ Cross-platform: Works on Windows, macOS, Linux, Web, iOS, and Android
- ✅ Simple API: Easy-to-use CRUD operations
- ✅ Collections: Organize data in named collections
- ✅ Batch operations: Create, retrieve, and update multiple items at once
- ✅ Type-safe: Full Dart type safety with generics
- ✅ No dependencies: Minimal footprint (only
pathpackage for IO) - ✅ Well tested: 99 tests across all implementations
Installation
dependencies:
work_db: ^1.0.0
Quick Start
import 'package:work_db/work_db.dart';
void main() async {
// Create a database instance
final db = WorkDbFactory.forIo(dataPath: './data');
// Create an item
await db.create(ItemWithId(
id: 'user-1',
collection: 'users',
item: {'name': 'John Doe', 'email': 'john@example.com'},
));
// Retrieve the item
final user = await db.retrieve(ItemId(id: 'user-1', collection: 'users'));
print(user?.item['name']); // John Doe
// Update the item
await db.update(ItemWithId(
id: 'user-1',
collection: 'users',
item: {'name': 'John Doe', 'email': 'john.updated@example.com'},
));
// Delete the item
await db.delete(ItemId(id: 'user-1', collection: 'users'));
}
Platform-Specific Setup
Desktop (Windows, macOS, Linux) & Server
import 'package:work_db/work_db.dart';
final db = WorkDbFactory.forIo(dataPath: './my_app_data');
Web
import 'package:work_db/work_db.dart';
// Uses localStorage under the hood
final db = WorkDbFactory.forWeb();
Flutter Mobile (iOS, Android)
import 'package:work_db/work_db.dart';
import 'package:path_provider/path_provider.dart';
Future<IWorkDb> createDatabase() async {
final dir = await getApplicationDocumentsDirectory();
return WorkDbFactory.forIo(dataPath: dir.path);
}
Testing
import 'package:work_db/work_db.dart';
// In-memory storage, perfect for unit tests
final db = WorkDbFactory.forMemory();
API Reference
Factory Methods
| Method | Description |
|---|---|
WorkDbFactory.forIo(dataPath:) |
File system storage (Desktop/Server) |
WorkDbFactory.forWeb(storage:) |
localStorage storage (Web) |
WorkDbFactory.forMemory() |
In-memory storage (Testing) |
WorkDbFactory.createIo(dataPath:) |
Non-singleton IO instance |
WorkDbFactory.createWeb(storage:) |
Non-singleton Web instance |
WorkDbFactory.createMemory() |
Non-singleton Memory instance |
Database Operations
| Method | Description |
|---|---|
create(ItemWithId) |
Create a new item (throws if exists) |
createMultiple(List<ItemWithId>) |
Create multiple items |
update(ItemWithId) |
Update existing item (throws if not exists) |
createOrUpdate(ItemWithId) |
Create or update (upsert) |
createOrUpdateMultiple(List<ItemWithId>) |
Batch upsert |
retrieve(ItemId) |
Get item or null |
retrieveMultiple(List<ItemId>) |
Get multiple items |
delete(ItemId) |
Delete item (throws if not exists) |
deleteCollection(String) |
Delete entire collection |
clearDatabase() |
Delete all data |
getItemsInCollection(String) |
List item IDs in collection |
getCollections() |
List all collection names |
Examples
Batch Operations
// Create multiple items at once
await db.createMultiple([
ItemWithId(id: 'user-1', collection: 'users', item: {'name': 'Alice'}),
ItemWithId(id: 'user-2', collection: 'users', item: {'name': 'Bob'}),
ItemWithId(id: 'user-3', collection: 'users', item: {'name': 'Charlie'}),
]);
// Retrieve multiple items
final users = await db.retrieveMultiple([
ItemId(id: 'user-1', collection: 'users'),
ItemId(id: 'user-2', collection: 'users'),
]);
Upsert (Create or Update)
// Creates if not exists, updates if exists
await db.createOrUpdate(ItemWithId(
id: 'settings',
collection: 'config',
item: {'theme': 'dark', 'language': 'en'},
));
Collection Management
// List all collections
final collections = await db.getCollections();
print(collections); // ['users', 'config', 'posts']
// List items in a collection
final userIds = await db.getItemsInCollection('users');
print(userIds); // ['user-1', 'user-2', 'user-3']
// Delete entire collection
await db.deleteCollection('cache');
// Clear everything
await db.clearDatabase();
Nested Data
await db.create(ItemWithId(
id: 'post-1',
collection: 'posts',
item: {
'title': 'Hello World',
'content': 'This is my first post',
'author': {
'name': 'John',
'email': 'john@example.com',
},
'tags': ['dart', 'flutter', 'database'],
'metadata': {
'views': 0,
'likes': 0,
'published': true,
},
},
));
Storage Format
Data is stored as JSON files in a simple directory structure:
<dataPath>/
└── WorkDB/
├── users/
│ ├── user-1 (JSON file)
│ └── user-2 (JSON file)
└── posts/
└── post-1 (JSON file)
Error Handling
try {
await db.create(ItemWithId(
id: 'duplicate',
collection: 'test',
item: {'data': 'value'},
));
// This will throw - item already exists
await db.create(ItemWithId(
id: 'duplicate',
collection: 'test',
item: {'data': 'new value'},
));
} catch (e) {
print('Error: $e');
}
// Use createOrUpdate to avoid exceptions
await db.createOrUpdate(ItemWithId(
id: 'safe',
collection: 'test',
item: {'data': 'value'},
));
Testing Your Code
import 'package:test/test.dart';
import 'package:work_db/work_db.dart';
void main() {
late IWorkDb db;
setUp(() {
// Fresh in-memory database for each test
db = WorkDbFactory.createMemory();
});
test('should store and retrieve data', () async {
await db.create(ItemWithId(
id: 'test-1',
collection: 'test',
item: {'value': 42},
));
final result = await db.retrieve(ItemId(id: 'test-1', collection: 'test'));
expect(result?.item['value'], equals(42));
});
}
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
Libraries
- work_db
- WorkDB - A cross-platform local database for Dart.