#include "collection_registry.hpp" #include "db_gateway.hpp" #include "errors.hpp" #include "json_http.hpp" #include "server.hpp" #include namespace svapi { void registerProjectRoutes(ApiServer& s) { auto& svr = s.raw(); ServerDeps* d = &s.deps(); svr.Get("/api/v1/projects", [d](const httplib::Request& req, httplib::Response& res) { ApiKey k = requireKey(*d, req); auto all = d->db.listProjects(); nlohmann::json arr = nlohmann::json::array(); for (const auto& p : all) if (k.canAccess(p)) arr.push_back(p); sendJson(res, 200, {{"projects", arr}}); }); svr.Post("/api/v1/projects", [d](const httplib::Request& req, httplib::Response& res) { ApiKey k = requireKey(*d, req); requireAdmin(k); auto body = bodyJson(req); std::string name = body.value("name", ""); if (name.empty()) throw ApiError(ErrCode::Unprocessable, "validation", "name is required"); if (!d->db.ensureProject(name)) throw ApiError(ErrCode::Unprocessable, "bad_project", "could not create project (check name rules)"); d->registry.ensure(name); sendJson(res, 201, {{"name", name}}); }); svr.Get(R"(/api/v1/projects/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) { ApiKey k = requireKey(*d, req); std::string project = req.matches[1]; requireProjectAccess(k, project); auto all = d->db.listProjects(); if (std::find(all.begin(), all.end(), project) == all.end()) throw ApiError(ErrCode::NotFound, "not_found", "no such project"); sendJson(res, 200, {{"name", project}, {"collections", d->registry.list(project).size()}}); }); svr.Delete(R"(/api/v1/projects/([^/]+))", [d](const httplib::Request& req, httplib::Response& res) { ApiKey k = requireKey(*d, req); requireAdmin(k); std::string project = req.matches[1]; if (project == "default") throw ApiError(ErrCode::Unprocessable, "protected", "cannot drop the default project"); for (const auto& m : d->registry.list(project)) d->db.client().dropCollection(qualify(project, m.name)); d->db.client().dropCollection(qualify(project, "vectorapi_collections")); if (!d->db.dropProject(project)) throw ApiError(ErrCode::Unavailable, "db_error", "drop failed"); sendJson(res, 200, {{"deleted", project}}); }); } }