Main.vala 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. using Astralis;
  2. using Invercargill.DataStructures;
  3. using Inversion;
  4. using Statum;
  5. using Example;
  6. void main(string[] args) {
  7. int port = args.length > 1 ? int.parse(args[1]) : 8080;
  8. try {
  9. var application = new WebApplication(port);
  10. application.use_compression();
  11. application.add_module<StatumModule>();
  12. var statum = application.configure_with<StatumConfigurator>();
  13. // HomePage is generated from home.html; HomeEntrypoint hydrates it and
  14. // embeds the login/bump action references. Routes come from each page's
  15. // <pstm-uri>; actions are auto-mapped to GUID endpoints; the Statum
  16. // client scripts are embedded by default.
  17. statum.add_page<HomePage, HomeEntrypoint>();
  18. statum.add_page<DashboardPage, DashboardEntrypoint>();
  19. statum.action<LoginAction>();
  20. statum.action<LogoutAction>();
  21. statum.action<BumpCounterAction>();
  22. statum.action<UpdateAnnouncementAction>();
  23. statum.add_resource<StylesResource>();
  24. // Register a global broadcast slot (deterministic key "global:announcement").
  25. var announcement = new AnnouncementPublic();
  26. announcement.text = "Welcome to the Statum demo!";
  27. statum.global<AnnouncementPublic>("announcement", announcement);
  28. // Register a topic + modifier: when triggered, derives a short preview
  29. // from the current announcement and pushes it to watching clients.
  30. statum.topic<AnnouncementTopic>("announcement");
  31. statum.topic_modifier<AnnouncementPreviewModifier, AnnouncementPreview>("announcement");
  32. // Background timer: cycle the announcement every 10 seconds. Every
  33. // subscribed tab receives the update via the SSE push — open two tabs
  34. // side by side to see the broadcast in action.
  35. string[] messages = {
  36. "Welcome to the Statum demo!",
  37. "Slots are client-carried and signed.",
  38. "Try logging in as \"admin\".",
  39. "Global slots use deterministic keys for broadcast.",
  40. "The counter uses typed models with action references."
  41. };
  42. int msg_index = 0;
  43. Timeout.add_seconds(10, () => {
  44. msg_index = (msg_index + 1) % messages.length;
  45. try {
  46. var model = new AnnouncementPublic();
  47. model.text = messages[msg_index];
  48. var state = new State() {
  49. type_name = "announcement",
  50. public_data = GObjectMapping.to_properties(model),
  51. private_data = new PropertyDictionary()
  52. };
  53. statum.state_service.update_global.begin("announcement", state);
  54. // Trigger the topic so derived "preview" slots update too.
  55. statum.topic_registry.trigger.begin("announcement:latest", () => {
  56. stderr.printf("[topic] trigger completed\n");
  57. });
  58. } catch (GLib.Error e) {
  59. warning("Failed to update announcement: %s", e.message);
  60. }
  61. return true;
  62. });
  63. application.run();
  64. } catch (Error e) {
  65. printerr("Error: %s\n", e.message);
  66. Process.exit(1);
  67. }
  68. }