mid 0.0.1
mid: ^0.0.1 copied to clipboard
an API generation tool
mid - build end-to-end type-safe APIs (Experimental) #
⚠️ warning: The project is experimental! ⚠️
mid is a tool to build an end-to-end type-safe API. The tool generates an API server and a client library as well as handling requests and managing the communication between the server and the client.
mid simply works by converting the public methods for a given list of classes into endpoints (i.e. /class_name/method_name). The return type and the parameters of each method are parsed to generate the requests handlers, the serialization/deserialization code and the client library to be directly used by the frontend -- as simple as calling functions.
For example:
-
you write this on the server side:
class App { final Database database; App(this.database); Future<UserData> getUserData(int uid) async { final user = await database.getUserById(uid); return user; } } -
you will be able to do this on the client side:
final client = AppClient(url: 'localhost:8080'); final UserData data = await client.getUserData(42);
In order for mid to generate the server side and client side code, the endpoints must be provided in the following manner:
Future<List<Object>> endpoints(Logger logger) async {
final database = Database(url: String.fromEnvironment('DATABASE_URL'));
return [
App(apiKey: apiKey, database: database, logger: logger);,
];
}
One can also create multiple routes and endpoints such as:
Future<List<Object>> endpoints(Logger logger) async {
final database = Database(url: String.fromEnvironment('DATABASE_URL'));
final storageURL = String.fromEnvironment('STORAGE_KEY');
final apiKey = String.fromEnvironment('API_KEY');
final authAPI = Auth(database: database, logger: logger);
final storageAPI = Storage(apiKey: apiKey, url: storageURL, database: database, logger: logger);
final applicationAPI = App(apiKey: apiKey, database: database, logger: logger);
return [
authAPI,
storageAPI,
applicationAPI,
];
}
For more details, see Getting Started or Examples and see the Caveats below.
Motivation #
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.
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.
Getting Started #
-
Install
mid:dart pub global activate mid -
Create a
midproject:mid create <project_name>This will create two dart projects in the following structure:
<project_name> |- <project_name>_client |- <project_name>_server -
open
<project_name>/<project_name>_server/mid/endpoints.dartand add your endpoints there.You can create the endpoints classes inside the
libfolder, and then import them to theendpointsfile. -
Generate endpoints:
mid generate endpointsThis will generate the server side code on top of shelf server within
midfolder. -
Generate teh client code
mid generate client
Examples #
Examples will be added soon to the examples folder.
Caveats #
Supported Classes #
Any class. mid will only expose the public methods of the given class and it'll not expose any of its superclass(es).
Supported Return Types and Method Parameters Types #
- All core Types (
int,double,num,bool,String,DateTime,Duration, etc.) - User defined Classes*
- Collections (i.e.,
Map,Set,List) of the Basic Types or Data Classes. FutureorStream(not supported yet) 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 using this). An example class would be:
class UserData {
final int id;
final String name;
// `MetaData` will be serialized even if it doesn't appear in any method return type or parameters types
final MetaData metadata;
// Must have unnamed generative constructor with formal parameters (i.e. using `this`).
UserData({this.id, this.name, this.metadata});
/*
you can define your own methods, factory constructors, and whatnot
*/
}