Data Layer API
SQLite persistence with versioned schema migrations and parameterized queries.
LocalStorage
lib/data/local_storage.dart
Singleton SQLite database manager using sqflite. Provides a shared Database instance with lazy initialization.
Database Schema (v4)
users
| Column | Type | Constraint |
|---|---|---|
id | TEXT | PRIMARY KEY |
name | TEXT | โ |
email | TEXT | โ |
events
| Column | Type | Default | Added in |
|---|---|---|---|
id | TEXT | PRIMARY KEY | v1 |
title | TEXT | โ | v1 |
description | TEXT | '' | v2 |
date | TEXT | โ | v1 |
priority | TEXT | 'medium' | v2 |
tags | TEXT | '[]' | v3 |
recurrence | TEXT | null | v4 |
Schema Migrations
Migrations run incrementally via
onUpgrade. Each version check is independent โ upgrading from v1โv4 runs all three ALTER TABLE statements. This ensures any prior version upgrades correctly.
Static Methods
| Method | Signature | Description |
|---|---|---|
database | Future<Database> (getter) | Returns cached DB instance; creates on first access |
insert | (String table, Map data) โ Future<void> | Insert/upsert row with ConflictAlgorithm.replace |
getAll | (String table) โ Future<List<Map>> | Query all rows from a table |
delete | (String table, String id) โ Future<void> | Delete row by ID (parameterized query) |
close | () โ Future<void> | Close DB connection and clear cache. Next access re-opens. |
SQL Injection Prevention
All queries use parameterized
whereArgs โ never string interpolation. The delete method uses where: 'id = ?', whereArgs: [id].
EventRepository
lib/data/repositories/event_repository.dart
Thin wrapper around LocalStorage providing domain-specific event operations.
Methods
| Method | Signature | Description |
|---|---|---|
getEvents() | Future<List<Map>> | Fetch all events from the events table |
saveEvent(json) | Future<void> | Insert/upsert an event |
updateEvent(json) | Future<void> | Update an existing event (uses upsert) |
deleteEvent(id) | Future<void> | Delete event by ID |
UserRepository
lib/data/repositories/user_repository.dart
Persists user profiles for session restoration.
Methods
| Method | Signature | Description |
|---|---|---|
saveUser(json) | Future<void> | Persist user profile |
getUser(id) | Future<Map?> | Retrieve user by ID |
Persistence Flow
Widget Action
โ
โผ
EventService
โโโ EventProvider.addEvent() โ instant UI update
โโโ EventRepository.saveEvent() โ async disk write
โโโ LocalStorage.insert('events', json)
โโโ sqflite INSERT OR REPLACE
Why This Pattern?
- Responsiveness โ UI updates instantly (in-memory first)
- Resilience โ Disk failures don't crash the app
- Consistency โ Single service coordinates both stores
- Testability โ Repository can be mocked in EventService tests