Rix is the official package layer for Vix.cpp Browse packages
Skip to content

Facade API ​

This page documents the public Rix facade API.

The facade is provided by:

cpp
#include <rix.hpp>

It exposes one public object:

cpp
rix

and mounts Rix packages as members:

cpp
rix.auth
rix.csv
rix.debug
rix.pdf

Use this API for most Rix application code and documentation examples.

Package ​

The facade package is:

txt
rix/rix

Install it with:

bash
vix add rix/rix
vix install

In vix.app, keep it in deps:

txt
deps = [
  "rix/rix",
]

Use:

cpp
#include <rix.hpp>

This header exposes the unified Rix facade.

Object ​

The public facade object is:

cpp
rix

Example:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello from Rix");
  return 0;
}

Mounted modules ​

The facade can expose these modules:

cpp
rix.auth
rix.csv
rix.debug
rix.pdf

Each module belongs to a Rix package.

Facade memberPackagePurpose
rix.authrix/authAuthentication, passwords, sessions, tokens
rix.csvrix/csvCSV parsing and writing
rix.debugrix/debugPrinting, formatting, inspection helpers
rix.pdfrix/pdfPDF document generation

Basic usage ​

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello from Rix");

  const auto table = rix.csv.parse(
      "name,language\n"
      "Ada,C++\n");

  rix.debug.print("rows:", table.size());

  auto doc = rix.pdf.document();

  return 0;
}

Facade naming model ​

The facade follows the Rix package model:

txt
Registry package  -> rix/name
Header            -> <rix/name.hpp>
Facade access     -> rix.name
Namespace         -> rixlib::name

Examples:

txt
rix/auth   -> rix.auth
rix/csv    -> rix.csv
rix/debug  -> rix.debug
rix/pdf    -> rix.pdf

The facade package itself is:

txt
rix/rix -> <rix.hpp> -> rix.*

Default behavior ​

If no feature macro is defined, the facade enables all mounted modules.

This means:

cpp
#include <rix.hpp>

gives access to:

cpp
rix.auth
rix.csv
rix.debug
rix.pdf

This keeps simple examples short.

Feature macros ​

You can limit the facade with feature macros.

If at least one RIX_ENABLE_* macro is defined, only selected modules are mounted.

Example:

cpp
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  auto doc = rix.pdf.document();

  rix.debug.print("PDF module loaded");

  return 0;
}

Available macros include:

txt
RIX_ENABLE_AUTH
RIX_ENABLE_CSV
RIX_ENABLE_DEBUG
RIX_ENABLE_PDF

Enable only auth ​

cpp
#define RIX_ENABLE_AUTH
#include <rix.hpp>

int main()
{
  auto auth = rix.auth.memory();

  auto registered = auth.register_user({
      "ada@example.com",
      "correct-password"});

  return registered.ok() ? 0 : 1;
}

Enable only CSV ​

cpp
#define RIX_ENABLE_CSV
#include <rix.hpp>

int main()
{
  const auto table = rix.csv.parse(
      "name\n"
      "Ada\n");

  return table.empty() ? 1 : 0;
}

Enable CSV and debug ​

cpp
#define RIX_ENABLE_CSV
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  const auto table = rix.csv.parse(
      "name,language\n"
      "Ada,C++\n");

  rix.debug.print("rows:", table.size());

  return 0;
}

Enable only PDF ​

cpp
#define RIX_ENABLE_PDF
#include <rix.hpp>

int main()
{
  auto doc = rix.pdf.document();

  auto &page = doc.add_page();

  page.text(
      page.x_left(),
      page.y_top(),
      "Hello from rix.pdf");

  auto saved = rix.pdf.save(doc, "hello.pdf");

  return saved.ok() ? 0 : 1;
}

Enable PDF and debug ​

cpp
#define RIX_ENABLE_PDF
#define RIX_ENABLE_DEBUG
#include <rix.hpp>

int main()
{
  auto doc = rix.pdf.document();

  auto &page = doc.add_page();

  page.text(
      page.x_left(),
      page.y_top(),
      "Hello from rix.pdf");

  auto saved = rix.pdf.save(doc, "hello.pdf");

  if (saved.failed())
  {
    rix.debug.eprint(
        "pdf error:",
        rix.pdf.error.to_string(saved.error()),
        saved.error().message());

    return 1;
  }

  rix.debug.print("created:", "hello.pdf");
  return 0;
}

