Skip to content

Commit

Permalink
fix(supabase): remove foreignKey property from supabase annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
tshedor committed Sep 3, 2024
1 parent b43b27a commit 3eacc67
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 102 deletions.
22 changes: 20 additions & 2 deletions docs/offline_first/offline_first_with_supabase_repository.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ await Supabase.initialize(httpClient: client)
final supabaseProvider = SupabaseProvider(Supabase.instance.client, modelDictionary: ...)
```

### ConnectOfflineFirstWithSupabase
### @ConnectOfflineFirstWithSupabase

`@ConnectOfflineFirstWithSupabase` decorates the model that can be serialized by one or more providers. Offline First does not have configuration at the class level and only extends configuration held by its providers:

Expand All @@ -102,4 +102,22 @@ Ideally, `@OfflineFirst(where:)` shouldn't be necessary to specify to make the a
final Pizza pizza;
```

!> Multiple `where` keys (`OfflineFirst(where: {'id': 'data["id"]', 'otherVar': 'data["otherVar"]'})`) will be ignored. Nested properties (`OfflineFirst(where: {'id': 'data["subfield"]["id"]})`) will also be ignored.
!> Multiple `where` keys (`OfflineFirst(where: {'id': 'data["id"]', 'otherVar': 'data["otherVar"]'})`) will be ignored.

### Associations and Foreign Keys

Field types of classes that `extends OfflineFirstWithSupabaseModel` will automatically be assumed as a foreign key in Supabase. You will only need to specify the column name if it differs from your field name to help Brick fetch the right data and serialize/deserialize it locally.

