⚠️ warning: the project is still experimental!so things may change often until a stable version is released.
mid
is a tool to build an end-to-end typesafe API in dart. The tool generates an API server and a client library in addition to handling requests and managing communication between the server and the client.
In short:
-
You write this on the server side:
class App extends EndPoints { final Database database; App(this.database); Future<UserData> getUserData(int uid) async { final user = await database.getUserById(uid); return user; } Stream<List<Post>> timeline(int uid) { return database.timelineStream(uid); } Future<void> updateProfile(UserProfile profile) { await database.updateProfile(profile); } }
-
And
mid
enables you to do this on the client side:final client = TheClient(url: 'localhost:8080'); final UserData data = await client.getUserData(42); final Stream<List<Post>> posts = await client.timeline(uid); final newProfile = profile.copyWith(photoURL: photoURL); await client.updateProfile(newProfile);
See the Quick Start Tutorial to learn how to use mid
in no time.
dart pub global activate mid
- Examples will be added SOON to the examples folder.
The documentation is being created incrementally within docs folder. Currently the following is available:
To have the ability to call the backend code from the frontend in a type safe manner and as simple as calling a function in pure Dart.
Note:
mid
is not intended to generate a REST API, but to generate an API server that can be seamlessly used by a Dart or Flutter frontend with a minimal effort.
mid
simply works by converting the public methods for a given list of classes into endpoints on a shelf server by generating a shelf_router and its handlers. In addition, the return type and the parameters types of each method are parsed and analyzed to generate the serialization/deserialization code for each type.
The client library is generated in a similar manner where each class, method, return type and parameter type is regenerated so that each endpoint becomes a simple function.
To support streaming data from the server to the client, shelf_web_socket is used on the server while web_socket_channel on the client.
Any class of an EndPoints
* type. mid
will only expose the public methods of the given class and it'll not expose any of its superclass(es).
* EndPoints
is just a type -- for now there's nothing to implement. a class just needs to implement, extend or mixin EndPoints
so it can be converted.
-
All core Types (
int
,double
,num
,bool
,String
,DateTime
,Duration
,enum
,Uri
,BigInt
) -
User defined Classes*
-
Collections (i.e.,
Map
,Set
,List
) of any of the above. -
Future
orStream
for any of the above.*
mid
is able to serialize user defined classes and their members recursively as long as they have an unnamed generative constructor with formal parameters only (i.e. all parameters usingthis
). An example class would be:class UserData { final int id; final String name; final bool isAdmin; // `MetaData` must follow the same rules including its members. final MetaData? metadata; // this is what `mid` is looking for (i.e. no assignment in initializer list or constructor body): UserData({ required this.id, required this.name, this.metadata, this.isAdmin = false, }); /* you can define your own methods, factory constructors, and whatnot */ }