Przejdź do treści
Biblioteka skilli
Programowanie · Nauka i wyjaśnianie

cpp-server

/cpp-server

Dostarcza referencję SDK SpacetimeDB dla modułów serwerowych w C++: tabel, reducerów i logiki modułu.

Repozytorium
spacetimedb ↗
Licencja
AGPL-3.0
Ostatnia zmiana repozytorium
12.11.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
1
Skrypty
0
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 12.11.2026, bez odwołań do wycofanych modeli i API.

Licencja

AGPL-3.0, copyleft: przeróbki udostępniane innym muszą mieć tę samą licencję.

Co robi i kiedy

Dostarcza referencję SDK SpacetimeDB dla modułów serwerowych w C++: tabel, reducerów i logiki modułu.

Oryginalny opis (EN)

SpacetimeDB C++ server module SDK reference. Use when writing tables, reducers, or module logic in C++.

Jak działa

  1. Imports
  2. Tables
  3. Column Types
  4. Indexes
  5. Reducers
  6. DB Operations
  7. Lifecycle Hooks
  8. Authentication & Timestamps
  9. Reducer Context
  10. HTTP Handlers
Sekcje z nagłówków SKILL.md, w oryginale · 315 linii, 978 słów
Podgląd SKILL.md
---
name: cpp-server
description: SpacetimeDB C++ server module SDK reference. Use when writing tables, reducers, or module logic in C++.
license: Apache-2.0
metadata:
  author: clockworklabs
  version: "2.0"
  role: server
  language: cpp
  cursor_globs: "**/*.cpp,**/*.h,**/*.hpp"
  cursor_always_apply: true
---

# SpacetimeDB C++ SDK Reference

## Imports

```cpp
#include <spacetimedb.h>
using namespace SpacetimeDB;
```

## Tables

Register structs with macros, then declare as tables:

```cpp
struct Entity {
    uint64_t id;
    Identity owner;
    std::string name;
    bool active;
};
SPACETIMEDB_STRUCT(Entity, id, owner, name, active)
SPACETIMEDB_TABLE(Entity, entity, Public)
FIELD_PrimaryKeyAutoInc(entity, id)
FIELD_Index(entity, name)
```

Options:
- `SPACETIMEDB_TABLE(Type, accessor, Public|Private)`: regular table
- `SPACETIMEDB_TABLE(Type, accessor, Public|Private, true)`: event table

Field constraints:
- `FIELD_PrimaryKey(accessor, field)`: primary key
- `FIELD_PrimaryKeyAutoInc(accessor, field)`: primary key with auto-increment (use 0 on insert)
- `FIELD_Unique(accessor, field)`: unique constraint
- `FIELD_Index(accessor, field)`: btree index (enables `.filter()`)

## Column Types

| C++ type | Notes |
|----------|-------|
| `uint8_t` / `uint16_t` / `uint32_t` / `uint64_t` | unsigned integers |
| `SpacetimeDB::u128` / `SpacetimeDB::u256` | large unsigned integers |
| `int8_t` / `int16_t` / `int32_t` / `int64_t` | signed integers |
| `SpacetimeDB::i128` / `SpacetimeDB::i256` | large signed integers |
| `float` / `double` | floats |
| `bool` | boolean |
| `std::string` | text |
| `std::vector<T>` | list/array |
| `std::optional<T>` | nullable column |
| `Identity` | user identity |
| `ConnectionId` | connection handle |
| `Timestamp` | server timestamp (microseconds since epoch) |
| `TimeDuration` | duration in microseconds |
| `ScheduleAt` | for scheduled tables |

## Indexes

```cpp
// Single-column:
FIELD_Index(entity, name)
// Access: ctx.db[entity_name].filter("Alice")

// Multi-column:
FIELD_NamedMultiColumnIndex(score, by_player_and_level, player_id, level)
```

Range queries (included by `spacetimedb.h`; include `<spacetimedb/range_queries.h>` directly only when not using the umbrella header):
```cpp
ctx.db[user_age].filter(range_inclusive(uint8_t(18), uint8_t(65)));
ctx.db[user_age].filter(range_from(uint8_t(18)));
```

## Reducers

All reducers return `ReducerResult`. Use `Ok()` or `Err(message)`:

```cpp
SPACETIMEDB_REDUCER(create_entity, ReducerContext ctx, std::string name) {
    if (name.empty()) {
        return Err("Name cannot be empty");
    }
    ctx.db[entity].insert(Entity{0, ctx.sender(), name, true});
    return Ok();
}
```

## DB Operations

