feat: being able to provide custom main() method for initialization on startup
Description
At the moment Dart Frog provides an own main() method. This causes problems since as a developer I can't run my own initialization on startup. Examples are:
- Database migration
- One-time-initialization of other packages, such as Reflectable
Requirements
- [ ] Being able to provide own main() method
- [ ] Or alternative getting some other initialization call on startup
Additional Context
If there are already other solutions for the above two cases, then please let me know
Could this be a function in an _initialize.dart file, kinda like _middleware.dart? That way dart_frog doesn't have to support a completely custom main(), but you could still inject those types of functions on startup.
Hi @mtwichel,
thanks for your prompt response.
TLDR: _initialize.dart would definitely help! Having no main.dart file might still cause problems with other packages though.
Having _initialize.dart would definitely already help. There is one drawback though. It seems that some packages, such as Reflectable, only look in main.dart for certain things. At least this is the situation I currently have. I added a fake main.dart file just so that the Reflectable code generator "finds" the file and generates the reflection code for the dart files included from main. When renaming main.dart to e.g. main2.dart, Reflectable will not generate code for it.
This is not really a Frog issue. However, the approach of hiding the main() method might break compatibility with other packages which depend on main being available. In case of Reflectable it actually works; it is just a bit hacky to add the main file just for that purpose, and then having _initialize.dart separately.
Especially Reflectable is useful in combination with Frog, since it allows setting up a simple ORM system.
I also agree that having an entry point is important -- especially for initializing processes/components that are vital for the server to run properly. It also makes it easier to handle errors at startup.
Currently, the only workaround is to create a top level variable as suggested in #142. The main issue with such approach that it makes handling errors difficult/impossible since the error won't appear until that variable is called.
Hi everyone! This is on our roadmap to support very soon. An initial proposal I have is to allow developers to optionally create a main.dart file which contains a run method with the following signature:
import 'dart:async';
import 'dart:io';
import 'package:dart_frog/dart_frog.dart';
FutureOr<HttpServer> run(
Handler handler,
InternetAddress ip,
int port,
) {
// This will be called on startup and the HttpServer can be configured here.
return serve(handler, ip, port);
}
Let us know what you think, thanks! 🙏
After being asked on Twitter about this proposal, I would like to add some further insight.
Another use case for a place for initialization code is error monitoring. This is often done by wrapping the entry point with runZonedGuarded and using its error callback to send error reports. This approach is used by Sentry, Datadog, et al.
Also the initialization of those error tracking SDKs needs to be done once at the startup of the server.
As far as I can tell, the approach, as outlined above, works for this use case.