diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index a32586d85..0ccbc3602 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -13,14 +13,14 @@ jobs: image: google/dart:latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Collect coverage run: | - pub get - pub global activate test_coverage - pub global run test_coverage --exclude "**/js/**" + dart pub get + dart pub global activate test_coverage + dart pub global run test_coverage --exclude "**/js/**" working-directory: hive - - uses: codecov/codecov-action@v1.0.0 + - uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} file: hive/coverage/lcov.info diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ac20af956..6ccba3d24 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,31 +7,34 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - test-platform: [vm, chrome] - dart-channel: ["2.12.0", "2.13.0", "2.14.0"] + include: + - test-platform: vm + compiler: kernel + - test-platform: chrome + compiler: dart2js + - test-platform: chrome + compiler: dart2wasm steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 + - uses: browser-actions/setup-chrome@v1 - uses: dart-lang/setup-dart@v1 with: - sdk: ${{ matrix.dart-channel }} + sdk: 3.4.0 - name: Install dependencies - run: pub get + run: dart pub get working-directory: hive - name: Run tests - run: pub run test -p ${{ matrix.test-platform }} + run: dart test -p ${{ matrix.test-platform }} -c ${{ matrix.compiler }} working-directory: hive test-hive-flutter: runs-on: ubuntu-latest strategy: matrix: - flutter-channel: [dev, beta, stable] + flutter-channel: [beta, stable] steps: - - uses: actions/checkout@v1 - - uses: actions/setup-java@v1 - with: - java-version: "12.x" - - uses: subosito/flutter-action@v1 + - uses: actions/checkout@v4 + - uses: subosito/flutter-action@v2 with: channel: ${{ matrix.flutter-channel }} - name: Override dependency version @@ -49,17 +52,17 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dart-channel: ["2.12.0", "2.13.0"] + dart-channel: ["3.4.0"] steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.dart-channel }} - name: Install dependencies - run: pub get + run: dart pub get working-directory: hive_generator/example - name: Generate build_runner output - run: pub run build_runner build --delete-conflicting-outputs + run: dart pub run build_runner build --delete-conflicting-outputs working-directory: hive_generator/example check-score: @@ -68,9 +71,10 @@ jobs: matrix: package: [hive, hive_generator, hive_flutter] steps: - - uses: actions/checkout@v1 - - uses: axel-op/dart-package-analyzer@v3 - with: - githubToken: ${{ secrets.GITHUB_TOKEN }} - relativePath: ${{ matrix.package }} - minAnnotationLevel: warning + - uses: actions/checkout@v4 + - uses: subosito/flutter-action@v2 + - run: | + cd ${{ matrix.package }} + flutter pub get + dart pub global activate pana + pana --no-warning --exit-code-threshold 0 diff --git a/hive/example/pubspec.yaml b/hive/example/pubspec.yaml index 497bea585..8306ab156 100644 --- a/hive/example/pubspec.yaml +++ b/hive/example/pubspec.yaml @@ -8,7 +8,7 @@ dev_dependencies: build_runner: any environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: ^3.0.0 dependency_overrides: hive: diff --git a/hive/lib/hive.dart b/hive/lib/hive.dart index df8685d1d..31ce2e9ff 100644 --- a/hive/lib/hive.dart +++ b/hive/lib/hive.dart @@ -19,7 +19,7 @@ import 'package:hive/src/util/extensions.dart'; import 'package:meta/meta.dart'; export 'src/box_collection/box_collection_stub.dart' - if (dart.library.html) 'package:hive/src/box_collection/box_collection_indexed_db.dart' + if (dart.library.js_interop) 'package:hive/src/box_collection/box_collection_indexed_db.dart' if (dart.library.io) 'package:hive/src/box_collection/box_collection.dart'; export 'src/object/hive_object.dart' show HiveObject, HiveObjectMixin; diff --git a/hive/lib/src/backend/js/native/backend_manager.dart b/hive/lib/src/backend/js/native/backend_manager.dart index 1909b7033..fa97b584a 100644 --- a/hive/lib/src/backend/js/native/backend_manager.dart +++ b/hive/lib/src/backend/js/native/backend_manager.dart @@ -1,16 +1,14 @@ import 'dart:async'; -import 'dart:html'; -import 'dart:indexed_db'; -import 'dart:js' as js; +import 'dart:js_interop'; import 'package:hive/hive.dart'; import 'package:hive/src/backend/js/native/storage_backend_js.dart'; +import 'package:hive/src/backend/js/native/utils.dart'; import 'package:hive/src/backend/storage_backend.dart'; +import 'package:web/web.dart'; /// Opens IndexedDB databases class BackendManager implements BackendManagerInterface { - IdbFactory? get indexedDB => js.context.hasProperty('window') - ? window.indexedDB - : WorkerGlobalScope.instance.indexedDB; + IDBFactory? get indexedDB => window.self.indexedDB; @override Future open(String name, String? path, bool crashRecovery, @@ -19,29 +17,28 @@ class BackendManager implements BackendManagerInterface { final databaseName = collection ?? name; final objectStoreName = collection == null ? 'box' : name; - var db = - await indexedDB!.open(databaseName, version: 1, onUpgradeNeeded: (e) { - var db = e.target.result as Database; - if (!(db.objectStoreNames ?? []).contains(objectStoreName)) { + final request = indexedDB!.open(databaseName, 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + if (!db.objectStoreNames.contains(objectStoreName)) { db.createObjectStore(objectStoreName); } - }); + }.toJS; + var db = await request.asFuture(); // in case the objectStore is not contained, re-open the db and // update version - if (!(db.objectStoreNames ?? []).contains(objectStoreName)) { + if (!db.objectStoreNames.contains(objectStoreName)) { print( 'Creating objectStore $objectStoreName in database $databaseName...'); - db = await indexedDB!.open( - databaseName, - version: (db.version ?? 1) + 1, - onUpgradeNeeded: (e) { - var db = e.target.result as Database; - if (!(db.objectStoreNames ?? []).contains(objectStoreName)) { - db.createObjectStore(objectStoreName); - } - }, - ); + final request = indexedDB!.open(databaseName, db.version + 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + if (!db.objectStoreNames.contains(objectStoreName)) { + db.createObjectStore(objectStoreName); + } + }.toJS; + db = await request.asFuture(); } print('Got object store $objectStoreName in database $databaseName.'); @@ -59,17 +56,18 @@ class BackendManager implements BackendManagerInterface { // directly deleting the entire DB if a non-collection Box if (collection == null) { - await indexedDB!.deleteDatabase(databaseName); + await indexedDB!.deleteDatabase(databaseName).asFuture(); } else { - final db = - await indexedDB!.open(databaseName, version: 1, onUpgradeNeeded: (e) { - var db = e.target.result as Database; - if ((db.objectStoreNames ?? []).contains(objectStoreName)) { + final request = indexedDB!.open(databaseName, 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + if (db.objectStoreNames.contains(objectStoreName)) { db.deleteObjectStore(objectStoreName); } - }); - if ((db.objectStoreNames ?? []).isEmpty) { - indexedDB!.deleteDatabase(databaseName); + }.toJS; + final db = await request.asFuture(); + if (db.objectStoreNames.length == 0) { + await indexedDB!.deleteDatabase(databaseName).asFuture(); } } } @@ -83,17 +81,20 @@ class BackendManager implements BackendManagerInterface { try { var _exists = true; if (collection == null) { - await indexedDB!.open(databaseName, version: 1, onUpgradeNeeded: (e) { - e.target.transaction!.abort(); + final request = indexedDB!.open(databaseName, 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + (e.target as IDBOpenDBRequest).transaction!.abort(); _exists = false; - }); + }.toJS; + await request.asFuture(); } else { - final db = - await indexedDB!.open(collection, version: 1, onUpgradeNeeded: (e) { - var db = e.target.result as Database; - _exists = (db.objectStoreNames ?? []).contains(objectStoreName); - }); - _exists = (db.objectStoreNames ?? []).contains(objectStoreName); + final request = indexedDB!.open(collection, 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + _exists = db.objectStoreNames.contains(objectStoreName); + }.toJS; + final db = await request.asFuture(); + _exists = db.objectStoreNames.contains(objectStoreName); } return _exists; } catch (error) { diff --git a/hive/lib/src/backend/js/native/storage_backend_js.dart b/hive/lib/src/backend/js/native/storage_backend_js.dart index 772d0c136..0074f524b 100644 --- a/hive/lib/src/backend/js/native/storage_backend_js.dart +++ b/hive/lib/src/backend/js/native/storage_backend_js.dart @@ -1,11 +1,10 @@ import 'dart:async'; -import 'dart:html'; -import 'dart:indexed_db'; -import 'dart:js' as js; -import 'dart:js_util'; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'dart:typed_data'; import 'package:hive/hive.dart'; +import 'package:hive/src/backend/js/native/utils.dart'; import 'package:hive/src/backend/storage_backend.dart'; import 'package:hive/src/binary/binary_reader_impl.dart'; import 'package:hive/src/binary/binary_writer_impl.dart'; @@ -13,11 +12,12 @@ import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/box/keystore.dart'; import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:meta/meta.dart'; +import 'package:web/web.dart'; /// Handles all IndexedDB related tasks class StorageBackendJs extends StorageBackend { static const _bytePrefix = [0x90, 0xA9]; - final Database _db; + final IDBDatabase _db; final HiveCipher? _cipher; final String objectStoreName; @@ -41,14 +41,14 @@ class StorageBackendJs extends StorageBackend { /// Not part of public API @visibleForTesting - dynamic encodeValue(Frame frame) { + JSAny? encodeValue(Frame frame) { var value = frame.value; if (_cipher == null) { if (value == null) { - return value; + return null; } else if (value is Uint8List) { if (!_isEncoded(value)) { - return value.buffer; + return value.buffer.toJS; } } else if (value is num || value is bool || @@ -56,7 +56,7 @@ class StorageBackendJs extends StorageBackend { value is List || value is List || value is List) { - return value; + return value.jsify(); } } @@ -71,14 +71,15 @@ class StorageBackendJs extends StorageBackend { var bytes = frameWriter.toBytes(); var sublist = bytes.sublist(0, bytes.length); - return sublist.buffer; + return sublist.buffer.toJS; } /// Not part of public API @visibleForTesting - dynamic decodeValue(dynamic value) { - if (value is ByteBuffer) { - var bytes = Uint8List.view(value); + Object? decodeValue(JSAny? value) { + if (value.isA()) { + value as JSArrayBuffer; + var bytes = Uint8List.view(value.toDart); if (_isEncoded(bytes)) { var reader = BinaryReaderImpl(bytes, _registry); reader.skip(2); @@ -91,56 +92,49 @@ class StorageBackendJs extends StorageBackend { return bytes; } } else { - return value; + return value.dartify(); } } /// Not part of public API @visibleForTesting - ObjectStore getStore(bool write) { + IDBObjectStore getStore(bool write) { return _db - .transaction(objectStoreName, write ? 'readwrite' : 'readonly') + .transaction(objectStoreName.toJS, write ? 'readwrite' : 'readonly') .objectStore(objectStoreName); } /// Not part of public API @visibleForTesting - Future> getKeys({bool cursor = false}) { + Future> getKeys({bool cursor = false}) async { var store = getStore(false); - if (hasProperty(store, 'getAllKeys') && !cursor) { - var completer = Completer>(); - var request = getStore(false).getAllKeys(null); - request.onSuccess.listen((_) { - completer.complete(request.result as List?); - }); - request.onError.listen((_) { - completer.completeError(request.error!); - }); - return completer.future; + if (store.has('getAllKeys') && !cursor) { + final result = await getStore(false).getAllKeys(null).asFuture(); + return result.toDart.map((e) { + if (e.isA()) { + e as JSNumber; + return e.toDartInt; + } else if (e.isA()) { + e as JSString; + return e.toDart; + } + }).toList(); } else { - return store.openCursor(autoAdvance: true).map((e) => e.key).toList(); + return store.iterate().map((e) => e.key.dartify()).toList(); } } /// Not part of public API @visibleForTesting - Future> getValues({bool cursor = false}) { + Future> getValues({bool cursor = false}) async { var store = getStore(false); - if (hasProperty(store, 'getAll') && !cursor) { - var completer = Completer>(); - var request = store.getAll(null); - request.onSuccess.listen((_) { - var values = (request.result as List).map(decodeValue); - completer.complete(values); - }); - request.onError.listen((_) { - completer.completeError(request.error!); - }); - return completer.future; + if (store.has('getAll') && !cursor) { + final result = await store.getAll(null).asFuture(); + return result.toDart.map(decodeValue); } else { - return store.openCursor(autoAdvance: true).map((e) => e.value).toList(); + return store.iterate().map((e) => e.value.dartify()).toList(); } } @@ -166,8 +160,8 @@ class StorageBackendJs extends StorageBackend { } @override - Future readValue(Frame frame) async { - var value = await getStore(false).getObject(frame.key); + Future readValue(Frame frame) async { + final value = await getStore(false).get(frame.key.jsify()).asFuture(); return decodeValue(value); } @@ -176,9 +170,9 @@ class StorageBackendJs extends StorageBackend { var store = getStore(true); for (var frame in frames) { if (frame.deleted) { - await store.delete(frame.key); + await store.delete(frame.key.jsify()).asFuture(); } else { - await store.put(encodeValue(frame), frame.key); + await store.put(encodeValue(frame), frame.key.jsify()).asFuture(); } } } @@ -190,7 +184,7 @@ class StorageBackendJs extends StorageBackend { @override Future clear() { - return getStore(true).clear(); + return getStore(true).clear().asFuture(); } @override @@ -201,25 +195,24 @@ class StorageBackendJs extends StorageBackend { @override Future deleteFromDisk() async { - final indexDB = js.context.hasProperty('window') - ? window.indexedDB - : WorkerGlobalScope.instance.indexedDB; + final indexDB = window.self.indexedDB; print('Delete ${_db.name} // $objectStoreName from disk'); // directly deleting the entire DB if a non-collection Box - if (_db.objectStoreNames?.length == 1) { - await indexDB!.deleteDatabase(_db.name!); + if (_db.objectStoreNames.length == 1) { + await indexDB.deleteDatabase(_db.name).asFuture(); } else { - final db = - await indexDB!.open(_db.name!, version: 1, onUpgradeNeeded: (e) { - var db = e.target.result as Database; - if ((db.objectStoreNames ?? []).contains(objectStoreName)) { + final request = indexDB.open(_db.name, 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + if (db.objectStoreNames.contains(objectStoreName)) { db.deleteObjectStore(objectStoreName); } - }); - if ((db.objectStoreNames ?? []).isEmpty) { - await indexDB.deleteDatabase(_db.name!); + }.toJS; + final db = await request.asFuture(); + if (db.objectStoreNames.length == 0) { + await indexDB.deleteDatabase(_db.name).asFuture(); } } } diff --git a/hive/lib/src/backend/js/native/utils.dart b/hive/lib/src/backend/js/native/utils.dart new file mode 100644 index 000000000..3cf81328d --- /dev/null +++ b/hive/lib/src/backend/js/native/utils.dart @@ -0,0 +1,37 @@ +import 'dart:async'; +import 'dart:js_interop'; + +import 'package:web/web.dart'; + +extension IDBRequestExtension on IDBRequest { + Future asFuture() { + final completer = Completer(); + onsuccess = (Event e) { + completer.complete(result as T); + }.toJS; + onerror = (Event e) { + completer.completeError(error!); + }.toJS; + return completer.future; + } +} + +extension IDBObjectStoreExtension on IDBObjectStore { + Stream iterate() { + final controller = StreamController(); + final request = openCursor(); + request.onsuccess = (Event e) { + final cursor = (e.target as IDBRequest).result as IDBCursorWithValue?; + if (cursor == null) { + controller.close(); + return; + } + controller.add(cursor); + cursor.continue_(); + }.toJS; + request.onerror = (Event e) { + controller.addError(request.error!); + }.toJS; + return controller.stream; + } +} diff --git a/hive/lib/src/backend/storage_backend.dart b/hive/lib/src/backend/storage_backend.dart index 8d20adb12..31bd612ef 100644 --- a/hive/lib/src/backend/storage_backend.dart +++ b/hive/lib/src/backend/storage_backend.dart @@ -6,7 +6,7 @@ import 'package:hive/src/box/keystore.dart'; export 'package:hive/src/backend/stub/backend_manager.dart' if (dart.library.io) 'package:hive/src/backend/vm/backend_manager.dart' - if (dart.library.html) 'package:hive/src/backend/js/backend_manager.dart'; + if (dart.library.js_interop) 'package:hive/src/backend/js/backend_manager.dart'; /// Abstract storage backend abstract class StorageBackend { diff --git a/hive/lib/src/binary/frame.dart b/hive/lib/src/binary/frame.dart index 5130f4700..cbb1062e4 100644 --- a/hive/lib/src/binary/frame.dart +++ b/hive/lib/src/binary/frame.dart @@ -3,10 +3,10 @@ import 'package:hive/hive.dart'; /// Not part of public API class Frame { /// Not part of public API - final dynamic key; + final Object? key; /// Not part of public API - final dynamic value; + final Object? value; /// Not part of public API final bool deleted; diff --git a/hive/lib/src/box_collection/box_collection_indexed_db.dart b/hive/lib/src/box_collection/box_collection_indexed_db.dart index 306cc45b5..31f44253c 100644 --- a/hive/lib/src/box_collection/box_collection_indexed_db.dart +++ b/hive/lib/src/box_collection/box_collection_indexed_db.dart @@ -1,13 +1,15 @@ -import 'dart:html'; -import 'dart:indexed_db'; +import 'dart:async'; +import 'dart:js_interop'; import 'package:hive/hive.dart'; +import 'package:hive/src/backend/js/native/utils.dart'; import 'package:hive/src/box_collection/box_collection_stub.dart' as implementation; +import 'package:web/web.dart'; /// represents a [BoxCollection] for raw use with indexed DB class BoxCollection implements implementation.BoxCollection { - final Database _db; + final IDBDatabase _db; @override final Set boxNames; @@ -16,26 +18,25 @@ class BoxCollection implements implementation.BoxCollection { static Future open( String name, Set boxNames, { - dynamic path, + String? path, HiveCipher? key, }) async { - final factory = window.indexedDB; - if (factory == null) { - throw Exception( - 'Unable to open FluffyBox collection - IndexedDB not supported in this browser!'); - } - final _db = await factory.open(name, version: 1, - onUpgradeNeeded: (VersionChangeEvent event) { - final _db = event.target.result; + final request = window.self.indexedDB.open(name, 1); + request.onupgradeneeded = (IDBVersionChangeEvent event) { + final _db = (event.target as IDBOpenDBRequest).result as IDBDatabase; for (final name in boxNames) { - _db.createObjectStore(name, autoIncrement: true); + _db.createObjectStore( + name, + IDBObjectStoreParameters(autoIncrement: true), + ); } - }); + }.toJS; + final _db = await request.asFuture(); return BoxCollection(_db, boxNames); } @override - String get name => _db.name!; + String get name => _db.name; @override Future> openBox(String name, @@ -61,7 +62,7 @@ class BoxCollection implements implementation.BoxCollection { final List _openBoxes = []; - List Function(Transaction txn)>? _txnCache; + List Function(IDBTransaction txn)>? _txnCache; @override Future transaction( @@ -77,14 +78,20 @@ class BoxCollection implements implementation.BoxCollection { _txnCache = []; await action(); final cache = - List Function(Transaction txn)>.from(_txnCache ?? []); + List Function(IDBTransaction txn)>.from(_txnCache ?? []); _txnCache = null; if (cache.isEmpty) return; - final txn = _db.transaction(boxNames, readOnly ? 'readonly' : 'readwrite'); + final txn = _db.transaction( + boxNames.map((e) => e.toJS).toList().toJS, + readOnly ? 'readonly' : 'readwrite', + ); for (final fun in cache) { fun(txn); } - await txn.completed; + final completer = Completer(); + txn.oncomplete = (Event e) { + completer.complete(); + }.toJS; return; } @@ -93,17 +100,13 @@ class BoxCollection implements implementation.BoxCollection { @override Future deleteFromDisk() async { - final factory = window.indexedDB; for (final box in _openBoxes) { box._cache.clear(); box._cachedKeys = null; } _openBoxes.clear(); _db.close(); - if (factory == null || _db.name == null) { - throw Exception('Unable to delete fluffybox collection'); - } - factory.deleteDatabase(_db.name!); + window.self.indexedDB.deleteDatabase(_db.name); } } @@ -128,58 +131,58 @@ class CollectionBox implements implementation.CollectionBox { } @override - Future> getAllKeys([Transaction? txn]) async { + Future> getAllKeys([IDBTransaction? txn]) async { final cachedKey = _cachedKeys; if (cachedKey != null) return cachedKey.toList(); - txn ??= boxCollection._db.transaction(name, 'readonly'); + txn ??= boxCollection._db.transaction(name.toJS, 'readonly'); final store = txn.objectStore(name); - final request = store.getAllKeys(null); - await request.onSuccess.first; + final result = await store.getAllKeys(null).asFuture(); final List keys = - List.from(request.result.cast() as Iterable); + List.from(result.toDart.cast().map((e) => e.toDart)); _cachedKeys = keys.toSet(); return keys; } @override - Future> getAllValues([Transaction? txn]) async { - txn ??= boxCollection._db.transaction(name, 'readonly'); + Future> getAllValues([IDBTransaction? txn]) async { + txn ??= boxCollection._db.transaction(name.toJS, 'readonly'); final store = txn.objectStore(name); final map = {}; - final cursorStream = store.openCursor(autoAdvance: true); - await for (final cursor in cursorStream) { - map[cursor.key as String] = cursor.value as V; + await for (final entry in store.iterate()) { + map[(entry.key as JSString).toDart] = entry.value.dartify() as V; } return map; } @override - Future get(String key, [Transaction? txn]) async { + Future get(String key, [IDBTransaction? txn]) async { if (_cache.containsKey(key)) return _cache[key]; - txn ??= boxCollection._db.transaction(name, 'readonly'); + txn ??= boxCollection._db.transaction(name.toJS, 'readonly'); final store = txn.objectStore(name); - _cache[key] = await store.getObject(key) as V?; + final value = await store.get(key.toJS).asFuture(); + _cache[key] = value.dartify() as V?; return _cache[key]; } @override - Future> getAll(List keys, [Transaction? txn]) async { + Future> getAll(List keys, [IDBTransaction? txn]) async { if (!keys.any((key) => !_cache.containsKey(key))) { return keys.map((key) => _cache[key]).toList(); } - txn ??= boxCollection._db.transaction(name, 'readonly'); + txn ??= boxCollection._db.transaction(name.toJS, 'readonly'); final store = txn.objectStore(name); - final list = await Future.wait(keys.map(store.getObject)); + final list = + await Future.wait(keys.map((e) => store.get(e.toJS).asFuture())); for (var i = 0; i < keys.length; i++) { - _cache[keys[i]] = list[i] as V?; + _cache[keys[i]] = list[i].dartify() as V?; } return list.cast(); } @override Future put(String key, V val, [Object? transaction]) async { - Transaction? txn; - if (transaction is Transaction) { + IDBTransaction? txn; + if (transaction is IDBTransaction) { txn = transaction; } if (val == null) { @@ -193,16 +196,16 @@ class CollectionBox implements implementation.CollectionBox { return; } - txn ??= boxCollection._db.transaction(name, 'readwrite'); + txn ??= boxCollection._db.transaction(name.toJS, 'readwrite'); final store = txn.objectStore(name); - await store.put(val, key); + await store.put(val.jsify(), key.toJS).asFuture(); _cache[key] = val; _cachedKeys?.add(key); return; } @override - Future delete(String key, [Transaction? txn]) async { + Future delete(String key, [IDBTransaction? txn]) async { final txnCache = boxCollection._txnCache; if (txnCache != null) { txnCache.add((txn) => delete(key, txn)); @@ -211,16 +214,16 @@ class CollectionBox implements implementation.CollectionBox { return; } - txn ??= boxCollection._db.transaction(name, 'readwrite'); + txn ??= boxCollection._db.transaction(name.toJS, 'readwrite'); final store = txn.objectStore(name); - await store.delete(key); + await store.delete(key.toJS).asFuture(); _cache[key] = null; _cachedKeys?.remove(key); return; } @override - Future deleteAll(List keys, [Transaction? txn]) async { + Future deleteAll(List keys, [IDBTransaction? txn]) async { final txnCache = boxCollection._txnCache; if (txnCache != null) { txnCache.add((txn) => deleteAll(keys, txn)); @@ -231,10 +234,10 @@ class CollectionBox implements implementation.CollectionBox { return; } - txn ??= boxCollection._db.transaction(name, 'readwrite'); + txn ??= boxCollection._db.transaction(name.toJS, 'readwrite'); final store = txn.objectStore(name); for (final key in keys) { - await store.delete(key); + await store.delete(key.toJS).asFuture(); _cache[key] = null; _cachedKeys?.removeAll(keys); } @@ -242,7 +245,7 @@ class CollectionBox implements implementation.CollectionBox { } @override - Future clear([Transaction? txn]) async { + Future clear([IDBTransaction? txn]) async { final txnCache = boxCollection._txnCache; if (txnCache != null) { txnCache.add(clear); @@ -251,9 +254,9 @@ class CollectionBox implements implementation.CollectionBox { return; } - txn ??= boxCollection._db.transaction(name, 'readwrite'); + txn ??= boxCollection._db.transaction(name.toJS, 'readwrite'); final store = txn.objectStore(name); - await store.clear(); + await store.clear().asFuture(); _cache.clear(); _cachedKeys = null; return; diff --git a/hive/lib/src/object/hive_collection_mixin.dart b/hive/lib/src/object/hive_collection_mixin.dart index 86890f016..6c378b0f2 100644 --- a/hive/lib/src/object/hive_collection_mixin.dart +++ b/hive/lib/src/object/hive_collection_mixin.dart @@ -1,7 +1,7 @@ import 'package:hive/hive.dart'; /// Implemetation of [HiveCollection]. -abstract class HiveCollectionMixin +mixin HiveCollectionMixin implements HiveCollection { @override Iterable get keys sync* { diff --git a/hive/lib/src/util/delegating_list_view_mixin.dart b/hive/lib/src/util/delegating_list_view_mixin.dart index 43cc86c54..2f78ba935 100644 --- a/hive/lib/src/util/delegating_list_view_mixin.dart +++ b/hive/lib/src/util/delegating_list_view_mixin.dart @@ -1,7 +1,7 @@ import 'package:meta/meta.dart'; /// Not part of public API -abstract class DelegatingListViewMixin implements List { +mixin DelegatingListViewMixin implements List { /// Not part of public API @protected @visibleForTesting diff --git a/hive/pubspec.yaml b/hive/pubspec.yaml index 35dafb498..1d67e764a 100644 --- a/hive/pubspec.yaml +++ b/hive/pubspec.yaml @@ -5,11 +5,12 @@ homepage: https://github.com/hivedb/hive/tree/master/hive documentation: https://docs.hivedb.dev/ environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ^3.4.0 dependencies: meta: ^1.3.0 crypto: ^3.0.0 + web: ^0.5.1 dev_dependencies: test: ^1.17.12 diff --git a/hive/test/integration/integration.dart b/hive/test/integration/integration.dart index 108a2ded1..5cccddd87 100644 --- a/hive/test/integration/integration.dart +++ b/hive/test/integration/integration.dart @@ -23,7 +23,7 @@ Future createHive() async { Future> openBox(bool lazy, {HiveInterface? hive, List? encryptionKey}) async { hive ??= await createHive(); - var id = Random().nextInt(99999999); + var id = Random.secure().nextInt(99999999); HiveCipher? cipher; if (encryptionKey != null) { cipher = HiveAesCipher(encryptionKey); diff --git a/hive/test/tests/backend/js/backend_manager_test.dart b/hive/test/tests/backend/js/backend_manager_test.dart index 2af99f4fd..60de6d198 100644 --- a/hive/test/tests/backend/js/backend_manager_test.dart +++ b/hive/test/tests/backend/js/backend_manager_test.dart @@ -1,18 +1,21 @@ @TestOn('browser') -import 'dart:html'; -import 'dart:indexed_db'; + +import 'dart:js_interop'; import 'package:hive/src/backend/js/backend_manager.dart'; +import 'package:hive/src/backend/js/native/utils.dart'; import 'package:test/test.dart'; +import 'package:web/web.dart'; -Future _openDb() async { - return await window.indexedDB!.open('testBox', version: 1, - onUpgradeNeeded: (e) { - var db = e.target.result as Database; - if (!db.objectStoreNames!.contains('box')) { +Future _openDb() { + final request = window.self.indexedDB.open('testBox', 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + if (!db.objectStoreNames.contains('box')) { db.createObjectStore('box'); } - }); + }.toJS; + return request.asFuture(); } void main() { diff --git a/hive/test/tests/backend/js/storage_backend_js_test.dart b/hive/test/tests/backend/js/storage_backend_js_test.dart index d91f50dcc..6daeaab2a 100644 --- a/hive/test/tests/backend/js/storage_backend_js_test.dart +++ b/hive/test/tests/backend/js/storage_backend_js_test.dart @@ -1,48 +1,51 @@ @TestOn('browser') import 'dart:async' show Future; -import 'dart:html'; -import 'dart:indexed_db'; +import 'dart:js_interop'; import 'dart:typed_data'; import 'package:hive/hive.dart'; import 'package:hive/src/backend/js/native/storage_backend_js.dart'; +import 'package:hive/src/backend/js/native/utils.dart'; import 'package:hive/src/binary/binary_writer_impl.dart'; import 'package:hive/src/binary/frame.dart'; import 'package:hive/src/box/change_notifier.dart'; import 'package:hive/src/box/keystore.dart'; import 'package:hive/src/registry/type_registry_impl.dart'; import 'package:test/test.dart'; +import 'package:web/web.dart'; import '../../frames.dart'; -late final Database _nullDatabase; +late final IDBDatabase _nullDatabase; StorageBackendJs _getBackend({ - Database? db, + IDBDatabase? db, HiveCipher? cipher, TypeRegistry registry = TypeRegistryImpl.nullImpl, }) { return StorageBackendJs(db ?? _nullDatabase, cipher, 'box', registry); } -Future _openDb([String name = 'testBox']) async { - return await window.indexedDB!.open(name, version: 1, onUpgradeNeeded: (e) { - var db = e.target.result as Database; - if (!db.objectStoreNames!.contains('box')) { +Future _openDb([String name = 'testBox']) async { + final request = window.self.indexedDB.open(name, 1); + request.onupgradeneeded = (IDBVersionChangeEvent e) { + var db = (e.target as IDBOpenDBRequest).result as IDBDatabase; + if (!db.objectStoreNames.contains('box')) { db.createObjectStore('box'); } - }); + }.toJS; + return await request.asFuture(); } -ObjectStore _getStore(Database db) { - return db.transaction('box', 'readwrite').objectStore('box'); +IDBObjectStore _getStore(IDBDatabase db) { + return db.transaction('box'.toJS, 'readwrite').objectStore('box'); } -Future _getDbWith(Map content) async { +Future _getDbWith(Map content) async { var db = await _openDb(); var store = _getStore(db); - await store.clear(); - content.forEach((k, v) => store.put(v, k)); + await store.clear().asFuture(); + content.forEach((k, v) => store.put(v.jsify(), k.toJS)); return db; } @@ -61,12 +64,12 @@ void main() async { ]; var backend = _getBackend(); for (var value in values) { - expect(backend.encodeValue(Frame('key', value)), value); + expect(backend.encodeValue(Frame('key', value)).dartify(), value); } var bytes = Uint8List.fromList([1, 2, 3]); - var buffer = backend.encodeValue(Frame('key', bytes)) as ByteBuffer; - expect(Uint8List.view(buffer), [1, 2, 3]); + var buffer = backend.encodeValue(Frame('key', bytes)) as JSArrayBuffer; + expect(Uint8List.view(buffer.toDart), [1, 2, 3]); }); test('crypto', () { @@ -74,8 +77,8 @@ void main() async { StorageBackendJs(_nullDatabase, testCipher, 'box', testRegistry); var i = 0; for (var frame in testFrames) { - var buffer = backend.encodeValue(frame) as ByteBuffer; - var bytes = Uint8List.view(buffer); + var buffer = backend.encodeValue(frame) as JSArrayBuffer; + var bytes = Uint8List.view(buffer.toDart); expect(bytes.sublist(28), [0x90, 0xA9, ...frameValuesBytesEncrypted[i]].sublist(28)); i++; @@ -89,8 +92,8 @@ void main() async { 'otherKey': null }); var backend = StorageBackendJs(_nullDatabase, null, 'box'); - var encoded = - Uint8List.view(backend.encodeValue(frame) as ByteBuffer); + var encoded = Uint8List.view( + (backend.encodeValue(frame) as JSArrayBuffer).toDart); var writer = BinaryWriterImpl(TypeRegistryImpl.nullImpl) ..write(frame.value); @@ -100,8 +103,9 @@ void main() async { test('bytes which start with signature', () { var frame = Frame(0, Uint8List.fromList([0x90, 0xA9, 1, 2, 3])); var backend = _getBackend(); - var encoded = - Uint8List.view(backend.encodeValue(frame) as ByteBuffer); + var encoded = Uint8List.view( + (backend.encodeValue(frame) as JSArrayBuffer).toDart, + ); var writer = BinaryWriterImpl(TypeRegistryImpl.nullImpl) ..write(frame.value); @@ -114,15 +118,15 @@ void main() async { test('primitive', () { var backend = _getBackend(); expect(backend.decodeValue(null), null); - expect(backend.decodeValue(11), 11); - expect(backend.decodeValue(17.25), 17.25); - expect(backend.decodeValue(true), true); - expect(backend.decodeValue('hello'), 'hello'); - expect(backend.decodeValue([11, 12, 13]), [11, 12, 13]); - expect(backend.decodeValue([17.25, 17.26]), [17.25, 17.26]); + expect(backend.decodeValue(11.toJS), 11); + expect(backend.decodeValue(17.25.toJS), 17.25); + expect(backend.decodeValue(true.toJS), true); + expect(backend.decodeValue('hello'.toJS), 'hello'); + expect(backend.decodeValue([11, 12, 13].jsify()), [11, 12, 13]); + expect(backend.decodeValue([17.25, 17.26].jsify()), [17.25, 17.26]); var bytes = Uint8List.fromList([1, 2, 3]); - expect(backend.decodeValue(bytes.buffer), [1, 2, 3]); + expect(backend.decodeValue(bytes.buffer.toJS), [1, 2, 3]); }); test('crypto', () { @@ -131,7 +135,8 @@ void main() async { var i = 0; for (var testFrame in testFrames) { var bytes = [0x90, 0xA9, ...frameValuesBytesEncrypted[i]]; - var value = backend.decodeValue(Uint8List.fromList(bytes).buffer); + var value = + backend.decodeValue(Uint8List.fromList(bytes).buffer.toJS); expect(value, testFrame.value); i++; } diff --git a/hive/test/tests/box_collection/box_collection_test.dart b/hive/test/tests/box_collection/box_collection_test.dart new file mode 100644 index 000000000..294f5a569 --- /dev/null +++ b/hive/test/tests/box_collection/box_collection_test.dart @@ -0,0 +1,120 @@ +import 'package:hive/src/box_collection/box_collection.dart'; +import 'package:test/test.dart'; + +Future _openCollection({bool withData = false}) async { + final collection = + await BoxCollection.open('MyFirstFluffyBox', {'cats', 'dogs'}); + if (withData) { + final catsBox = await collection.openBox('cats'); + await catsBox.put('fluffy', {'name': 'Fluffy', 'age': 4}); + await catsBox.put('loki', {'name': 'Loki', 'age': 2}); + } + return collection; +} + +void main() { + group('BoxCollection', () { + test('.open', () async { + final collection = await _openCollection(); + expect(collection.name, 'MyFirstFluffyBox'); + expect(collection.boxNames, {'cats', 'dogs'}); + }); + test('.openBox', () async { + final collection = await _openCollection(); + try { + await collection.openBox('rabbits'); + throw Exception('BoxCollection.openBox did not throw'); + } catch (e) { + // The test passed + } + final box1 = await collection.openBox('cats'); + expect(box1.name, 'MyFirstFluffyBox_cats'); + }); + + test('.transaction', () async { + final collection = await _openCollection(); + final catsBox = await collection.openBox('cats'); + await collection.transaction(() async { + await catsBox.put('fluffy', {'name': 'Fluffy', 'age': 4}); + await catsBox.put('loki', {'name': 'Loki', 'age': 2}); + }); + expect(await catsBox.get('fluffy'), {'name': 'Fluffy', 'age': 4}); + expect(await catsBox.get('loki'), {'name': 'Loki', 'age': 2}); + }); + }); + + group('CollectionBox', () { + test('.name', () async { + final collection = await _openCollection(); + final box = await collection.openBox('cats'); + expect(box.name, 'MyFirstFluffyBox_cats'); + }); + + test('.boxCollection', () async { + final collection = await _openCollection(); + final box = await collection.openBox('cats'); + expect(box.boxCollection, collection); + }); + + test('.getAllKeys()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + final keys = await box.getAllKeys(); + expect(keys, ['fluffy', 'loki']); + }); + + test('.getAllValues()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + final values = await box.getAllValues(); + expect(values, { + 'fluffy': {'name': 'Fluffy', 'age': 4}, + 'loki': {'name': 'Loki', 'age': 2} + }); + }); + + test('.get()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + expect(await box.get('fluffy'), {'name': 'Fluffy', 'age': 4}); + }); + + test('.getAll()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + final values = await box.getAll(['fluffy', 'loki']); + expect(values, [ + {'name': 'Fluffy', 'age': 4}, + {'name': 'Loki', 'age': 2} + ]); + }); + + test('.put()', () async { + final collection = await _openCollection(); + final box = await collection.openBox('cats'); + await box.put('fluffy', {'name': 'Fluffy', 'age': 4}); + expect(await box.get('fluffy'), {'name': 'Fluffy', 'age': 4}); + }); + + test('.delete()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + await box.delete('fluffy'); + expect(await box.get('fluffy'), null); + }); + + test('.deleteAll()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + await box.deleteAll(['fluffy', 'loki']); + expect(await box.getAllKeys(), []); + }); + + test('.clear()', () async { + final collection = await _openCollection(withData: true); + final box = await collection.openBox('cats'); + await box.clear(); + expect(await box.getAllKeys(), []); + }); + }); +} diff --git a/hive/test/tests/frames.dart b/hive/test/tests/frames.dart index 96d4b8c44..bf0c22164 100644 --- a/hive/test/tests/frames.dart +++ b/hive/test/tests/frames.dart @@ -137,8 +137,10 @@ Frame lazyFrameWithLength(Frame frame, int length) { void expectFrame(Frame f1, Frame f2) { expect(f1.key, f2.key); - if (f1.value is double && f2.value is double) { - if (f1.value.isNaN as bool && f1.value.isNaN as bool) return; + final f1Value = f1.value; + final f2Value = f2.value; + if (f1Value is double && f2Value is double) { + if (f1Value.isNaN && f2Value.isNaN) return; } expect(f1.value, f2.value); expect(f1.length, f2.length); diff --git a/hive/test/util/is_browser.dart b/hive/test/util/is_browser.dart index 5f9cb392e..2e579bd61 100644 --- a/hive/test/util/is_browser.dart +++ b/hive/test/util/is_browser.dart @@ -1 +1 @@ -export 'is_browser_vm.dart' if (dart.library.html) 'is_browser_js.dart'; +export 'is_browser_vm.dart' if (dart.library.js_interop) 'is_browser_js.dart'; diff --git a/hive_flutter/example/pubspec.yaml b/hive_flutter/example/pubspec.yaml index db449f083..585a2d2f5 100644 --- a/hive_flutter/example/pubspec.yaml +++ b/hive_flutter/example/pubspec.yaml @@ -1,3 +1,3 @@ name: example environment: - sdk: '>=2.10.0 <3.0.0' \ No newline at end of file + sdk: ^3.0.0 \ No newline at end of file diff --git a/hive_flutter/lib/hive_flutter.dart b/hive_flutter/lib/hive_flutter.dart index ac7f52d31..13c862f01 100644 --- a/hive_flutter/lib/hive_flutter.dart +++ b/hive_flutter/lib/hive_flutter.dart @@ -5,10 +5,10 @@ import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:hive/hive.dart'; -import 'package:path/path.dart' if (dart.library.html) 'src/stub/path.dart' - as path_helper; +import 'package:path/path.dart' + if (dart.library.js_interop) 'src/stub/path.dart' as path_helper; import 'package:path_provider/path_provider.dart' - if (dart.library.html) 'src/stub/path_provider.dart'; + if (dart.library.js_interop) 'src/stub/path_provider.dart'; export 'package:hive/hive.dart'; diff --git a/hive_flutter/pubspec.yaml b/hive_flutter/pubspec.yaml index 07545fbf2..d77c0de72 100644 --- a/hive_flutter/pubspec.yaml +++ b/hive_flutter/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://github.com/hivedb/hive/tree/master/hive_flutter documentation: https://docs.hivedb.dev/ environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ^3.0.0 dependencies: flutter: diff --git a/hive_flutter/test/mocks.dart b/hive_flutter/test/mocks.dart index 0eb720890..b8c6cef63 100644 --- a/hive_flutter/test/mocks.dart +++ b/hive_flutter/test/mocks.dart @@ -6,8 +6,8 @@ import 'package:mockito/annotations.dart'; export 'mocks.mocks.dart'; @GenerateMocks([], customMocks: [ - MockSpec(returnNullOnMissingStub: true), - MockSpec(returnNullOnMissingStub: true), + MockSpec(onMissingStub: OnMissingStub.returnDefault), + MockSpec(onMissingStub: OnMissingStub.returnDefault), ]) // ignore: prefer_typing_uninitialized_variables, unused_element var _mocks; diff --git a/hive_generator/example/lib/types.g.dart b/hive_generator/example/lib/types.g.dart index 8cca919d8..945579956 100644 --- a/hive_generator/example/lib/types.g.dart +++ b/hive_generator/example/lib/types.g.dart @@ -6,50 +6,6 @@ part of 'types.dart'; // TypeAdapterGenerator // ************************************************************************** -class Enum1Adapter extends TypeAdapter { - @override - final int typeId = 3; - - @override - Enum1 read(BinaryReader reader) { - switch (reader.readByte()) { - case 0: - return Enum1.emumValue1; - case 1: - return Enum1.emumValue2; - case 2: - return Enum1.emumValue3; - default: - return Enum1.emumValue2; - } - } - - @override - void write(BinaryWriter writer, Enum1 obj) { - switch (obj) { - case Enum1.emumValue1: - writer.writeByte(0); - break; - case Enum1.emumValue2: - writer.writeByte(1); - break; - case Enum1.emumValue3: - writer.writeByte(2); - break; - } - } - - @override - int get hashCode => typeId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is Enum1Adapter && - runtimeType == other.runtimeType && - typeId == other.typeId; -} - class Class1Adapter extends TypeAdapter { @override final int typeId = 1; @@ -107,10 +63,10 @@ class Class2Adapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return Class2( - fields[0] == null ? 0 : fields[0] as int, + fields[0] == null ? 0 : (fields[0] as num).toInt(), fields[1] as String, (fields[6] as Map?)?.map((dynamic k, dynamic v) => MapEntry( - k as int, + (k as num).toInt(), (v as Map).map((dynamic k, dynamic v) => MapEntry(k as String, (v as List).cast())))), ); @@ -150,7 +106,7 @@ class EmptyClassAdapter extends TypeAdapter { @override void write(BinaryWriter writer, EmptyClass obj) { - writer..writeByte(0); + writer.writeByte(0); } @override @@ -163,3 +119,47 @@ class EmptyClassAdapter extends TypeAdapter { runtimeType == other.runtimeType && typeId == other.typeId; } + +class Enum1Adapter extends TypeAdapter { + @override + final int typeId = 3; + + @override + Enum1 read(BinaryReader reader) { + switch (reader.readByte()) { + case 0: + return Enum1.emumValue1; + case 1: + return Enum1.emumValue2; + case 2: + return Enum1.emumValue3; + default: + return Enum1.emumValue2; + } + } + + @override + void write(BinaryWriter writer, Enum1 obj) { + switch (obj) { + case Enum1.emumValue1: + writer.writeByte(0); + break; + case Enum1.emumValue2: + writer.writeByte(1); + break; + case Enum1.emumValue3: + writer.writeByte(2); + break; + } + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is Enum1Adapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/hive_generator/example/pubspec.yaml b/hive_generator/example/pubspec.yaml index 3727b308a..e8f615315 100644 --- a/hive_generator/example/pubspec.yaml +++ b/hive_generator/example/pubspec.yaml @@ -6,7 +6,7 @@ dev_dependencies: hive_generator: path: .. environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: ^3.0.0 dependency_overrides: hive: path: ../../hive diff --git a/hive_generator/lib/src/builder.dart b/hive_generator/lib/src/builder.dart index c523cb389..f8d350bb6 100644 --- a/hive_generator/lib/src/builder.dart +++ b/hive_generator/lib/src/builder.dart @@ -12,7 +12,7 @@ class AdapterField { } abstract class Builder { - final ClassElement cls; + final InterfaceElement cls; final List getters; final List setters; diff --git a/hive_generator/lib/src/class_builder.dart b/hive_generator/lib/src/class_builder.dart index 8b9ce0202..29d2ac141 100644 --- a/hive_generator/lib/src/class_builder.dart +++ b/hive_generator/lib/src/class_builder.dart @@ -7,13 +7,14 @@ import 'package:analyzer/dart/element/type.dart'; import 'package:hive/hive.dart'; import 'package:hive_generator/src/builder.dart'; import 'package:hive_generator/src/helper.dart'; +import 'package:hive_generator/src/type_adapter_generator.dart'; import 'package:source_gen/source_gen.dart'; import 'type_helper.dart'; class ClassBuilder extends Builder { ClassBuilder( - ClassElement cls, + InterfaceElement cls, List getters, List setters, ) : super(cls, getters, setters); @@ -99,6 +100,10 @@ class ClassBuilder extends Builder { return '($variable as List$suffix)${_castIterable(type)}'; } else if (mapChecker.isAssignableFromType(type)) { return '($variable as Map$suffix)${_castMap(type)}'; + } else if (type.isDartCoreInt) { + return '($variable as num$suffix)$suffix.toInt()'; + } else if (type.isDartCoreDouble) { + return '($variable as num$suffix)$suffix.toDouble()'; } else { return '$variable as ${_displayString(type)}'; } diff --git a/hive_generator/lib/src/enum_builder.dart b/hive_generator/lib/src/enum_builder.dart index 8dee4f3c2..6a54ed97b 100644 --- a/hive_generator/lib/src/enum_builder.dart +++ b/hive_generator/lib/src/enum_builder.dart @@ -3,7 +3,7 @@ import 'package:hive_generator/src/builder.dart'; import 'package:hive_generator/src/helper.dart'; class EnumBuilder extends Builder { - EnumBuilder(ClassElement cls, List getters) + EnumBuilder(InterfaceElement cls, List getters) : super(cls, getters); @override diff --git a/hive_generator/lib/src/helper.dart b/hive_generator/lib/src/helper.dart index 0b26021e6..3fb569864 100644 --- a/hive_generator/lib/src/helper.dart +++ b/hive_generator/lib/src/helper.dart @@ -32,13 +32,6 @@ bool isLibraryNNBD(Element element) { } } -Iterable getTypeAndAllSupertypes(ClassElement cls) { - var types = {}; - types.add(cls); - types.addAll(cls.allSupertypes.map((it) => it.element)); - return types; -} - void check(bool condition, Object error) { if (!condition) { // ignore: only_throw_errors diff --git a/hive_generator/lib/src/type_adapter_generator.dart b/hive_generator/lib/src/type_adapter_generator.dart index 7f00d4a90..adff6106b 100644 --- a/hive_generator/lib/src/type_adapter_generator.dart +++ b/hive_generator/lib/src/type_adapter_generator.dart @@ -6,6 +6,7 @@ import 'package:hive_generator/src/class_builder.dart'; import 'package:hive_generator/src/enum_builder.dart'; import 'package:hive_generator/src/helper.dart'; import 'package:source_gen/source_gen.dart'; +import 'package:source_helper/source_helper.dart'; class TypeAdapterGenerator extends GeneratorForAnnotation { static String generateName(String typeName) { @@ -36,7 +37,7 @@ class TypeAdapterGenerator extends GeneratorForAnnotation { var typeId = getTypeId(annotation); var adapterName = getAdapterName(cls.name, annotation); - var builder = cls.isEnum + var builder = cls.thisType.isEnum ? EnumBuilder(cls, getters) : ClassBuilder(cls, getters, setters); @@ -68,14 +69,14 @@ class TypeAdapterGenerator extends GeneratorForAnnotation { '''; } - ClassElement getClass(Element element) { + InterfaceElement getClass(Element element) { check(element.kind == ElementKind.CLASS || element.kind == ElementKind.ENUM, 'Only classes or enums are allowed to be annotated with @HiveType.'); - return element as ClassElement; + return element as InterfaceElement; } - Set getAllAccessorNames(ClassElement cls) { + Set getAllAccessorNames(InterfaceElement cls) { var accessorNames = {}; var supertypes = cls.allSupertypes.map((it) => it.element); @@ -94,7 +95,7 @@ class TypeAdapterGenerator extends GeneratorForAnnotation { } List> getAccessors( - ClassElement cls, LibraryElement library) { + InterfaceElement cls, LibraryElement library) { var accessorNames = getAllAccessorNames(cls); var getters = []; diff --git a/hive_generator/pubspec.yaml b/hive_generator/pubspec.yaml index d9802becc..a9220e6b9 100644 --- a/hive_generator/pubspec.yaml +++ b/hive_generator/pubspec.yaml @@ -5,13 +5,13 @@ homepage: https://github.com/hivedb/hive/tree/master/hive_generator documentation: https://docs.hivedb.dev/ environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ^3.0.0 dependencies: build: ^2.0.0 source_gen: ^1.0.0 hive: ^2.0.4 - analyzer: ">=1.0.0 <5.0.0" + analyzer: ^6.0.0 source_helper: ^1.1.0 dev_dependencies: