From 6b277647b7be0ba828eba0a3999a4255992f5062 Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Sun, 5 Mar 2023 16:47:12 +0600 Subject: [PATCH] chore: bump version for pre release --- README.md | 117 ++++++++-- .../fl_query/.flutter-plugins-dependencies | 2 +- packages/fl_query/README.md | 200 ++++++++++-------- packages/fl_query/example/pubspec.lock | 2 +- packages/fl_query/example/pubspec.yaml | 3 +- packages/fl_query/pubspec.yaml | 2 +- .../.flutter-plugins-dependencies | 2 +- packages/fl_query_hooks/example/pubspec.lock | 4 +- packages/fl_query_hooks/example/pubspec.yaml | 6 +- packages/fl_query_hooks/pubspec.yaml | 4 +- 10 files changed, 226 insertions(+), 116 deletions(-) diff --git a/README.md b/README.md index 851c18f..f37cab9 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Fl-Query makes asynchronous server state management a breeze in flutter - Optimistic updates - Automatically cached data invalidation & unneeded query/mutation garbage collection - Infinite pagination via `InfiniteQuery` +- Lazy persistent cache (Uses [hive](https://pub.dev/packages/hive) for persisting query results to disk) (optional) - Easy to write & understand code. Follows DRY (Don't repeat yourself) convention - Compatible with both vanilla Flutter & elite [flutter_hooks](https://pub.dev/packages/flutter_hooks) @@ -28,16 +29,15 @@ Regular installation: $ flutter pub add fl_query ``` -For elite flutter_hooks user: +For elite flutter_hooks user (Welcome to the flutter cool community btw😎) ```bash -$ flutter pub add flutter_hooks -$ flutter pub add fl_query_hooks +$ flutter pub add flutter_hooks fl_query_hooks ``` # Docs -You can find the documentation (WIP) of fl-query at https://fl-query.vercel.app/ +You can find the documentation of fl-query at https://fl-query.vercel.app/ # Basic Usage @@ -69,6 +69,98 @@ In `MyApp` Widget's build method wrap your `MaterialApp` with with `QueryClientP } ``` +Let's write use a `Query` now +FL-Query provides a `QueryBuilder` widget that creates and listens to the specified `Query` +and re-runs the builder function whenever there's an update + +It has 2 required parameters(unnamed) `key` & `builder` + +```dart +class MyApp extends StatelessWidget{ + MyApp({super.key}); + + @override + build(context){ + return QueryBuilder( + 'hello', + () { + return Future.delayed( + const Duration(seconds: 6), () => 'Hello World!'); + }, + initial: 'A replacement', + jsonConfig: JsonConfig( + fromJson: (json) => json['data'], + toJson: (data) => {'data': data}, + ), + onData: (value) { + debugPrint('onData: $value'); + }, + onError: (error) { + debugPrint('onError: $error'); + }, + builder: (context, query) { + if (query.isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (query.hasError) { + return Center( + child: Text(query.error.toString()), + ); + } + return Center( + child: Text(query.data ?? "Unfortunately, there's no data"), + ); + }, + ); + } +} +``` + +And if you're using **flutter_hooks** you got that too + +```dart +class MyApp extends HookWidget{ + MyApp({super.key}); + + @override + build(context){ + final query = useQuery( + 'hello', + () { + return Future.delayed( + const Duration(seconds: 6), () => 'Hello World!'); + }, + initial: 'A replacement', + jsonConfig: JsonConfig( + fromJson: (json) => json['data'], + toJson: (data) => {'data': data}, + ), + onData: (value) { + debugPrint('onData: $value'); + }, + onError: (error) { + debugPrint('onError: $error'); + }, + ); + + if (query.isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (query.hasError) { + return Center( + child: Text(query.error.toString()), + ); + } + return Center( + child: Text(query.data ?? "Unfortunately, there's no data"), + ); + } +} +``` + +*To master the fl-query follow the official blog at https://fl-query.vercel.app/blog* # Why?

@@ -76,18 +168,17 @@ In `MyApp` Widget's build method wrap your `MaterialApp` with with `QueryClientP

The main purpose of Fl-Query is providing the easiest way to manage the messy server-state part requiring the least amount of code with code reusability & performance +This let's you focus more on those cool UI animations & transitions✨. Leave the boring stuff to fl-query -**Isn't `FutureBuilder` good?** -Yes but it is only if your commercial server has huge load of power & you're made of money or your app is simple or mostly offline & barely requires internet connection -`FutureBuilder` isn't good for data persistency & its impossible to share data across the entire application using it +**Q. Isn't `FutureBuilder` good?** -**So `FutureProvider` from riverpod or provider not enough?** -Yeah, indeed its more than enough for many applications but what if your app needs Optimistic Updates & proper server-state synchronization or simply want a custom `cacheTime`? Although `FutureProvider` is a viable solution most of the `Future` related stuff, why not kick it up a notch with smart refetching capabilities with proper server-state synchronization? -Riverpod is definitely a inspiration for Fl-Query & the `QueryJob` is actually inspired by riverpod & imo is the best state management solution any library has ever provided but that's still a client state manager just like other client state manager or synchronous data manager + No, of course not. Unless you're from 2013 or your app is a purely offline app +**Q. So `FutureProvider` from riverpod or provider not enough?** + +Probably yes. Although riverpod@v2 has added a lot of caching related features but still optimistic updates, periodic refetching & disk persistence are missing. Let's not forget about infinite pagination, it's a nightmare😅. In case of provider, same story. It's a great package but it's not ideal for server-state management # Notice Board -This project is currently under heavy development & not yet production ready. There are lot of features to cover. If anyone encounters any unintended behavior or any bug please report it. Also we're open to improvement suggestions & feature requests - -**Important!:** The project needs Dart-Flutter developers who are willing to contribute to the project by writing Tests. (I'm the worst example for tester) \ No newline at end of file +We need some bada** coders to write tests and ruin our life🥲 +100% coverage is our goal🙃 \ No newline at end of file diff --git a/packages/fl_query/.flutter-plugins-dependencies b/packages/fl_query/.flutter-plugins-dependencies index d269dd2..c25c10e 100644 --- a/packages/fl_query/.flutter-plugins-dependencies +++ b/packages/fl_query/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_android-2.0.22/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.8/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-03-05 15:00:54.195603","version":"3.7.3"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_android-2.0.22/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.8/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-03-05 16:45:34.480911","version":"3.7.3"} \ No newline at end of file diff --git a/packages/fl_query/README.md b/packages/fl_query/README.md index bb626c9..f37cab9 100644 --- a/packages/fl_query/README.md +++ b/packages/fl_query/README.md @@ -16,7 +16,8 @@ Fl-Query makes asynchronous server state management a breeze in flutter - Smart + effective refetching - Optimistic updates - Automatically cached data invalidation & unneeded query/mutation garbage collection -- Infinite data pagination via `InfiniteQuery` +- Infinite pagination via `InfiniteQuery` +- Lazy persistent cache (Uses [hive](https://pub.dev/packages/hive) for persisting query results to disk) (optional) - Easy to write & understand code. Follows DRY (Don't repeat yourself) convention - Compatible with both vanilla Flutter & elite [flutter_hooks](https://pub.dev/packages/flutter_hooks) @@ -28,25 +29,34 @@ Regular installation: $ flutter pub add fl_query ``` -For elite flutter_hooks user: +For elite flutter_hooks user (Welcome to the flutter cool community btw😎) ```bash -$ flutter pub add flutter_hooks -$ flutter pub add fl_query_hooks +$ flutter pub add flutter_hooks fl_query_hooks ``` # Docs -You can find the documentation (WIP) of fl-query at https://fl-query.vercel.app/ +You can find the documentation of fl-query at https://fl-query.vercel.app/ # Basic Usage -First wrap your `MaterialApp` with with `QueryBowlScope` widget +Initialize the cache databases in your `main` method + +> fl-query uses [hive](https://pub.dev/packages/hive) for persisting data to disk + +```dart +void main()async { + WidgetsFlutterBinding.ensureInitialized(); + await QueryClient.initialize(cachePrefix: 'fl_query_example'); + runApp(MyApp()); +} +``` +In `MyApp` Widget's build method wrap your `MaterialApp` with with `QueryClientProvider` widget ```dart Widget build(BuildContext context) { - return QueryBowlScope( - bowl: QueryBowl(), + return QueryClientProvider( child: MaterialApp( title: 'Fl-Query Example App', theme: ThemeData( @@ -59,104 +69,116 @@ First wrap your `MaterialApp` with with `QueryBowlScope` widget } ``` -Fl-Query has two types of jobs - - `QueryJob`: Used for storing GET requests or for storing changeable yet readonly async data - - `MutationJob`: Used for POST/PUT/DELETE requests or for mutating/changing data in services or a store asynchronously +Let's write use a `Query` now +FL-Query provides a `QueryBuilder` widget that creates and listens to the specified `Query` +and re-runs the builder function whenever there's an update -You can write all your query or mutation logic a method parameter named `task` & identify the query uniquely by passing a unique `queryKey` - -Example of a QueryJob: +It has 2 required parameters(unnamed) `key` & `builder` ```dart -final exampleQueryJob = QueryJob( - queryKey: "example", // have to be unique - task: (queryKey, externalData) async { - final res = await http.get("/api/example-data"); - return jsonDecode(res.body); - } -); -``` +class MyApp extends StatelessWidget{ + MyApp({super.key}); -Store the `QueryJob` somewhere globally accessible in your project so you can reuse it later - -Now you can use this `QueryJob` anywhere inside your flutter app inside the build method using a `QueryBuilder` widget - -```dart -Widget build(BuildContext context){ - return QueryBuilder( - job: exampleQueryJob, - externalData: null, - builder: (context, query) { - if (!query.hasData || query.isLoading) { - return const CircularProgressIndicator(); - } - return Row( - children: [ - Text(query.data!), - ElevatedButton( - child: const Text("Refetch"), - onPressed: () async { - // refetches the query - await query.refetch(); - }, - ), - ], - ); - }, - ); -} -``` - -Or if you're an elite **flutter_hooks** user you can use the `useQuery` hook which is exported from the `package:fl_query_hooks/fl_query_hooks.dart` to do the same thing as above - -```dart -/* other imports */ -import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:fl_query_hooks/fl_query_hooks.dart'; // importing the fl-query hook package - -class Example extends HookWidget{ - Example(super.key); - - Widget build(BuildContext context) { - final query = useQuery(job: exampleQueryJob, externalData: null); - - if (!query.hasData || query.isLoading) { - return const CircularProgressIndicator(); - } - return Row( - children: [ - Text(query.data!), - ElevatedButton( - child: const Text("Refetch"), - onPressed: () async { - // refetches the query - await query.refetch(); - }, + @override + build(context){ + return QueryBuilder( + 'hello', + () { + return Future.delayed( + const Duration(seconds: 6), () => 'Hello World!'); + }, + initial: 'A replacement', + jsonConfig: JsonConfig( + fromJson: (json) => json['data'], + toJson: (data) => {'data': data}, ), - ], - ); - } + onData: (value) { + debugPrint('onData: $value'); + }, + onError: (error) { + debugPrint('onError: $error'); + }, + builder: (context, query) { + if (query.isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (query.hasError) { + return Center( + child: Text(query.error.toString()), + ); + } + return Center( + child: Text(query.data ?? "Unfortunately, there's no data"), + ); + }, + ); + } } ``` +And if you're using **flutter_hooks** you got that too + +```dart +class MyApp extends HookWidget{ + MyApp({super.key}); + + @override + build(context){ + final query = useQuery( + 'hello', + () { + return Future.delayed( + const Duration(seconds: 6), () => 'Hello World!'); + }, + initial: 'A replacement', + jsonConfig: JsonConfig( + fromJson: (json) => json['data'], + toJson: (data) => {'data': data}, + ), + onData: (value) { + debugPrint('onData: $value'); + }, + onError: (error) { + debugPrint('onError: $error'); + }, + ); + + if (query.isLoading) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (query.hasError) { + return Center( + child: Text(query.error.toString()), + ); + } + return Center( + child: Text(query.data ?? "Unfortunately, there's no data"), + ); + } +} +``` + +*To master the fl-query follow the official blog at https://fl-query.vercel.app/blog* + # Why?

The hell, why?

The main purpose of Fl-Query is providing the easiest way to manage the messy server-state part requiring the least amount of code with code reusability & performance +This let's you focus more on those cool UI animations & transitions✨. Leave the boring stuff to fl-query -**Isn't `FutureBuilder` good?** -Yes but it is only if your commercial server has huge load of power & you're made of money or your app is simple or mostly offline & barely requires internet connection -`FutureBuilder` isn't good for data persistency & its impossible to share data across the entire application using it +**Q. Isn't `FutureBuilder` good?** -**So `FutureProvider` from riverpod or provider not enough?** -Yeah, indeed its more than enough for many applications but what if your app needs Optimistic Updates & proper server-state synchronization or simply want a custom `cacheTime`? Although `FutureProvider` is a viable solution most of the `Future` related stuff, why not kick it up a notch with smart refetching capabilities with proper server-state synchronization? -Riverpod is definitely a inspiration for Fl-Query & the `QueryJob` is actually inspired by riverpod & imo is the best state management solution any library has ever provided but that's still a client state manager just like other client state manager or synchronous data manager + No, of course not. Unless you're from 2013 or your app is a purely offline app +**Q. So `FutureProvider` from riverpod or provider not enough?** + +Probably yes. Although riverpod@v2 has added a lot of caching related features but still optimistic updates, periodic refetching & disk persistence are missing. Let's not forget about infinite pagination, it's a nightmare😅. In case of provider, same story. It's a great package but it's not ideal for server-state management # Notice Board -This project is currently under heavy development & not yet production ready. There are lot of features to cover. If anyone encounters any unintended behavior or any bug please report it. Also we're open to improvement suggestions & feature requests - -**Important!:** The project needs Dart-Flutter developers who are willing to contribute to the project by writing Tests. (I'm the worst example for tester) \ No newline at end of file +We need some bada** coders to write tests and ruin our life🥲 +100% coverage is our goal🙃 \ No newline at end of file diff --git a/packages/fl_query/example/pubspec.lock b/packages/fl_query/example/pubspec.lock index fa104a6..25aa27e 100644 --- a/packages/fl_query/example/pubspec.lock +++ b/packages/fl_query/example/pubspec.lock @@ -79,7 +79,7 @@ packages: path: ".." relative: true source: path - version: "0.3.1" + version: "1.0.0-alpha.1" flutter: dependency: "direct main" description: flutter diff --git a/packages/fl_query/example/pubspec.yaml b/packages/fl_query/example/pubspec.yaml index b151425..dad762c 100644 --- a/packages/fl_query/example/pubspec.yaml +++ b/packages/fl_query/example/pubspec.yaml @@ -9,8 +9,7 @@ environment: dependencies: flutter: sdk: flutter - fl_query: - path: ../ + fl_query: ^1.0.0-alpha.1 go_router: ^6.0.9 http: ^0.13.5 diff --git a/packages/fl_query/pubspec.yaml b/packages/fl_query/pubspec.yaml index 3fe7053..f704016 100644 --- a/packages/fl_query/pubspec.yaml +++ b/packages/fl_query/pubspec.yaml @@ -1,6 +1,6 @@ name: fl_query description: Asynchronous data caching, refetching & invalidation library for Flutter -version: 0.3.1 +version: 1.0.0-alpha.1 homepage: https://fl-query.vercel.app issue_tracker: https://github.com/KRTirtho/fl-query/issues diff --git a/packages/fl_query_hooks/.flutter-plugins-dependencies b/packages/fl_query_hooks/.flutter-plugins-dependencies index 2aebf83..8256515 100644 --- a/packages/fl_query_hooks/.flutter-plugins-dependencies +++ b/packages/fl_query_hooks/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_android-2.0.22/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.8/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-03-05 15:00:50.835313","version":"3.7.3"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_android-2.0.22/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.1.1/","native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_linux-2.1.8/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/home/kingkor/.pub-cache/hosted/pub.dev/path_provider_windows-2.1.3/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]}],"date_created":"2023-03-05 16:45:33.656499","version":"3.7.3"} \ No newline at end of file diff --git a/packages/fl_query_hooks/example/pubspec.lock b/packages/fl_query_hooks/example/pubspec.lock index d05c750..0211d56 100644 --- a/packages/fl_query_hooks/example/pubspec.lock +++ b/packages/fl_query_hooks/example/pubspec.lock @@ -87,14 +87,14 @@ packages: path: "../../fl_query" relative: true source: path - version: "0.3.1" + version: "1.0.0-alpha.1" fl_query_hooks: dependency: "direct main" description: path: ".." relative: true source: path - version: "0.3.1" + version: "1.0.0-alpha.1" flutter: dependency: "direct main" description: flutter diff --git a/packages/fl_query_hooks/example/pubspec.yaml b/packages/fl_query_hooks/example/pubspec.yaml index 396d2ef..d2a4a4c 100644 --- a/packages/fl_query_hooks/example/pubspec.yaml +++ b/packages/fl_query_hooks/example/pubspec.yaml @@ -13,10 +13,8 @@ dependencies: sdk: flutter cupertino_icons: ^1.0.2 - fl_query: - path: ../../fl_query - fl_query_hooks: - path: ../ + fl_query: ^1.0.0-alpha.1 + fl_query_hooks: ^1.0.0-alpha.1 go_router: ^6.0.9 http: ^0.13.5 flutter_hooks: ^0.18.6 diff --git a/packages/fl_query_hooks/pubspec.yaml b/packages/fl_query_hooks/pubspec.yaml index ef630f2..f95357e 100644 --- a/packages/fl_query_hooks/pubspec.yaml +++ b/packages/fl_query_hooks/pubspec.yaml @@ -1,7 +1,7 @@ name: fl_query_hooks description: Elite flutter_hooks compatible library for fl_query, the Asynchronous data caching, refetching & invalidation library for Flutter -version: 0.3.1 +version: 1.0.0-alpha.1 homepage: https://fl-query.vercel.app issue_tracker: https://github.com/KRTirtho/fl-query/issues @@ -15,7 +15,7 @@ environment: dependencies: flutter: sdk: flutter - fl_query: ^0.3.1 + fl_query: ^1.0.0-alpha.1 flutter_hooks: ^0.18.6 dev_dependencies: