diff --git a/.github/workflows/reusable-dart-analyze-format-test.yaml b/.github/workflows/reusable-dart-analyze-format-test.yaml index 548274e5..ad22a27a 100644 --- a/.github/workflows/reusable-dart-analyze-format-test.yaml +++ b/.github/workflows/reusable-dart-analyze-format-test.yaml @@ -7,6 +7,10 @@ on: required: true type: string +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.package }} + cancel-in-progress: true + jobs: dart_analyze_format_test: runs-on: ubuntu-latest @@ -15,10 +19,6 @@ jobs: matrix: sdk_version: [beta, stable] steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@89f242ee29e10c53a841bfe71cc0ce7b2f065abc - with: - access_token: ${{ github.token }} - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk_version }} diff --git a/.github/workflows/reusable-flutter-analyze-format-test.yaml b/.github/workflows/reusable-flutter-analyze-format-test.yaml index f64014d2..8401344d 100644 --- a/.github/workflows/reusable-flutter-analyze-format-test.yaml +++ b/.github/workflows/reusable-flutter-analyze-format-test.yaml @@ -7,6 +7,10 @@ on: required: true type: string +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.package }} + cancel-in-progress: true + jobs: flutter_analyze_format_test: runs-on: ubuntu-latest @@ -17,11 +21,6 @@ jobs: matrix: flutter_version: [beta, stable] steps: - - name: Cancel Previous Runs - uses: styfle/cancel-workflow-action@89f242ee29e10c53a841bfe71cc0ce7b2f065abc - with: - access_token: ${{ github.token }} - - name: Install SQLite3 run: sudo apt-get update && sudo apt-get -y install sqlite3 libsqlite3-dev diff --git a/packages/brick_core/CHANGELOG.md b/packages/brick_core/CHANGELOG.md index 884c4510..d287b86b 100644 --- a/packages/brick_core/CHANGELOG.md +++ b/packages/brick_core/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +## 1.2.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 diff --git a/packages/brick_core/pubspec.yaml b/packages/brick_core/pubspec.yaml index dd8b67b9..52366c2d 100644 --- a/packages/brick_core/pubspec.yaml +++ b/packages/brick_core/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_core issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 1.1.2 +version: 1.2.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_graphql/CHANGELOG.md b/packages/brick_graphql/CHANGELOG.md index 780ff338..46c4e389 100644 --- a/packages/brick_graphql/CHANGELOG.md +++ b/packages/brick_graphql/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +## 3.1.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 diff --git a/packages/brick_graphql/pubspec.yaml b/packages/brick_graphql/pubspec.yaml index 76788d50..6f960acb 100644 --- a/packages/brick_graphql/pubspec.yaml +++ b/packages/brick_graphql/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_graphql issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.1 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_graphql_generators/CHANGELOG.md b/packages/brick_graphql_generators/CHANGELOG.md index 00b18c81..1cf0c019 100644 --- a/packages/brick_graphql_generators/CHANGELOG.md +++ b/packages/brick_graphql_generators/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +## 3.1.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 diff --git a/packages/brick_graphql_generators/pubspec.yaml b/packages/brick_graphql_generators/pubspec.yaml index cefb1ffe..fc191634 100644 --- a/packages/brick_graphql_generators/pubspec.yaml +++ b/packages/brick_graphql_generators/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_graphql_g issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.1 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_offline_first/CHANGELOG.md b/packages/brick_offline_first/CHANGELOG.md index 2c0acbbe..9e80dce4 100644 --- a/packages/brick_offline_first/CHANGELOG.md +++ b/packages/brick_offline_first/CHANGELOG.md @@ -1,6 +1,9 @@ ## Unreleased +## 3.2.0 + * Apply desired policy to all association fetches during `OfflineFirstRepository#get` requests. Fixes #371. +* Upgrade minimum Dart to 2.18 ## 3.1.0 diff --git a/packages/brick_offline_first/pubspec.yaml b/packages/brick_offline_first/pubspec.yaml index 7b80c2b6..cc6d167d 100644 --- a/packages/brick_offline_first/pubspec.yaml +++ b/packages/brick_offline_first/pubspec.yaml @@ -5,10 +5,10 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_offline_f issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.1.0 +version: 3.2.0 environment: - sdk: ">=2.12.0 <4.0.0" + sdk: ">=2.18.0 <4.0.0" dependencies: brick_core: ^1.1.1 diff --git a/packages/brick_offline_first_build/CHANGELOG.md b/packages/brick_offline_first_build/CHANGELOG.md index e4bccb87..48142086 100644 --- a/packages/brick_offline_first_build/CHANGELOG.md +++ b/packages/brick_offline_first_build/CHANGELOG.md @@ -1,6 +1,9 @@ ## Unreleased +## 3.1.0 + * Apply standardized lints +* Support using `OfflineFirstSerdes` as a unique field in SQLite ## 3.0.1 diff --git a/packages/brick_offline_first_build/lib/src/offline_first_sqlite_generators.dart b/packages/brick_offline_first_build/lib/src/offline_first_sqlite_generators.dart index f9e62497..a3b7528c 100644 --- a/packages/brick_offline_first_build/lib/src/offline_first_sqlite_generators.dart +++ b/packages/brick_offline_first_build/lib/src/offline_first_sqlite_generators.dart @@ -50,6 +50,15 @@ class OfflineFirstSqliteSerialize extends SqliteSerialize { fieldAnnotation: fieldAnnotation, ); } + + @override + String uniqueValueForField(fieldName, {required checker}) { + if ((checker as OfflineFirstChecker).hasSerdes) { + return '$fieldName.toSqlite()'; + } + + return super.uniqueValueForField(fieldName, checker: checker); + } } class OfflineFirstSqliteDeserialize extends SqliteDeserialize { diff --git a/packages/brick_offline_first_build/pubspec.yaml b/packages/brick_offline_first_build/pubspec.yaml index 7ac6d46c..ad196318 100644 --- a/packages/brick_offline_first_build/pubspec.yaml +++ b/packages/brick_offline_first_build/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_offline_f issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.1 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0" @@ -16,7 +16,7 @@ dependencies: brick_json_generators: ">=3.0.0 <4.0.0" brick_offline_first: ">=3.0.0 <4.0.0" brick_sqlite: ">=3.0.0 <4.0.0" - brick_sqlite_generators: ">=3.0.0 <4.0.0" + brick_sqlite_generators: ">=3.1.0 <4.0.0" build: ">=2.0.0 <3.0.0" dart_style: ">=2.0.0 <3.0.0" logging: ">=1.0.0 <2.0.0" diff --git a/packages/brick_offline_first_build/test/offline_first_generator/test_offlne_first_serdes_with_type_argument.dart b/packages/brick_offline_first_build/test/offline_first_generator/test_offline_first_serdes_with_type_argument.dart similarity index 100% rename from packages/brick_offline_first_build/test/offline_first_generator/test_offlne_first_serdes_with_type_argument.dart rename to packages/brick_offline_first_build/test/offline_first_generator/test_offline_first_serdes_with_type_argument.dart diff --git a/packages/brick_offline_first_build/test/offline_first_generator/test_unique_offline_first_serdes.dart b/packages/brick_offline_first_build/test/offline_first_generator/test_unique_offline_first_serdes.dart new file mode 100644 index 00000000..1631144c --- /dev/null +++ b/packages/brick_offline_first_build/test/offline_first_generator/test_unique_offline_first_serdes.dart @@ -0,0 +1,128 @@ +import 'package:brick_offline_first/brick_offline_first.dart' show OfflineFirstSerdes; +import 'package:brick_offline_first_with_rest/brick_offline_first_with_rest.dart'; +import 'package:brick_sqlite/brick_sqlite.dart'; + +final output = r""" +// GENERATED CODE DO NOT EDIT +part of '../brick.g.dart'; + +Future _$CustomOfflineFirstSerdesFromTest( + Map data, + {required TestProvider provider, + OfflineFirstRepository? repository}) async { + return CustomOfflineFirstSerdes( + string: Serializable.fromTest(data['string'])); +} + +Future> _$CustomOfflineFirstSerdesToTest( + CustomOfflineFirstSerdes instance, + {required TestProvider provider, + OfflineFirstRepository? repository}) async { + return {'string': instance.string?.toTest()}; +} + +Future _$CustomOfflineFirstSerdesFromSqlite( + Map data, + {required SqliteProvider provider, + OfflineFirstRepository? repository}) async { + return CustomOfflineFirstSerdes( + string: data['string'] == null + ? null + : Serializable.fromSqlite(data['string'] as int)) + ..primaryKey = data['_brick_id'] as int; +} + +Future> _$CustomOfflineFirstSerdesToSqlite( + CustomOfflineFirstSerdes instance, + {required SqliteProvider provider, + OfflineFirstRepository? repository}) async { + return {}; +} + +/// Construct a [CustomOfflineFirstSerdes] +class CustomOfflineFirstSerdesAdapter + extends OfflineFirstAdapter { + CustomOfflineFirstSerdesAdapter(); + + @override + final Map fieldsToSqliteColumns = { + 'primaryKey': const RuntimeSqliteColumnDefinition( + association: false, + columnName: '_brick_id', + iterable: false, + type: int, + ), + 'string': const RuntimeSqliteColumnDefinition( + association: false, + columnName: 'string', + iterable: false, + type: Serializable, + ) + }; + @override + Future primaryKeyByUniqueColumns( + CustomOfflineFirstSerdes instance, DatabaseExecutor executor) async { + final results = await executor.rawQuery(''' + SELECT * FROM `CustomOfflineFirstSerdes` WHERE string = ? LIMIT 1''', + [instance.string.toSqlite()]); + + // SQFlite returns [{}] when no results are found + if (results.isEmpty || (results.length == 1 && results.first.isEmpty)) { + return null; + } + + return results.first['_brick_id'] as int; + } + + @override + final String tableName = 'CustomOfflineFirstSerdes'; + + @override + Future fromTest(Map input, + {required provider, + covariant OfflineFirstRepository? repository}) async => + await _$CustomOfflineFirstSerdesFromTest(input, + provider: provider, repository: repository); + @override + Future> toTest(CustomOfflineFirstSerdes input, + {required provider, + covariant OfflineFirstRepository? repository}) async => + await _$CustomOfflineFirstSerdesToTest(input, + provider: provider, repository: repository); + @override + Future fromSqlite(Map input, + {required provider, + covariant OfflineFirstRepository? repository}) async => + await _$CustomOfflineFirstSerdesFromSqlite(input, + provider: provider, repository: repository); + @override + Future> toSqlite(CustomOfflineFirstSerdes input, + {required provider, + covariant OfflineFirstRepository? repository}) async => + await _$CustomOfflineFirstSerdesToSqlite(input, + provider: provider, repository: repository); +} +"""; + +class Serializable extends OfflineFirstSerdes, int> { + final int age; + Serializable(this.age); + + Map toTest() => {'age': '$age'}; + + factory Serializable.fromTest(Map data) { + return Serializable(data['age']); + } + + factory Serializable.fromSqlite(age) { + return Serializable(age); + } +} + +@ConnectOfflineFirstWithRest() +class CustomOfflineFirstSerdes { + CustomOfflineFirstSerdes({this.string}); + + @Sqlite(unique: true) + final Serializable? string; +} diff --git a/packages/brick_offline_first_build/test/offline_first_generator_test.dart b/packages/brick_offline_first_build/test/offline_first_generator_test.dart index 2047711d..2980320f 100644 --- a/packages/brick_offline_first_build/test/offline_first_generator_test.dart +++ b/packages/brick_offline_first_build/test/offline_first_generator_test.dart @@ -11,13 +11,14 @@ import 'offline_first_generator/test_no_final_no_const.dart' as noFinalNoConst; import 'offline_first_generator/test_nullable_field.dart' as nullableField; import 'offline_first_generator/test_offline_first_apply_to_remote_deserialization.dart' as offlineFirstRemoteDeserialization; +import 'offline_first_generator/test_offline_first_serdes_with_type_argument.dart' + as offlineFirstSerdesWithTypeArgument; import 'offline_first_generator/test_offline_first_where.dart' as offlineFirstWhere; -import 'offline_first_generator/test_offlne_first_serdes_with_type_argument.dart' - as oflineFirstSerdesWithTypeArgument; import 'offline_first_generator/test_one_to_many_association.dart' as oneToManyAssociation; import 'offline_first_generator/test_one_to_one_association.dart' as oneToOneAssociation; import 'offline_first_generator/test_only_static_members.dart' as onlyStaticMembers; import 'offline_first_generator/test_primitive_fields.dart' as primitiveFields; +import 'offline_first_generator/test_unique_offline_first_serdes.dart' as uniqueOfflineFirstSerdes; import 'offline_first_generator/test_unrelated_association.dart' as unrelatedAssociation; void main() { @@ -47,6 +48,13 @@ void main() { await generateExpectation('custom_offline_first_serdes', customOfflineFirstSerdes.output); }); + test('UniqueOfflineFirstSerdes', () async { + await generateAdapterExpectation( + 'unique_offline_first_serdes', + uniqueOfflineFirstSerdes.output, + ); + }); + test('EnumFactorySerialize', () async { await generateExpectation('enum_factory_serialize', enumFactorySerialize.output); }); @@ -81,8 +89,8 @@ void main() { test('OfflineFirstSerdesWithTypeArgument', () async { await generateAdapterExpectation( - 'offlne_first_serdes_with_type_argument', - oflineFirstSerdesWithTypeArgument.output, + 'offline_first_serdes_with_type_argument', + offlineFirstSerdesWithTypeArgument.output, ); }); }); diff --git a/packages/brick_offline_first_with_graphql/CHANGELOG.md b/packages/brick_offline_first_with_graphql/CHANGELOG.md index 900840af..b3368708 100644 --- a/packages/brick_offline_first_with_graphql/CHANGELOG.md +++ b/packages/brick_offline_first_with_graphql/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +## 3.1.0 + * Upgrade minimum Dart to 2.18 ## 3.0.1 diff --git a/packages/brick_offline_first_with_graphql/pubspec.yaml b/packages/brick_offline_first_with_graphql/pubspec.yaml index 20b1a8da..68cd3902 100644 --- a/packages/brick_offline_first_with_graphql/pubspec.yaml +++ b/packages/brick_offline_first_with_graphql/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_offline_f issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.1 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_offline_first_with_graphql_build/CHANGELOG.md b/packages/brick_offline_first_with_graphql_build/CHANGELOG.md index 5ac30735..705c98b1 100644 --- a/packages/brick_offline_first_with_graphql_build/CHANGELOG.md +++ b/packages/brick_offline_first_with_graphql_build/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +## 3.2.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 diff --git a/packages/brick_offline_first_with_graphql_build/pubspec.yaml b/packages/brick_offline_first_with_graphql_build/pubspec.yaml index e14f6b30..0eeedc8e 100644 --- a/packages/brick_offline_first_with_graphql_build/pubspec.yaml +++ b/packages/brick_offline_first_with_graphql_build/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_offline_f issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.1.0 +version: 3.2.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_rest_generators/CHANGELOG.md b/packages/brick_rest_generators/CHANGELOG.md index 73570d7e..3747afae 100644 --- a/packages/brick_rest_generators/CHANGELOG.md +++ b/packages/brick_rest_generators/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +## 3.1.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 diff --git a/packages/brick_rest_generators/pubspec.yaml b/packages/brick_rest_generators/pubspec.yaml index 7e36664e..095b7c8d 100644 --- a/packages/brick_rest_generators/pubspec.yaml +++ b/packages/brick_rest_generators/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_rest_gene issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.1 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_sqlite/CHANGELOG.md b/packages/brick_sqlite/CHANGELOG.md index 1a5c1ee2..9950a458 100644 --- a/packages/brick_sqlite/CHANGELOG.md +++ b/packages/brick_sqlite/CHANGELOG.md @@ -1,7 +1,10 @@ ## Unreleased +## 3.1.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 +* Add extra documentation to the `@Sqlite(unique:)` annotation ## 3.0.1 diff --git a/packages/brick_sqlite/lib/src/annotations/sqlite.dart b/packages/brick_sqlite/lib/src/annotations/sqlite.dart index fc2b19e8..3b7c9251 100644 --- a/packages/brick_sqlite/lib/src/annotations/sqlite.dart +++ b/packages/brick_sqlite/lib/src/annotations/sqlite.dart @@ -1,6 +1,6 @@ import 'package:brick_core/field_serializable.dart'; - import 'package:brick_sqlite/src/db/migration.dart' show Column; + export 'package:brick_sqlite/src/db/migration.dart' show Column; /// An annotation used to specify how a field is serialized. @@ -93,6 +93,14 @@ class Sqlite implements FieldSerializable { /// /// To index this column, [index] needs to be `true`. Indices **are not** automatically /// created for [unique] columns. + /// + /// Some libraries may provide serializable classes (i.e. OfflineFirstSerdes) that can be used + /// as a unique value. However, it is strongly, strongly discouraged to use anything more than + /// a primitive for unique values. A complex class with multiple fields and methods will + /// significantly confuse maintenance. A string or int or double is more than sufficient to + /// determine a row's uniqueness. If a complex class must determine uniqueness, it is + /// recommended to annotate a computed property with `@Sqlite(unique:)` instead of the class + /// (e.g. `String get id => serdes.toSqlite()`). final bool unique; /// Creates a new [Sqlite] instance. diff --git a/packages/brick_sqlite/pubspec.yaml b/packages/brick_sqlite/pubspec.yaml index cac42c4c..297d8032 100644 --- a/packages/brick_sqlite/pubspec.yaml +++ b/packages/brick_sqlite/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_sqlite issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.1 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/brick_sqlite_generators/CHANGELOG.md b/packages/brick_sqlite_generators/CHANGELOG.md index 3a513831..27f070ed 100644 --- a/packages/brick_sqlite_generators/CHANGELOG.md +++ b/packages/brick_sqlite_generators/CHANGELOG.md @@ -1,7 +1,10 @@ ## Unreleased +## 3.1.0 + * Apply standardized lints * Upgrade minimum Dart to 2.18 +* Add `SqliteSerialize#uniqueValueForField` for advanced control of unique field genertion ## 3.0.2 diff --git a/packages/brick_sqlite_generators/lib/src/sqlite_serialize.dart b/packages/brick_sqlite_generators/lib/src/sqlite_serialize.dart index d22aa3b3..57fcd0ec 100644 --- a/packages/brick_sqlite_generators/lib/src/sqlite_serialize.dart +++ b/packages/brick_sqlite_generators/lib/src/sqlite_serialize.dart @@ -49,7 +49,8 @@ class SqliteSerialize<_Model extends SqliteModel> extends SqliteSerdesGenerator< type: $columnInsertionType, )'''); if (annotation.unique) { - uniqueFields[field.name] = providerNameForField(annotation.name, checker: checker); + final value = uniqueValueForField(field.name, checker: checker); + uniqueFields[value] = columnName; } } @@ -334,6 +335,19 @@ class SqliteSerialize<_Model extends SqliteModel> extends SqliteSerdesGenerator< return '$fieldValue ? 1 : 0'; } + + /// Provides the value for the SQL lookup. Most often this is simply the field + /// name, but more complex use cases may require a specific property to be called + /// on the class itself. + /// + /// However, it is strongly, strongly discouraged to use anything more than a primitive + /// for unique values. A complex class with multiple fields and methods will significantly + /// confuse maintenance. A string or int or double is more than sufficient to determine + /// a row's uniqueness. + @protected + String uniqueValueForField(String? fieldName, {required SharedChecker checker}) { + return fieldName ?? ''; + } } String _removeStaleAssociations( diff --git a/packages/brick_sqlite_generators/pubspec.yaml b/packages/brick_sqlite_generators/pubspec.yaml index 37792ea4..1d1b668f 100644 --- a/packages/brick_sqlite_generators/pubspec.yaml +++ b/packages/brick_sqlite_generators/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_sqlite_ge issue_tracker: https://github.com/GetDutchie/brick/issues repository: https://github.com/GetDutchie/brick -version: 3.0.2 +version: 3.1.0 environment: sdk: ">=2.18.0 <4.0.0"