# Description of Changes <!-- Please describe your change, mention any related tickets, and so on here. --> - Bumps version to 2.2.0 # API and ABI breaking changes <!-- If this is an API or ABI breaking change, please apply the corresponding GitHub label. --> None # Expected complexity level and risk - 1 - this is just a version bump <!-- How complicated do you think these changes are? Grade on a scale from 1 to 5, where 1 is a trivial change, and 5 is a deep-reaching and complex change. This complexity rating applies not only to the complexity apparent in the diff, but also to its interactions with existing and future code. If you answered more than a 2, explain what is complex about the PR, and what other components it interacts with in potentially concerning ways. --> # Testing <!-- Describe any testing you've done, and any testing you'd like your reviewers to do, so that you're confident that all the changes work as expected! --> - [x] Version number is correct (`2.2.0`) - [x] BSL license file has been updated with the new date and version number --------- Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com> Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
SpacetimeDB C++ Module Library
The SpacetimeDB C++ Module Library provides a modern C++20 API for building SpacetimeDB modules that run inside the database as WebAssembly.
Current State
This library provides a production-ready C++ bindings for SpacetimeDB with complete type system support:
✅ Features
- Module compilation and publishing to SpacetimeDB
- All lifecycle reducers (init, client_connected, client_disconnected)
- User-defined reducers with unlimited parameters
- Table registration with constraints (PrimaryKey, Unique, AutoInc)
- Insert, update and delete operations
- All primitive types (u8-u256, i8-i256, bool, f32, f64, string)
- All special types (Identity, ConnectionId, Timestamp, TimeDuration, Uuid, Result<>)
- Vector types for all primitives and special types
- Optional types (std::optional)
- Custom struct serialization via BSATN
- Complex enum support with proper variant names
- Enhanced logging system with file/line info
🏗️ Architecture
- Hybrid Compile-Time/Runtime System: C++20 concepts for compile-time validation with preinit runtime registration
- V9 Type Registration System: Unified type registration with comprehensive error detection and circular reference prevention
- Nominal Type System: Types identified by their declared names with explicit registration via SPACETIMEDB_STRUCT macros
- Multi-Layer Validation: Static assertions, runtime constraint checking, and error module replacement strategy
See ARCHITECTURE.md for detailed technical documentation.
✅ Advanced Features Available
- Btree indexes: Full support with
FIELD_Indexmacros and optimized queries - Range queries: Complete range query system with
range_from(),range_to(),range_inclusive(), etc. - Client visibility filters: Row-level security with
SPACETIMEDB_CLIENT_VISIBILITY_FILTERmacro - Scheduled reducers:
SPACETIMEDB_SCHEDULEmacro for time-based execution - Procedures: Pure functions with return values using
SPACETIMEDB_PROCEDUREmacro - Views: Read-only query functions with
SPACETIMEDB_VIEWmacro - Field accessor patterns: Efficient indexed operations with
ctx.db[table_field]
See the working examples in modules/*-cpp/src/lib.cpp for comprehensive feature usage.
Features
- Modern C++20 API: Uses concepts, structured bindings, and other C++20 features
- BSATN Serialization: Binary Serialization And Type Notation for efficient data transfer
- Automatic Field Registration: Tables register their fields using SPACETIMEDB_STRUCT macro
- Unified Reducer System: Single macro for all reducer types with automatic lifecycle detection
- Type-Safe Database Access: Template-based table accessors with compile-time type checking
- Memory Safety: WASI shims for safe memory operations in WebAssembly environment
- Enhanced Logging: Multiple log levels with file/line information
- Namespace Support: Clean namespace qualification for enums with just 2 lines of code
Prerequisites
- Emscripten SDK (emsdk)
- CMake 3.16+
- C++20 compatible compiler
Quick Start
Option 1: Using spacetime init (Recommended)
# Create a new C++ project
spacetime init --lang cpp my-project
cd my-project
# Build and publish
spacetime build -p ./spacetimedb
spacetime publish -p ./spacetimedb my-database
Option 2: Manual Setup
For existing projects, add the following to your C++ module:
#include <spacetimedb.h>
using namespace SpacetimeDB;
// Define a table structure
struct User {
Identity identity;
std::string name;
std::string email;
};
// Register BSATN serialization
SPACETIMEDB_STRUCT(User, identity, name, email)
// Register as a table
SPACETIMEDB_TABLE(User, users, Public)
// Add constraints using FIELD_ macros
FIELD_PrimaryKey(users, identity);
FIELD_Unique(users, email);
// Define an enum with namespace qualification
SPACETIMEDB_ENUM(UserRole, Admin, Moderator, Member)
SPACETIMEDB_NAMESPACE(UserRole, "Auth") // Will be "Auth.UserRole" in client code
// User-defined reducer
SPACETIMEDB_REDUCER(add_user, ReducerContext ctx, std::string name, std::string email) {
User user{ctx.sender(), name, email}; // id will be auto-generated
ctx.db[users].insert(user);
LOG_INFO("Added user: " + name);
return Ok();
}
// Delete user by id (using primary key)
SPACETIMEDB_REDUCER(delete_user, ReducerContext ctx) {
ctx.db[users_identity].delete_by_key(ctx.sender());
return Ok();
}
// Lifecycle reducers (optional)
SPACETIMEDB_INIT(init, ReducerContext ctx) {
LOG_INFO("Module initialized");
return Ok();
}
SPACETIMEDB_CLIENT_CONNECTED(on_connect, ReducerContext ctx) {
LOG_INFO("Client connected: " + ctx.sender().to_hex_string());
return Ok();
}
SPACETIMEDB_CLIENT_DISCONNECTED(on_disconnect, ReducerContext ctx) {
LOG_INFO("Client disconnected: " + ctx.sender().to_hex_string());
return Ok();
}
// Define a view for querying data (finds the calling user)
SPACETIMEDB_VIEW(std::optional<User>, find_my_user, Public, ViewContext ctx) {
// Use indexed field to find user by their identity
return ctx.db[users_identity].find(ctx.sender());
}
// Define a procedure (pure function with return value)
SPACETIMEDB_PROCEDURE(uint32_t, add_numbers, ProcedureContext ctx, uint32_t a, uint32_t b) {
return a + b;
}
Building Modules
Build Steps
# Navigate to your module directory
cd modules/your-module
# Build the project
spacetime build -p ./spacetimedb
# Publish to SpacetimeDB
spacetime publish --bin-path ./spacetimedb/build/lib.wasm your-database-name
# Or use the directory (auto-detects build/lib.wasm)
spacetime publish ./spacetimedb your-database-name
Custom Module Source
To build a different source file:
# Build a specific test module
emcmake cmake -B build -DMODULE_SOURCE=src/test_module.cpp -DOUTPUT_NAME=test_module .
cmake --build build
# This creates build/test_module.wasm
API Reference
Macros
Table Definition
SPACETIMEDB_TABLE(Type, table_name, Public/Private)- Register a tableSPACETIMEDB_STRUCT(Type, field1, field2, ...)- Register type for BSATN serialization
Enum Definition
SPACETIMEDB_ENUM(EnumName, Value1, Value2, ...)- Define a simple enumSPACETIMEDB_ENUM(EnumName, (Variant1, Type1), (Variant2, Type2), ...)- Define an enum with payloadsSPACETIMEDB_NAMESPACE(EnumName, "Namespace")- Add namespace qualification to an enum
Reducers
SPACETIMEDB_REDUCER(name, ReducerContext ctx, ...)- User-defined reducer- Returns
ReducerResult(alias forOutcome<void>) - Use
return Ok();for success orreturn Err("message");for errors - Failed reducers (Err) trigger transaction rollback
- Returns
SPACETIMEDB_INIT(name, ReducerContext ctx)- Module initialization reducer (optional)SPACETIMEDB_CLIENT_CONNECTED(name, ReducerContext ctx)- Client connection reducer (optional)SPACETIMEDB_CLIENT_DISCONNECTED(name, ReducerContext ctx)- Client disconnection reducer (optional)
Views
SPACETIMEDB_VIEW(return_type, name, Public/Private, ViewContext ctx)- Read-only query functionSPACETIMEDB_VIEW(return_type, name, Public/Private, AnonymousViewContext ctx)- Anonymous view (no sender identity)- Note: Views currently only support the context parameter (no additional parameters yet)
Procedures
SPACETIMEDB_PROCEDURE(return_type, name, ProcedureContext ctx, ...)- Pure function that returns a value- Returns the type directly (not wrapped in Outcome)
- Can return any SpacetimeType (primitives, structs, enums, Unit, etc.)
- Database access requires explicit transactions (use
ctx.WithTx()orctx.TryWithTx()) - Always public (no access control)
Field Constraints (applied after table registration)
FIELD_PrimaryKey(table_name, field)- Primary key constraintFIELD_PrimaryKeyAutoInc(table_name, field)- Auto-incrementing primary keyFIELD_Unique(table_name, field)- Unique constraintFIELD_UniqueAutoInc(table_name, field)- Auto-incrementing unique fieldFIELD_Index(table_name, field)- Index for faster queriesFIELD_IndexAutoInc(table_name, field)- Auto-incrementing indexed fieldFIELD_AutoInc(table_name, field)- Auto-increment without other constraints
Logging
LOG_DEBUG("Debug message");
LOG_INFO("Info message");
LOG_WARN("Warning message");
LOG_ERROR("Error message");
LOG_PANIC("Fatal error message");
// With timing
{
LogStopwatch timer("Operation name");
// ... code to time ...
} // Automatically logs duration
Architecture
The library uses a sophisticated hybrid compile-time/runtime architecture:
- Compile-Time Validation (
table_with_constraints.h): C++20 concepts and static assertions for constraint validation - Module Type Registration System (
internal/module_type_registration.h): Unified type registration with error detection and circular reference prevention - Priority-Ordered Initialization (
internal/Module.cpp): preinit functions with numbered priorities ensure correct registration order - Error Detection System (
internal/Module.cpp): Multi-layer validation with error module replacement for clear diagnostics - BSATN Serialization (
bsatn/): Binary serialization system with algebraic type support for all data types - Database Interface (
database.h,table_with_constraints.h): Type-safe table access with optimized field accessors - Reducer System (
reducer_macros.h): Unified macro system for all reducer types with parameter type capture - Logging (
logger.h): Comprehensive logging with source location tracking
For detailed technical documentation, see ARCHITECTURE.md.
Note on Architecture Documentation: ARCHITECTURE.md contains references to some legacy implementation details. The current implementation is streamlined and production-ready.
Limitations
-
Type System
- Very large type combinations may exceed WASM memory limits
- Complex recursive type references require careful ordering
-
Database Operations
- Index-based operations use field accessors:
ctx.db[table_field].delete_by_key(value) - Table constraints are declared and enforced by server
- Supports insert, delete, and update operations through field accessors
- Index-based operations use field accessors:
-
Advanced Features
- Btree indexes:
FIELD_Indexcreates btree indexes for efficient range queries - Range queries: Full support for
range_from(),range_to(),range_inclusive(), etc. - Client visibility filters: Row-level security via
SPACETIMEDB_CLIENT_VISIBILITY_FILTER - Limited migrations: Only adding tables supported automatically
- SQL execution: Available via CLI (
spacetime sql) but not within modules
- Btree indexes:
Examples
See the modules/*-cpp/src/ directory for example modules:
lib.cpp- Comprehensive working module with all primitive types, tables, and reducers- Full equivalence with Rust and C# SDK test modules
- Examples of all constraint types and database operations
Contributing
This library is part of the SpacetimeDB project. Please see the main repository for contribution guidelines.