#include "App.hpp" #include "../fw/Http.hpp" #include "../fw/Router.hpp" #include "../fw/Validate.hpp" namespace molo::example::app { namespace { fw::OrmDb* pick_db(Services& services, const fw::Request& req) { if (fw::parse_backend(req.query_or("backend", "sqlite")) == fw::OrmBackend::Postgres) return services.postgres.get(); return services.sqlite.get(); } std::string rows_json(const std::vector& rows) { std::string out = "["; bool first = true; for (const auto& r : rows) { if (!first) out += ","; first = false; out += "{"; bool fc = true; for (const auto& [k, v] : r.columns) { if (!fc) out += ","; fc = false; out += "\"" + fw::json_escape(k) + "\":\"" + fw::json_escape(v) + "\""; } out += "}"; } return out + "]"; } } // namespace void register_data_demo(fw::Router& router, Services& services) { fw::OrmDb* sqlite = services.sqlite.get(); fw::OrmDb* postgres = services.postgres.get(); fw::KvStore* kv = services.kv.get(); fw::Cache* cache = services.cache.get(); fw::Pubsub* pubsub = services.pubsub.get(); router.get("/orm/users", "orm-users", [sqlite, postgres](fw::Request req) { fw::OrmDb* db = req.query_or("backend", "sqlite") == "postgres" ? postgres : sqlite; fw::OrmResult res = db->select_all("users"); std::string body = "{\"backend\":\"" + fw::backend_name(db->backend()) + "\",\"healed\":" + (res.healed ? "true" : "false") + ",\"note\":\"" + fw::json_escape(res.healed_note) + "\",\"rows\":" + rows_json(res.rows) + "}"; return fw::JsonResponse(body, 200); }); router.post("/orm/users", "orm-users-post", [sqlite, postgres](fw::Request req) { fw::OrmDb* db = req.query_or("backend", "sqlite") == "postgres" ? postgres : sqlite; auto input = fw::parse_json_object_flat(req.body); if (input.empty()) input = fw::parse_form(req.body); fw::OrmResult res = db->insert("users", input); if (!res.ok) return fw::JsonResponse("{\"error\":\"store full\"}", 500); std::string body = "{\"backend\":\"" + fw::backend_name(db->backend()) + "\",\"healed\":" + (res.healed ? "true" : "false") + ",\"note\":\"" + fw::json_escape(res.healed_note) + "\",\"rows\":" + rows_json(res.rows) + "}"; return fw::JsonResponse(body, 201); }); router.get("/kv/items", "kv-get", [kv](fw::Request req) { std::string key = req.query_or("key", ""); if (key.empty()) return fw::JsonResponse("{\"error\":\"key required\"}", 400); std::string value; if (!kv->get(key, value)) return fw::JsonResponse("{\"error\":\"not found\"}", 404); return fw::JsonResponse("{\"key\":\"" + fw::json_escape(key) + "\",\"value\":\"" + fw::json_escape(value) + "\"}", 200); }); router.post("/kv/items", "kv-set", [kv](fw::Request req) { auto input = fw::parse_json_object_flat(req.body); if (input.empty()) input = fw::parse_form(req.body); if (!input.count("key") || !input.count("value")) return fw::JsonResponse("{\"error\":\"key and value required\"}", 400); if (!kv->set(input["key"], input["value"])) return fw::JsonResponse("{\"error\":\"store full\"}", 500); return fw::JsonResponse("{\"stored\":\"" + fw::json_escape(input["key"]) + "\"}", 201); }); router.get("/cache/lookup", "cache", [cache](fw::Request req) { std::string key = req.query_or("key", "demo"); std::string value; bool hit = cache->lookup(key, value, 1000); if (!hit) { value = "computed-for-" + key; cache->put(key, value, 60, 1000); return fw::JsonResponse( "{\"key\":\"" + fw::json_escape(key) + "\",\"hit\":false,\"value\":\"" + fw::json_escape(value) + "\"}", 200); } return fw::JsonResponse( "{\"key\":\"" + fw::json_escape(key) + "\",\"hit\":true,\"value\":\"" + fw::json_escape(value) + "\"}", 200); }); router.post("/pubsub/publish", "pubsub", [pubsub](fw::Request req) { auto input = fw::parse_json_object_flat(req.body); if (input.empty()) input = fw::parse_form(req.body); std::string topic = input.count("topic") ? input["topic"] : "news"; std::string message = input.count("message") ? input["message"] : "hello"; std::size_t delivered = pubsub->publish(topic, message); return fw::JsonResponse("{\"topic\":\"" + fw::json_escape(topic) + "\",\"delivered\":" + std::to_string(delivered) + "}", 200); }); router.get("/pubsub/publish", "pubsub-history", [pubsub](fw::Request req) { std::string topic = req.query_or("topic", "news"); auto hist = pubsub->history(topic); std::string body = "{\"topic\":\"" + fw::json_escape(topic) + "\",\"history\":["; bool first = true; for (const auto& m : hist) { if (!first) body += ","; first = false; body += "\"" + fw::json_escape(m) + "\""; } return fw::JsonResponse(body + "]}", 200); }); (void)pick_db; } } // namespace molo::example::app