```dart
class User extends OfflineFirstWithSupabaseModel {
// The foreign key is a relation to the `id` column of the Address table
@Supabase(name: 'address_id')
// Help the SQLite provider connect the association locally to the one provided from remote
@OfflineFirst(where: {'id': "data['address']['id']"})
final Address address;
}
class Address extends OfflineFirstWithSupabaseModel{
final String id;
}
```
20 changes: 0 additions & 20 deletions docs/supabase/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,6 @@ Supabase.instance.client.from('users')
.upsert(user).eq('uuid', instance.uuid)
```

### `@Supabase(foreignKey:)`

Specify the foreign key to use on the table when fetching for a remote association.

For example, given the `orders` table has a `customer_id` column that associates the `customers` table, an `Order` class in Dart may look like:

```dart
@SupabaseSerializeable(tableName: 'orders')
class Order {
@Supabase(foreignKey: 'customer_uuid')
final Customer customer;
}
@SupabaseSerializeable(tableName: 'customers')
class Customer {
@Supabase(unique: true)
final String uuid;
}
```

### `@Supabase(name:)`

Supabase keys can be renamed per field. This will override the default set by `SupabaseSerializable#fieldRename`.
Expand Down
20 changes: 19 additions & 1 deletion packages/brick_offline_first_with_supabase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ final supabaseProvider = SupabaseProvider(Supabase.instance.client, modelDiction

## Models

### ConnectOfflineFirstWithSupabase
### @ConnectOfflineFirstWithSupabase

`@ConnectOfflineFirstWithSupabase` decorates the model that can be serialized by one or more providers. Offline First does not have configuration at the class level and only extends configuration held by its providers:

Expand All @@ -78,6 +78,24 @@ final supabaseProvider = SupabaseProvider(Supabase.instance.client, modelDiction
class MyModel extends OfflineFirstWithSupabaseModel {}
```

### Associations and Foreign Keys

Field types of classes that `extends OfflineFirstWithSupabaseModel` will automatically be assumed as a foreign key in Supabase. You will only need to specify the column name if it differs from your field name to help Brick fetch the right data and serialize/deserialize it locally.

```dart
class User extends OfflineFirstWithSupabaseModel {
// The foreign key is a relation to the `id` column of the Address table
@Supabase(name: 'address_id')
// Help the SQLite provider connect the association locally to the one provided from remote
@OfflineFirst(where: {'id': "data['address']['id']"})
final Address address;
}
class Address extends OfflineFirstWithSupabaseModel{
final String id;
}
```

### FAQ

#### Why can't I declare a model argument?
Expand Down
21 changes: 0 additions & 21 deletions packages/brick_supabase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,6 @@ Connect Supabase's primary key (or any other index) to your application code. Th
final String supabaseUuid;
```

### `@Supabase(foreignKey:)`

Specify the foreign key to use on the table when fetching for a remote association.

For example, given the `orders` table has a `customer_id` column that associates
the `customers` table, an `Order` class in Dart may look like:

```dart
@SupabaseSerializeable(tableName: 'orders')
class Order {
@Supabase(foreignKey: 'customer_uuid')
final Customer customer;
}
@SupabaseSerializeable(tableName: 'customers')
class Customer {
@Supabase(unique: true)
final String uuid;
}
```

### `@Supabase(enumAsString:)`

Brick by default assumes enums from a Supabase API will be delivered as integers matching the index in the Flutter app. However, if your API delivers strings instead, the field can be easily annotated without writing a custom generator.
Expand Down
36 changes: 15 additions & 21 deletions packages/brick_supabase/lib/src/annotations/supabase.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import 'package:brick_core/field_serializable.dart';

/// An annotation used to specify how a field is serialized for a [SupabaseAdapter].
/// Heavily inspired by [JsonKey](https://github.com/dart-lang/json_serializable/blob/master/json_annotation/lib/src/json_key.dart)
///
/// If this annotates a field type that extends this model's type, the Supabase column
/// should be a foreign key.
///
/// ```dart
/// class User extends OfflineFirstWithSupabaseModel{
/// // The foreign key is a relation to the `id` column of the Address table
/// @Supabase(name: 'address_id')
/// final Address address;
/// }
///
/// class Address extends OfflineFirstWithSupabaseModel{
/// final String id;
/// }
/// ```
class Supabase implements FieldSerializable {
/// The value to use if the source does not contain this key or if the
/// value is `null`. **Only applicable during deserialization.**
Expand All @@ -19,25 +33,6 @@ class Supabase implements FieldSerializable {
@override
final bool enumAsString;

/// Specify the foreign key to use on the table when fetching for a remote association.
///
/// For example, given the `orders` table has a `customer_id` column that associates
/// the `customers` table, an `Order` class in Dart may look like:
///
/// ```dart
/// @SupabaseSerializeable(tableName: 'orders')
/// class Order {
/// @Supabase(foreignKey: 'customer_uuid')
/// final Customer customer;
/// }
///
/// @SupabaseSerializeable(tableName: 'customers')
/// class Customer {
/// final String uuid;
/// }
/// ```
final String? foreignKey;

@override
final String? fromGenerator;

Expand Down Expand Up @@ -81,7 +76,6 @@ class Supabase implements FieldSerializable {
this.defaultValue,
bool? enumAsString,
this.fromGenerator,
this.foreignKey,
bool? ignore,
bool? ignoreFrom,
bool? ignoreTo,
Expand Down
15 changes: 6 additions & 9 deletions packages/brick_supabase/test/__mocks__.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class DemoNestedAssociationModel extends SupabaseModel {

final String name;

@Supabase(foreignKey: 'nested_id')
@Supabase(name: 'nested_id')
final DemoAssociationModel nested;

DemoNestedAssociationModel({
Expand Down Expand Up @@ -130,9 +130,8 @@ class DemoNestedAssociationModelAdapter extends SupabaseAdapter<DemoNestedAssoci
),
'nested': const RuntimeSupabaseColumnDefinition(
association: true,
columnName: 'nested',
columnName: 'nested_id',
associationType: DemoAssociationModel,
associationForeignKey: 'nested_id',
),
};

Expand All @@ -150,10 +149,10 @@ class DemoNestedAssociationModelAdapter extends SupabaseAdapter<DemoNestedAssoci
}

class DemoAssociationModel extends SupabaseModel {
@Supabase(foreignKey: 'assocs_id')
@Supabase(name: 'assocs_id')
final List<DemoModel>? assocs;

@Supabase(foreignKey: 'assoc_id')
@Supabase(name: 'assoc_id')
final DemoModel assoc;

@Supabase(unique: true)
Expand Down Expand Up @@ -221,15 +220,13 @@ class DemoAssociationModelAdapter extends SupabaseAdapter<DemoAssociationModel>
),
'assoc': const RuntimeSupabaseColumnDefinition(
association: true,
columnName: 'assoc',
columnName: 'assoc_id',
associationType: DemoModel,
associationForeignKey: 'assoc_id',
),
'assocs': const RuntimeSupabaseColumnDefinition(
association: true,
columnName: 'assocs',
columnName: 'assocs_id',
associationType: DemoModel,
associationForeignKey: 'assocs_id',
),
};

Expand Down
4 changes: 1 addition & 3 deletions packages/brick_supabase/test/supabase_provider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import 'package:test/test.dart';
import '__mocks__.dart';

class _SupabaseRequest {
final String method;
final String? requestMethod;
final String tableName;
final String fields;
Expand All @@ -21,7 +20,6 @@ class _SupabaseRequest {

_SupabaseRequest(
this.tableName, {
this.method = 'select',
this.requestMethod = 'GET',
required this.fields,
this.filter,
Expand All @@ -30,7 +28,7 @@ class _SupabaseRequest {

@override
String toString() =>
'/rest/v1/$tableName${filter != null ? '?$filter&' : '?'}$method=${Uri.encodeComponent(fields)}${limit != null ? '&limit=$limit' : ''}';
'/rest/v1/$tableName${filter != null ? '?$filter&' : '?'}select=${Uri.encodeComponent(fields)}${limit != null ? '&limit=$limit' : ''}';

Uri get uri => Uri.parse(toString());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class SupabaseAnnotationFinder extends AnnotationFinder<Supabase>
defaultValue: obj.getField('defaultValue')!.toStringValue(),
enumAsString: obj.getField('enumAsString')!.toBoolValue() ?? Supabase.defaults.enumAsString,
fromGenerator: obj.getField('fromGenerator')!.toStringValue(),
foreignKey: obj.getField('foreignKey')!.toStringValue(),
ignore: obj.getField('ignore')!.toBoolValue() ?? Supabase.defaults.ignore,
ignoreFrom: obj.getField('ignoreFrom')!.toBoolValue() ?? Supabase.defaults.ignoreFrom,
ignoreTo: obj.getField('ignoreTo')!.toBoolValue() ?? Supabase.defaults.ignoreTo,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ class SupabaseSerialize extends SupabaseSerdesGenerator
association: $isAssociation,
columnName: '$columnName',
''';
if (annotation.foreignKey != null) {
definition += "associationForeignKey: '${annotation.foreignKey}',";
}
if (isAssociation) definition += 'associationType: ${checker.withoutNullResultType},';
definition += ')';
fieldsToColumns.add(definition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ Future<SupabaseRuntime> _$SupabaseRuntimeFromSupabase(Map<String, dynamic> data,
provider: provider,
repository: repository),
annotatedAssoc: await AssocAdapter().fromSupabase(data['annotated_assoc'],
provider: provider, repository: repository),
differentNameAssoc: await AssocAdapter().fromSupabase(
data['differing_name'],
provider: provider,
repository: repository));
provider: provider, repository: repository));
}
Future<Map<String, dynamic>> _$SupabaseRuntimeToSupabase(
Expand All @@ -33,10 +29,6 @@ Future<Map<String, dynamic>> _$SupabaseRuntimeToSupabase(
repository: repository),
'annotated_assoc': await AssocAdapter().toSupabase(instance.annotatedAssoc,
provider: provider, repository: repository),
'differing_name': await AssocAdapter().toSupabase(
instance.differentNameAssoc,
provider: provider,
repository: repository)
};
}
Expand All @@ -60,13 +52,6 @@ class SupabaseRuntimeAdapter extends SupabaseFirstAdapter<SupabaseRuntime> {
'annotatedAssoc': const RuntimeSupabaseColumnDefinition(
association: true,
columnName: 'annotated_assoc',
associationForeignKey: 'assoc_id',
associationType: Assoc,
),
'differentNameAssoc': const RuntimeSupabaseColumnDefinition(
association: true,
columnName: 'differing_name',
associationForeignKey: 'assoc_id',
associationType: Assoc,
)
};
Expand Down Expand Up @@ -96,17 +81,13 @@ class SupabaseRuntime extends SupabaseModel {

final Assoc unannotatedAssoc;

@Supabase(foreignKey: 'assoc_id')
@Supabase(name: 'assoc_id')
final Assoc annotatedAssoc;

@Supabase(foreignKey: 'assoc_id', name: 'differing_name')
final Assoc differentNameAssoc;

SupabaseRuntime({
required this.unannotatedAssoc,
required this.annotatedAssoc,
required this.someField,
required this.differentNameAssoc,
});
}

Expand Down

0 comments on commit 3eacc67

Please sign in to comment.