MantisBase v0.3.4
Loading...
Searching...
No Matches
Embedding MantisBase

MantisBase is designed as a lightweight C++ library that can be embedded directly into your desktop, mobile, or embedded application. This guide explains how to integrate MantisBase into your project and configure it.


Why Embed MantisBase?

  • Add full-featured local storage and REST API support to your Qt, Slint, or CLI app
  • Serve data to local UI components through HTTP or direct C++ API calls
  • Retain full control of the application lifecycle and logic
  • No separate server deployment required

Dependencies

On Linux, MantisBase depends on ZSTD and libpq for PostgreSQL support:

sudo apt-get install -y libzstd-dev
sudo apt install libpq-dev

Integration

As a Static or Shared Library

Add MantisBase as a submodule or include it in your CMake project:

add_subdirectory(mantisbase)
target_link_libraries(your_app PRIVATE mantisbase)

Basic Usage

Using Command-Line Arguments

The simplest way to embed MantisBase is using command-line arguments:

int main(int argc, char* argv[])
{
auto& app = mb::MantisBase::create(argc, argv);
return app.run();
}
static MantisBase & create(int argc, char **argv)
Create class instance given cmd args passed in.
Definition mantisbase.cpp:56
int main(const int argc, char *argv[])
MantisApp standalone entrypoint.
Definition main.cpp:16
The main application for mantisbase.

This allows your application to accept standard MantisBase CLI arguments like --port, --host, --database, etc.

Using JSON Configuration

For more control when embedding, use JSON configuration:

int main()
{
mb::json config;
config["dev"] = true;
config["serve"] = {
{"port", 8080},
{"host", "127.0.0.1"},
{"poolSize", 5}
};
config["dataDir"] = "./data";
config["publicDir"] = "./public";
config["scriptsDir"] = "./scripts";
auto& app = mb::MantisBase::create(config);
return app.run();
}
nlohmann::json json
Shorten JSON namespace.
Definition context_store.h:18

Minimal Configuration

You can also create an instance with default settings:

int main()
{
// Uses all defaults (port 7070, SQLite, etc.)
auto& app = mb::MantisBase::create();
return app.run();
}

Configuration Options

The JSON configuration supports the following options:

{
"database": "SQLITE", // or "PSQL"
"connection": "connection_string", // For PSQL: "dbname=db user=user password=pass"
"dataDir": "./data", // Directory for SQLite DB and files
"publicDir": "./public", // Static file serving directory
"scriptsDir": "./scripts", // JavaScript scripts directory
"dev": true, // Enable development mode
"serve": {
"port": 7070, // HTTP server port
"host": "127.0.0.1", // HTTP server host
"poolSize": 2 // Database connection pool size
}
}

All options are optional and will use sensible defaults if omitted.


Adding Custom Routes

You can add custom API endpoints using the router:

int main()
{
auto& app = mb::MantisBase::create();
auto& router = app.router();
// Simple GET endpoint
router.Get("/api/v2/custom", [](mb::MantisRequest& req, mb::MantisResponse& res) {
res.sendJSON(200, {{"message", "Custom endpoint"}});
});
// POST endpoint with admin authentication
router.Post("/api/v2/admin/stats", [](mb::MantisRequest& req, mb::MantisResponse& res) {
mb::json stats = {{"users", 100}, {"posts", 500}};
res.sendJSON(200, stats);
// GET endpoint with entity authentication
router.Get("/api/v2/users/profile", [](mb::MantisRequest& req, mb::MantisResponse& res) {
auto auth = req.getOr<mb::json>("auth", mb::json::object());
std::string userId = auth["id"];
// ... fetch and return user profile
res.sendJSON(200, {{"user_id", userId}});
}, {mb::requireEntityAuth("users")});
return app.run();
}
A wrapper class around httplib::Request offering a consistent API and allowing for easy wrapper metho...
Definition http.h:42
T & getOr(const std::string &key, T default_value)
Get value from context store or return default.
Definition http.h:288
Wrapper around httplib::Response for consistent API.
Definition http.h:318
void sendJSON(int statusCode=200, const json &data=json::object()) const
Send JSON response.
Definition http_response.cpp:145
Middleware functions for request processing.
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireAdminAuth()
Require admin authentication.
Definition middlewares.cpp:299
std::function< HandlerResponse(MantisRequest &, MantisResponse &)> requireEntityAuth(const std::string &entity_name)
Require entity-specific authentication.
Definition middlewares.cpp:381

Accessing Database

You can access the database directly for custom operations:

#include <soci/soci.h>
int main()
{
auto& app = mb::MantisBase::create();
// Get a database session
auto sql = app.db().session();
// Execute queries
soci::row row;
*sql << "SELECT * FROM users WHERE id = :id",
soci::use("user123"),
soci::into(row);
if (sql->got_data()) {
// Process row data
}
return app.run();
}

Working with Entities

You can interact with entities programmatically:

int main()
{
auto& app = mb::MantisBase::create();
// Get an entity
auto users = app.entity("users");
// Create a record
mb::json newUser = {
{"name", "John Doe"},
{"email", "john@example.com"}
};
auto created = users.create(newUser);
// List records
auto allUsers = users.list();
// Read a record
if (auto user = users.read("user123"); user.has_value()) {
// Process user data
}
// Update a record
mb::json updates = {{"name", "Jane Doe"}};
auto updated = users.update("user123", updates);
// Delete a record
users.remove("user123");
return app.run();
}

Project Structure

A typical embedded project structure:

your-app/
├── main.cpp
├── CMakeLists.txt
├── data/ # SQLite database and files (created automatically)
├── public/ # Static assets (optional)
├── scripts/ # JavaScript extensions (optional)
└── mantisbase/ # MantisBase submodule

Using as a Submodule

Add MantisBase as a git submodule:

git submodule add https://github.com/allankoechke/mantisbase.git
git submodule update --init --recursive

Then include it in your CMakeLists.txt:

add_subdirectory(mantisbase)
target_link_libraries(your_app PRIVATE mantisbase)

Testing Embedded APIs

Once your app is running, test the APIs:

# Test entity endpoints
curl http://localhost:7070/api/v1/entities/users
# Test custom endpoints
curl http://localhost:7070/api/v1/custom
# Test with authentication
curl -H "Authorization: Bearer <token>" \
http://localhost:7070/api/v1/entities/posts

Notes

  • MantisBase APIs respect all access rules and authentication even in embedded mode
  • The run() method is blocking - use a separate thread if you need non-blocking behavior
  • All entity endpoints follow the pattern /api/v1/entities/<entity_name>
  • Authentication endpoints are at /api/v1/auth/*
  • Schema management endpoints are at /api/v1/schemas/* (admin only)

Complete Example

int main()
{
// Configure using JSON
mb::json config;
config["dev"] = true;
config["serve"] = {{"port", 8080}};
auto& app = mb::MantisBase::create(config);
auto& router = app.router();
// Add custom route
router.Get("/api/v1/hello", [](mb::MantisRequest& req, mb::MantisResponse& res) {
res.sendJSON(200, {{"message", "Hello from embedded MantisBase!"}});
});
// Start server (blocking)
return app.run();
}

Summary

By embedding MantisBase, you gain powerful backend features including database storage, authentication, and REST APIs without requiring a separate server deployment. The library integrates seamlessly into your C++ application with minimal configuration.