|
|
@@ -3,6 +3,11 @@ using Astralis;
|
|
|
|
|
|
namespace Statum {
|
|
|
|
|
|
+ /** Configuration-time errors (e.g. a page registered without a route). */
|
|
|
+ public errordomain StatumError {
|
|
|
+ CONFIGURATION,
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Inversion module that registers the Statum runtime services and framework
|
|
|
* endpoints.
|
|
|
@@ -66,19 +71,16 @@ namespace Statum {
|
|
|
/**
|
|
|
* Binds application pages, entrypoints and resources into the container.
|
|
|
*
|
|
|
- * Usage mirrors Spry's {@link Spry.SpryConfigurator}:
|
|
|
- *
|
|
|
* ```
|
|
|
* var statum = application.configure_with<StatumConfigurator>();
|
|
|
- * statum.add_entrypoint_page<HomePage, HomeEntrypoint>(new EndpointRoute("/"));
|
|
|
- * statum.add_page<AboutPage>(new EndpointRoute("/about"));
|
|
|
+ * statum.add_page<HomePage, HomeEntrypoint>();
|
|
|
+ * statum.add_static_page<AboutPage>();
|
|
|
* statum.add_resource<LogoResource>();
|
|
|
* ```
|
|
|
*
|
|
|
- * {@link add_entrypoint_page} registers the generated {@link StatumPage}
|
|
|
- * (served at its URI) and adds the entrypoint to the {@link EntrypointRouteTable}
|
|
|
- * so `/_statum/entrypoint?uri=…` dispatches to it. The page route is supplied
|
|
|
- * explicitly (mirroring Spry) rather than read reflectively from the class.
|
|
|
+ * Each page's route is read from its generated {@link StatumPage.route}
|
|
|
+ * (set at build time from its `<pstm-uri>`); no route is passed by hand. A
|
|
|
+ * page without a `<pstm-uri>` (empty route) fails at startup.
|
|
|
*/
|
|
|
public class StatumConfigurator : Object {
|
|
|
|
|
|
@@ -87,28 +89,41 @@ namespace Statum {
|
|
|
private ActionRegistry action_registry = inject<ActionRegistry>();
|
|
|
|
|
|
/**
|
|
|
- * Registers a static page (no entrypoint) served at `route`.
|
|
|
+ * Resolves a page's route from its {@link StatumPage.route} property,
|
|
|
+ * throwing at startup when the page has no `<pstm-uri>`.
|
|
|
*/
|
|
|
- public void add_page<TPage>(EndpointRoute route) {
|
|
|
- container.register_scoped<TPage>()
|
|
|
- .as<Endpoint>()
|
|
|
- .with_metadata<EndpointRoute>(route);
|
|
|
+ private static EndpointRoute route_for<TPage>() throws Error {
|
|
|
+ var page = (StatumPage) Object.new(typeof(TPage));
|
|
|
+ var path = page.route;
|
|
|
+ if (path == null || path.length == 0) {
|
|
|
+ throw new StatumError.CONFIGURATION(@"Page %s has no <pstm-uri> (route is empty)", typeof(TPage).name());
|
|
|
+ }
|
|
|
+ return new EndpointRoute(path);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Registers a page served at `route` AND binds `TEntrypoint` to that route
|
|
|
- * in the entrypoint table (so `/_statum/entrypoint?uri=route` dispatches to
|
|
|
- * it).
|
|
|
- *
|
|
|
- * (Named distinctly from {@link add_page} because Vala does not permit
|
|
|
- * methods that overload on generic arity.)
|
|
|
+ * Registers a page AND its entrypoint. The page is served at its
|
|
|
+ * `<pstm-uri>` route, and the entrypoint is bound to that route in the
|
|
|
+ * {@link EntrypointRouteTable} so `/_statum/entrypoint?uri=…` dispatches
|
|
|
+ * to it.
|
|
|
*/
|
|
|
- public void add_entrypoint_page<TPage, TEntrypoint>(EndpointRoute route) {
|
|
|
- add_page<TPage>(route);
|
|
|
+ public void add_page<TPage, TEntrypoint>() throws Error {
|
|
|
+ var route = route_for<TPage>();
|
|
|
+ container.register_scoped<TPage>()
|
|
|
+ .as<Endpoint>()
|
|
|
+ .with_metadata<EndpointRoute>(route);
|
|
|
container.register_transient<TEntrypoint>();
|
|
|
route_table.register(route, typeof(TEntrypoint));
|
|
|
}
|
|
|
|
|
|
+ /** Registers a static page (no entrypoint) served at its `<pstm-uri>` route. */
|
|
|
+ public void add_static_page<TPage>() throws Error {
|
|
|
+ var route = route_for<TPage>();
|
|
|
+ container.register_scoped<TPage>()
|
|
|
+ .as<Endpoint>()
|
|
|
+ .with_metadata<EndpointRoute>(route);
|
|
|
+ }
|
|
|
+
|
|
|
/** Registers a {@link StatumResource} for serving from `/_statum/resource/{name}`. */
|
|
|
public void add_resource<T>() {
|
|
|
container.register_startup<T>()
|