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

ColumnTypeConstraint
idTEXTPRIMARY KEY
nameTEXTโ€”
emailTEXTโ€”

events

ColumnTypeDefaultAdded in
idTEXTPRIMARY KEYv1
titleTEXTโ€”v1
descriptionTEXT''v2
dateTEXTโ€”v1
priorityTEXT'medium'v2
tagsTEXT'[]'v3
recurrenceTEXTnullv4
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

MethodSignatureDescription
databaseFuture<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

MethodSignatureDescription
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

MethodSignatureDescription
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?