Open valpetli opened 2 years ago
This sounds great! After some consideration I think a dio-specific generator is going to be easier to manage going forward than a pluggable one. What do you think?
Sounds good @eandre, we'll create the example shortly then!
@eandre We finally have a draft for the dart client:
Foo? Foo
) and therefore fields are always lowercasedimport 'package:dio/dio.dart';
abstract class Client {
Client(Dio dio) : serviceClient = ServiceClient(dio);
final ServiceClient serviceClient;
}
class ServiceClient {
ServiceClient(this.dio);
final Dio dio;
Future<void> DummyAPI(
{required String boo, Foo? Foo, required dynamic Raw}) async {
await dio.post<void>('/svc.DummyAPI', data: <String, dynamic>{
'boo': boo,
if (Foo != null) 'foo': Foo,
'raw': Raw
});
}
Future<void> Get({required String Baz}) async {
await dio.get<void>('/svc.Get', queryParameters: <String, dynamic>{
'boo': Baz,
});
}
Future<void> RESTPath({required String a, required int b}) async {
await dio.get<void>('/path/$a/$b');
}
Future<Tuple<bool, Foo>> TupleInputOutput(
Tuple<String, WrappedRequest> params) async {
final response =
await dio.post<void>('/svc.TupleInputOutput', data: params);
return Tuple<bool, Foo>.fromJson(response.data as Map<String, dynamic>);
}
}
typedef Foo = num;
class Request {
Request({this.foo, required this.boo, required this.raw});
Foo? foo;
String boo;
dynamic raw;
}
class Wrapper<T> {}
class WrappedRequest<T> extends Wrapper<T> {}
const dynamic valueNotSet = 'valueNotSet';
class Tuple<A, B> {
Tuple({required this.a, required this.b});
final A a;
final B b;
Tuple<A, B> copyWith({
A? a,
B? b,
}) =>
_copyWith(a: a, b: b);
Tuple<A, B> _copyWith({
Object? a = valueNotSet,
Object? b = valueNotSet,
}) =>
Tuple(
a: (a == valueNotSet) ? this.a : (a as A),
b: (b == valueNotSet) ? this.b : (b as B),
);
factory Tuple.fromJson(Map<String, dynamic> json) => Tuple(
a: json['a'] as A,
b: json['b'] as B,
);
Map<String, dynamic> toJson() => <String, dynamic>{'a': a, 'b': b};
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Tuple &&
runtimeType == other.runtimeType &&
a == other.a &&
b == other.b;
@override
int get hashCode => toJson().hashCode;
}
Oh and I forgot to mention, that we might need to split generated code in multiple files (one per service + umbrella client) as this seems to be the only way of implementing namespaces in Dart.
that we might need to split generated code in multiple files (one per service + umbrella client) as this seems to be the only way of implementing namespaces in Dart.
For the Go client, we've prefixed the structures with the service name, such that Request
became SvcRequest
and we had SvcFoo
, would this work for Dart as well?
@DomBlack Yeah that was a workaround we had in mind as well. The types would be have a stutter names like UsersUser
or LikesLikes
, but other than that it'll work ofc :-)
+1
Hey @darthwade, thanks for the feedback. Could you share a bit more about your use case? Thanks!
Hey @darthwade, thanks for the feedback. Could you share a bit more about your use case? Thanks!
Hey @eandre, first of all, great job with the encore! We're planning to build an app in Flutter and currently I'm researching tools for easy backend infrastructure. Encore looks great, the only 2 things I'd like to have are Dart client generation & gRPC, but second is not critical.
Thanks @darthwade, I'm really happy to hear that. If Flutter is critical for your use case we're happy to prioritize it. I'll send you an email to discuss further.
Our front-end is a Flutter application and it'd be awesome to add null-safe strongly typed Dart client generation to Encore. We can provide example client as well as open a PR to implement this feature.
We'd like to use Dio as a base client and we could start with implementing
dart-dio
generation and treat other implementations as separate languages as suggested by @eandre or try to come up with a more generic solution.Additionally the resulting class can accept URL instead of environment name to handle custom URLs, PR and local environments.
How does that sound? 🙏