ZenStorage class abstract

Interface for persisting query data.

Implement this to enable offline support and hydration for ZenQuery.

Important: the wire format is Map<String, dynamic>, not a JSON string

The write and read methods pass a plain Dart map — there is no jsonEncode/jsonDecode anywhere in the ZenQuery cache layer itself. Whether you encode that map to a string (e.g. for SharedPreferences) or store it natively (e.g. SQLite/Drift columns) is entirely up to your adapter.

This also means ZenQueryConfig.toJson and fromJson return/accept Map<String, dynamic> directly — Drift's toMap()/fromMap() work without any JSON encoding step.

Copy-paste recipes

SharedPreferences (encodes map → JSON string)

import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:zenify/zenify.dart';

class SharedPreferencesStorage implements ZenStorage {
  SharedPreferences? _prefs;
  Future<SharedPreferences> get _instance async =>
      _prefs ??= await SharedPreferences.getInstance();

  @override
  Future<void> write(String key, Map<String, dynamic> json) async =>
      (await _instance).setString(key, jsonEncode(json));

  @override
  Future<Map<String, dynamic>?> read(String key) async {
    final raw = (await _instance).getString(key);
    return raw != null ? jsonDecode(raw) as Map<String, dynamic> : null;
  }

  @override
  Future<void> delete(String key) async =>
      (await _instance).remove(key);
}

SQLite / Drift (stores map natively — no JSON encoding needed)

import 'package:zenify/zenify.dart';

// Drift database with a simple key-value table:
// CREATE TABLE zen_cache (key TEXT PRIMARY KEY, data TEXT, timestamp INTEGER)
class DriftStorage implements ZenStorage {
  final AppDatabase _db;
  DriftStorage(this._db);

  @override
  Future<void> write(String key, Map<String, dynamic> json) =>
      _db.zenCache.insertOrReplace(ZenCacheCompanion(
        key: Value(key),
        data: Value(jsonEncode(json['data'])), // encode only the data payload
        timestamp: Value(json['timestamp'] as int),
      ));

  @override
  Future<Map<String, dynamic>?> read(String key) async {
    final row = await _db.zenCache.select()
        .where((t) => t.key.equals(key)).getSingleOrNull();
    if (row == null) return null;
    return {'data': jsonDecode(row.data), 'timestamp': row.timestamp, 'version': 1};
  }

  @override
  Future<void> delete(String key) =>
      (_db.zenCache.delete()..where((t) => t.key.equals(key))).go();
}

// Usage — toMap()/fromMap() plug in directly, no extra encoding:
ZenQueryConfig<User>(
  persist: true,
  storage: DriftStorage(db),
  toJson: (user) => user.toMap(),   // Drift's native Map — no jsonEncode
  fromJson: User.fromMap,            // Drift's native Map — no jsonDecode
)
Implementers

Constructors

ZenStorage()

Properties

hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

delete(String key) Future<void>
Delete data from storage.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
read(String key) Future<Map<String, dynamic>?>
Read data from storage.
toString() String
A string representation of this object.
inherited
write(String key, Map<String, dynamic> json) Future<void>
Write data to storage.

Operators

operator ==(Object other) bool
The equality operator.
inherited