rix.auth ​

rix.auth exposes the auth package API.

Common helpers:

cpp
rix.auth.memory()
rix.auth.password.hash(...)
rix.auth.password.verify(...)
rix.auth.password.accepts(...)
rix.auth.config.development()
rix.auth.config.production()
rix.auth.error.to_string(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  auto auth = rix.auth.memory();

  auto registered = auth.register_user({
      "ada@example.com",
      "correct-password"});

  if (registered.failed())
  {
    rix.debug.eprint(
        "auth error:",
        rix.auth.error.to_string(registered.error()),
        registered.error().message());

    return 1;
  }

  rix.debug.print("registered:", registered.value().email());
  return 0;
}

rix.csv ​

rix.csv exposes the CSV package API.

Common helpers:

cpp
rix.csv.parse(...)
rix.csv.write(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  const auto table = rix.csv.parse(
      "name,language\n"
      "Ada,C++\n"
      "Gaspard,Vix\n");

  rix.debug.print("rows:", table.size());

  for (const auto &row : table)
  {
    rix.debug.inspect(row);
  }

  return 0;
}

rix.debug ​

rix.debug exposes the debug package API.

Common helpers:

cpp
rix.debug.print(...)
rix.debug.eprint(...)
rix.debug.dprint(...)
rix.debug.sprint(...)
rix.debug.format(...)
rix.debug.format.to(...)
rix.debug.format.append(...)
rix.debug.inspect(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello", "Rix");

  const auto message = rix.debug.format(
      "Package: {}",
      "rix/rix");

  rix.debug.print(message);
  rix.debug.inspect(message);

  return 0;
}

rix.debug is useful for examples, small tools, formatting, and inspection.

For real Vix application logs, prefer the Vix logging system.

rix.pdf ​

rix.pdf exposes the PDF package API.

Common helpers:

cpp
rix.pdf.document()
rix.pdf.save(...)
rix.pdf.write(...)
rix.pdf.make_text(...)
rix.pdf.image.load_jpeg(...)
rix.pdf.error.to_string(...)

Example:

cpp
#include <rix.hpp>

int main()
{
  auto doc = rix.pdf.document();

  auto &page = doc.add_page();

  page.text(
      page.x_left(),
      page.y_top(),
      "Hello from rix.pdf");

  auto saved = rix.pdf.save(doc, "hello.pdf");

  if (saved.failed())
  {
    rix.debug.eprint(
        "pdf error:",
        rix.pdf.error.to_string(saved.error()),
        saved.error().message());

    return 1;
  }

  rix.debug.print("created:", "hello.pdf");
  return 0;
}

Result handling ​

Some Rix APIs return explicit results or statuses.

Check them before reading values.

Wrong:

cpp
auto bytes = rix.pdf.write(doc);

rix.debug.print(bytes.value().size());

Correct:

cpp
auto bytes = rix.pdf.write(doc);

if (bytes.failed())
{
  rix.debug.eprint(
      "pdf error:",
      rix.pdf.error.to_string(bytes.error()),
      bytes.error().message());

  return 1;
}

rix.debug.print(bytes.value().size());

Status handling ​

Operations such as saving a PDF can return a status:

cpp
auto saved = rix.pdf.save(doc, "hello.pdf");

if (saved.failed())
{
  rix.debug.eprint(
      "pdf error:",
      rix.pdf.error.to_string(saved.error()),
      saved.error().message());

  return 1;
}

Use:

cpp
status.ok()
status.failed()
status.error()

Value result handling ​

Operations that return a value use result objects.

Example:

cpp
auto bytes = rix.pdf.write(doc);

Use:

cpp
result.ok()
result.failed()
result.value()
result.error()

Only call value() after checking success.

Error helpers ​

Packages with domain errors expose error helpers.

Examples:

cpp
rix.auth.error.to_string(error)
rix.auth.error.is(error, code)

rix.pdf.error.to_string(error)
rix.pdf.error.is(error, code)

Use to_string for stable error code text.

Use message() for human-readable details.

Example:

cpp
const auto &error = saved.error();

rix.debug.eprint(
    "pdf error:",
    rix.pdf.error.to_string(error),
    error.message());

