diff --git a/.cspell/cspell.yaml b/.cspell/cspell.yaml index 59ec0343..c017efef 100644 --- a/.cspell/cspell.yaml +++ b/.cspell/cspell.yaml @@ -13,7 +13,6 @@ ignorePaths: - "**/*.freezed.dart" - "**/*.g.dart" - "**/*.gr.dart" - - "**/*.realm.dart" enableGlobDot: true dictionaryDefinitions: - name: global-allow diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index f50637c1..31aa9677 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -311,17 +311,6 @@ updates: - feat - b:altoke-storage - s:reference - - package-ecosystem: pub - directory: /bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/ - schedule: - interval: daily - reviewers: - - mrverdant13 - labels: - - build - - feat - - b:altoke-storage - - s:reference - package-ecosystem: pub directory: /bricks/altoke_storage/reference/_cd___use_sembast___altoke_entities_sembast_storage/ schedule: diff --git a/README.md b/README.md index 0b4d2324..6da493a4 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,6 @@ Create a storage, **_al toque_** (_quickly_). - [`drift`][pub_package_drift] - [`hive`][pub_package_hive] - [`isar`][pub_package_isar] - - [`realm`][pub_package_realm] - [`sembast`][pub_package_sembast] - **Strict lint rules:**\ @@ -189,7 +188,6 @@ Create a storage, **_al toque_** (_quickly_). [pub_package_freezed]: https://pub.dev/packages/freezed [pub_package_hive]: https://pub.dev/packages/hive [pub_package_isar]: https://pub.dev/packages/isar -[pub_package_realm]: https://pub.dev/packages/realm [pub_package_sembast]: https://pub.dev/packages/sembast [pub_package_drift]: https://pub.dev/packages/drift diff --git a/bricks/altoke_storage/brick/CHANGELOG.md b/bricks/altoke_storage/brick/CHANGELOG.md index bc3dd1c7..ced4f906 100644 --- a/bricks/altoke_storage/brick/CHANGELOG.md +++ b/bricks/altoke_storage/brick/CHANGELOG.md @@ -3,7 +3,6 @@ - **FEAT**: Data persistence with `drift`. - **FEAT**: Data persistence with `hive`. - **FEAT**: Data persistence with `isar`. -- **FEAT**: Data persistence with `realm`. - **FEAT**: Data persistence with `sembast`. - **FEAT**: Strict lint rules with `very_good_analysis`. - **FEAT**: 100% test coverage. diff --git a/bricks/altoke_storage/brick/README.md b/bricks/altoke_storage/brick/README.md index 5f51bdb0..7f286bda 100644 --- a/bricks/altoke_storage/brick/README.md +++ b/bricks/altoke_storage/brick/README.md @@ -55,7 +55,6 @@ Create a storage, **_al toque_** (_quickly_). - [`drift`][pub_package_drift] - [`hive`][pub_package_hive] - [`isar`][pub_package_isar] - - [`realm`][pub_package_realm] - [`sembast`][pub_package_sembast] - **Strict lint rules:**\ @@ -81,7 +80,6 @@ Create a storage, **_al toque_** (_quickly_). [docs_dart_and_flutter_linter_rules_link]: https://dart.dev/tools/linter-rules [pub_package_hive]: https://pub.dev/packages/hive [pub_package_isar]: https://pub.dev/packages/isar -[pub_package_realm]: https://pub.dev/packages/realm [pub_package_sembast]: https://pub.dev/packages/sembast [pub_package_drift]: https://pub.dev/packages/drift [pub_package_very_good_analysis]: https://pub.dev/packages/very_good_analysis diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/.gitignore b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/.gitignore deleted file mode 100644 index 118f3226..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# See https://www.dartlang.org/guides/libraries/private-files - -# Files and directories created by pub -/.dart_tool/ -/.packages -/build/ -/pubspec.lock - -# Testing -/coverage/ - -# Realm -/default.realm.lock -/default.realm.management/ -/binary/ diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/README.md b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/README.md deleted file mode 100644 index 97857577..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Altoke Entities Realm Storage - -A persistent storage for Altoke Entities built on top of Realm. diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/analysis_options.yaml b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/analysis_options.yaml deleted file mode 100644 index 6b773509..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:very_good_analysis/analysis_options.yaml -analyzer: - exclude: - - lib/**.realm.dart diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/altoke_entities_realm_storage.dart b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/altoke_entities_realm_storage.dart deleted file mode 100644 index d34bac0b..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/altoke_entities_realm_storage.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// A persistent storage for Altoke Entities built on top of Realm. -library altoke_entities_realm_storage; - -export 'src/altoke_entities_filter.dart'; -export 'src/altoke_entities_realm_storage.dart'; -export 'src/realm_{{object.snakeCase()}}.dart'; diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/altoke_entities_filter.dart b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/altoke_entities_filter.dart deleted file mode 100644 index 51b67dfc..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/altoke_entities_filter.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:altoke_common/common.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:collection/collection.dart'; - -/// A set of filters to apply on [AltokeEntity]s -abstract class AltokeEntitiesFilter { - /// A filter to match the given [partialAltokeEntity]. - static String? matchesPartial( - PartialAltokeEntity? partialAltokeEntity, - ) { - if (partialAltokeEntity == null) return null; - final PartialAltokeEntity(:name, :description) = partialAltokeEntity; - final nameMatches = switch (name) { - None() => null, - Some(value: final nameFragment) => nameContains(nameFragment), - }; - final descriptionMatches = switch (description) { - None() => null, - Some(value: final descriptionFragment) => switch ( - descriptionFragment?.trim()) { - null => descriptionIsNull(), - final descriptionFragment => descriptionContains(descriptionFragment), - }, - }; - return andAll([nameMatches, descriptionMatches]); - } - - /// A filter to match the given [name] against the [AltokeEntity.name]. - static String? nameContains(String name) { - return switch (name.trim()) { - String(:final isEmpty) when isEmpty => null, - final searchTerm => 'name CONTAINS "$searchTerm"', - }; - } - - /// A filter to match `null` [AltokeEntity.description]s. - static String descriptionIsNull() { - return 'description == null'; - } - - /// A filter to match non-`null` [AltokeEntity.description]s. - static String descriptionIsNotNull() { - return 'description != null'; - } - - /// A filter to match the given [description] against the - /// [AltokeEntity.description]. - static String? descriptionContains(String description) { - return switch (description.trim()) { - String(:final isEmpty) when isEmpty => descriptionIsNotNull(),final descriptionFragment => - 'description CONTAINS "$descriptionFragment"', - }; - } - - /// A filter to match the given [content] against the [AltokeEntity.name] and - /// [AltokeEntity.description]. - static String? matchesContent(String? content) { - return switch (content?.trim()) { - null => null, - String(:final isEmpty) when isEmpty => null, - final content => orAll([ - nameContains(content), - descriptionContains(content), - ]), - }; - } - - /// A filter that combines the given [filters] to match all of them. - static String? andAll(Iterable filters) { - final validFilters = filters.whereNotNull(); - if (validFilters.isEmpty) return null; - return validFilters.join(' AND '); - } - - /// A filter that combines the given [filters] to match any of them. - static String? orAll(Iterable filters) { - final validFilters = filters.whereNotNull(); - if (validFilters.isEmpty) return null; - return validFilters.join(' OR '); - } -} diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/altoke_entities_realm_storage.dart b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/altoke_entities_realm_storage.dart deleted file mode 100644 index 5be32be0..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/altoke_entities_realm_storage.dart +++ /dev/null @@ -1,153 +0,0 @@ -import 'package:altoke_common/common.dart'; -import 'package:altoke_entities_realm_storage/src/altoke_entities_filter.dart'; -import 'package:altoke_entities_realm_storage/src/realm_{{object.snakeCase()}}.dart'; -import 'package:altoke_entities_storage/altoke_entities_storage.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:collection/collection.dart'; -import 'package:meta/meta.dart'; -import 'package:realm/realm.dart'; - -/// {@template altoke_entities_realm_storage} -/// A persistent [AltokeEntitiesStorage] implementation using Realm. -/// {@endtemplate} -class AltokeEntitiesRealmStorage implements AltokeEntitiesStorage { - /// {@macro altoke_entities_realm_storage} - AltokeEntitiesRealmStorage({ - required this.database, - }); - - /// The Realm database. - @visibleForTesting - final Realm database; - - /// Equality checker for [AltokeEntity]s. - @visibleForTesting - static const altokeEntitiesEqualityChecker = IterableEquality(); - - @override - Future create({ - required NewAltokeEntity newAltokeEntity, - }) async { - if (newAltokeEntity.name.isEmpty) { - throw const CreateAltokeEntityFailureEmptyName(); - } - await database.write(() async { - final latestAltokeEntityId = database - .query('id != 0 SORT(id DESC) LIMIT(1)') - .firstOrNull - ?.id ?? - 0; - final newId = latestAltokeEntityId + 1; - database.add(newAltokeEntity.toRealmWithId(newId)); - }); - } - - @override - Future insert({ - required AltokeEntity altokeEntity, - }) async { - await database.write(() async { - database.add( - altokeEntity.toRealm(), - update: true, - ); - }); - } - - @override - Future getById( - int altokeEntityId, - ) async { - final realmAltokeEntity = database.find(altokeEntityId); - return realmAltokeEntity?.toAltokeEntity(); - } - - @override - Stream> watch({ - String? searchTerm, - }) { - final queryExpression = AltokeEntitiesFilter.matchesContent(searchTerm); - final filteredAltokeEntitiesQuery = switch (queryExpression) { - String() => database.query( - '$queryExpression SORT(name ASC)', - ), - null => database.query( - // cspell:disable-next-line - 'TRUEPREDICATE SORT(name ASC)', - ), - }; - return filteredAltokeEntitiesQuery.changes - .asBroadcastStream() - .map((changes) => changes.results) - .map(altokeEntitiesFromRealmAltokeEntities) - .distinct(altokeEntitiesEqualityChecker.equals); - } - - @override - Stream watchCount({ - String? searchTerm, - }) { - final queryExpression = AltokeEntitiesFilter.matchesContent(searchTerm); - final allAltokeEntitiesQuery = database.all(); - final filteredAltokeEntitiesQuery = queryExpression == null - ? allAltokeEntitiesQuery - : allAltokeEntitiesQuery.query(queryExpression); - return filteredAltokeEntitiesQuery.changes - .map((changes) => changes.results.length) - .distinct(); - } - - @override - Future update({ - required int altokeEntityId, - required PartialAltokeEntity partialAltokeEntity, - }) async { - if (partialAltokeEntity - case PartialAltokeEntity(name: Some(value: String(:final isEmpty))) - when isEmpty) { - throw const UpdateAltokeEntityFailureEmptyName(); - } - final existingAltokeEntity = - database.find(altokeEntityId); - if (existingAltokeEntity == null) return; - await database.write(() async { - database.add( - existingAltokeEntity.copyWithAppliedPartial(partialAltokeEntity), - update: true, - ); - }); - } - - @override - Future deleteById( - int altokeEntityId, - ) async { - final existingRealmAltokeEntity = - database.find(altokeEntityId); - if (existingRealmAltokeEntity == null) return null; - final existingAltokeEntity = existingRealmAltokeEntity.toAltokeEntity(); - await database.write(() async { - database.delete(existingRealmAltokeEntity); - }); - return existingAltokeEntity; - } - - @override - Future deleteAll({ - PartialAltokeEntity? referenceAltokeEntity, - }) async { - final queryExpression = - AltokeEntitiesFilter.matchesPartial(referenceAltokeEntity); - if (queryExpression == null) { - await database.write(() async { - database.deleteAll(); - }); - return; - } - await database.write(() async { - final matchingAltokeEntities = - database.all().query(queryExpression); - database.deleteMany(matchingAltokeEntities); - }); - } -} diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.dart b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.dart deleted file mode 100644 index fae7e8cf..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:altoke_common/common.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:realm/realm.dart'; - -part 'realm_{{object.snakeCase()}}.realm.dart'; - -/// Realm schema for Altoke Entities. -// ignore: non_constant_identifier_names -final RealmAltokeEntitySchema = RealmAltokeEntity.schema; - -/// A Realm representation of an Altoke Entity. -@RealmModel() -class _RealmAltokeEntity { - /// The ID of this altoke entity. - @PrimaryKey() - late int id; - - /// The name of this altoke entity. - late String name; - - /// The description of this altoke entity. - late String? description; - - /// Converts this [RealmAltokeEntity] to an [AltokeEntity]. - AltokeEntity toAltokeEntity() { - return AltokeEntity( - id: id, - name: name, - description: description, - ); - } - - /// Applies the [partialAltokeEntity] to this [RealmAltokeEntity]. - RealmAltokeEntity copyWithAppliedPartial( - PartialAltokeEntity partialAltokeEntity, - ) { - final realmAltokeEntity = RealmAltokeEntity( - id, - name, - description: description, - ); - if (partialAltokeEntity.name case Some(value: final name)) { - realmAltokeEntity.name = name.trim(); - } - if (partialAltokeEntity.description case Some(value: final description)) { - realmAltokeEntity.description = switch (description?.trim()) { - null => null, - String(:final isEmpty) when isEmpty => null, - final description => description.trim(), - }; - } - return realmAltokeEntity; - } -} - -/// An extension on [AltokeEntity] to add mapping capabilities. -extension MappableAltokeEntity on AltokeEntity { - /// Converts this [AltokeEntity] to a [RealmAltokeEntity]. - RealmAltokeEntity toRealm() { - return RealmAltokeEntity( - id, - name, - description: description, - ); - } -} - -/// An extension on [NewAltokeEntity] to add mapping capabilities. -extension MappableNewAltokeEntity on NewAltokeEntity { - /// Converts this [NewAltokeEntity] to a [RealmAltokeEntity]. - RealmAltokeEntity toRealmWithId(int id) { - return RealmAltokeEntity( - id, - name, - description: description, - ); - } -} - -/// An [Iterable] of [RealmAltokeEntity]s. -typedef RealmAltokeEntitiesIterable = Iterable; - -/// Converts a list of [RealmAltokeEntity]s to a list of [AltokeEntity]s. -List altokeEntitiesFromRealmAltokeEntities( - RealmAltokeEntitiesIterable realmAltokeEntities, -) { - return [ - for (final realmAltokeEntity in realmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; -} diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.realm.dart b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.realm.dart deleted file mode 100644 index 732c30aa..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.realm.dart +++ /dev/null @@ -1,87 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'realm_{{object.snakeCase()}}.dart'; - -// ************************************************************************** -// RealmObjectGenerator -// ************************************************************************** - -// ignore_for_file: type=lint -class RealmAltokeEntity extends _RealmAltokeEntity - with RealmEntity, RealmObjectBase, RealmObject { - RealmAltokeEntity( - int id, - String name, { - String? description, - }) { - RealmObjectBase.set(this, 'id', id); - RealmObjectBase.set(this, 'name', name); - RealmObjectBase.set(this, 'description', description); - } - - RealmAltokeEntity._(); - - @override - int get id => RealmObjectBase.get(this, 'id') as int; - @override - set id(int value) => RealmObjectBase.set(this, 'id', value); - - @override - String get name => RealmObjectBase.get(this, 'name') as String; - @override - set name(String value) => RealmObjectBase.set(this, 'name', value); - - @override - String? get description => - RealmObjectBase.get(this, 'description') as String?; - @override - set description(String? value) => - RealmObjectBase.set(this, 'description', value); - - @override - Stream> get changes => - RealmObjectBase.getChanges(this); - - @override - RealmAltokeEntity freeze() => - RealmObjectBase.freezeObject(this); - - EJsonValue toEJson() { - return { - 'id': id.toEJson(), - 'name': name.toEJson(), - 'description': description.toEJson(), - }; - } - - static EJsonValue _toEJson(RealmAltokeEntity value) => value.toEJson(); - static RealmAltokeEntity _fromEJson(EJsonValue ejson) { - return switch (ejson) { - { - 'id': EJsonValue id, - 'name': EJsonValue name, - 'description': EJsonValue description, - } => - RealmAltokeEntity( - fromEJson(id), - fromEJson(name), - description: fromEJson(description), - ), - _ => raiseInvalidEJson(ejson), - }; - } - - static final schema = () { - RealmObjectBase.registerFactory(RealmAltokeEntity._); - register(_toEJson, _fromEJson); - return SchemaObject( - ObjectType.realmObject, RealmAltokeEntity, 'RealmAltokeEntity', [ - SchemaProperty('id', RealmPropertyType.int, primaryKey: true), - SchemaProperty('name', RealmPropertyType.string), - SchemaProperty('description', RealmPropertyType.string, optional: true), - ]); - }(); - - @override - SchemaObject get objectSchema => RealmObjectBase.getSchema(this) ?? schema; -} diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/pubspec.yaml b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/pubspec.yaml deleted file mode 100644 index 026db3db..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/pubspec.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: altoke_entities_realm_storage -description: A persistent storage for Altoke Entities built on top of Realm. -version: 0.0.1+1 -publish_to: none - -environment: - sdk: ">=3.3.1 <4.0.0" - -dependencies: - common: - path: ../../common/ - altoke_entities_storage: - path: ../altoke_entities_storage/ - {{object.snakeCase()}}: - path: ../../{{object.snakeCase()}}/ - collection: ^1.18.0 - meta: ^1.11.0 - realm: ^2.1.0 - -dev_dependencies: - test: ^1.25.2 - very_good_analysis: ^5.1.0 diff --git a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/test/src/altoke_entities_realm_storage_test.dart b/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/test/src/altoke_entities_realm_storage_test.dart deleted file mode 100644 index 276b19aa..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{altoke_objects.snake_case}}/{{#use_realm}}altoke_entities_realm_storage{{/use_realm}}/test/src/altoke_entities_realm_storage_test.dart +++ /dev/null @@ -1,1624 +0,0 @@ -import 'dart:async'; - -import 'package:altoke_common/common.dart'; -import 'package:altoke_entities_realm_storage/altoke_entities_realm_storage.dart'; -import 'package:altoke_entities_storage/altoke_entities_storage.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:collection/collection.dart'; -import 'package:realm/realm.dart'; -import 'package:test/test.dart'; - -Future openRealm() async { - final realm = Realm( - Configuration.inMemory( - [RealmAltokeEntitySchema], - ), - ); - return realm; -} - -void main() { - test( - ''' - -GIVEN a constructor for an altoke entities storage -├─ THAT uses a Realm database -WHEN the constructor is called -THEN an instance of the storage is returned -''', - () async { - final realm = await openRealm(); - final storage = AltokeEntitiesRealmStorage(database: realm); - expect(storage, isNotNull); - expect(storage, isA()); - realm.close(); - }, - ); - - group( - ''' - -GIVEN an altoke entities storage -├─ THAT uses a Realm database''', - () { - late Realm database; - late AltokeEntitiesRealmStorage storage; - - setUp(() async { - database = await openRealm(); - storage = AltokeEntitiesRealmStorage(database: database); - }); - - tearDown(() async { - database.close(); - }); - - test( - ''' - -│ ├─ THAT does not have altoke entity records -AND the valid data for a new altoke entity -WHEN the altoke entity is created -THEN a altoke entity record is registered -''', - () async { - const newAltokeEntity = NewAltokeEntity( - name: 'name', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - await storage.create(newAltokeEntity: newAltokeEntity); - final query = ' ' - 'name == ${newAltokeEntity.name} ' - 'AND ' - 'description == ${newAltokeEntity.description}'; - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect( - resultingMatchingAltokeEntitiesCount, - existingAltokeEntitiesCount + 1, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the valid data for a new altoke entity -WHEN the altoke entity is created -THEN a altoke entity record is registered -''', - () async { - const existingAltokeEntityId = 13; - const existingAltokeEntity = NewAltokeEntity( - name: 'existing', - description: 'description', - ); - await database.write( - () async => database.add( - existingAltokeEntity.toRealmWithId( - existingAltokeEntityId, - ), - ), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, 1); - const newAltokeEntity = NewAltokeEntity( - name: 'new', - description: 'description', - ); - await storage.create(newAltokeEntity: newAltokeEntity); - final query = ' ' - 'name == "${newAltokeEntity.name}" ' - 'AND ' - 'description == "${newAltokeEntity.description}"'; - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(resultingMatchingAltokeEntitiesCount, 1); - }, - ); - - test( - ''' - -AND the invalid data for a new altoke entity -WHEN the altoke entity is created -THEN an exception is thrown -AND no altoke entity record is registered -''', - () async { - const newAltokeEntity = NewAltokeEntity( - name: '', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - expect( - () async => storage.create(newAltokeEntity: newAltokeEntity), - throwsA(isA()), - ); - final resultingAltokeEntitiesCount = - database.all().length; - expect(resultingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of a registered altoke entity -WHEN the altoke entity is deleted -THEN the altoke entity record is dropped -AND the deleted altoke entity is returned -''', - () async { - const altokeEntityId = 1; - const newAltokeEntity = NewAltokeEntity( - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - newAltokeEntity.toRealmWithId( - altokeEntityId, - ), - ), - ); - const query = 'id == $altokeEntityId'; - final initialMatchingAltokeEntitiesCount = - database.query(query).length; - expect(initialMatchingAltokeEntitiesCount, 1); - final deletedAltokeEntity = await storage.deleteById(altokeEntityId); - expect(deletedAltokeEntity, isNotNull); - expect(deletedAltokeEntity!.id, altokeEntityId); - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(resultingMatchingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of an unregistered altoke entity -WHEN the altoke entity is deleted -THEN no altoke entity record is dropped -AND null is returned -''', - () async { - const altokeEntityId = 13; - const newAltokeEntity = - NewAltokeEntity(name: 'name', description: 'description'); - await database.write( - () async => database.add( - newAltokeEntity.toRealmWithId(altokeEntityId + 1), - ), - ); - final initialAltokeEntities = database.all(); - expect(initialAltokeEntities, hasLength(1)); - final initialAltokeEntity = initialAltokeEntities.single; - expect(initialAltokeEntity.id, isNot(altokeEntityId)); - final deletedAltokeEntity = await storage.deleteById(altokeEntityId); - expect(deletedAltokeEntity, isNull); - final resultingAltokeEntities = database.all(); - expect(resultingAltokeEntities, hasLength(1)); - final resultingAltokeEntity = resultingAltokeEntities.single; - expect( - resultingAltokeEntity.toAltokeEntity(), - initialAltokeEntity.toAltokeEntity(), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT includes a non-null name matcher -├─ AND includes a non-null description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some('matching-pattern'), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name, :description) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - if (description == null) return true; - final noMatchInDescription = - !description.contains('matching-pattern'); - return noMatchInDescription; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT does not include a name matcher -├─ AND includes a non-null description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - description: Some('matching-pattern'), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:description) = altokeEntity; - if (description == null) return true; - final noMatchInDescription = - !description.contains('matching-pattern'); - return noMatchInDescription; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT includes a non-null name matcher -├─ AND includes a null description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some(null), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name, :description) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - return description != null; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT includes a non-null name matcher -├─ AND includes a non-null empty description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some(''), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - return noMatchInTitle; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ AND includes non-null name matcher -├─ AND includes empty description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some(null), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name, :description) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - final noMatchInDescription = - description != null && description.isNotEmpty; - return noMatchInDescription; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -WHEN a delete operation is performed with no reference altoke entity -THEN all altoke entity records are dropped -''', - () async { - final altokeEntities = List.generate( - 30, - (index) => AltokeEntity( - id: index, - name: 'name $index', - description: 'description $index', - ), - ); - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - await storage.deleteAll(); - final resultingRealmAltokeEntitiesCount = - database.all().length; - expect(resultingRealmAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -AND a altoke entity -WHEN the altoke entity is inserted -THEN a altoke entity record is registered -''', - () async { - const altokeEntity = AltokeEntity( - id: 1, - name: 'name', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - await storage.insert(altokeEntity: altokeEntity); - final resultingRealmAltokeEntities = - database.all(); - expect(resultingRealmAltokeEntities, hasLength(1)); - final resultingRealmAltokeEntity = - resultingRealmAltokeEntities.single; - expect(resultingRealmAltokeEntity.toAltokeEntity(), altokeEntity); - }, - ); - - test( - ''' - -AND the ID of a registered altoke entity -AND the valid partial altoke entity data -WHEN the altoke entity is updated -THEN a altoke entity record is updated -''', - () async { - const altokeEntity = AltokeEntity( - id: 13, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - altokeEntity.toRealm(), - ), - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, 1); - const newName = 'new name'; - const newDescription = 'new description'; - final query = ' ' - 'id == ${altokeEntity.id} ' - 'AND ' - 'name == "$newName" ' - 'AND ' - 'description == "$newDescription"'; - final existingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(existingMatchingAltokeEntitiesCount, isZero); - await storage.update( - altokeEntityId: altokeEntity.id, - partialAltokeEntity: const PartialAltokeEntity( - name: Some(newName), - description: Some(newDescription), - ), - ); - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect( - resultingMatchingAltokeEntitiesCount, - existingMatchingAltokeEntitiesCount + 1, - ); - }, - ); - - test( - ''' - -AND the invalid data for a new altoke entity -WHEN the altoke entity is created -THEN an exception is thrown -AND no altoke entity record is registered -''', - () async { - const newAltokeEntity = NewAltokeEntity( - name: '', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - expect( - () async => storage.create(newAltokeEntity: newAltokeEntity), - throwsA(isA()), - ); - final resultingAltokeEntitiesCount = - database.all().length; - expect(resultingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -AND the ID of a registered altoke entity -AND the invalid partial altoke entity data -WHEN the altoke entity is updated -THEN an exception is thrown -AND no altoke entity record is updated -''', - () async { - const altokeEntity = AltokeEntity( - id: 76, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - altokeEntity.toRealm(), - ), - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, 1); - const newName = ''; - const newDescription = 'new description'; - final query = ' ' - 'id == ${altokeEntity.id} ' - 'AND ' - 'name == "$newName" ' - 'AND ' - 'description == "$newDescription"'; - final existingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(existingMatchingAltokeEntitiesCount, isZero); - expect( - () async => storage.update( - altokeEntityId: altokeEntity.id, - partialAltokeEntity: const PartialAltokeEntity( - name: Some(newName), - description: Some(newDescription), - ), - ), - throwsA(isA()), - ); - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(resultingMatchingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of a registered altoke entity -WHEN the altoke entity is requested -THEN the altoke entity is returned -''', - () async { - const altokeEntityId = 8; - const altokeEntity = AltokeEntity( - id: altokeEntityId, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add(altokeEntity.toRealm()), - ); - final initialMatchingAltokeEntitiesCount = - database.query('id == $altokeEntityId').length; - expect(initialMatchingAltokeEntitiesCount, 1); - final retrievedAltokeEntity = await storage.getById(altokeEntityId); - expect(retrievedAltokeEntity, isNotNull); - expect(retrievedAltokeEntity, altokeEntity); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of an unregistered altoke entity -WHEN the altoke entity is requested -THEN null is returned -''', - () async { - const altokeEntityId = 7; - final initialMatchingAltokeEntitiesCount = - database.query('id == $altokeEntityId').length; - expect(initialMatchingAltokeEntitiesCount, isZero); - final retrievedAltokeEntity = await storage.getById(altokeEntityId); - expect(retrievedAltokeEntity, isNull); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities are watched -├─ AND are not filtered by their content -THEN the altoke entities that match the conditions are continuously emitted as they change -''', - () async { - final stream = storage.watch(); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const AltokeEntity( - id: 1, - name: 'name 01', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - ), - ]; - final sortedAltokeEntitiesForStage00 = [...altokeEntitiesForStage00] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 3, - name: 'name 03', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - final sortedAltokeEntitiesForStage01 = [...altokeEntitiesForStage01] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('01')) altokeEntity, - ]; - final sortedAltokeEntitiesForStage02 = [...altokeEntitiesForStage02] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 03 - final altokeEntitiesForStage03 = [ - for (final altokeEntity in altokeEntitiesForStage02) - if (altokeEntity.description == null) - AltokeEntity( - id: altokeEntity.id, - name: altokeEntity.name, - description: 'updated description', - ) - else - altokeEntity, - ]; - final sortedAltokeEntitiesForStage03 = [...altokeEntitiesForStage03] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - orderedEquals(sortedAltokeEntitiesForStage00), - orderedEquals(sortedAltokeEntitiesForStage01), - orderedEquals(sortedAltokeEntitiesForStage02), - orderedEquals(sortedAltokeEntitiesForStage03), - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database - .add(newAltokeEntityInStage01.toRealm()), - ); - - // Stage 02 - await database.write( - () async { - final matchingAltokeEntities = - database.query('name CONTAINS "01"'); - database.deleteMany(matchingAltokeEntities); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = 'updated description'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities are watched -├─ AND are filtered by their content -THEN the altoke entities that match the conditions are continuously emitted as they change -''', - () async { - final stream = storage.watch(searchTerm: 'matching-pattern'); - - bool matches(AltokeEntity altokeEntity) => - altokeEntity.name.contains('matching-pattern') || - (altokeEntity.description?.contains('matching-pattern') ?? false); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00 matching-pattern', - ), - const AltokeEntity( - id: 1, - name: 'name 01', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - ), - const AltokeEntity( - id: 3, - name: 'name 03', - description: 'description 03 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 04', - ), - const AltokeEntity( - id: 5, - name: 'name 05', - description: 'description 05 matching-pattern', - ), - ]; - final sortedAltokeEntitiesForStage00 = [...altokeEntitiesForStage00] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 6, - name: 'name 06 matching-pattern', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - final sortedAltokeEntitiesForStage01 = [...altokeEntitiesForStage01] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('00')) altokeEntity, - ]; - final sortedAltokeEntitiesForStage02 = [...altokeEntitiesForStage02] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 03 - final altokeEntitiesForStage03 = [ - for (final altokeEntity in altokeEntitiesForStage02) - if (altokeEntity.description == null) - AltokeEntity( - id: altokeEntity.id, - name: altokeEntity.name, - description: 'updated description matching-pattern', - ) - else - altokeEntity, - ]; - final sortedAltokeEntitiesForStage03 = [...altokeEntitiesForStage03] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - orderedEquals(sortedAltokeEntitiesForStage00), - orderedEquals(sortedAltokeEntitiesForStage01), - orderedEquals(sortedAltokeEntitiesForStage02), - orderedEquals(sortedAltokeEntitiesForStage03), - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database - .add(newAltokeEntityInStage01.toRealm()), - ); - - // Stage 02 - await database.write( - () async { - final altokeEntityToDelete = - database.query('name CONTAINS "00"'); - database.deleteMany(altokeEntityToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = - 'updated description matching-pattern'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities count is watched -├─ AND are not filtered by their content -THEN the quantity of persisted altoke entities that match the conditions is continuously emitted as it changes -''', - () async { - final stream = storage.watchCount(); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const AltokeEntity( - id: 1, - name: 'name 01', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - description: 'description 02', - ), - ]; - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 3, - name: 'name 03', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('01')) altokeEntity, - ]; - - // Stage 03 - // final altokeEntitiesForStage03 = [ - // for (final altokeEntity in altokeEntitiesForStage02) - // if (altokeEntity.description == null) - // AltokeEntity( - // id: altokeEntity.id, - // name: altokeEntity.name, - // description: 'updated description', - // ) - // else - // altokeEntity, - // ]; - - unawaited( - expectLater( - stream, - emitsInOrder([ - altokeEntitiesForStage00.length, - altokeEntitiesForStage01.length, - altokeEntitiesForStage02.length, - - // Not emitted as the altoke entities count has not changed - // altokeEntitiesForStage03.length, - ]), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database.add( - newAltokeEntityInStage01.toRealm(), - ), - ); - - // Stage 02 - await database.write( - () async { - final altokeEntitiesToDelete = - database.query('name CONTAINS "01"'); - database.deleteMany(altokeEntitiesToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = 'updated description'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities count is watched -├─ AND are filtered by their content -THEN the quantity of persisted altoke entities that match the conditions is continuously emitted as it changes -''', - () async { - final stream = storage.watchCount(searchTerm: 'matching-pattern'); - bool match(AltokeEntity altokeEntity) => - altokeEntity.name.contains('matching-pattern') || - (altokeEntity.description?.contains('matching-pattern') ?? false); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const AltokeEntity( - id: 1, - name: 'name 01 matching-pattern', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - description: 'description 02 matching-pattern', - ), - ]; - final expectedAltokeEntitiesForStage00 = - altokeEntitiesForStage00.where(match); - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 3, - name: 'name 03 matching-pattern', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - final expectedAltokeEntitiesForStage01 = - altokeEntitiesForStage01.where(match); - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('01')) altokeEntity, - ]; - final expectedAltokeEntitiesForStage02 = - altokeEntitiesForStage02.where(match); - - // Stage 03 - // final altokeEntitiesForStage03 = [ - // for (final altokeEntity in altokeEntitiesForStage02) - // if (altokeEntity.description == null) - // AltokeEntity( - // id: altokeEntity.id, - // name: altokeEntity.name, - // description: 'updated description', - // ) - // else - // altokeEntity, - // ]; - // final expectedAltokeEntitiesForStage03 = - // altokeEntitiesForStage03.where(match); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - expectedAltokeEntitiesForStage00.length, - expectedAltokeEntitiesForStage01.length, - expectedAltokeEntitiesForStage02.length, - - // Not emitted as the altoke entities count has not changed - // expectedAltokeEntitiesForStage03.length, - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database.add( - newAltokeEntityInStage01.toRealm(), - ), - ); - - // Stage 02 - await database.write( - () async { - final altokeEntityToDelete = - database.query('name CONTAINS "01"'); - database.deleteMany(altokeEntityToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = 'updated description'; - } - }, - ); - }, - ); - }, - ); -} diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/.gitignore b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/.gitignore deleted file mode 100644 index 118f3226..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# See https://www.dartlang.org/guides/libraries/private-files - -# Files and directories created by pub -/.dart_tool/ -/.packages -/build/ -/pubspec.lock - -# Testing -/coverage/ - -# Realm -/default.realm.lock -/default.realm.management/ -/binary/ diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/README.md b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/README.md deleted file mode 100644 index ddb892f8..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# {{objects.titleCase()}} Realm Storage - -A persistent storage for {{objects.titleCase()}} built on top of Realm. diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/analysis_options.yaml b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/analysis_options.yaml deleted file mode 100644 index 6b773509..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:very_good_analysis/analysis_options.yaml -analyzer: - exclude: - - lib/**.realm.dart diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.dart b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.dart deleted file mode 100644 index 9f31359f..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:common/common.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:realm/realm.dart'; - -part 'realm_{{object.snakeCase()}}.realm.dart'; - -/// Realm schema for {{objects.titleCase()}}. -// ignore: non_constant_identifier_names -final Realm{{object.pascalCase()}}Schema = Realm{{object.pascalCase()}}.schema; - -/// A Realm representation of an {{object.titleCase()}}. -@RealmModel() -class _Realm{{object.pascalCase()}} { - /// The ID of this {{object.lowerCase()}}. - @PrimaryKey() - late int id; - - /// The name of this {{object.lowerCase()}}. - late String name; - - /// The description of this {{object.lowerCase()}}. - late String? description; - - /// Converts this [Realm{{object.pascalCase()}}] to an [{{object.pascalCase()}}]. - {{object.pascalCase()}} to{{object.pascalCase()}}() { - return {{object.pascalCase()}}( - id: id, - name: name, - description: description, - ); - } - - /// Applies the [partial{{object.pascalCase()}}] to this [Realm{{object.pascalCase()}}]. - Realm{{object.pascalCase()}} copyWithAppliedPartial( - Partial{{object.pascalCase()}} partial{{object.pascalCase()}}, - ) { - final realm{{object.pascalCase()}} = Realm{{object.pascalCase()}}( - id, - name, - description: description, - ); - if (partial{{object.pascalCase()}}.name case Some(value: final name)) { - realm{{object.pascalCase()}}.name = name.trim(); - } - if (partial{{object.pascalCase()}}.description case Some(value: final description)) { - realm{{object.pascalCase()}}.description = switch (description?.trim()) { - null => null, - String(:final isEmpty) when isEmpty => null, - final description => description.trim(), - }; - } - return realm{{object.pascalCase()}}; - } -} - -/// An extension on [{{object.pascalCase()}}] to add mapping capabilities. -extension Mappable{{object.pascalCase()}} on {{object.pascalCase()}} { - /// Converts this [{{object.pascalCase()}}] to a [Realm{{object.pascalCase()}}]. - Realm{{object.pascalCase()}} toRealm() { - return Realm{{object.pascalCase()}}( - id, - name, - description: description, - ); - } -} - -/// An extension on [New{{object.pascalCase()}}] to add mapping capabilities. -extension MappableNew{{object.pascalCase()}} on New{{object.pascalCase()}} { - /// Converts this [New{{object.pascalCase()}}] to a [Realm{{object.pascalCase()}}]. - Realm{{object.pascalCase()}} toRealmWithId(int id) { - return Realm{{object.pascalCase()}}( - id, - name, - description: description, - ); - } -} - -/// An [Iterable] of [Realm{{object.pascalCase()}}]s. -typedef Realm{{objects.pascalCase()}}Iterable = Iterable; - -/// Converts a list of [Realm{{object.pascalCase()}}]s to a list of [{{object.pascalCase()}}]s. -List<{{object.pascalCase()}}> {{objects.camelCase()}}FromRealm{{objects.pascalCase()}}( - Realm{{objects.pascalCase()}}Iterable realm{{objects.pascalCase()}}, -) { - return [ - for (final realm{{object.pascalCase()}} in realm{{objects.pascalCase()}}) - realm{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ]; -} diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.realm.dart b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.realm.dart deleted file mode 100644 index 862e9556..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/realm_{{object.snakeCase()}}.realm.dart +++ /dev/null @@ -1,87 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'realm_{{object.snakeCase()}}.dart'; - -// ************************************************************************** -// RealmObjectGenerator -// ************************************************************************** - -// ignore_for_file: type=lint -class Realm{{object.pascalCase()}} extends _Realm{{object.pascalCase()}} - with RealmEntity, RealmObjectBase, RealmObject { - Realm{{object.pascalCase()}}( - int id, - String name, { - String? description, - }) { - RealmObjectBase.set(this, 'id', id); - RealmObjectBase.set(this, 'name', name); - RealmObjectBase.set(this, 'description', description); - } - - Realm{{object.pascalCase()}}._(); - - @override - int get id => RealmObjectBase.get(this, 'id') as int; - @override - set id(int value) => RealmObjectBase.set(this, 'id', value); - - @override - String get name => RealmObjectBase.get(this, 'name') as String; - @override - set name(String value) => RealmObjectBase.set(this, 'name', value); - - @override - String? get description => - RealmObjectBase.get(this, 'description') as String?; - @override - set description(String? value) => - RealmObjectBase.set(this, 'description', value); - - @override - Stream> get changes => - RealmObjectBase.getChanges(this); - - @override - Realm{{object.pascalCase()}} freeze() => - RealmObjectBase.freezeObject(this); - - EJsonValue toEJson() { - return { - 'id': id.toEJson(), - 'name': name.toEJson(), - 'description': description.toEJson(), - }; - } - - static EJsonValue _toEJson(Realm{{object.pascalCase()}} value) => value.toEJson(); - static Realm{{object.pascalCase()}} _fromEJson(EJsonValue ejson) { - return switch (ejson) { - { - 'id': EJsonValue id, - 'name': EJsonValue name, - 'description': EJsonValue description, - } => - Realm{{object.pascalCase()}}( - fromEJson(id), - fromEJson(name), - description: fromEJson(description), - ), - _ => raiseInvalidEJson(ejson), - }; - } - - static final schema = () { - RealmObjectBase.registerFactory(Realm{{object.pascalCase()}}._); - register(_toEJson, _fromEJson); - return SchemaObject( - ObjectType.realmObject, Realm{{object.pascalCase()}}, 'Realm{{object.pascalCase()}}', [ - SchemaProperty('id', RealmPropertyType.int, primaryKey: true), - SchemaProperty('name', RealmPropertyType.string), - SchemaProperty('description', RealmPropertyType.string, optional: true), - ]); - }(); - - @override - SchemaObject get objectSchema => RealmObjectBase.getSchema(this) ?? schema; -} diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/{{objects.snakeCase()}}_filter.dart b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/{{objects.snakeCase()}}_filter.dart deleted file mode 100644 index 3d042d09..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/{{objects.snakeCase()}}_filter.dart +++ /dev/null @@ -1,81 +0,0 @@ -import 'package:common/common.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:collection/collection.dart'; - -/// A set of filters to apply on [{{object.pascalCase()}}]s -abstract class {{objects.pascalCase()}}Filter { - /// A filter to match the given [partial{{object.pascalCase()}}]. - static String? matchesPartial( - Partial{{object.pascalCase()}}? partial{{object.pascalCase()}}, - ) { - if (partial{{object.pascalCase()}} == null) return null; - final Partial{{object.pascalCase()}}(:name, :description) = partial{{object.pascalCase()}}; - final nameMatches = switch (name) { - None() => null, - Some(value: final nameFragment) => nameContains(nameFragment), - }; - final descriptionMatches = switch (description) { - None() => null, - Some(value: final descriptionFragment) => switch ( - descriptionFragment?.trim()) { - null => descriptionIsNull(), - final descriptionFragment => descriptionContains(descriptionFragment), - }, - }; - return andAll([nameMatches, descriptionMatches]); - } - - /// A filter to match the given [name] against the [{{object.pascalCase()}}.name]. - static String? nameContains(String name) { - return switch (name.trim()) { - String(:final isEmpty) when isEmpty => null, - final searchTerm => 'name CONTAINS "$searchTerm"', - }; - } - - /// A filter to match `null` [{{object.pascalCase()}}.description]s. - static String descriptionIsNull() { - return 'description == null'; - } - - /// A filter to match non-`null` [{{object.pascalCase()}}.description]s. - static String descriptionIsNotNull() { - return 'description != null'; - } - - /// A filter to match the given [description] against the - /// [{{object.pascalCase()}}.description]. - static String? descriptionContains(String description) { - return switch (description.trim()) { - String(:final isEmpty) when isEmpty => descriptionIsNotNull(),final descriptionFragment => - 'description CONTAINS "$descriptionFragment"', - }; - } - - /// A filter to match the given [content] against the [{{object.pascalCase()}}.name] and - /// [{{object.pascalCase()}}.description]. - static String? matchesContent(String? content) { - return switch (content?.trim()) { - null => null, - String(:final isEmpty) when isEmpty => null, - final content => orAll([ - nameContains(content), - descriptionContains(content), - ]), - }; - } - - /// A filter that combines the given [filters] to match all of them. - static String? andAll(Iterable filters) { - final validFilters = filters.whereNotNull(); - if (validFilters.isEmpty) return null; - return validFilters.join(' AND '); - } - - /// A filter that combines the given [filters] to match any of them. - static String? orAll(Iterable filters) { - final validFilters = filters.whereNotNull(); - if (validFilters.isEmpty) return null; - return validFilters.join(' OR '); - } -} diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/{{objects.snakeCase()}}_realm_storage.dart b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/{{objects.snakeCase()}}_realm_storage.dart deleted file mode 100644 index 9433c253..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/src/{{objects.snakeCase()}}_realm_storage.dart +++ /dev/null @@ -1,153 +0,0 @@ -import 'package:common/common.dart'; -import 'package:{{objects.snakeCase()}}_realm_storage/src/{{objects.snakeCase()}}_filter.dart'; -import 'package:{{objects.snakeCase()}}_realm_storage/src/realm_{{object.snakeCase()}}.dart'; -import 'package:{{objects.snakeCase()}}_storage/{{objects.snakeCase()}}_storage.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:collection/collection.dart'; -import 'package:meta/meta.dart'; -import 'package:realm/realm.dart'; - -/// {@template {{objects.snakeCase()}}_realm_storage} -/// A persistent [{{objects.pascalCase()}}Storage] implementation using Realm. -/// {@endtemplate} -class {{objects.pascalCase()}}RealmStorage implements {{objects.pascalCase()}}Storage { - /// {@macro {{objects.snakeCase()}}_realm_storage} - {{objects.pascalCase()}}RealmStorage({ - required this.database, - }); - - /// The Realm database. - @visibleForTesting - final Realm database; - - /// Equality checker for [{{object.pascalCase()}}]s. - @visibleForTesting - static const {{objects.camelCase()}}EqualityChecker = IterableEquality<{{object.pascalCase()}}>(); - - @override - Future create({ - required New{{object.pascalCase()}} new{{object.pascalCase()}}, - }) async { - if (new{{object.pascalCase()}}.name.isEmpty) { - throw const Create{{object.pascalCase()}}FailureEmptyName(); - } - await database.write(() async { - final latest{{object.pascalCase()}}Id = database - .query('id != 0 SORT(id DESC) LIMIT(1)') - .firstOrNull - ?.id ?? - 0; - final newId = latest{{object.pascalCase()}}Id + 1; - database.add(new{{object.pascalCase()}}.toRealmWithId(newId)); - }); - } - - @override - Future insert({ - required {{object.pascalCase()}} {{object.camelCase()}}, - }) async { - await database.write(() async { - database.add( - {{object.camelCase()}}.toRealm(), - update: true, - ); - }); - } - - @override - Future<{{object.pascalCase()}}?> getById( - int {{object.camelCase()}}Id, - ) async { - final realm{{object.pascalCase()}} = database.find({{object.camelCase()}}Id); - return realm{{object.pascalCase()}}?.to{{object.pascalCase()}}(); - } - - @override - Stream> watch({ - String? searchTerm, - }) { - final queryExpression = {{objects.pascalCase()}}Filter.matchesContent(searchTerm); - final filtered{{objects.pascalCase()}}Query = switch (queryExpression) { - String() => database.query( - '$queryExpression SORT(name ASC)', - ), - null => database.query( - // cspell:disable-next-line - 'TRUEPREDICATE SORT(name ASC)', - ), - }; - return filtered{{objects.pascalCase()}}Query.changes - .asBroadcastStream() - .map((changes) => changes.results) - .map({{objects.camelCase()}}FromRealm{{objects.pascalCase()}}) - .distinct({{objects.camelCase()}}EqualityChecker.equals); - } - - @override - Stream watchCount({ - String? searchTerm, - }) { - final queryExpression = {{objects.pascalCase()}}Filter.matchesContent(searchTerm); - final all{{objects.pascalCase()}}Query = database.all(); - final filtered{{objects.pascalCase()}}Query = queryExpression == null - ? all{{objects.pascalCase()}}Query - : all{{objects.pascalCase()}}Query.query(queryExpression); - return filtered{{objects.pascalCase()}}Query.changes - .map((changes) => changes.results.length) - .distinct(); - } - - @override - Future update({ - required int {{object.camelCase()}}Id, - required Partial{{object.pascalCase()}} partial{{object.pascalCase()}}, - }) async { - if (partial{{object.pascalCase()}} - case Partial{{object.pascalCase()}}(name: Some(value: String(:final isEmpty))) - when isEmpty) { - throw const Update{{object.pascalCase()}}FailureEmptyName(); - } - final existing{{object.pascalCase()}} = - database.find({{object.camelCase()}}Id); - if (existing{{object.pascalCase()}} == null) return; - await database.write(() async { - database.add( - existing{{object.pascalCase()}}.copyWithAppliedPartial(partial{{object.pascalCase()}}), - update: true, - ); - }); - } - - @override - Future<{{object.pascalCase()}}?> deleteById( - int {{object.camelCase()}}Id, - ) async { - final existingRealm{{object.pascalCase()}} = - database.find({{object.camelCase()}}Id); - if (existingRealm{{object.pascalCase()}} == null) return null; - final existing{{object.pascalCase()}} = existingRealm{{object.pascalCase()}}.to{{object.pascalCase()}}(); - await database.write(() async { - database.delete(existingRealm{{object.pascalCase()}}); - }); - return existing{{object.pascalCase()}}; - } - - @override - Future deleteAll({ - Partial{{object.pascalCase()}}? reference{{object.pascalCase()}}, - }) async { - final queryExpression = - {{objects.pascalCase()}}Filter.matchesPartial(reference{{object.pascalCase()}}); - if (queryExpression == null) { - await database.write(() async { - database.deleteAll(); - }); - return; - } - await database.write(() async { - final matching{{objects.pascalCase()}} = - database.all().query(queryExpression); - database.deleteMany(matching{{objects.pascalCase()}}); - }); - } -} diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/{{objects.snakeCase()}}_realm_storage.dart b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/{{objects.snakeCase()}}_realm_storage.dart deleted file mode 100644 index b1ff4c5c..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/lib/{{objects.snakeCase()}}_realm_storage.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// A persistent storage for {{objects.titleCase()}} built on top of Realm. -library {{objects.snakeCase()}}_realm_storage; - -export 'src/{{objects.snakeCase()}}_filter.dart'; -export 'src/{{objects.snakeCase()}}_realm_storage.dart'; -export 'src/realm_{{object.snakeCase()}}.dart'; diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/pubspec.yaml b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/pubspec.yaml deleted file mode 100644 index d6a68d75..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/pubspec.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: {{objects.snakeCase()}}_realm_storage -description: A persistent storage for {{objects.titleCase()}} built on top of Realm. -version: 0.0.1+1 -publish_to: none - -environment: - sdk: ">=3.3.1 <4.0.0" - -dependencies: - common: - path: ../../common/ - {{objects.snakeCase()}}_storage: - path: ../{{objects.snakeCase()}}_storage/ - {{object.snakeCase()}}: - path: ../../{{object.snakeCase()}}/ - collection: ^1.18.0 - meta: ^1.11.0 - realm: ^2.1.0 - -dev_dependencies: - test: ^1.25.2 - very_good_analysis: ^5.1.0 diff --git a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/test/src/{{objects.snakeCase()}}_realm_storage_test.dart b/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/test/src/{{objects.snakeCase()}}_realm_storage_test.dart deleted file mode 100644 index 5e391e17..00000000 --- a/bricks/altoke_storage/brick/__brick__/{{objects.snakeCase()}}_storage/{{#use_realm}}{{objects.snakeCase()}}_realm_storage{{/use_realm}}/test/src/{{objects.snakeCase()}}_realm_storage_test.dart +++ /dev/null @@ -1,1624 +0,0 @@ -import 'dart:async'; - -import 'package:common/common.dart'; -import 'package:{{objects.snakeCase()}}_realm_storage/{{objects.snakeCase()}}_realm_storage.dart'; -import 'package:{{objects.snakeCase()}}_storage/{{objects.snakeCase()}}_storage.dart'; -import 'package:{{object.snakeCase()}}/{{object.snakeCase()}}.dart'; -import 'package:collection/collection.dart'; -import 'package:realm/realm.dart'; -import 'package:test/test.dart'; - -Future openRealm() async { - final realm = Realm( - Configuration.inMemory( - [Realm{{object.pascalCase()}}Schema], - ), - ); - return realm; -} - -void main() { - test( - ''' - -GIVEN a constructor for an {{objects.lowerCase()}} storage -├─ THAT uses a Realm database -WHEN the constructor is called -THEN an instance of the storage is returned -''', - () async { - final realm = await openRealm(); - final storage = {{objects.pascalCase()}}RealmStorage(database: realm); - expect(storage, isNotNull); - expect(storage, isA<{{objects.pascalCase()}}Storage>()); - realm.close(); - }, - ); - - group( - ''' - -GIVEN an {{objects.lowerCase()}} storage -├─ THAT uses a Realm database''', - () { - late Realm database; - late {{objects.pascalCase()}}RealmStorage storage; - - setUp(() async { - database = await openRealm(); - storage = {{objects.pascalCase()}}RealmStorage(database: database); - }); - - tearDown(() async { - database.close(); - }); - - test( - ''' - -│ ├─ THAT does not have {{object.lowerCase()}} records -AND the valid data for a new {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is created -THEN a {{object.lowerCase()}} record is registered -''', - () async { - const new{{object.pascalCase()}} = New{{object.pascalCase()}}( - name: 'name', - description: 'description', - ); - final existing{{objects.pascalCase()}}Count = - database.all().length; - expect(existing{{objects.pascalCase()}}Count, isZero); - await storage.create(new{{object.pascalCase()}}: new{{object.pascalCase()}}); - final query = ' ' - 'name == ${new{{object.pascalCase()}}.name} ' - 'AND ' - 'description == ${new{{object.pascalCase()}}.description}'; - final resultingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect( - resultingMatching{{objects.pascalCase()}}Count, - existing{{objects.pascalCase()}}Count + 1, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -AND the valid data for a new {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is created -THEN a {{object.lowerCase()}} record is registered -''', - () async { - const existing{{object.pascalCase()}}Id = 13; - const existing{{object.pascalCase()}} = New{{object.pascalCase()}}( - name: 'existing', - description: 'description', - ); - await database.write( - () async => database.add( - existing{{object.pascalCase()}}.toRealmWithId( - existing{{object.pascalCase()}}Id, - ), - ), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, 1); - const new{{object.pascalCase()}} = New{{object.pascalCase()}}( - name: 'new', - description: 'description', - ); - await storage.create(new{{object.pascalCase()}}: new{{object.pascalCase()}}); - final query = ' ' - 'name == "${new{{object.pascalCase()}}.name}" ' - 'AND ' - 'description == "${new{{object.pascalCase()}}.description}"'; - final resultingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect(resultingMatching{{objects.pascalCase()}}Count, 1); - }, - ); - - test( - ''' - -AND the invalid data for a new {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is created -THEN an exception is thrown -AND no {{object.lowerCase()}} record is registered -''', - () async { - const new{{object.pascalCase()}} = New{{object.pascalCase()}}( - name: '', - description: 'description', - ); - final existing{{objects.pascalCase()}}Count = - database.all().length; - expect(existing{{objects.pascalCase()}}Count, isZero); - expect( - () async => storage.create(new{{object.pascalCase()}}: new{{object.pascalCase()}}), - throwsA(isA()), - ); - final resulting{{objects.pascalCase()}}Count = - database.all().length; - expect(resulting{{objects.pascalCase()}}Count, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -AND the ID of a registered {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is deleted -THEN the {{object.lowerCase()}} record is dropped -AND the deleted {{object.lowerCase()}} is returned -''', - () async { - const {{object.camelCase()}}Id = 1; - const new{{object.pascalCase()}} = New{{object.pascalCase()}}( - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - new{{object.pascalCase()}}.toRealmWithId( - {{object.camelCase()}}Id, - ), - ), - ); - const query = 'id == ${{object.camelCase()}}Id'; - final initialMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect(initialMatching{{objects.pascalCase()}}Count, 1); - final deleted{{object.pascalCase()}} = await storage.deleteById({{object.camelCase()}}Id); - expect(deleted{{object.pascalCase()}}, isNotNull); - expect(deleted{{object.pascalCase()}}!.id, {{object.camelCase()}}Id); - final resultingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect(resultingMatching{{objects.pascalCase()}}Count, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -AND the ID of an unregistered {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is deleted -THEN no {{object.lowerCase()}} record is dropped -AND null is returned -''', - () async { - const {{object.camelCase()}}Id = 13; - const new{{object.pascalCase()}} = - New{{object.pascalCase()}}(name: 'name', description: 'description'); - await database.write( - () async => database.add( - new{{object.pascalCase()}}.toRealmWithId({{object.camelCase()}}Id + 1), - ), - ); - final initial{{objects.pascalCase()}} = database.all(); - expect(initial{{objects.pascalCase()}}, hasLength(1)); - final initial{{object.pascalCase()}} = initial{{objects.pascalCase()}}.single; - expect(initial{{object.pascalCase()}}.id, isNot({{object.camelCase()}}Id)); - final deleted{{object.pascalCase()}} = await storage.deleteById({{object.camelCase()}}Id); - expect(deleted{{object.pascalCase()}}, isNull); - final resulting{{objects.pascalCase()}} = database.all(); - expect(resulting{{objects.pascalCase()}}, hasLength(1)); - final resulting{{object.pascalCase()}} = resulting{{objects.pascalCase()}}.single; - expect( - resulting{{object.pascalCase()}}.to{{object.pascalCase()}}(), - initial{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several {{object.lowerCase()}} records -AND a reference {{object.lowerCase()}} -├─ THAT includes a non-null name matcher -├─ AND includes a non-null description matcher -WHEN a delete operation is performed with the reference {{object.lowerCase()}} -THEN the {{object.lowerCase()}} records matching the reference {{object.lowerCase()}} are dropped -AND the {{object.lowerCase()}} records not matching the reference {{object.lowerCase()}} are kept -''', - () async { - final {{objects.camelCase()}} = [ - const {{object.pascalCase()}}( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const {{object.pascalCase()}}( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const {{object.pascalCase()}}( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const {{object.pascalCase()}}( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const {{object.pascalCase()}}( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const {{object.pascalCase()}}( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const {{object.pascalCase()}}( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) {{object.camelCase()}}.toRealm(), - ]), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, {{objects.camelCase()}}.length); - const reference{{object.pascalCase()}} = Partial{{object.pascalCase()}}( - name: Some('matching-pattern'), - description: Some('matching-pattern'), - ); - await storage.deleteAll(reference{{object.pascalCase()}}: reference{{object.pascalCase()}}); - final resultingRealm{{objects.pascalCase()}} = - database.all(); - - bool shouldBeKept({{object.pascalCase()}} {{object.camelCase()}}) { - final {{object.pascalCase()}}(:name, :description) = {{object.camelCase()}}; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - if (description == null) return true; - final noMatchInDescription = - !description.contains('matching-pattern'); - return noMatchInDescription; - } - - final expectedResulting{{objects.pascalCase()}} = [ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) - if (shouldBeKept({{object.camelCase()}})) {{object.camelCase()}}, - ]; - expect( - resultingRealm{{objects.pascalCase()}}, - hasLength(expectedResulting{{objects.pascalCase()}}.length), - ); - final resulting{{objects.pascalCase()}} = [ - for (final realm{{object.pascalCase()}} in resultingRealm{{objects.pascalCase()}}) - realm{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ]; - expect( - resulting{{objects.pascalCase()}}, - unorderedEquals(expectedResulting{{objects.pascalCase()}}), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several {{object.lowerCase()}} records -AND a reference {{object.lowerCase()}} -├─ THAT does not include a name matcher -├─ AND includes a non-null description matcher -WHEN a delete operation is performed with the reference {{object.lowerCase()}} -THEN the {{object.lowerCase()}} records matching the reference {{object.lowerCase()}} are dropped -AND the {{object.lowerCase()}} records not matching the reference {{object.lowerCase()}} are kept -''', - () async { - final {{objects.camelCase()}} = [ - const {{object.pascalCase()}}( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const {{object.pascalCase()}}( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const {{object.pascalCase()}}( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const {{object.pascalCase()}}( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const {{object.pascalCase()}}( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const {{object.pascalCase()}}( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const {{object.pascalCase()}}( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) {{object.camelCase()}}.toRealm(), - ]), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, {{objects.camelCase()}}.length); - const reference{{object.pascalCase()}} = Partial{{object.pascalCase()}}( - description: Some('matching-pattern'), - ); - await storage.deleteAll(reference{{object.pascalCase()}}: reference{{object.pascalCase()}}); - final resultingRealm{{objects.pascalCase()}} = - database.all(); - - bool shouldBeKept({{object.pascalCase()}} {{object.camelCase()}}) { - final {{object.pascalCase()}}(:description) = {{object.camelCase()}}; - if (description == null) return true; - final noMatchInDescription = - !description.contains('matching-pattern'); - return noMatchInDescription; - } - - final expectedResulting{{objects.pascalCase()}} = [ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) - if (shouldBeKept({{object.camelCase()}})) {{object.camelCase()}}, - ]; - expect( - resultingRealm{{objects.pascalCase()}}, - hasLength(expectedResulting{{objects.pascalCase()}}.length), - ); - final resulting{{objects.pascalCase()}} = [ - for (final realm{{object.pascalCase()}} in resultingRealm{{objects.pascalCase()}}) - realm{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ]; - expect( - resulting{{objects.pascalCase()}}, - unorderedEquals(expectedResulting{{objects.pascalCase()}}), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several {{object.lowerCase()}} records -AND a reference {{object.lowerCase()}} -├─ THAT includes a non-null name matcher -├─ AND includes a null description matcher -WHEN a delete operation is performed with the reference {{object.lowerCase()}} -THEN the {{object.lowerCase()}} records matching the reference {{object.lowerCase()}} are dropped -AND the {{object.lowerCase()}} records not matching the reference {{object.lowerCase()}} are kept -''', - () async { - final {{objects.camelCase()}} = [ - const {{object.pascalCase()}}( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const {{object.pascalCase()}}( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const {{object.pascalCase()}}( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const {{object.pascalCase()}}( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const {{object.pascalCase()}}( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const {{object.pascalCase()}}( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const {{object.pascalCase()}}( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) {{object.camelCase()}}.toRealm(), - ]), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, {{objects.camelCase()}}.length); - const reference{{object.pascalCase()}} = Partial{{object.pascalCase()}}( - name: Some('matching-pattern'), - description: Some(null), - ); - await storage.deleteAll(reference{{object.pascalCase()}}: reference{{object.pascalCase()}}); - final resultingRealm{{objects.pascalCase()}} = - database.all(); - - bool shouldBeKept({{object.pascalCase()}} {{object.camelCase()}}) { - final {{object.pascalCase()}}(:name, :description) = {{object.camelCase()}}; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - return description != null; - } - - final expectedResulting{{objects.pascalCase()}} = [ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) - if (shouldBeKept({{object.camelCase()}})) {{object.camelCase()}}, - ]; - expect( - resultingRealm{{objects.pascalCase()}}, - hasLength(expectedResulting{{objects.pascalCase()}}.length), - ); - final resulting{{objects.pascalCase()}} = [ - for (final realm{{object.pascalCase()}} in resultingRealm{{objects.pascalCase()}}) - realm{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ]; - expect( - resulting{{objects.pascalCase()}}, - unorderedEquals(expectedResulting{{objects.pascalCase()}}), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several {{object.lowerCase()}} records -AND a reference {{object.lowerCase()}} -├─ THAT includes a non-null name matcher -├─ AND includes a non-null empty description matcher -WHEN a delete operation is performed with the reference {{object.lowerCase()}} -THEN the {{object.lowerCase()}} records matching the reference {{object.lowerCase()}} are dropped -AND the {{object.lowerCase()}} records not matching the reference {{object.lowerCase()}} are kept -''', - () async { - final {{objects.camelCase()}} = [ - const {{object.pascalCase()}}( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const {{object.pascalCase()}}( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const {{object.pascalCase()}}( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const {{object.pascalCase()}}( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const {{object.pascalCase()}}( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const {{object.pascalCase()}}( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const {{object.pascalCase()}}( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) {{object.camelCase()}}.toRealm(), - ]), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, {{objects.camelCase()}}.length); - const reference{{object.pascalCase()}} = Partial{{object.pascalCase()}}( - name: Some('matching-pattern'), - description: Some(''), - ); - await storage.deleteAll(reference{{object.pascalCase()}}: reference{{object.pascalCase()}}); - final resultingRealm{{objects.pascalCase()}} = - database.all(); - - bool shouldBeKept({{object.pascalCase()}} {{object.camelCase()}}) { - final {{object.pascalCase()}}(:name) = {{object.camelCase()}}; - final noMatchInTitle = !name.contains('matching-pattern'); - return noMatchInTitle; - } - - final expectedResulting{{objects.pascalCase()}} = [ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) - if (shouldBeKept({{object.camelCase()}})) {{object.camelCase()}}, - ]; - expect( - resultingRealm{{objects.pascalCase()}}, - hasLength(expectedResulting{{objects.pascalCase()}}.length), - ); - final resulting{{objects.pascalCase()}} = [ - for (final realm{{object.pascalCase()}} in resultingRealm{{objects.pascalCase()}}) - realm{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ]; - expect( - resulting{{objects.pascalCase()}}, - unorderedEquals(expectedResulting{{objects.pascalCase()}}), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several {{object.lowerCase()}} records -AND a reference {{object.lowerCase()}} -├─ AND includes non-null name matcher -├─ AND includes empty description matcher -WHEN a delete operation is performed with the reference {{object.lowerCase()}} -THEN the {{object.lowerCase()}} records matching the reference {{object.lowerCase()}} are dropped -AND the {{object.lowerCase()}} records not matching the reference {{object.lowerCase()}} are kept -''', - () async { - final {{objects.camelCase()}} = [ - const {{object.pascalCase()}}( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 2', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 3, - name: 'name 3 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const {{object.pascalCase()}}( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const {{object.pascalCase()}}( - id: 6, - name: 'name 6', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 7, - name: 'name 7 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const {{object.pascalCase()}}( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const {{object.pascalCase()}}( - id: 10, - name: 'name 10', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 11, - name: 'name 11 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const {{object.pascalCase()}}( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const {{object.pascalCase()}}( - id: 14, - name: 'name 14', - // ignore: avoid_redundant_argument_values - description: null, - ), - const {{object.pascalCase()}}( - id: 15, - name: 'name 15 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - ]; - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) {{object.camelCase()}}.toRealm(), - ]), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, {{objects.camelCase()}}.length); - const reference{{object.pascalCase()}} = Partial{{object.pascalCase()}}( - name: Some('matching-pattern'), - description: Some(null), - ); - await storage.deleteAll(reference{{object.pascalCase()}}: reference{{object.pascalCase()}}); - final resultingRealm{{objects.pascalCase()}} = - database.all(); - - bool shouldBeKept({{object.pascalCase()}} {{object.camelCase()}}) { - final {{object.pascalCase()}}(:name, :description) = {{object.camelCase()}}; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - final noMatchInDescription = - description != null && description.isNotEmpty; - return noMatchInDescription; - } - - final expectedResulting{{objects.pascalCase()}} = [ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) - if (shouldBeKept({{object.camelCase()}})) {{object.camelCase()}}, - ]; - expect( - resultingRealm{{objects.pascalCase()}}, - hasLength(expectedResulting{{objects.pascalCase()}}.length), - ); - final resulting{{objects.pascalCase()}} = [ - for (final realm{{object.pascalCase()}} in resultingRealm{{objects.pascalCase()}}) - realm{{object.pascalCase()}}.to{{object.pascalCase()}}(), - ]; - expect( - resulting{{objects.pascalCase()}}, - unorderedEquals(expectedResulting{{objects.pascalCase()}}), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several {{object.lowerCase()}} records -WHEN a delete operation is performed with no reference {{object.lowerCase()}} -THEN all {{object.lowerCase()}} records are dropped -''', - () async { - final {{objects.camelCase()}} = List.generate( - 30, - (index) => {{object.pascalCase()}}( - id: index, - name: 'name $index', - description: 'description $index', - ), - ); - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}) {{object.camelCase()}}.toRealm(), - ]), - ); - final initial{{objects.pascalCase()}}Count = - database.all().length; - expect(initial{{objects.pascalCase()}}Count, {{objects.camelCase()}}.length); - await storage.deleteAll(); - final resultingRealm{{objects.pascalCase()}}Count = - database.all().length; - expect(resultingRealm{{objects.pascalCase()}}Count, isZero); - }, - ); - - test( - ''' - -AND a {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is inserted -THEN a {{object.lowerCase()}} record is registered -''', - () async { - const {{object.camelCase()}} = {{object.pascalCase()}}( - id: 1, - name: 'name', - description: 'description', - ); - final existing{{objects.pascalCase()}}Count = - database.all().length; - expect(existing{{objects.pascalCase()}}Count, isZero); - await storage.insert({{object.camelCase()}}: {{object.camelCase()}}); - final resultingRealm{{objects.pascalCase()}} = - database.all(); - expect(resultingRealm{{objects.pascalCase()}}, hasLength(1)); - final resultingRealm{{object.pascalCase()}} = - resultingRealm{{objects.pascalCase()}}.single; - expect(resultingRealm{{object.pascalCase()}}.to{{object.pascalCase()}}(), {{object.camelCase()}}); - }, - ); - - test( - ''' - -AND the ID of a registered {{object.lowerCase()}} -AND the valid partial {{object.lowerCase()}} data -WHEN the {{object.lowerCase()}} is updated -THEN a {{object.lowerCase()}} record is updated -''', - () async { - const {{object.camelCase()}} = {{object.pascalCase()}}( - id: 13, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - {{object.camelCase()}}.toRealm(), - ), - ); - final existing{{objects.pascalCase()}}Count = - database.all().length; - expect(existing{{objects.pascalCase()}}Count, 1); - const newName = 'new name'; - const newDescription = 'new description'; - final query = ' ' - 'id == ${{{object.camelCase()}}.id} ' - 'AND ' - 'name == "$newName" ' - 'AND ' - 'description == "$newDescription"'; - final existingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect(existingMatching{{objects.pascalCase()}}Count, isZero); - await storage.update( - {{object.camelCase()}}Id: {{object.camelCase()}}.id, - partial{{object.pascalCase()}}: const Partial{{object.pascalCase()}}( - name: Some(newName), - description: Some(newDescription), - ), - ); - final resultingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect( - resultingMatching{{objects.pascalCase()}}Count, - existingMatching{{objects.pascalCase()}}Count + 1, - ); - }, - ); - - test( - ''' - -AND the invalid data for a new {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is created -THEN an exception is thrown -AND no {{object.lowerCase()}} record is registered -''', - () async { - const new{{object.pascalCase()}} = New{{object.pascalCase()}}( - name: '', - description: 'description', - ); - final existing{{objects.pascalCase()}}Count = - database.all().length; - expect(existing{{objects.pascalCase()}}Count, isZero); - expect( - () async => storage.create(new{{object.pascalCase()}}: new{{object.pascalCase()}}), - throwsA(isA()), - ); - final resulting{{objects.pascalCase()}}Count = - database.all().length; - expect(resulting{{objects.pascalCase()}}Count, isZero); - }, - ); - - test( - ''' - -AND the ID of a registered {{object.lowerCase()}} -AND the invalid partial {{object.lowerCase()}} data -WHEN the {{object.lowerCase()}} is updated -THEN an exception is thrown -AND no {{object.lowerCase()}} record is updated -''', - () async { - const {{object.camelCase()}} = {{object.pascalCase()}}( - id: 76, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - {{object.camelCase()}}.toRealm(), - ), - ); - final existing{{objects.pascalCase()}}Count = - database.all().length; - expect(existing{{objects.pascalCase()}}Count, 1); - const newName = ''; - const newDescription = 'new description'; - final query = ' ' - 'id == ${{{object.camelCase()}}.id} ' - 'AND ' - 'name == "$newName" ' - 'AND ' - 'description == "$newDescription"'; - final existingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect(existingMatching{{objects.pascalCase()}}Count, isZero); - expect( - () async => storage.update( - {{object.camelCase()}}Id: {{object.camelCase()}}.id, - partial{{object.pascalCase()}}: const Partial{{object.pascalCase()}}( - name: Some(newName), - description: Some(newDescription), - ), - ), - throwsA(isA()), - ); - final resultingMatching{{objects.pascalCase()}}Count = - database.query(query).length; - expect(resultingMatching{{objects.pascalCase()}}Count, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -AND the ID of a registered {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is requested -THEN the {{object.lowerCase()}} is returned -''', - () async { - const {{object.camelCase()}}Id = 8; - const {{object.camelCase()}} = {{object.pascalCase()}}( - id: {{object.camelCase()}}Id, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add({{object.camelCase()}}.toRealm()), - ); - final initialMatching{{objects.pascalCase()}}Count = - database.query('id == ${{object.camelCase()}}Id').length; - expect(initialMatching{{objects.pascalCase()}}Count, 1); - final retrieved{{object.pascalCase()}} = await storage.getById({{object.camelCase()}}Id); - expect(retrieved{{object.pascalCase()}}, isNotNull); - expect(retrieved{{object.pascalCase()}}, {{object.camelCase()}}); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -AND the ID of an unregistered {{object.lowerCase()}} -WHEN the {{object.lowerCase()}} is requested -THEN null is returned -''', - () async { - const {{object.camelCase()}}Id = 7; - final initialMatching{{objects.pascalCase()}}Count = - database.query('id == ${{object.camelCase()}}Id').length; - expect(initialMatching{{objects.pascalCase()}}Count, isZero); - final retrieved{{object.pascalCase()}} = await storage.getById({{object.camelCase()}}Id); - expect(retrieved{{object.pascalCase()}}, isNull); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -WHEN the {{objects.lowerCase()}} are watched -├─ AND are not filtered by their content -THEN the {{objects.lowerCase()}} that match the conditions are continuously emitted as they change -''', - () async { - final stream = storage.watch(); - - // Stage 00 - final {{objects.camelCase()}}ForStage00 = <{{object.pascalCase()}}>[ - const {{object.pascalCase()}}( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 01', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 02', - ), - ]; - final sorted{{objects.pascalCase()}}ForStage00 = [...{{objects.camelCase()}}ForStage00] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 01 - const new{{object.pascalCase()}}InStage01 = {{object.pascalCase()}}( - id: 3, - name: 'name 03', - ); - final {{objects.camelCase()}}ForStage01 = <{{object.pascalCase()}}>[ - ...{{objects.camelCase()}}ForStage00, - new{{object.pascalCase()}}InStage01, - ]; - final sorted{{objects.pascalCase()}}ForStage01 = [...{{objects.camelCase()}}ForStage01] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 02 - final {{objects.camelCase()}}ForStage02 = <{{object.pascalCase()}}>[ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage01) - if (!{{object.camelCase()}}.name.contains('01')) {{object.camelCase()}}, - ]; - final sorted{{objects.pascalCase()}}ForStage02 = [...{{objects.camelCase()}}ForStage02] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 03 - final {{objects.camelCase()}}ForStage03 = <{{object.pascalCase()}}>[ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage02) - if ({{object.camelCase()}}.description == null) - {{object.pascalCase()}}( - id: {{object.camelCase()}}.id, - name: {{object.camelCase()}}.name, - description: 'updated description', - ) - else - {{object.camelCase()}}, - ]; - final sorted{{objects.pascalCase()}}ForStage03 = [...{{objects.camelCase()}}ForStage03] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - orderedEquals(sorted{{objects.pascalCase()}}ForStage00), - orderedEquals(sorted{{objects.pascalCase()}}ForStage01), - orderedEquals(sorted{{objects.pascalCase()}}ForStage02), - orderedEquals(sorted{{objects.pascalCase()}}ForStage03), - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage00) - {{object.camelCase()}}.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database - .add(new{{object.pascalCase()}}InStage01.toRealm()), - ); - - // Stage 02 - await database.write( - () async { - final matching{{objects.pascalCase()}} = - database.query('name CONTAINS "01"'); - database.deleteMany(matching{{objects.pascalCase()}}); - }, - ); - - // Stage 03 - await database.write( - () async { - final {{objects.camelCase()}}WithNullDescription = - database.query('description == null'); - for (final {{object.camelCase()}} in {{objects.camelCase()}}WithNullDescription) { - {{object.camelCase()}}.description = 'updated description'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -WHEN the {{objects.lowerCase()}} are watched -├─ AND are filtered by their content -THEN the {{objects.lowerCase()}} that match the conditions are continuously emitted as they change -''', - () async { - final stream = storage.watch(searchTerm: 'matching-pattern'); - - bool matches({{object.pascalCase()}} {{object.camelCase()}}) => - {{object.camelCase()}}.name.contains('matching-pattern') || - ({{object.camelCase()}}.description?.contains('matching-pattern') ?? false); - - // Stage 00 - final {{objects.camelCase()}}ForStage00 = <{{object.pascalCase()}}>[ - const {{object.pascalCase()}}( - id: 0, - name: 'name 00', - description: 'description 00 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 01', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 02', - ), - const {{object.pascalCase()}}( - id: 3, - name: 'name 03', - description: 'description 03 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 4, - name: 'name 04', - ), - const {{object.pascalCase()}}( - id: 5, - name: 'name 05', - description: 'description 05 matching-pattern', - ), - ]; - final sorted{{objects.pascalCase()}}ForStage00 = [...{{objects.camelCase()}}ForStage00] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 01 - const new{{object.pascalCase()}}InStage01 = {{object.pascalCase()}}( - id: 6, - name: 'name 06 matching-pattern', - ); - final {{objects.camelCase()}}ForStage01 = <{{object.pascalCase()}}>[ - ...{{objects.camelCase()}}ForStage00, - new{{object.pascalCase()}}InStage01, - ]; - final sorted{{objects.pascalCase()}}ForStage01 = [...{{objects.camelCase()}}ForStage01] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 02 - final {{objects.camelCase()}}ForStage02 = <{{object.pascalCase()}}>[ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage01) - if (!{{object.camelCase()}}.name.contains('00')) {{object.camelCase()}}, - ]; - final sorted{{objects.pascalCase()}}ForStage02 = [...{{objects.camelCase()}}ForStage02] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 03 - final {{objects.camelCase()}}ForStage03 = <{{object.pascalCase()}}>[ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage02) - if ({{object.camelCase()}}.description == null) - {{object.pascalCase()}}( - id: {{object.camelCase()}}.id, - name: {{object.camelCase()}}.name, - description: 'updated description matching-pattern', - ) - else - {{object.camelCase()}}, - ]; - final sorted{{objects.pascalCase()}}ForStage03 = [...{{objects.camelCase()}}ForStage03] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - orderedEquals(sorted{{objects.pascalCase()}}ForStage00), - orderedEquals(sorted{{objects.pascalCase()}}ForStage01), - orderedEquals(sorted{{objects.pascalCase()}}ForStage02), - orderedEquals(sorted{{objects.pascalCase()}}ForStage03), - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage00) - {{object.camelCase()}}.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database - .add(new{{object.pascalCase()}}InStage01.toRealm()), - ); - - // Stage 02 - await database.write( - () async { - final {{object.camelCase()}}ToDelete = - database.query('name CONTAINS "00"'); - database.deleteMany({{object.camelCase()}}ToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final {{objects.camelCase()}}WithNullDescription = - database.query('description == null'); - for (final {{object.camelCase()}} in {{objects.camelCase()}}WithNullDescription) { - {{object.camelCase()}}.description = - 'updated description matching-pattern'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -WHEN the {{objects.lowerCase()}} count is watched -├─ AND are not filtered by their content -THEN the quantity of persisted {{objects.lowerCase()}} that match the conditions is continuously emitted as it changes -''', - () async { - final stream = storage.watchCount(); - - // Stage 00 - final {{objects.camelCase()}}ForStage00 = <{{object.pascalCase()}}>[ - const {{object.pascalCase()}}( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 01', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 02', - description: 'description 02', - ), - ]; - - // Stage 01 - const new{{object.pascalCase()}}InStage01 = {{object.pascalCase()}}( - id: 3, - name: 'name 03', - ); - final {{objects.camelCase()}}ForStage01 = <{{object.pascalCase()}}>[ - ...{{objects.camelCase()}}ForStage00, - new{{object.pascalCase()}}InStage01, - ]; - - // Stage 02 - final {{objects.camelCase()}}ForStage02 = <{{object.pascalCase()}}>[ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage01) - if (!{{object.camelCase()}}.name.contains('01')) {{object.camelCase()}}, - ]; - - // Stage 03 - // final {{objects.camelCase()}}ForStage03 = <{{object.pascalCase()}}>[ - // for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage02) - // if ({{object.camelCase()}}.description == null) - // {{object.pascalCase()}}( - // id: {{object.camelCase()}}.id, - // name: {{object.camelCase()}}.name, - // description: 'updated description', - // ) - // else - // {{object.camelCase()}}, - // ]; - - unawaited( - expectLater( - stream, - emitsInOrder([ - {{objects.camelCase()}}ForStage00.length, - {{objects.camelCase()}}ForStage01.length, - {{objects.camelCase()}}ForStage02.length, - - // Not emitted as the {{objects.lowerCase()}} count has not changed - // {{objects.camelCase()}}ForStage03.length, - ]), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage00) - {{object.camelCase()}}.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database.add( - new{{object.pascalCase()}}InStage01.toRealm(), - ), - ); - - // Stage 02 - await database.write( - () async { - final {{objects.camelCase()}}ToDelete = - database.query('name CONTAINS "01"'); - database.deleteMany({{objects.camelCase()}}ToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final {{objects.camelCase()}}WithNullDescription = - database.query('description == null'); - for (final {{object.camelCase()}} in {{objects.camelCase()}}WithNullDescription) { - {{object.camelCase()}}.description = 'updated description'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has {{object.lowerCase()}} records -WHEN the {{objects.lowerCase()}} count is watched -├─ AND are filtered by their content -THEN the quantity of persisted {{objects.lowerCase()}} that match the conditions is continuously emitted as it changes -''', - () async { - final stream = storage.watchCount(searchTerm: 'matching-pattern'); - bool match({{object.pascalCase()}} {{object.camelCase()}}) => - {{object.camelCase()}}.name.contains('matching-pattern') || - ({{object.camelCase()}}.description?.contains('matching-pattern') ?? false); - - // Stage 00 - final {{objects.camelCase()}}ForStage00 = <{{object.pascalCase()}}>[ - const {{object.pascalCase()}}( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const {{object.pascalCase()}}( - id: 1, - name: 'name 01 matching-pattern', - ), - const {{object.pascalCase()}}( - id: 2, - name: 'name 02', - description: 'description 02 matching-pattern', - ), - ]; - final expected{{objects.pascalCase()}}ForStage00 = - {{objects.camelCase()}}ForStage00.where(match); - - // Stage 01 - const new{{object.pascalCase()}}InStage01 = {{object.pascalCase()}}( - id: 3, - name: 'name 03 matching-pattern', - ); - final {{objects.camelCase()}}ForStage01 = <{{object.pascalCase()}}>[ - ...{{objects.camelCase()}}ForStage00, - new{{object.pascalCase()}}InStage01, - ]; - final expected{{objects.pascalCase()}}ForStage01 = - {{objects.camelCase()}}ForStage01.where(match); - - // Stage 02 - final {{objects.camelCase()}}ForStage02 = <{{object.pascalCase()}}>[ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage01) - if (!{{object.camelCase()}}.name.contains('01')) {{object.camelCase()}}, - ]; - final expected{{objects.pascalCase()}}ForStage02 = - {{objects.camelCase()}}ForStage02.where(match); - - // Stage 03 - // final {{objects.camelCase()}}ForStage03 = <{{object.pascalCase()}}>[ - // for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage02) - // if ({{object.camelCase()}}.description == null) - // {{object.pascalCase()}}( - // id: {{object.camelCase()}}.id, - // name: {{object.camelCase()}}.name, - // description: 'updated description', - // ) - // else - // {{object.camelCase()}}, - // ]; - // final expected{{objects.pascalCase()}}ForStage03 = - // {{objects.camelCase()}}ForStage03.where(match); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - expected{{objects.pascalCase()}}ForStage00.length, - expected{{objects.pascalCase()}}ForStage01.length, - expected{{objects.pascalCase()}}ForStage02.length, - - // Not emitted as the {{objects.lowerCase()}} count has not changed - // expected{{objects.pascalCase()}}ForStage03.length, - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final {{object.camelCase()}} in {{objects.camelCase()}}ForStage00) - {{object.camelCase()}}.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database.add( - new{{object.pascalCase()}}InStage01.toRealm(), - ), - ); - - // Stage 02 - await database.write( - () async { - final {{object.camelCase()}}ToDelete = - database.query('name CONTAINS "01"'); - database.deleteMany({{object.camelCase()}}ToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final {{objects.camelCase()}}WithNullDescription = - database.query('description == null'); - for (final {{object.camelCase()}} in {{objects.camelCase()}}WithNullDescription) { - {{object.camelCase()}}.description = 'updated description'; - } - }, - ); - }, - ); - }, - ); -} diff --git a/bricks/altoke_storage/brick/brick.yaml b/bricks/altoke_storage/brick/brick.yaml index 7820fc17..b8d2dcad 100644 --- a/bricks/altoke_storage/brick/brick.yaml +++ b/bricks/altoke_storage/brick/brick.yaml @@ -22,7 +22,6 @@ vars: - drift - hive - isar - - realm - sembast description: The approach to use for data persistence. default: hive diff --git a/bricks/altoke_storage/brick/hooks/post_gen.dart b/bricks/altoke_storage/brick/hooks/post_gen.dart index 9b6bf964..6eda9830 100644 --- a/bricks/altoke_storage/brick/hooks/post_gen.dart +++ b/bricks/altoke_storage/brick/hooks/post_gen.dart @@ -45,7 +45,7 @@ Future run(HookContext context) async { Future runCommands({ required Directory projectDir, - String? codeGenerationCommand, + required bool runCodeGeneration, }) async { sortPubspecDependencies(projectDir.path); await Dart.getPackages( @@ -54,10 +54,9 @@ Future run(HookContext context) async { onSuccess: onSuccess('📦 Dependencies installed!'), onError: onError('📦 Failed to install dependencies'), ); - if (codeGenerationCommand != null) { - await Shell.run( - codeGenerationCommand, - workingDir: projectDir.path, + if (runCodeGeneration) { + await Dart.generateCode( + projectDir, onStart: onStart('🏭 Running code generation'), onSuccess: onSuccess('🏭 Code generation complete!'), onError: onError('🏭 Failed to run code generation'), @@ -88,6 +87,7 @@ Future run(HookContext context) async { ); await runCommands( projectDir: Directory(interfaceProjectPath), + runCodeGeneration: false, ); final implementationProjectPath = path.join( umbrellaPath, @@ -95,6 +95,6 @@ Future run(HookContext context) async { ); await runCommands( projectDir: Directory(implementationProjectPath), - codeGenerationCommand: selectedApproach.codeGenerationCommand, + runCodeGeneration: true, ); } diff --git a/bricks/altoke_storage/brick/hooks/pre_gen.dart b/bricks/altoke_storage/brick/hooks/pre_gen.dart index 21314abc..db0671e5 100644 --- a/bricks/altoke_storage/brick/hooks/pre_gen.dart +++ b/bricks/altoke_storage/brick/hooks/pre_gen.dart @@ -2,6 +2,11 @@ import 'package:data_persistence_approach/data_persistence_approach.dart'; import 'package:mason/mason.dart'; void run(HookContext context) { + final selectedDataPersistenceApproach = + DataPersistenceApproach.getSelectedApproach(context); + if (selectedDataPersistenceApproach == DataPersistenceApproach.realm) { + throw UnsupportedError('Realm is not supported anymore'); + } context.vars = { ...context.vars, ...DataPersistenceApproach.getSelectionMap(context), diff --git a/bricks/altoke_storage/e2e/e2e/brick_e2e_test.dart b/bricks/altoke_storage/e2e/e2e/brick_e2e_test.dart index b43f8f59..380b0ece 100644 --- a/bricks/altoke_storage/e2e/e2e/brick_e2e_test.dart +++ b/bricks/altoke_storage/e2e/e2e/brick_e2e_test.dart @@ -26,11 +26,6 @@ Future main() async { final rawDataPersistenceApproach = vars[DataPersistenceApproach.varKey]!; final dataPersistenceApproaches = rawDataPersistenceApproach.values! .map(DataPersistenceApproach.fromVarIdentifier); - // FIXME: Test Realm approach once it is testable. - // Ref: https://github.com/realm/realm-dart/issues/1619 - final testableApproaches = dataPersistenceApproaches.where( - (approach) => approach != DataPersistenceApproach.realm, - ); await testGeneration( ''' @@ -39,7 +34,7 @@ WHEN the generation is run THEN the generated outputs should be valid and testable ''', generationCases: { - for (final dataPersistenceApproach in testableApproaches) + for (final dataPersistenceApproach in dataPersistenceApproaches) (dataPersistenceApproach: dataPersistenceApproach), }, ); diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/.gitignore b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/.gitignore deleted file mode 100644 index 118f3226..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -# See https://www.dartlang.org/guides/libraries/private-files - -# Files and directories created by pub -/.dart_tool/ -/.packages -/build/ -/pubspec.lock - -# Testing -/coverage/ - -# Realm -/default.realm.lock -/default.realm.management/ -/binary/ diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/README.md b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/README.md deleted file mode 100644 index 97857577..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Altoke Entities Realm Storage - -A persistent storage for Altoke Entities built on top of Realm. diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/analysis_options.yaml b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/analysis_options.yaml deleted file mode 100644 index 6b773509..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:very_good_analysis/analysis_options.yaml -analyzer: - exclude: - - lib/**.realm.dart diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/altoke_entities_realm_storage.dart b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/altoke_entities_realm_storage.dart deleted file mode 100644 index f5fd5ca4..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/altoke_entities_realm_storage.dart +++ /dev/null @@ -1,6 +0,0 @@ -/// A persistent storage for Altoke Entities built on top of Realm. -library altoke_entities_realm_storage; - -export 'src/altoke_entities_filter.dart'; -export 'src/altoke_entities_realm_storage.dart'; -export 'src/realm_altoke_entity.dart'; diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/altoke_entities_filter.dart b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/altoke_entities_filter.dart deleted file mode 100644 index 6626d904..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/altoke_entities_filter.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:altoke_common/common.dart'; -import 'package:altoke_entity/altoke_entity.dart'; -import 'package:collection/collection.dart'; - -/// A set of filters to apply on [AltokeEntity]s -abstract class AltokeEntitiesFilter { - /// A filter to match the given [partialAltokeEntity]. - static String? matchesPartial( - PartialAltokeEntity? partialAltokeEntity, - ) { - if (partialAltokeEntity == null) return null; - final PartialAltokeEntity(:name, :description) = partialAltokeEntity; - final nameMatches = switch (name) { - None() => null, - Some(value: final nameFragment) => nameContains(nameFragment), - }; - final descriptionMatches = switch (description) { - None() => null, - Some(value: final descriptionFragment) => switch ( - descriptionFragment?.trim()) { - null => descriptionIsNull(), - final descriptionFragment => descriptionContains(descriptionFragment), - }, - }; - return andAll([nameMatches, descriptionMatches]); - } - - /// A filter to match the given [name] against the [AltokeEntity.name]. - static String? nameContains(String name) { - return switch (name.trim()) { - String(:final isEmpty) when isEmpty => null, - final searchTerm => 'name CONTAINS "$searchTerm"', - }; - } - - /// A filter to match `null` [AltokeEntity.description]s. - static String descriptionIsNull() { - return 'description == null'; - } - - /// A filter to match non-`null` [AltokeEntity.description]s. - static String descriptionIsNotNull() { - return 'description != null'; - } - - /// A filter to match the given [description] against the - /// [AltokeEntity.description]. - static String? descriptionContains(String description) { - return switch (description.trim()) { - String(:final isEmpty) when isEmpty => descriptionIsNotNull(), - /*remove-start*/ - // TODO(mrverdant13): Review if it is necessary to check nullability. - /*remove-end*/ - final descriptionFragment => - 'description CONTAINS "$descriptionFragment"', - }; - } - - /// A filter to match the given [content] against the [AltokeEntity.name] and - /// [AltokeEntity.description]. - static String? matchesContent(String? content) { - return switch (content?.trim()) { - null => null, - String(:final isEmpty) when isEmpty => null, - final content => orAll([ - nameContains(content), - descriptionContains(content), - ]), - }; - } - - /// A filter that combines the given [filters] to match all of them. - static String? andAll(Iterable filters) { - final validFilters = filters.whereNotNull(); - if (validFilters.isEmpty) return null; - return validFilters.join(' AND '); - } - - /// A filter that combines the given [filters] to match any of them. - static String? orAll(Iterable filters) { - final validFilters = filters.whereNotNull(); - if (validFilters.isEmpty) return null; - return validFilters.join(' OR '); - } -} diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/altoke_entities_realm_storage.dart b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/altoke_entities_realm_storage.dart deleted file mode 100644 index f6d76a53..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/altoke_entities_realm_storage.dart +++ /dev/null @@ -1,153 +0,0 @@ -import 'package:altoke_common/common.dart'; -import 'package:altoke_entities_realm_storage/src/altoke_entities_filter.dart'; -import 'package:altoke_entities_realm_storage/src/realm_altoke_entity.dart'; -import 'package:altoke_entities_storage/altoke_entities_storage.dart'; -import 'package:altoke_entity/altoke_entity.dart'; -import 'package:collection/collection.dart'; -import 'package:meta/meta.dart'; -import 'package:realm/realm.dart'; - -/// {@template altoke_entities_realm_storage} -/// A persistent [AltokeEntitiesStorage] implementation using Realm. -/// {@endtemplate} -class AltokeEntitiesRealmStorage implements AltokeEntitiesStorage { - /// {@macro altoke_entities_realm_storage} - AltokeEntitiesRealmStorage({ - required this.database, - }); - - /// The Realm database. - @visibleForTesting - final Realm database; - - /// Equality checker for [AltokeEntity]s. - @visibleForTesting - static const altokeEntitiesEqualityChecker = IterableEquality(); - - @override - Future create({ - required NewAltokeEntity newAltokeEntity, - }) async { - if (newAltokeEntity.name.isEmpty) { - throw const CreateAltokeEntityFailureEmptyName(); - } - await database.write(() async { - final latestAltokeEntityId = database - .query('id != 0 SORT(id DESC) LIMIT(1)') - .firstOrNull - ?.id ?? - 0; - final newId = latestAltokeEntityId + 1; - database.add(newAltokeEntity.toRealmWithId(newId)); - }); - } - - @override - Future insert({ - required AltokeEntity altokeEntity, - }) async { - await database.write(() async { - database.add( - altokeEntity.toRealm(), - update: true, - ); - }); - } - - @override - Future getById( - int altokeEntityId, - ) async { - final realmAltokeEntity = database.find(altokeEntityId); - return realmAltokeEntity?.toAltokeEntity(); - } - - @override - Stream> watch({ - String? searchTerm, - }) { - final queryExpression = AltokeEntitiesFilter.matchesContent(searchTerm); - final filteredAltokeEntitiesQuery = switch (queryExpression) { - String() => database.query( - '$queryExpression SORT(name ASC)', - ), - null => database.query( - // cspell:disable-next-line - 'TRUEPREDICATE SORT(name ASC)', - ), - }; - return filteredAltokeEntitiesQuery.changes - .asBroadcastStream() - .map((changes) => changes.results) - .map(altokeEntitiesFromRealmAltokeEntities) - .distinct(altokeEntitiesEqualityChecker.equals); - } - - @override - Stream watchCount({ - String? searchTerm, - }) { - final queryExpression = AltokeEntitiesFilter.matchesContent(searchTerm); - final allAltokeEntitiesQuery = database.all(); - final filteredAltokeEntitiesQuery = queryExpression == null - ? allAltokeEntitiesQuery - : allAltokeEntitiesQuery.query(queryExpression); - return filteredAltokeEntitiesQuery.changes - .map((changes) => changes.results.length) - .distinct(); - } - - @override - Future update({ - required int altokeEntityId, - required PartialAltokeEntity partialAltokeEntity, - }) async { - if (partialAltokeEntity - case PartialAltokeEntity(name: Some(value: String(:final isEmpty))) - when isEmpty) { - throw const UpdateAltokeEntityFailureEmptyName(); - } - final existingAltokeEntity = - database.find(altokeEntityId); - if (existingAltokeEntity == null) return; - await database.write(() async { - database.add( - existingAltokeEntity.copyWithAppliedPartial(partialAltokeEntity), - update: true, - ); - }); - } - - @override - Future deleteById( - int altokeEntityId, - ) async { - final existingRealmAltokeEntity = - database.find(altokeEntityId); - if (existingRealmAltokeEntity == null) return null; - final existingAltokeEntity = existingRealmAltokeEntity.toAltokeEntity(); - await database.write(() async { - database.delete(existingRealmAltokeEntity); - }); - return existingAltokeEntity; - } - - @override - Future deleteAll({ - PartialAltokeEntity? referenceAltokeEntity, - }) async { - final queryExpression = - AltokeEntitiesFilter.matchesPartial(referenceAltokeEntity); - if (queryExpression == null) { - await database.write(() async { - database.deleteAll(); - }); - return; - } - await database.write(() async { - final matchingAltokeEntities = - database.all().query(queryExpression); - database.deleteMany(matchingAltokeEntities); - }); - } -} diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/realm_altoke_entity.dart b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/realm_altoke_entity.dart deleted file mode 100644 index 58ddd001..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/realm_altoke_entity.dart +++ /dev/null @@ -1,91 +0,0 @@ -import 'package:altoke_common/common.dart'; -import 'package:altoke_entity/altoke_entity.dart'; -import 'package:realm/realm.dart'; - -part 'realm_altoke_entity.realm.dart'; - -/// Realm schema for Altoke Entities. -// ignore: non_constant_identifier_names -final RealmAltokeEntitySchema = RealmAltokeEntity.schema; - -/// A Realm representation of an Altoke Entity. -@RealmModel() -class _RealmAltokeEntity { - /// The ID of this altoke entity. - @PrimaryKey() - late int id; - - /// The name of this altoke entity. - late String name; - - /// The description of this altoke entity. - late String? description; - - /// Converts this [RealmAltokeEntity] to an [AltokeEntity]. - AltokeEntity toAltokeEntity() { - return AltokeEntity( - id: id, - name: name, - description: description, - ); - } - - /// Applies the [partialAltokeEntity] to this [RealmAltokeEntity]. - RealmAltokeEntity copyWithAppliedPartial( - PartialAltokeEntity partialAltokeEntity, - ) { - final realmAltokeEntity = RealmAltokeEntity( - id, - name, - description: description, - ); - if (partialAltokeEntity.name case Some(value: final name)) { - realmAltokeEntity.name = name.trim(); - } - if (partialAltokeEntity.description case Some(value: final description)) { - realmAltokeEntity.description = switch (description?.trim()) { - null => null, - String(:final isEmpty) when isEmpty => null, - final description => description.trim(), - }; - } - return realmAltokeEntity; - } -} - -/// An extension on [AltokeEntity] to add mapping capabilities. -extension MappableAltokeEntity on AltokeEntity { - /// Converts this [AltokeEntity] to a [RealmAltokeEntity]. - RealmAltokeEntity toRealm() { - return RealmAltokeEntity( - id, - name, - description: description, - ); - } -} - -/// An extension on [NewAltokeEntity] to add mapping capabilities. -extension MappableNewAltokeEntity on NewAltokeEntity { - /// Converts this [NewAltokeEntity] to a [RealmAltokeEntity]. - RealmAltokeEntity toRealmWithId(int id) { - return RealmAltokeEntity( - id, - name, - description: description, - ); - } -} - -/// An [Iterable] of [RealmAltokeEntity]s. -typedef RealmAltokeEntitiesIterable = Iterable; - -/// Converts a list of [RealmAltokeEntity]s to a list of [AltokeEntity]s. -List altokeEntitiesFromRealmAltokeEntities( - RealmAltokeEntitiesIterable realmAltokeEntities, -) { - return [ - for (final realmAltokeEntity in realmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; -} diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/realm_altoke_entity.realm.dart b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/realm_altoke_entity.realm.dart deleted file mode 100644 index d2bc1405..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/lib/src/realm_altoke_entity.realm.dart +++ /dev/null @@ -1,87 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'realm_altoke_entity.dart'; - -// ************************************************************************** -// RealmObjectGenerator -// ************************************************************************** - -// ignore_for_file: type=lint -class RealmAltokeEntity extends _RealmAltokeEntity - with RealmEntity, RealmObjectBase, RealmObject { - RealmAltokeEntity( - int id, - String name, { - String? description, - }) { - RealmObjectBase.set(this, 'id', id); - RealmObjectBase.set(this, 'name', name); - RealmObjectBase.set(this, 'description', description); - } - - RealmAltokeEntity._(); - - @override - int get id => RealmObjectBase.get(this, 'id') as int; - @override - set id(int value) => RealmObjectBase.set(this, 'id', value); - - @override - String get name => RealmObjectBase.get(this, 'name') as String; - @override - set name(String value) => RealmObjectBase.set(this, 'name', value); - - @override - String? get description => - RealmObjectBase.get(this, 'description') as String?; - @override - set description(String? value) => - RealmObjectBase.set(this, 'description', value); - - @override - Stream> get changes => - RealmObjectBase.getChanges(this); - - @override - RealmAltokeEntity freeze() => - RealmObjectBase.freezeObject(this); - - EJsonValue toEJson() { - return { - 'id': id.toEJson(), - 'name': name.toEJson(), - 'description': description.toEJson(), - }; - } - - static EJsonValue _toEJson(RealmAltokeEntity value) => value.toEJson(); - static RealmAltokeEntity _fromEJson(EJsonValue ejson) { - return switch (ejson) { - { - 'id': EJsonValue id, - 'name': EJsonValue name, - 'description': EJsonValue description, - } => - RealmAltokeEntity( - fromEJson(id), - fromEJson(name), - description: fromEJson(description), - ), - _ => raiseInvalidEJson(ejson), - }; - } - - static final schema = () { - RealmObjectBase.registerFactory(RealmAltokeEntity._); - register(_toEJson, _fromEJson); - return SchemaObject( - ObjectType.realmObject, RealmAltokeEntity, 'RealmAltokeEntity', [ - SchemaProperty('id', RealmPropertyType.int, primaryKey: true), - SchemaProperty('name', RealmPropertyType.string), - SchemaProperty('description', RealmPropertyType.string, optional: true), - ]); - }(); - - @override - SchemaObject get objectSchema => RealmObjectBase.getSchema(this) ?? schema; -} diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/pubspec.yaml b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/pubspec.yaml deleted file mode 100644 index 913581b2..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/pubspec.yaml +++ /dev/null @@ -1,35 +0,0 @@ -name: altoke_entities_realm_storage -description: A persistent storage for Altoke Entities built on top of Realm. -version: 0.0.1+1 -publish_to: none - -environment: - sdk: ">=3.3.1 <4.0.0" - -dependencies: - #*w 1v 2> w*# - #*replace-start*# - altoke_common: - path: ../../../altoke_common/reference/ - #*with i2*# - # common: - # path: ../../common/ - #*replace-end*# - #*w 1v 2> w*# - altoke_entities_storage: - path: ../altoke_entities_storage/ - altoke_entity: - #*w 1v 4> w*# - #*replace-start*# - path: ../../../altoke_entity/reference/ - #*with*# - # path: ../../altoke_entity/ - #*replace-end*# - #*w 1v 2> w*# - collection: ^1.18.0 - meta: ^1.11.0 - realm: ^2.1.0 - -dev_dependencies: - test: ^1.25.2 - very_good_analysis: ^5.1.0 diff --git a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/test/src/altoke_entities_realm_storage_test.dart b/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/test/src/altoke_entities_realm_storage_test.dart deleted file mode 100644 index 07c44dd0..00000000 --- a/bricks/altoke_storage/reference/_cd___use_realm___altoke_entities_realm_storage/test/src/altoke_entities_realm_storage_test.dart +++ /dev/null @@ -1,1624 +0,0 @@ -import 'dart:async'; - -import 'package:altoke_common/common.dart'; -import 'package:altoke_entities_realm_storage/altoke_entities_realm_storage.dart'; -import 'package:altoke_entities_storage/altoke_entities_storage.dart'; -import 'package:altoke_entity/altoke_entity.dart'; -import 'package:collection/collection.dart'; -import 'package:realm/realm.dart'; -import 'package:test/test.dart'; - -Future openRealm() async { - final realm = Realm( - Configuration.inMemory( - [RealmAltokeEntitySchema], - ), - ); - return realm; -} - -void main() { - test( - ''' - -GIVEN a constructor for an altoke entities storage -├─ THAT uses a Realm database -WHEN the constructor is called -THEN an instance of the storage is returned -''', - () async { - final realm = await openRealm(); - final storage = AltokeEntitiesRealmStorage(database: realm); - expect(storage, isNotNull); - expect(storage, isA()); - realm.close(); - }, - ); - - group( - ''' - -GIVEN an altoke entities storage -├─ THAT uses a Realm database''', - () { - late Realm database; - late AltokeEntitiesRealmStorage storage; - - setUp(() async { - database = await openRealm(); - storage = AltokeEntitiesRealmStorage(database: database); - }); - - tearDown(() async { - database.close(); - }); - - test( - ''' - -│ ├─ THAT does not have altoke entity records -AND the valid data for a new altoke entity -WHEN the altoke entity is created -THEN a altoke entity record is registered -''', - () async { - const newAltokeEntity = NewAltokeEntity( - name: 'name', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - await storage.create(newAltokeEntity: newAltokeEntity); - final query = ' ' - 'name == ${newAltokeEntity.name} ' - 'AND ' - 'description == ${newAltokeEntity.description}'; - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect( - resultingMatchingAltokeEntitiesCount, - existingAltokeEntitiesCount + 1, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the valid data for a new altoke entity -WHEN the altoke entity is created -THEN a altoke entity record is registered -''', - () async { - const existingAltokeEntityId = 13; - const existingAltokeEntity = NewAltokeEntity( - name: 'existing', - description: 'description', - ); - await database.write( - () async => database.add( - existingAltokeEntity.toRealmWithId( - existingAltokeEntityId, - ), - ), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, 1); - const newAltokeEntity = NewAltokeEntity( - name: 'new', - description: 'description', - ); - await storage.create(newAltokeEntity: newAltokeEntity); - final query = ' ' - 'name == "${newAltokeEntity.name}" ' - 'AND ' - 'description == "${newAltokeEntity.description}"'; - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(resultingMatchingAltokeEntitiesCount, 1); - }, - ); - - test( - ''' - -AND the invalid data for a new altoke entity -WHEN the altoke entity is created -THEN an exception is thrown -AND no altoke entity record is registered -''', - () async { - const newAltokeEntity = NewAltokeEntity( - name: '', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - expect( - () async => storage.create(newAltokeEntity: newAltokeEntity), - throwsA(isA()), - ); - final resultingAltokeEntitiesCount = - database.all().length; - expect(resultingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of a registered altoke entity -WHEN the altoke entity is deleted -THEN the altoke entity record is dropped -AND the deleted altoke entity is returned -''', - () async { - const altokeEntityId = 1; - const newAltokeEntity = NewAltokeEntity( - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - newAltokeEntity.toRealmWithId( - altokeEntityId, - ), - ), - ); - const query = 'id == $altokeEntityId'; - final initialMatchingAltokeEntitiesCount = - database.query(query).length; - expect(initialMatchingAltokeEntitiesCount, 1); - final deletedAltokeEntity = await storage.deleteById(altokeEntityId); - expect(deletedAltokeEntity, isNotNull); - expect(deletedAltokeEntity!.id, altokeEntityId); - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(resultingMatchingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of an unregistered altoke entity -WHEN the altoke entity is deleted -THEN no altoke entity record is dropped -AND null is returned -''', - () async { - const altokeEntityId = 13; - const newAltokeEntity = - NewAltokeEntity(name: 'name', description: 'description'); - await database.write( - () async => database.add( - newAltokeEntity.toRealmWithId(altokeEntityId + 1), - ), - ); - final initialAltokeEntities = database.all(); - expect(initialAltokeEntities, hasLength(1)); - final initialAltokeEntity = initialAltokeEntities.single; - expect(initialAltokeEntity.id, isNot(altokeEntityId)); - final deletedAltokeEntity = await storage.deleteById(altokeEntityId); - expect(deletedAltokeEntity, isNull); - final resultingAltokeEntities = database.all(); - expect(resultingAltokeEntities, hasLength(1)); - final resultingAltokeEntity = resultingAltokeEntities.single; - expect( - resultingAltokeEntity.toAltokeEntity(), - initialAltokeEntity.toAltokeEntity(), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT includes a non-null name matcher -├─ AND includes a non-null description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some('matching-pattern'), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name, :description) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - if (description == null) return true; - final noMatchInDescription = - !description.contains('matching-pattern'); - return noMatchInDescription; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT does not include a name matcher -├─ AND includes a non-null description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - description: Some('matching-pattern'), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:description) = altokeEntity; - if (description == null) return true; - final noMatchInDescription = - !description.contains('matching-pattern'); - return noMatchInDescription; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT includes a non-null name matcher -├─ AND includes a null description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some(null), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name, :description) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - return description != null; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ THAT includes a non-null name matcher -├─ AND includes a non-null empty description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - description: 'description 2 matching-pattern', - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - description: 'description 3 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - description: 'description 6 matching-pattern', - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - description: 'description 7 matching-pattern', - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - description: 'description 10 matching-pattern', - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - description: 'description 11 matching-pattern', - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - description: 'description 14 matching-pattern', - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - description: 'description 15 matching-pattern', - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some(''), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - return noMatchInTitle; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -AND a reference altoke entity -├─ AND includes non-null name matcher -├─ AND includes empty description matcher -WHEN a delete operation is performed with the reference altoke entity -THEN the altoke entity records matching the reference altoke entity are dropped -AND the altoke entity records not matching the reference altoke entity are kept -''', - () async { - final altokeEntities = [ - const AltokeEntity( - id: 0, - name: 'name 0', - description: 'description 0', - ), - const AltokeEntity( - id: 1, - name: 'name 1 matching-pattern', - description: 'description 1', - ), - const AltokeEntity( - id: 2, - name: 'name 2', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 3, - name: 'name 3 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 4, - name: 'name 4', - description: 'description 4', - ), - const AltokeEntity( - id: 5, - name: 'name 5 matching-pattern', - description: 'description 5', - ), - const AltokeEntity( - id: 6, - name: 'name 6', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 7, - name: 'name 7 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 8, - name: 'name 8', - description: 'description 8', - ), - const AltokeEntity( - id: 9, - name: 'name 9 matching-pattern', - description: 'description 9', - ), - const AltokeEntity( - id: 10, - name: 'name 10', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 11, - name: 'name 11 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 12, - name: 'name 12', - description: 'description 12', - ), - const AltokeEntity( - id: 13, - name: 'name 13 matching-pattern', - description: 'description 13', - ), - const AltokeEntity( - id: 14, - name: 'name 14', - // ignore: avoid_redundant_argument_values - description: null, - ), - const AltokeEntity( - id: 15, - name: 'name 15 matching-pattern', - // ignore: avoid_redundant_argument_values - description: null, - ), - ]; - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - const referenceAltokeEntity = PartialAltokeEntity( - name: Some('matching-pattern'), - description: Some(null), - ); - await storage.deleteAll(referenceAltokeEntity: referenceAltokeEntity); - final resultingRealmAltokeEntities = - database.all(); - - bool shouldBeKept(AltokeEntity altokeEntity) { - final AltokeEntity(:name, :description) = altokeEntity; - final noMatchInTitle = !name.contains('matching-pattern'); - if (noMatchInTitle) return true; - final noMatchInDescription = - description != null && description.isNotEmpty; - return noMatchInDescription; - } - - final expectedResultingAltokeEntities = [ - for (final altokeEntity in altokeEntities) - if (shouldBeKept(altokeEntity)) altokeEntity, - ]; - expect( - resultingRealmAltokeEntities, - hasLength(expectedResultingAltokeEntities.length), - ); - final resultingAltokeEntities = [ - for (final realmAltokeEntity in resultingRealmAltokeEntities) - realmAltokeEntity.toAltokeEntity(), - ]; - expect( - resultingAltokeEntities, - unorderedEquals(expectedResultingAltokeEntities), - ); - }, - ); - - test( - ''' - -│ ├─ THAT has several altoke entity records -WHEN a delete operation is performed with no reference altoke entity -THEN all altoke entity records are dropped -''', - () async { - final altokeEntities = List.generate( - 30, - (index) => AltokeEntity( - id: index, - name: 'name $index', - description: 'description $index', - ), - ); - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntities) altokeEntity.toRealm(), - ]), - ); - final initialAltokeEntitiesCount = - database.all().length; - expect(initialAltokeEntitiesCount, altokeEntities.length); - await storage.deleteAll(); - final resultingRealmAltokeEntitiesCount = - database.all().length; - expect(resultingRealmAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -AND a altoke entity -WHEN the altoke entity is inserted -THEN a altoke entity record is registered -''', - () async { - const altokeEntity = AltokeEntity( - id: 1, - name: 'name', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - await storage.insert(altokeEntity: altokeEntity); - final resultingRealmAltokeEntities = - database.all(); - expect(resultingRealmAltokeEntities, hasLength(1)); - final resultingRealmAltokeEntity = - resultingRealmAltokeEntities.single; - expect(resultingRealmAltokeEntity.toAltokeEntity(), altokeEntity); - }, - ); - - test( - ''' - -AND the ID of a registered altoke entity -AND the valid partial altoke entity data -WHEN the altoke entity is updated -THEN a altoke entity record is updated -''', - () async { - const altokeEntity = AltokeEntity( - id: 13, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - altokeEntity.toRealm(), - ), - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, 1); - const newName = 'new name'; - const newDescription = 'new description'; - final query = ' ' - 'id == ${altokeEntity.id} ' - 'AND ' - 'name == "$newName" ' - 'AND ' - 'description == "$newDescription"'; - final existingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(existingMatchingAltokeEntitiesCount, isZero); - await storage.update( - altokeEntityId: altokeEntity.id, - partialAltokeEntity: const PartialAltokeEntity( - name: Some(newName), - description: Some(newDescription), - ), - ); - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect( - resultingMatchingAltokeEntitiesCount, - existingMatchingAltokeEntitiesCount + 1, - ); - }, - ); - - test( - ''' - -AND the invalid data for a new altoke entity -WHEN the altoke entity is created -THEN an exception is thrown -AND no altoke entity record is registered -''', - () async { - const newAltokeEntity = NewAltokeEntity( - name: '', - description: 'description', - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, isZero); - expect( - () async => storage.create(newAltokeEntity: newAltokeEntity), - throwsA(isA()), - ); - final resultingAltokeEntitiesCount = - database.all().length; - expect(resultingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -AND the ID of a registered altoke entity -AND the invalid partial altoke entity data -WHEN the altoke entity is updated -THEN an exception is thrown -AND no altoke entity record is updated -''', - () async { - const altokeEntity = AltokeEntity( - id: 76, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add( - altokeEntity.toRealm(), - ), - ); - final existingAltokeEntitiesCount = - database.all().length; - expect(existingAltokeEntitiesCount, 1); - const newName = ''; - const newDescription = 'new description'; - final query = ' ' - 'id == ${altokeEntity.id} ' - 'AND ' - 'name == "$newName" ' - 'AND ' - 'description == "$newDescription"'; - final existingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(existingMatchingAltokeEntitiesCount, isZero); - expect( - () async => storage.update( - altokeEntityId: altokeEntity.id, - partialAltokeEntity: const PartialAltokeEntity( - name: Some(newName), - description: Some(newDescription), - ), - ), - throwsA(isA()), - ); - final resultingMatchingAltokeEntitiesCount = - database.query(query).length; - expect(resultingMatchingAltokeEntitiesCount, isZero); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of a registered altoke entity -WHEN the altoke entity is requested -THEN the altoke entity is returned -''', - () async { - const altokeEntityId = 8; - const altokeEntity = AltokeEntity( - id: altokeEntityId, - name: 'name', - description: 'description', - ); - await database.write( - () async => database.add(altokeEntity.toRealm()), - ); - final initialMatchingAltokeEntitiesCount = - database.query('id == $altokeEntityId').length; - expect(initialMatchingAltokeEntitiesCount, 1); - final retrievedAltokeEntity = await storage.getById(altokeEntityId); - expect(retrievedAltokeEntity, isNotNull); - expect(retrievedAltokeEntity, altokeEntity); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -AND the ID of an unregistered altoke entity -WHEN the altoke entity is requested -THEN null is returned -''', - () async { - const altokeEntityId = 7; - final initialMatchingAltokeEntitiesCount = - database.query('id == $altokeEntityId').length; - expect(initialMatchingAltokeEntitiesCount, isZero); - final retrievedAltokeEntity = await storage.getById(altokeEntityId); - expect(retrievedAltokeEntity, isNull); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities are watched -├─ AND are not filtered by their content -THEN the altoke entities that match the conditions are continuously emitted as they change -''', - () async { - final stream = storage.watch(); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const AltokeEntity( - id: 1, - name: 'name 01', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - ), - ]; - final sortedAltokeEntitiesForStage00 = [...altokeEntitiesForStage00] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 3, - name: 'name 03', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - final sortedAltokeEntitiesForStage01 = [...altokeEntitiesForStage01] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('01')) altokeEntity, - ]; - final sortedAltokeEntitiesForStage02 = [...altokeEntitiesForStage02] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 03 - final altokeEntitiesForStage03 = [ - for (final altokeEntity in altokeEntitiesForStage02) - if (altokeEntity.description == null) - AltokeEntity( - id: altokeEntity.id, - name: altokeEntity.name, - description: 'updated description', - ) - else - altokeEntity, - ]; - final sortedAltokeEntitiesForStage03 = [...altokeEntitiesForStage03] - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - orderedEquals(sortedAltokeEntitiesForStage00), - orderedEquals(sortedAltokeEntitiesForStage01), - orderedEquals(sortedAltokeEntitiesForStage02), - orderedEquals(sortedAltokeEntitiesForStage03), - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database - .add(newAltokeEntityInStage01.toRealm()), - ); - - // Stage 02 - await database.write( - () async { - final matchingAltokeEntities = - database.query('name CONTAINS "01"'); - database.deleteMany(matchingAltokeEntities); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = 'updated description'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities are watched -├─ AND are filtered by their content -THEN the altoke entities that match the conditions are continuously emitted as they change -''', - () async { - final stream = storage.watch(searchTerm: 'matching-pattern'); - - bool matches(AltokeEntity altokeEntity) => - altokeEntity.name.contains('matching-pattern') || - (altokeEntity.description?.contains('matching-pattern') ?? false); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00 matching-pattern', - ), - const AltokeEntity( - id: 1, - name: 'name 01', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - ), - const AltokeEntity( - id: 3, - name: 'name 03', - description: 'description 03 matching-pattern', - ), - const AltokeEntity( - id: 4, - name: 'name 04', - ), - const AltokeEntity( - id: 5, - name: 'name 05', - description: 'description 05 matching-pattern', - ), - ]; - final sortedAltokeEntitiesForStage00 = [...altokeEntitiesForStage00] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 6, - name: 'name 06 matching-pattern', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - final sortedAltokeEntitiesForStage01 = [...altokeEntitiesForStage01] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('00')) altokeEntity, - ]; - final sortedAltokeEntitiesForStage02 = [...altokeEntitiesForStage02] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - // Stage 03 - final altokeEntitiesForStage03 = [ - for (final altokeEntity in altokeEntitiesForStage02) - if (altokeEntity.description == null) - AltokeEntity( - id: altokeEntity.id, - name: altokeEntity.name, - description: 'updated description matching-pattern', - ) - else - altokeEntity, - ]; - final sortedAltokeEntitiesForStage03 = [...altokeEntitiesForStage03] - .where(matches) - .sorted((tA, tB) => tA.name.compareTo(tB.name)); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - orderedEquals(sortedAltokeEntitiesForStage00), - orderedEquals(sortedAltokeEntitiesForStage01), - orderedEquals(sortedAltokeEntitiesForStage02), - orderedEquals(sortedAltokeEntitiesForStage03), - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database - .add(newAltokeEntityInStage01.toRealm()), - ); - - // Stage 02 - await database.write( - () async { - final altokeEntityToDelete = - database.query('name CONTAINS "00"'); - database.deleteMany(altokeEntityToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = - 'updated description matching-pattern'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities count is watched -├─ AND are not filtered by their content -THEN the quantity of persisted altoke entities that match the conditions is continuously emitted as it changes -''', - () async { - final stream = storage.watchCount(); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const AltokeEntity( - id: 1, - name: 'name 01', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - description: 'description 02', - ), - ]; - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 3, - name: 'name 03', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('01')) altokeEntity, - ]; - - // Stage 03 - // final altokeEntitiesForStage03 = [ - // for (final altokeEntity in altokeEntitiesForStage02) - // if (altokeEntity.description == null) - // AltokeEntity( - // id: altokeEntity.id, - // name: altokeEntity.name, - // description: 'updated description', - // ) - // else - // altokeEntity, - // ]; - - unawaited( - expectLater( - stream, - emitsInOrder([ - altokeEntitiesForStage00.length, - altokeEntitiesForStage01.length, - altokeEntitiesForStage02.length, - - // Not emitted as the altoke entities count has not changed - // altokeEntitiesForStage03.length, - ]), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database.add( - newAltokeEntityInStage01.toRealm(), - ), - ); - - // Stage 02 - await database.write( - () async { - final altokeEntitiesToDelete = - database.query('name CONTAINS "01"'); - database.deleteMany(altokeEntitiesToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = 'updated description'; - } - }, - ); - }, - ); - - test( - ''' - -│ ├─ THAT has altoke entity records -WHEN the altoke entities count is watched -├─ AND are filtered by their content -THEN the quantity of persisted altoke entities that match the conditions is continuously emitted as it changes -''', - () async { - final stream = storage.watchCount(searchTerm: 'matching-pattern'); - bool match(AltokeEntity altokeEntity) => - altokeEntity.name.contains('matching-pattern') || - (altokeEntity.description?.contains('matching-pattern') ?? false); - - // Stage 00 - final altokeEntitiesForStage00 = [ - const AltokeEntity( - id: 0, - name: 'name 00', - description: 'description 00', - ), - const AltokeEntity( - id: 1, - name: 'name 01 matching-pattern', - ), - const AltokeEntity( - id: 2, - name: 'name 02', - description: 'description 02 matching-pattern', - ), - ]; - final expectedAltokeEntitiesForStage00 = - altokeEntitiesForStage00.where(match); - - // Stage 01 - const newAltokeEntityInStage01 = AltokeEntity( - id: 3, - name: 'name 03 matching-pattern', - ); - final altokeEntitiesForStage01 = [ - ...altokeEntitiesForStage00, - newAltokeEntityInStage01, - ]; - final expectedAltokeEntitiesForStage01 = - altokeEntitiesForStage01.where(match); - - // Stage 02 - final altokeEntitiesForStage02 = [ - for (final altokeEntity in altokeEntitiesForStage01) - if (!altokeEntity.name.contains('01')) altokeEntity, - ]; - final expectedAltokeEntitiesForStage02 = - altokeEntitiesForStage02.where(match); - - // Stage 03 - // final altokeEntitiesForStage03 = [ - // for (final altokeEntity in altokeEntitiesForStage02) - // if (altokeEntity.description == null) - // AltokeEntity( - // id: altokeEntity.id, - // name: altokeEntity.name, - // description: 'updated description', - // ) - // else - // altokeEntity, - // ]; - // final expectedAltokeEntitiesForStage03 = - // altokeEntitiesForStage03.where(match); - - unawaited( - expectLater( - stream, - emitsInOrder( - [ - expectedAltokeEntitiesForStage00.length, - expectedAltokeEntitiesForStage01.length, - expectedAltokeEntitiesForStage02.length, - - // Not emitted as the altoke entities count has not changed - // expectedAltokeEntitiesForStage03.length, - ], - ), - ), - ); - - // Stage 00 - await database.write( - () async => database.addAll([ - for (final altokeEntity in altokeEntitiesForStage00) - altokeEntity.toRealm(), - ]), - ); - - // Stage 01 - await database.write( - () async => database.add( - newAltokeEntityInStage01.toRealm(), - ), - ); - - // Stage 02 - await database.write( - () async { - final altokeEntityToDelete = - database.query('name CONTAINS "01"'); - database.deleteMany(altokeEntityToDelete); - }, - ); - - // Stage 03 - await database.write( - () async { - final altokeEntitiesWithNullDescription = - database.query('description == null'); - for (final altokeEntity in altokeEntitiesWithNullDescription) { - altokeEntity.description = 'updated description'; - } - }, - ); - }, - ); - }, - ); -} diff --git a/melos.yaml b/melos.yaml index 496a68b6..83415a19 100644 --- a/melos.yaml +++ b/melos.yaml @@ -58,28 +58,14 @@ scripts: concurrency: 1 failFast: true orderDependents: true - gen.realm: - description: Generate code for a package with Realm - run: dart run realm generate - packageFilters: - dependsOn: - - realm - ignore: - - altoke_app - exec: - concurrency: 1 - failFast: true - orderDependents: true gen.all: description: Generate code for all packages steps: - gen - - gen.realm gen.all.fast: description: Generate code for all packages (multi-threaded) steps: - melos exec --depends-on=build_runner --order-dependents -- "dart run build_runner build -d" - - melos exec --depends-on=realm --order-dependents --ignore=altoke_app -- "dart run realm generate" # Spell checking spellcheck: @@ -206,7 +192,7 @@ scripts: description: Merge all packages coverage trace files ignoring data related to generated files steps: - coverde rm MELOS_ROOT_PATH/coverage/filtered.lcov.info - - melos exec -c 1 --file-exists=coverage/lcov.info -- "coverde filter --input ./coverage/lcov.info --output MELOS_ROOT_PATH/coverage/filtered.lcov.info --paths-parent MELOS_PACKAGE_PATH --filters \.drift\.dart,\.freezed\.dart,\.g\.dart,\.gr\.dart,\.mapper\.dart,\.realm\.dart" + - melos exec -c 1 --file-exists=coverage/lcov.info -- "coverde filter --input ./coverage/lcov.info --output MELOS_ROOT_PATH/coverage/filtered.lcov.info --paths-parent MELOS_PACKAGE_PATH --filters \.drift\.dart,\.freezed\.dart,\.g\.dart,\.gr\.dart,\.mapper\.dart" coverage.check: description: Check test coverage steps: diff --git a/tools/data_persistence_approach/lib/src/data_persistence_approach.dart b/tools/data_persistence_approach/lib/src/data_persistence_approach.dart index 96d21687..18121f2c 100644 --- a/tools/data_persistence_approach/lib/src/data_persistence_approach.dart +++ b/tools/data_persistence_approach/lib/src/data_persistence_approach.dart @@ -11,9 +11,6 @@ enum DataPersistenceApproach { /// Use `isar` for data persistence. isar('isar'), - /// Use `realm` for data persistence. - realm('realm'), - /// Use `sembast` for data persistence. sembast('sembast'), ; @@ -50,10 +47,4 @@ enum DataPersistenceApproach { final selectedApproach = context.vars[varKey]! as String; return DataPersistenceApproach.fromVarIdentifier(selectedApproach); } - - /// Returns the code generation command for the data persistence approach. - String get codeGenerationCommand => switch (this) { - DataPersistenceApproach.realm => 'dart run realm generate', - _ => 'dart run build_runner build --delete-conflicting-outputs', - }; }