```cpp
ctx.db[entity].insert(Entity{0, owner, "Sample", true});     // Insert (0 for autoInc)
ctx.db[entity_id].find(entityId);                             // Find by PK → std::optional
ctx.db[entity_identity].find(ctx.sender());                   // Find by unique column
ctx.db[entity_name].filter("Alice");                          // Filter by index → iterable
ctx.db[entity];                                               // All rows → iterable (range-for)
ctx.db[entity].count();                                       // Count rows

// Update: find, mutate, update
if (auto e = ctx.db[entity_id].find(entityId)) {
    e->name = "New Name";
    ctx.db[entity_id].update(*e);
}

// Delete by primary key
ctx.db[entity_id].delete_by_key(entityId);
```

Note: Bracket notation `ctx.db[accessor]` is used for all table access. The accessor name comes from `SPACETIMEDB_TABLE` and `FIELD_*` macros.

## Lifecycle Hooks

```cpp
SPACETIMEDB_INIT(init, ReducerContext ctx) {
    LOG_INFO("Database initializing...");
    return Ok();
}

SPACETIMEDB_CLIENT_CONNECTED(on_connect, ReducerContext ctx) {
    LOG_INFO("Connected: " + ctx.sender().to_string());
    return Ok();
}

SPACETIMEDB_CLIENT_DISCONNECTED(on_disconnect, ReducerContext ctx) {
    LOG_INFO("Disconnected: " + ctx.sender().to_string());
    return Ok();
}
```

## Authentication & Timestamps

```cpp
// Auth: ctx.sender() is the caller's Identity
if (row.owner != ctx.sender()) {
    return Err("unauthorized");
}

// Server timestamps
ctx.db[item].insert(Item{0, ctx.sender(), ctx.timestamp});

// Timestamp arithmetic
Timestamp later = ctx.timestamp + TimeDuration::from_seconds(10);
```

## Reducer Context

`ReducerContext` is the single source of sender identity, deterministic time, and deterministic randomness inside a reducer. Always go through `ctx` for these. Standard library clocks and random sources are not available in modules.

```cpp
ctx.db[table]          // Table access (bracket notation)
ctx.sender()           // Caller's Identity
ctx.timestamp          // Invocation timestamp
ctx.connection_id      // std::optional<ConnectionId>
ctx.identity()         // Module's own identity
ctx.rng()              // Deterministic RNG
ctx.sender_auth()      // AuthCtx with JWT claims
```

## HTTP Handlers

HTTP handlers are unstable. Define `SPACETIMEDB_UNSTABLE_FEATURES` for both the module and the bindings, as the commented lines in the template's `CMakeLists.txt` do:

```cmake
target_compile_definitions(lib PRIVATE SPACETIMEDB_UNSTABLE_FEATURES)
target_compile_definitions(spacetimedb_cpp_library PUBLIC SPACETIMEDB_UNSTABLE_FEATURES)
```

A handler takes `HandlerContext` and `HttpRequest` by value and returns `HttpResponse`. One router per module binds handlers to paths:

```cpp
SPACETIMEDB_HTTP_HANDLER(health, HandlerContext ctx, HttpRequest request) {
    return HttpResponse{
        200,
        HttpVersion::Http11,
        { HttpHeader{"content-type", "text/plain; charset=utf-8"} },
        HttpBody::from_string("ok"),
    };
}

SPACETIMEDB_HTTP_ROUTER(router) {
    return Router().get("/health", health);
}
```

`HandlerContext` has no `db`; open a transaction with `ctx.with_tx([&](TxContext& tx) { ... })` and use `tx.db[table]` inside it. `HttpRequest` exposes `uri`, `method`, `headers` and `body`. Routers support `get`, `head`, `options`, `put`, `delete_`, `post`, `patch`, `any`, `nest` and `merge`.

## Environment Variables

Declare the environment in a dedicated `environment.h`:

```cpp
#pragma once
#include <spacetimedb/environment_declaration.h>

SPACETIMEDB_ENV(
    (API_KEY, std::string),
    (MODE, std::string, ("development", "production")),
    (LOG_LEVEL, std::optional<std::string>)
)
// In a root entry point: ctx.env.API_KEY(), ctx.env.LOG_LEVEL()
// String-key lookup: ctx.env.get("LOG_LEVEL")
```

Set `SPACETIMEDB_ENV_HEADER` to this header's full path in CMake **before** adding the SpacetimeDB module library directory, so the library and module see the same context declaration. Including it manually in only one source file is insufficient. `std::string` is required; `std::optional<std::string>` permits absence. The optional third tuple element restricts allowed strings.

See the concepts skill for shared environment and secret-handling rules.

## Scheduled Tables

