One of the most annoying things in web development is probably APIs behaving unexpectedly. Using a proper RESTful API usually avoids most of the problems, but we all know that sometimes inexperienced developers (and unfortunately, some seniors as well) mess it up.
Since Haxe can be used both for frontend and backend applications, I came up with the idea of using a common codebase for the two parts, which is compiled to two different applications, each with its own parts, that communicate with HTTP requests. But for the developer, the HTTP requests are abstracted away using macros. This way, api calls are type-checked, and we even get autocomplete! For example
typedef Task = {
var text: String,
var dueDate: Date
}
class TaskList extends Component {
var tasks: Array<Task> = [];
public function render() { // Client side rendered
return <ul>
for (task in tasks) {
<li>${task.text}</li>
}
</ul>
}
public function componentDidMount() {
this.tasks = @await Api.allTasks(); // Example using tink_await
}
}
class Api {
@:serverSide
static public function allTasks(): Array<Task> {
return /* Some database query */
}
}
On the backend app, allTasks
automatically gets assigned a route (such as /api/all-tasks
), the return value is automatically encoded when returned, as JSON or preferably some binary format to transport Haxe objects, using build macros. On the frontend, again using build macros, the function is converted into an HTTP request to that route which also decodes the data back to a Haxe object.
The major advantages are type checking, convenience, code reuse and rapid prototyping. This is of course just an idea (which I believe is possible to do with macros). There are definitely more things that need to be figured out such as caching, but I really like the idea. What do you guys think?