fix(graphql): Hive integration
MODIFY
packages/graphql/lib/src/cache/hive_store.dart
packages/graphql/lib/src/cache/hive_store.dart
@@ -13,9 +13,9 @@ class HiveStore extends Store {
/// Opens a box. Convenience pass through to [Hive.openBox].
///
/// If the box is already open, the instance is returned and all provided parameters are being ignored.
- static Future<Box<Map<String, dynamic>>> openBox(
- {required String boxName, String? path}) async {
- return await Hive.openBox<Map<String, dynamic>>(boxName, path: path);
+ static Future<Box<Map<dynamic, dynamic>?>> openBox(String boxName,
+ {String? path}) async {
+ return await Hive.openBox<Map<dynamic, dynamic>?>(boxName, path: path);
}
/// Convenience factory for `HiveStore(await openBox(boxName ?? 'graphqlClientStore', path: path))`
@@ -26,7 +26,7 @@ class HiveStore extends Store {
String boxName = defaultBoxName,
String? path,
}) async =>
- HiveStore(await openBox(boxName: boxName, path: path));
+ HiveStore(await openBox(boxName, path: path));
/// Init Hive on specific Path
static void init({required String onPath}) => Hive.init(onPath);
@@ -35,7 +35,7 @@ class HiveStore extends Store {
///
/// **WARNING**: Directly editing the contents of the store will not automatically
/// rebroadcast operations.
- final Box<Map<String, dynamic>?> box;
+ final Box<Map<dynamic, dynamic>?> box;
/// Creates a HiveStore initialized with the given [box], defaulting to `Hive.box(defaultBoxName)`
///
@@ -43,14 +43,14 @@ class HiveStore extends Store {
/// This lets us decouple the async initialization logic, making store usage elsewhere much more straightforward.
///
/// [opened]: https://docs.hivedb.dev/#/README?id=open-a-box
- HiveStore([Box<Map<String, dynamic>>? box])
- : this.box = box ?? Hive.box<Map<String, dynamic>>(defaultBoxName);
+ HiveStore([Box<Map<dynamic, dynamic>?>? box])
+ : this.box = box ?? Hive.box<Map<dynamic, dynamic>?>(defaultBoxName);
@override
Map<String, dynamic>? get(String dataId) {
final result = box.get(dataId);
if (result == null) return null;
- return Map.from(result);
+ return Map<String, dynamic>.from(result);
}
@override
@@ -59,7 +59,7 @@ class HiveStore extends Store {
}
@override
- void putAll(Map<String, Map<String, dynamic>> data) {
+ void putAll(Map<String, Map<String, dynamic>?> data) {
box.putAll(data);
}
@@ -69,7 +69,7 @@ class HiveStore extends Store {
}
@override
- Map<String, Map<String, dynamic>> toMap() => Map.unmodifiable(box.toMap());
+ Map<String, Map<String, dynamic>?> toMap() => Map.unmodifiable(box.toMap());
Future<void> reset() => box.clear();
}

MODIFY
packages/graphql/lib/src/cache/store.dart
packages/graphql/lib/src/cache/store.dart
@@ -15,7 +15,7 @@ abstract class Store {
/// [put] all entries from [data] into the store
///
/// Functionally equivalent to `data.map(put);`
- void putAll(Map<String, Map<String, dynamic>> data);
+ void putAll(Map<String, Map<String, dynamic>?> data);
/// Delete the value of the [dataId] from the store, if preset
void delete(String dataId);
@@ -27,7 +27,7 @@ abstract class Store {
///
/// NOTE: some [Store]s might return mutable objects
/// referenced by the store itself.
- Map<String, Map<String, dynamic>> toMap();
+ Map<String, Map<String, dynamic>?> toMap();
}
/// Simplest possible [Map]-backed store
@@ -52,7 +52,7 @@ class InMemoryStore extends Store {
void put(String dataId, Map<String, dynamic>? value) => data[dataId] = value;
@override
- void putAll(Map<String, Map<String, dynamic>> entries) =>
+ void putAll(Map<String, Map<String, dynamic>?> entries) =>
data.addAll(entries);
@override
@@ -60,7 +60,7 @@ class InMemoryStore extends Store {
/// Return the underlying [data] as an unmodifiable [Map].
@override
- Map<String, Map<String, dynamic>> toMap() => Map.unmodifiable(data);
+ Map<String, Map<String, dynamic>?> toMap() => Map.unmodifiable(data);
void reset() => data.clear();
}

MODIFY
packages/graphql/test/cache/store_test.dart
packages/graphql/test/cache/store_test.dart
@@ -71,6 +71,49 @@ void main() {
await store.box.deleteFromDisk();
});
+ group("Re-open store works", () {
+ test("Can re-open store", () async {
+ final box1 = await HiveStore.openBox(
+ 're-open-store',
+ path: path,
+ );
+ final store = HiveStore(box1);
+ store.put("id", {'foo': 'bar'});
+ final readData = await store.get("id");
+ expect(readData, equals({'foo': 'bar'}));
+ expect(readData, isA<Map<String, dynamic>>());
+ await box1.close();
+ final box2 = await HiveStore.openBox(
+ 're-open-store',
+ path: path,
+ );
+ final store2 = HiveStore(box2);
+ final readData2 = await store2.get('id');
+ expect(readData2, equals({'foo': 'bar'}));
+ expect(readData2, isA<Map<String, dynamic>>());
+ });
+ test("Can put null", () async {
+ final box1 = await HiveStore.openBox(
+ 'put-null',
+ path: path,
+ );
+ final store = HiveStore(box1);
+ store.put("id", {'foo': 'bar'});
+ store.put("id", null);
+ final readData = await store.get("id");
+ expect(readData, equals(null));
+ await box1.close();
+ final box2 = await HiveStore.openBox(
+ 'put-null',
+ path: path,
+ );
+ final store2 = HiveStore(box2);
+ final readData2 = await store2.get('id');
+ expect(readData2, equals(null));
+ expect(store2.toMap(), isA<Map<String, Map<String, dynamic>?>>());
+ expect(store2.toMap(), equals({'id': null}));
+ });
+ });
tearDownAll(() async {
await Directory(path).delete(recursive: true);

fix(graphql): Hive integration