```cpp
struct Reminder {
    uint64_t scheduled_id;
    ScheduleAt scheduled_at;
    std::string message;
};
SPACETIMEDB_STRUCT(Reminder, scheduled_id, scheduled_at, message)
SPACETIMEDB_TABLE(Reminder, reminder, Public)
FIELD_PrimaryKeyAutoInc(reminder, scheduled_id)
SPACETIMEDB_SCHEDULE(reminder, 1, send_reminder)  // 1 = scheduled_at field index (0-based)

SPACETIMEDB_REDUCER(send_reminder, ReducerContext ctx, Reminder arg) {
    LOG_INFO("Reminder: " + arg.message);
    return Ok();
}

// One-time: fires at a specific time
ctx.db[reminder].insert(Reminder{0, ScheduleAt::time(ctx.timestamp + TimeDuration::from_seconds(10)), "msg"});
// Repeating: fires on an interval
ctx.db[reminder].insert(Reminder{0, ScheduleAt::interval(TimeDuration::from_seconds(5)), "msg"});
```

## Custom Types

```cpp
// Struct (product type):
struct Point { float x; float y; };
SPACETIMEDB_STRUCT(Point, x, y)

// Enum (sum type):
SPACETIMEDB_UNIT_TYPE(Active)
SPACETIMEDB_UNIT_TYPE(Inactive)
SPACETIMEDB_ENUM(PlayerStatus,
    (Active, Active),
    (Inactive, Inactive),
    (Suspended, std::string)
)
```

## Logging

```cpp
LOG_INFO("Message: " + msg);
LOG_WARN("Warning: " + msg);
LOG_ERROR("Error: " + msg);
LOG_DEBUG("Debug: " + msg);
LOG_PANIC("Fatal: " + msg);   // terminates reducer
```

## Complete Example

```cpp
#include <spacetimedb.h>
using namespace SpacetimeDB;

struct Entity {
    Identity identity;
    std::string name;
    bool active;
};
SPACETIMEDB_STRUCT(Entity, identity, name, active)
SPACETIMEDB_TABLE(Entity, entity, Public)
FIELD_PrimaryKey(entity, identity)

struct Record {
    uint64_t id;
    Identity owner;
    uint32_t value;
    Timestamp created_at;
};
SPACETIMEDB_STRUCT(Record, id, owner, value, created_at)
SPACETIMEDB_TABLE(Record, record, Public)
FIELD_PrimaryKeyAutoInc(record, id)

SPACETIMEDB_CLIENT_CONNECTED(on_connect, ReducerContext ctx) {
    if (auto existing = ctx.db[entity_identity].find(ctx.sender())) {
        existing->active = true;
        ctx.db[entity_identity].update(*existing);
    }
    return Ok();
}

SPACETIMEDB_CLIENT_DISCONNECTED(on_disconnect, ReducerContext ctx) {
    if (auto existing = ctx.db[entity_identity].find(ctx.sender())) {
        existing->active = false;
        ctx.db[entity_identity].update(*existing);
    }
    return Ok();
}

SPACETIMEDB_REDUCER(create_entity, ReducerContext ctx, std::string name) {
    if (ctx.db[entity_identity].find(ctx.sender())) {
        return Err("already exists");
    }
    ctx.db[entity].insert(Entity{ctx.sender(), name, true});
    return Ok();
}

SPACETIMEDB_REDUCER(add_record, ReducerContext ctx, uint32_t value) {
    if (!ctx.db[entity_identity].find(ctx.sender())) {
        return Err("not found");
    }
    ctx.db[record].insert(Record{0, ctx.sender(), value, ctx.timestamp});
    return Ok();
}
```

Wersje

RepozytoriumWynikLicencja
Ta strona · clockworklabs/spacetimedb100AGPL-3.0
clockworklabs/spacetimedb100AGPL-3.0

Migawka bazy z 13.11.2026 · wersja paczki 29ecbd24e5e2 (skrót SHA-256 całej paczki)

Pobrania w ostatnich 30 dniach: 0 · ranking

Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.

Podobne skille

  • 95typescript-server
    Opisuje SDK modułów serwerowych SpacetimeDB w TypeScript: tabele, reducery i logikę modułu.
  • 100rust-server
    Podaje dokumentację SDK modułów serwerowych SpacetimeDB w Rust: tabele, reducery i logikę modułu.
  • 91spacetimedb-local
    Pomaga uruchamiać moduł SpacetimeDB lokalnie na własnym komputerze.
  • 85{setup-skill-name}
    Prawdopodobnie szablon instalacji modułu w projekcie, z nazwą i kodem modułu do uzupełnienia przed użyciem.
  • 90cc-cpp-project-standard
    Opisuje standardy projektu C++: granice modułów i nagłówków, czas życia zasobów, bezpieczeństwo wyjątków, ABI i kontrole w całym projekcie.
  • 100audit-logic
    Czyta cały kod modułu linia po linii i szuka błędów logiki biznesowej, odkrywając w trakcie testy, dokumentację i strukturę projektu, bez rysowania diagramów.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.