Files
quicproquo/docs/src/getting-started/generators.md
Chris Nennemann db46b72f58 feat: Sprint 3 — C FFI bindings, WASM compilation, Python example, SDK docs
- Create quicproquo-ffi crate with 7 extern "C" functions: connect,
  login, send, receive, disconnect, last_error, free_string
  (produces libquicproquo_ffi.so and .a)
- Feature-gate quicproquo-core for WASM: identity, hybrid_kem,
  safety_numbers, sealed_sender, app_message, padding, transcript
  all compile to wasm32-unknown-unknown
- Add Python ctypes example (examples/python/qpq_client.py) with
  QpqClient wrapper class and CLI
- Add SDK documentation: FFI reference, WASM guide, qpq-gen generators
- Update Dockerfile for quicproquo-ffi workspace member
2026-03-03 23:47:40 +01:00

172 lines
5.3 KiB
Markdown

# Code Generators (qpq-gen)
The `qpq-gen` CLI tool scaffolds new plugins, bots, RPC methods, and hook
events for the quicproquo ecosystem.
## Installation
```bash
cargo install --path crates/quicproquo-gen
```
Or run directly from the workspace:
```bash
cargo run -p quicproquo-gen -- <subcommand>
```
## Subcommands
### `qpq-gen plugin <name>` -- Server Plugin
Scaffolds a standalone Cargo project for a server plugin compiled as a shared
library (`cdylib`). The generated plugin implements the `HookVTable` C ABI
and is loaded by the server at startup via `--plugin-dir`.
```bash
qpq-gen plugin rate-limiter
qpq-gen plugin audit-log --output /tmp/plugins
```
**Generated files:**
```
rate_limiter/
Cargo.toml # cdylib crate depending on quicproquo-plugin-api
README.md # Build and install instructions
src/lib.rs # Plugin skeleton with qpq_plugin_init entry point
```
The template includes:
- `qpq_plugin_init` -- called by the server on load; populates the `HookVTable`
- `on_message_enqueue` -- sample hook that rejects payloads larger than 1 MB
- `error_message` -- returns the rejection reason as a C string
- `destroy` -- frees the plugin state
**What to customize:** Replace the `on_message_enqueue` logic with your own
policy. Add more hooks by setting additional fields on the `HookVTable`
(`on_auth`, `on_channel_created`, `on_fetch`, `on_user_registered`,
`on_batch_enqueue`).
**Build and install:**
```bash
cd rate_limiter
cargo build --release
cp target/release/librate_limiter.so /path/to/plugins/
qpq-server --plugin-dir /path/to/plugins/
```
### `qpq-gen bot <name>` -- Bot Project
Scaffolds a standalone bot project using the Bot SDK. The generated binary
connects to a quicproquo server, authenticates via OPAQUE, and runs a
message-handling loop.
```bash
qpq-gen bot echo-bot
qpq-gen bot moderation-bot --output /tmp/bots
```
**Generated files:**
```
moderation_bot/
Cargo.toml # Binary crate depending on quicproquo-bot + tokio
README.md # Quick-start and command reference
src/main.rs # Bot skeleton with handle_message dispatcher
```
The template ships with four built-in commands as examples:
| Command | Description |
|-----------------|---------------------------|
| `!help` | List available commands |
| `!echo <text>` | Echo back the text |
| `!whoami` | Show the sender's username|
| `!ping` | Respond with "pong!" |
**Configuration** is read from environment variables:
| Variable | Default |
|-------------------|----------------------|
| `QPQ_SERVER` | `127.0.0.1:7000` |
| `QPQ_USERNAME` | `<bot-name>` |
| `QPQ_PASSWORD` | `changeme` |
| `QPQ_CA_CERT` | `server-cert.der` |
| `QPQ_STATE_PATH` | `<bot-name>-state.bin` |
**What to customize:** Edit the `handle_message` function in `src/main.rs`
to add your own command handlers. Return `Some(response)` to reply, or
`None` to stay silent.
**Run:**
```bash
cd moderation_bot
QPQ_SERVER=127.0.0.1:7000 \
QPQ_USERNAME=moderation_bot \
QPQ_PASSWORD=changeme \
QPQ_CA_CERT=path/to/server-cert.der \
cargo run
```
### `qpq-gen rpc <Name>` -- RPC Method Guide
Prints a step-by-step guide for adding a new Cap'n Proto RPC method to the
server. This generator does not create files; it outputs instructions and
code snippets to copy into the appropriate locations.
```bash
qpq-gen rpc listChannels
```
The `Name` argument should be in camelCase (e.g., `listChannels`). The
generator derives the `snake_case` form automatically for file and function
names.
**Steps covered:**
1. **Schema** -- Add the method to the `interface NodeService` block in
`schemas/node.capnp`, then rebuild with `cargo build -p quicproquo-proto`
2. **Handler module** -- Create
`crates/quicproquo-server/src/node_service/<name>.rs` with the handler
implementation (template code is printed)
3. **Registration** -- Wire the handler into `node_service/mod.rs`
4. **Storage** (if needed) -- Add a method to the `Store` trait and implement
it in `sql_store.rs` and `storage.rs`
5. **Hook** (optional) -- Run `qpq-gen hook <name>` to let plugins observe
the new RPC
6. **Verify** -- `cargo build -p quicproquo-server && cargo test -p quicproquo-server`
### `qpq-gen hook <name>` -- Hook Event Guide
Prints a step-by-step guide for adding a new server hook event that plugins
can observe. Like `rpc`, this generator outputs instructions rather than
creating files.
```bash
qpq-gen hook message_deleted
```
The `name` argument should be in `snake_case` (e.g., `message_deleted`). The
generator derives the `PascalCase` form for struct names.
**Steps covered:**
1. **Event struct** -- Define `MessageDeletedEvent` in
`crates/quicproquo-server/src/hooks.rs`
2. **Trait method** -- Add `on_message_deleted` to the `ServerHooks` trait
with a default no-op implementation
3. **Tracing** -- Implement the hook in `TracingHooks` with a `tracing::info!`
call
4. **Plugin API** -- Add a C-compatible `CMessageDeletedEvent` struct and an
`on_message_deleted` field to `HookVTable` in
`crates/quicproquo-plugin-api/src/lib.rs`
5. **Plugin dispatch** -- Wire the conversion and dispatch in
`plugin_loader.rs`
6. **Call site** -- Fire the hook from the relevant RPC handler in
`node_service/`
7. **Verify** -- Build and test `quicproquo-plugin-api` and
`quicproquo-server`