feat(crud): add supabase implementation preview
Some checks failed
continuous-integration/drone/pr Build is failing
Some checks failed
continuous-integration/drone/pr Build is failing
This commit is contained in:
parent
0a3f0094c4
commit
b387cda3dd
46
packages/wyatt_crud_bloc/example/lib/main_supabase.dart
Normal file
46
packages/wyatt_crud_bloc/example/lib/main_supabase.dart
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2022 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:crud_bloc_example/app.dart';
|
||||
import 'package:crud_bloc_example/app_bloc_observer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart';
|
||||
import 'package:wyatt_crud_bloc_supabase/wyatt_crud_bloc_supabase.dart';
|
||||
|
||||
const supabaseUrl = 'https://yarkjotsulnccxdkztiv.supabase.co';
|
||||
const supabaseKey = String.fromEnvironment('SUPABASE_KEY');
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
Bloc.observer = AppBlocObserver();
|
||||
|
||||
await Supabase.initialize(
|
||||
url: supabaseUrl,
|
||||
anonKey: supabaseKey,
|
||||
);
|
||||
|
||||
final CrudDataSource crudDataSource = CrudDataSourceSupabaseImpl(
|
||||
'users',
|
||||
id: (_, json) => json['id'] as String,
|
||||
getIdKey: (_) => 'id',
|
||||
);
|
||||
|
||||
runApp(MyApp(
|
||||
crudDataSource: crudDataSource,
|
||||
));
|
||||
}
|
@ -33,11 +33,14 @@ dependencies:
|
||||
equatable: ^2.0.5
|
||||
firebase_core: ^2.22.0
|
||||
cloud_firestore: ^4.13.0
|
||||
supabase_flutter: ^2.3.4
|
||||
flutter_bloc: ^8.1.3
|
||||
wyatt_crud_bloc:
|
||||
path: "../"
|
||||
wyatt_crud_bloc_firestore:
|
||||
path: "../wyatt_crud_bloc_firestore"
|
||||
wyatt_crud_bloc_supabase:
|
||||
path: "../wyatt_crud_bloc_supabase"
|
||||
|
||||
wyatt_architecture:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
|
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/.gitignore
vendored
Symbolic link
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/.gitignore
vendored
Symbolic link
@ -0,0 +1 @@
|
||||
../../../.gitignore
|
10
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/.metadata
Normal file
10
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/.metadata
Normal file
@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/.pubignore
Symbolic link
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/.pubignore
Symbolic link
@ -0,0 +1 @@
|
||||
../../../.pubignore
|
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/AUTHORS
Symbolic link
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/AUTHORS
Symbolic link
@ -0,0 +1 @@
|
||||
../../../AUTHORS
|
@ -0,0 +1,3 @@
|
||||
## 0.0.1
|
||||
|
||||
* TODO: Describe initial release.
|
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/LICENSE
Symbolic link
1
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/LICENSE
Symbolic link
@ -0,0 +1 @@
|
||||
../../../LICENSE
|
39
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/README.md
Normal file
39
packages/wyatt_crud_bloc/wyatt_crud_bloc_supabase/README.md
Normal file
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
This README describes the package. If you publish this package to pub.dev,
|
||||
this README's contents appear on the landing page for your package.
|
||||
|
||||
For information about how to write a good package README, see the guide for
|
||||
[writing package pages](https://dart.dev/guides/libraries/writing-package-pages).
|
||||
|
||||
For general information about developing packages, see the Dart guide for
|
||||
[creating packages](https://dart.dev/guides/libraries/create-library-packages)
|
||||
and the Flutter guide for
|
||||
[developing packages and plugins](https://flutter.dev/developing-packages).
|
||||
-->
|
||||
|
||||
TODO: Put a short description of the package here that helps potential users
|
||||
know whether this package might be useful for them.
|
||||
|
||||
## Features
|
||||
|
||||
TODO: List what your package can do. Maybe include images, gifs, or videos.
|
||||
|
||||
## Getting started
|
||||
|
||||
TODO: List prerequisites and provide or point to information on how to
|
||||
start using the package.
|
||||
|
||||
## Usage
|
||||
|
||||
TODO: Include short and useful examples for package users. Add longer examples
|
||||
to `/example` folder.
|
||||
|
||||
```dart
|
||||
const like = 'sample';
|
||||
```
|
||||
|
||||
## Additional information
|
||||
|
||||
TODO: Tell users more about the package: where to find more information, how to
|
||||
contribute to the package, how to file issues, what response they can expect
|
||||
from the package authors, and more.
|
@ -0,0 +1 @@
|
||||
include: package:wyatt_analysis/analysis_options.flutter.yaml
|
@ -0,0 +1,255 @@
|
||||
// Copyright (C) 2023 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||
import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart' as crud show Query;
|
||||
import 'package:wyatt_crud_bloc/wyatt_crud_bloc.dart' hide Query;
|
||||
|
||||
typedef QueryBuilder = PostgrestTransformBuilder<List<Map<String, dynamic>>>;
|
||||
typedef StreamBuilder = SupabaseStreamBuilder;
|
||||
|
||||
/// {@template crud_data_source_supabase_impl}
|
||||
/// A concrete implementation of [CrudDataSource] that uses
|
||||
/// [Supabase] as the data source.
|
||||
/// {@endtemplate}
|
||||
class CrudDataSourceSupabaseImpl extends CrudDataSource {
|
||||
/// {@macro crud_data_source_supabase_impl}
|
||||
CrudDataSourceSupabaseImpl(
|
||||
String table, {
|
||||
required super.id,
|
||||
this.getIdKey,
|
||||
SupabaseClient? supabase,
|
||||
}) : _supabase = supabase ?? Supabase.instance.client {
|
||||
_supabaseQueryBuilder = _supabase.from(table);
|
||||
}
|
||||
|
||||
final SupabaseClient _supabase;
|
||||
late SupabaseQueryBuilder _supabaseQueryBuilder;
|
||||
|
||||
/// Get the id field name depending on the operation type.
|
||||
/// If null, 'id' will be used.
|
||||
final String? Function(
|
||||
OperationType operationType,
|
||||
)? getIdKey;
|
||||
|
||||
@override
|
||||
Future<void> create(Map<String, dynamic> object, {String? id}) {
|
||||
if (id != null) {
|
||||
return _supabaseQueryBuilder.upsert(object);
|
||||
} else {
|
||||
final String? id = this.id(
|
||||
OperationType.create,
|
||||
object,
|
||||
);
|
||||
|
||||
if (id != null) {
|
||||
return _supabaseQueryBuilder.upsert(object);
|
||||
}
|
||||
return _supabaseQueryBuilder.insert(object);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(String id) {
|
||||
final String idKey = getIdKey?.call(OperationType.delete) ?? 'id';
|
||||
return _supabaseQueryBuilder.delete().match({idKey: id});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteAll() async {
|
||||
final List<Map<String, dynamic>> snapshots =
|
||||
await _supabaseQueryBuilder.select();
|
||||
for (final Map<String, dynamic> snapshot in snapshots) {
|
||||
final String idKey = getIdKey?.call(OperationType.delete) ?? 'id';
|
||||
await _supabaseQueryBuilder.delete().match({idKey: snapshot[idKey]});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>?> get(String id) async {
|
||||
final String idKey = getIdKey?.call(OperationType.read) ?? 'id';
|
||||
final List<Map<String, dynamic>> snapshots =
|
||||
await _supabaseQueryBuilder.select().match({idKey: id});
|
||||
return snapshots.firstOrNull;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>?>> getAll() async =>
|
||||
_supabaseQueryBuilder.select();
|
||||
|
||||
@override
|
||||
Future<List<Map<String, dynamic>?>> search(
|
||||
List<crud.Query> conditions,
|
||||
) async {
|
||||
final PostgrestFilterBuilder<List<Map<String, dynamic>>> query =
|
||||
_supabaseQueryBuilder.select();
|
||||
|
||||
final filter = conditions.whereType<WhereQuery<dynamic>>().firstOrNull;
|
||||
final modifiers = [
|
||||
...conditions.whereType<LimitQuery>(),
|
||||
...conditions.whereType<OrderByQuery>(),
|
||||
];
|
||||
|
||||
PostgrestTransformBuilder<List<Map<String, dynamic>>>? queryTransform;
|
||||
|
||||
if (filter != null) {
|
||||
queryTransform = _queryFilterParser(filter, query);
|
||||
}
|
||||
|
||||
for (final condition in modifiers) {
|
||||
queryTransform = _queryModifierParser(condition, queryTransform ?? query);
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<Map<String, dynamic>?>> stream({
|
||||
String? id,
|
||||
List<crud.Query>? conditions,
|
||||
bool includeMetadataChanges = false,
|
||||
}) {
|
||||
// TODO(hpcl): use conditions!!
|
||||
final stream = _supabaseQueryBuilder
|
||||
.stream(primaryKey: [getIdKey?.call(OperationType.read) ?? 'id']);
|
||||
|
||||
if (id != null) {
|
||||
return stream.eq(
|
||||
getIdKey?.call(OperationType.read) ?? 'id',
|
||||
id,
|
||||
);
|
||||
} else {
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update(
|
||||
String id, {
|
||||
Map<String, dynamic>? object,
|
||||
}) async {
|
||||
if (object != null) {
|
||||
final String idKey = getIdKey?.call(OperationType.update) ?? 'id';
|
||||
return _supabaseQueryBuilder.update(object).match({idKey: id});
|
||||
} else {
|
||||
throw Exception('You must provide data to update');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateAll(Map<String, Object?>? data) async {
|
||||
if (data == null) {
|
||||
throw Exception('You must provide data to update');
|
||||
}
|
||||
return _supabaseQueryBuilder.update(data);
|
||||
}
|
||||
|
||||
QueryBuilder _queryFilterParser(
|
||||
crud.Query condition,
|
||||
PostgrestFilterBuilder<List<Map<String, dynamic>>> query,
|
||||
) {
|
||||
if (condition is WhereQuery) {
|
||||
switch (condition.type) {
|
||||
case WhereQueryType.isEqualTo:
|
||||
return query.eq(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isNotEqualTo:
|
||||
return query.neq(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isLessThan:
|
||||
return query.lt(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isLessThanOrEqualTo:
|
||||
return query.lte(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isGreaterThan:
|
||||
return query.gt(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isGreaterThanOrEqualTo:
|
||||
return query.gte(condition.field, condition.value as Object);
|
||||
case WhereQueryType.arrayContains:
|
||||
return query.contains(condition.field, condition.value as Object);
|
||||
case WhereQueryType.whereIn:
|
||||
return query.inFilter(
|
||||
condition.field,
|
||||
condition.value as List<Object>,
|
||||
);
|
||||
case WhereQueryType.whereNotIn:
|
||||
return query.not(
|
||||
condition.field,
|
||||
'in',
|
||||
condition.value as List<Object>,
|
||||
);
|
||||
case WhereQueryType.isNull:
|
||||
if (condition.value as bool) {
|
||||
return query.isFilter(condition.field, null);
|
||||
} else {
|
||||
return query.not(condition.field, 'is', null);
|
||||
}
|
||||
case WhereQueryType.arrayContainsAny:
|
||||
throw UnsupportedError(
|
||||
'${condition.type} is not supported by Supabase',
|
||||
);
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
StreamBuilder _streamFilterParser(
|
||||
crud.Query condition,
|
||||
SupabaseStreamFilterBuilder query,
|
||||
) {
|
||||
if (condition is WhereQuery) {
|
||||
switch (condition.type) {
|
||||
case WhereQueryType.isEqualTo:
|
||||
return query.eq(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isNotEqualTo:
|
||||
return query.neq(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isLessThan:
|
||||
return query.lt(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isLessThanOrEqualTo:
|
||||
return query.lte(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isGreaterThan:
|
||||
return query.gt(condition.field, condition.value as Object);
|
||||
case WhereQueryType.isGreaterThanOrEqualTo:
|
||||
return query.gte(condition.field, condition.value as Object);
|
||||
case WhereQueryType.whereIn:
|
||||
return query.inFilter(
|
||||
condition.field,
|
||||
condition.value as List<Object>,
|
||||
);
|
||||
case WhereQueryType.arrayContains:
|
||||
case WhereQueryType.arrayContainsAny:
|
||||
case WhereQueryType.whereNotIn:
|
||||
case WhereQueryType.isNull:
|
||||
throw UnsupportedError(
|
||||
'${condition.type} is not supported in stream by Supabase',
|
||||
);
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
QueryBuilder _queryModifierParser(
|
||||
crud.Query condition,
|
||||
QueryBuilder query,
|
||||
) {
|
||||
if (condition is LimitQuery) {
|
||||
return query.limit(condition.limit);
|
||||
} else if (condition is OrderByQuery) {
|
||||
return query.order(
|
||||
condition.field,
|
||||
ascending: condition.ascending,
|
||||
);
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
// Copyright (C) 2023 WYATT GROUP
|
||||
// Please see the AUTHORS file for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/// Create/Read/Update/Delete BLoC implementation for Supabase.
|
||||
library wyatt_crud_bloc_supabase;
|
||||
|
||||
export 'src/data/crud_data_source_supabase_impl.dart';
|
@ -0,0 +1,35 @@
|
||||
name: wyatt_crud_bloc_supabase
|
||||
description: Create/Read/Update/Delete implementation for Supabase
|
||||
repository: https://git.wyatt-studio.fr/Wyatt-FOSS/wyatt-packages/src/branch/master/packages/wyatt_crud_bloc
|
||||
version: 0.2.0
|
||||
|
||||
publish_to: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter: { sdk: flutter }
|
||||
|
||||
flutter_bloc: ^8.1.1
|
||||
equatable: ^2.0.5
|
||||
supabase_flutter: ^2.3.4
|
||||
|
||||
wyatt_architecture:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: ^0.2.0+1
|
||||
|
||||
wyatt_type_utils:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: ^0.0.5
|
||||
|
||||
wyatt_crud_bloc:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub/
|
||||
version: ^0.2.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test: { sdk: flutter }
|
||||
bloc_test: ^9.1.0
|
||||
wyatt_analysis:
|
||||
hosted: https://git.wyatt-studio.fr/api/packages/Wyatt-FOSS/pub
|
||||
version: ^2.6.1
|
Loading…
x
Reference in New Issue
Block a user