Open ayushin opened 4 years ago
👍 Thanks for opening this issue! 🏷 I have applied any labels matching special text in your issue.
The team will review the labels and make any necessary changes.
The wish-list:
I believe it would be really useful to agree on a pattern here before anyone starts working on this. There are so many patterns supported with libraries or using basic language features that it needs to be recognised and discussed which implementation should come here. The linked flutter_bloc_patterns
pub doesnt seem to be too popular: https://pub.dev/packages?q=bloc
Another thing, I strongly believe that such implementation must be dart-native, not dependent on Flutter, and package like analyser, builder or other that change frequently with their transitional dependencies.
Hi @agilob, I actually agree with you on all points. I've played with flutter_bloc_patterns and while the idea is nice I don't really agree on the way the data abstraction is constructed. I'm going to publish my own take on the matter, with one basic DataBloc<T,F> and two extensions ListBloc<T,F> extends DataBloc<List<T,F>> and PaginatedBloc<T,F> extends DataBloc<Page<T,F>> which seems to be producing minimal boiler plate and covers all the cases.
I'm very open to the ideas and contribution to hopefully produce something of the quality of form_bloc for lists and pages so we don't reinvent the wheel over and over.
Bloc's built-in onError() handler is a nice bonus too.
Then on top of that one would have PaginatedRepository<Page
Ordering and filtering and page access is all done via the Filter that can extend OffsetLimitFilter (int offset; int limit)
https://github.com/apexlabs-ai/list_bloc
I think the key here is to keep it very simple and flexible.
The link with the openapi-generator would be to generate the Filter classes for the list endpoints and perhaps even both the Paginated or List repositories and the translation between the Filter class fields and api methods parameters.
I'm actually very happy with the results - made the filter class a built_value and it all seem to fall into place.
The library you wrote looks nice, but I wouldnt rush into using it in openapi without it having some level of adoption in community, which will just take time and advertising effort (having it in openapi is also advertising effort?).
On an unrelated note, could you please take a look at my MRs? I've been asking for days on different channels for a review and not getting a single response/comment from anyone, I feel this is discoursing me from future contributions https://github.com/OpenAPITools/openapi-generator/pulls/agilob
Hi, thanks for your remarks! I think we are all super busy (I know for sure I am really short on time) and I am not really looking for advertisement, I'd be very very happy if I did not have to write those libraries and use some other's, which I tried for a while and it did not really work and would not match with the automatic code generation.
So my only interest in terms of open source is to save myself time in the long run, therefore if you are interested in helping I'd be very happy to accept PRs and there are a few issues open, especially missing example and tests.
Looked at your PRs - I think enums and complex json types are especially helpful, haven't run into those problems yet but sure will keep it in mind if I do.
I opened another issue and had to hack it in my fork - with endpoints returning raw streams instead of json (like downloading a binary file via the api)
And well, again as I said I am not making this code just to make code, I could really save some time by auto-generating the api repositories instead of writing boiler plate.
@wing328 @kuhnroyal
So some time later and we've been using https://pub.dev/packages/list_bloc in production for quite a while in conjunction with dio-next-gen
and I think a viable pattern emerges, that I'd like to run by you guys. I am not 100% sure this is completely generic, but it seems that parts of it can always be useful. So we can either create a clone as dart-cubit
or perhaps add some extra generated classes to the current generator.
Basically the idea is this:
import 'package:built_value/built_value.dart';
part 'currency_filter.g.dart';
abstract class CurrencyFilter
implements Built<CurrencyFilter, CurrencyFilterBuilder> {
factory CurrencyFilter([void Function(CurrencyFilterBuilder)? updates]) =
_$CurrencyFilter;
String? get search;
int get offset;
int get limit;
CurrencyFilter._();
}
This is easy to do (just list all query parameters) and is very useful for keeping track of the api states.
Autogenerate the operations wrappers that would take the above classes and pass them as query parameters to the relative endpoints - also easy to do
We could then auto-generate endpoint State classes, that's a combination of the Filter, progress, error and data, e.g.:
class CurrencyListState extends Equatable {
final CurrencyListFilter? filter;
final <BuiltList<Currency>? data;
double? progress; // null - loaded, < 0 undetermined, 0 >= progress >= 1 - loading progress
DioError error; // non-null - Api Error
}
I think this is pretty generic for working with all kind of lists and uploads and would allow to easily generate, for example Cubits, e.g:
class CurrencyListCubit extends Cubit<CurrencyListState?> {
Future<CurrencyListState> load([CurrencyListFilter? filter]) async {
try {
emit (await apiCurrencyList(filter: filter)).data;
} on DioError(e) {
emit state.withError(e);
}
}
And this covers 90% of use cases working with any REST api.
Any thoughts, ideas, suggestions?
We are using this pattern quite a lot so we could contribute resources to building the codegen.
I heavily use dart-dio and do nothing of this sort, I mainly write this into a database during some synchronisation.
Maybe 1. and 2. can be added behind a flag but I don't see 3. being useful for a broad audience tbh.
I suggest you start by making a PR for 1./2. by use of extension functions on the API classes in src/extensions
and behind a feature flag. This leaves the original API classes untouched.
And then we can see how that works out and if we want to take this further.
I suggest you start by making a PR for 1./2. by use of extension functions on the API classes in
src/extensions
and behind a feature flag. This leaves the original API classes untouched. And then we can see how that works out and if we want to take this further.
Thanks, that's what we'll do, really appreciate your input, working through openapi-generator internals always gives me a headache. I always wonder why this was not built in python/jinja
So what needs to be done:
queryClasses=true
to dio-next
similar like we have now -p nullableFields=true
we'll have -p queryClasses=true
false by default/query
similar to /model
but for each apiEndpoint that has query parameters there will be /query/endpoint_name.dart
Here is an example, all those get
s are query parameters:
import 'package:built_value/built_value.dart';
part 'flight_reports_list_filter.g.dart';
abstract class FlightReportsListFilter
implements Built<FlightReportsListFilter, FlightReportsListFilterBuilder> {
factory FlightReportsListFilter(
[void Function(FlightReportsListFilterBuilder) updates]) =
_$FlightReportsListFilter;
FlightReportsListFilter._();
String? get company;
String? get handling;
String? get date;
num? get reporterId;
String? get reporterCompany;
String? get ordering;
String? get search;
int? get limit;
int? get offset;
}
reportsFlightsListQuery => ...
await _api.reportsFlightsList(
company: f.company,
handling: f.handling,
date: f.date,
reporterId: f.reporterId,
reporterCompany: f.reporterCompany,
ordering: f.ordering,
search: f.search,
limit: f.limit,
offset: f.offset,
)
https://github.com/OpenAPITools/openapi-generator/issues/3785
I believe it would be a great help for the flutter/dart community if openapi-generator could generate the repositories boilerplate for the BLOC design patter as was discussed in the issue above.
I understand that many (including myself) have already done some work/research on the subject, so it would be great to combine the efforts and provide a joint uniform solution for this.