Skip to content

Commit

Permalink
fix(graphql): Hive integration
Browse files Browse the repository at this point in the history
  • Loading branch information
budde377 committed Apr 3, 2022
1 parent ebc96e7 commit a8726cb
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 14 deletions.
20 changes: 10 additions & 10 deletions packages/graphql/lib/src/cache/hive_store.dart
Expand Up @@ -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))`
Expand All @@ -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);
Expand All @@ -35,22 +35,22 @@ 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)`
///
/// **N.B.**: [box] must already be [opened] with either [openBox], [open], or `initHiveForFlutter` from `graphql_flutter`.
/// 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
Expand All @@ -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);
}

Expand All @@ -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();
}
8 changes: 4 additions & 4 deletions packages/graphql/lib/src/cache/store.dart
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -52,15 +52,15 @@ 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
void delete(String dataId) => data.remove(dataId);

/// 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();
}
43 changes: 43 additions & 0 deletions packages/graphql/test/cache/store_test.dart
Expand Up @@ -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);
Expand Down

0 comments on commit a8726cb

Please sign in to comment.