Use the facade in a Vix project ​

Create a Vix app:

bash
vix new rix-facade-app --app
cd rix-facade-app

Add Rix:

bash
vix add rix/rix
vix install

Make sure vix.app contains:

txt
deps = [
  "rix/rix",
]

Use in src/main.cpp:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello from Rix");
  return 0;
}

Build and run:

bash
vix build
vix run

Minimal vix.app ​

txt
name = "rix-facade-app"
type = "executable"
standard = "c++20"
output_dir = "bin"

sources = [
  "src/main.cpp",
]

include_dirs = [
  "include",
  "src",
]

deps = [
  "rix/rix",
]

packages = [
  "vix",
]

links = [
  "vix::vix",
]

The important part is:

txt
deps = [
  "rix/rix",
]

Use the facade from a single file ​

Create a file:

bash
mkdir -p ~/rix-facade-example
cd ~/rix-facade-example
touch main.cpp

Add:

cpp
#include <rix.hpp>

int main()
{
  rix.debug.print("Hello from Rix");
  return 0;
}

Run:

bash
vix run main.cpp

If Rix is not available globally:

bash
vix install -g rix/rix
vix run main.cpp

Facade vs independent package ​

Facade usage:

cpp
#include <rix.hpp>

rix.pdf.document()

Independent package usage:

cpp
#include <rix/pdf.hpp>

auto pdf = rixlib::pdf::module();
pdf.document()

Use the facade for most application code.

Use independent packages when a project only needs one package and does not need rix.*.

Independent PDF example ​

cpp
#include <rix/pdf.hpp>

int main()
{
  auto pdf = rixlib::pdf::module();

  auto doc = pdf.document();

  auto &page = doc.add_page();

  page.text(
      page.x_left(),
      page.y_top(),
      "Hello from independent rix/pdf");

  auto saved = pdf.save(doc, "independent.pdf");

  return saved.ok() ? 0 : 1;
}

Install independent PDF with:

bash
vix add rix/pdf
vix install

and keep:

txt
deps = [
  "rix/pdf",
]

Do not put Rix in packages ​

Wrong:

txt
packages = [
  "rix/rix",
]

Correct:

txt
deps = [
  "rix/rix",
]

For independent packages:

txt
deps = [
  "rix/pdf",
]

deps is for Vix Registry dependencies.

packages is for CMake package discovery.

Common mistakes ​

Forgetting to install the facade package ​

If your code uses:

cpp
#include <rix.hpp>

then install:

bash
vix add rix/rix
vix install

Installing one package but using the facade ​

If you install only:

bash
vix add rix/pdf

then use:

cpp
#include <rix/pdf.hpp>

If you want:

cpp
#include <rix.hpp>

install:

bash
vix add rix/rix

Calling value() before checking success ​

Wrong:

cpp
auto login = auth.login({
    "ada@example.com",
    "correct-password"});

rix.debug.print(login.value().user.email());

Correct:

cpp
auto login = auth.login({
    "ada@example.com",
    "correct-password"});

if (login.failed())
{
  return 1;
}

rix.debug.print(login.value().user.email());

Using rix.debug as production logging ​

rix.debug is useful for examples and small tools.

For real Vix application logs, prefer the Vix logging system.

Mixing facade and independent usage ​

Avoid this without a clear reason:

cpp
#include <rix.hpp>
#include <rix/pdf.hpp>

Use one style per file.

Facade:

cpp
#include <rix.hpp>

Independent:

cpp
#include <rix/pdf.hpp>

Forgetting feature macro behavior ​

If no feature macro is defined:

cpp
#include <rix.hpp>

all mounted modules are available.

If one or more feature macros are defined, only selected modules are mounted.

Example:

cpp
#define RIX_ENABLE_PDF
#include <rix.hpp>

Only rix.pdf is expected to be available.

What you should remember ​

Use the facade package:

bash
vix add rix/rix
vix install

Keep it in deps:

txt
deps = [
  "rix/rix",
]

Include:

cpp
#include <rix.hpp>

Use:

cpp
rix.auth
rix.csv
rix.debug
rix.pdf

Check results before calling value().

Use feature macros when you want a smaller facade.

For independent package usage, include the package header directly.

Next step ​

Continue with the auth API.

Next: Auth API

Released under the MIT License.