Feature: 006-docker-wasm-examples
Date: 2025-10-25
Audience: Developers setting up KalamDB with Docker, WASM, and React example
- Docker 20+ and Docker Compose 2.0+
- Rust 1.75+ with wasm32-unknown-unknown target
- Node.js 18+ and npm/yarn
- wasm-pack 0.12+
- Git
Install Rust WASM target:
rustup target add wasm32-unknown-unknownInstall wasm-pack:
cargo install wasm-packFrom backend directory:
cd backend
cargo run --bin kalamdb-serverServer starts on http://localhost:2900
Using backend server command:
cargo run --bin kalamdb-server -- create-user --name "demo-user" --role "user"
# Output:
# ✅ User created successfully!
# User ID: 1
# Name: demo-user
# Role: user
# API Key: 550e8400-e29b-41d4-a716-446655440000
#
# ⚠️ Save this API key securely - you won't see it again!Role options:
admin- Full access (future)user- Standard access (default)readonly- Read-only access (future)
Alternative using kalam-cli (from localhost):
kalam-cli user create --name "demo-user" --role "user"
# Output: (same as above)# With API key (works remotely)
curl -X POST http://localhost:2900/sql \
-H "Content-Type: application/json" \
-H "X-API-KEY: 550e8400-e29b-41d4-a716-446655440000" \
-d '{"query": "SELECT * FROM todos"}'
# Without API key (only works from localhost)
curl -X POST http://127.0.0.1:2900/sql \
-H "Content-Type: application/json" \
-d '{"query": "SELECT * FROM todos"}'-- Create test table
CREATE TABLE test_soft_delete (id INTEGER PRIMARY KEY, name TEXT);
-- Insert row
INSERT INTO test_soft_delete (name) VALUES ('test row');
-- Delete row (soft delete)
DELETE FROM test_soft_delete WHERE id = 1;
-- Verify row is hidden
SELECT * FROM test_soft_delete;
-- Returns: (empty result)
-- Show deleted rows (future enhancement)
SELECT * FROM test_soft_delete INCLUDE DELETED;
-- Returns: id=1, name='test row', deleted=trueUsing build script (recommended):
cd docker/build
./build-and-test-local.shThis script:
- Builds kalamdb-server and kalam-cli binaries
- Creates multi-stage Docker image
- Tags as
kalamdb:latest - Includes both server and CLI in the image
Manual build (alternative):
cd docker/build
docker build -t kalamdb:latest -f Dockerfile ../..Dockerfile overview:
- Multi-stage build (rust:1.75-slim → debian:bookworm-slim)
- Includes kalamdb-server and kalam-cli binaries
- Default CMD:
/usr/local/bin/kalamdb-server
Location: docker/run/single/docker-compose.yml
cd docker/run/single
docker-compose up -ddocker-compose.yml overview:
version: '3.8'
services:
kalamdb:
image: kalamdb:latest
container_name: kalamdb
ports:
- "2900:2900"
environment:
# Override config.toml values
KALAMDB_SERVER_PORT: "2900"
KALAMDB_DATA_DIR: "/data"
KALAMDB_LOG_LEVEL: "info"
volumes:
- kalamdb_data:/data
restart: unless-stopped
volumes:
kalamdb_data:
driver: local# Using kalam-cli inside the container (localhost exception applies)
docker exec -it kalamdb kalam-cli user create --name "docker-user" --role "user"
# Output:
# ✅ User created successfully!
# User ID: 1
# Name: docker-user
# Role: user
# API Key: 750a9500-b19c-31e4-b827-556755550111
#
# ⚠️ Save this API key securely - you won't see it again!# Check logs
docker-compose logs -f kalamdb
# Test health check
curl http://localhost:2900/health
# Test with API key
curl -X POST http://localhost:2900/sql \
-H "Content-Type: application/json" \
-H "X-API-KEY: 750a9500-b19c-31e4-b827-556755550111" \
-d '{"query": "SELECT 1"}'Supported variables (all optional, with defaults):
KALAMDB_SERVER_PORT(default: 2900)KALAMDB_DATA_DIR(default: /data)KALAMDB_LOG_LEVEL(default: info) - Options: debug, info, warn, errorKALAMDB_MAX_CONNECTIONS(default: 100)
Modify docker-compose.yml and restart:
environment:
KALAMDB_SERVER_PORT: "9000"
KALAMDB_LOG_LEVEL: "debug"docker-compose down
docker-compose up -dVerify data persists:
# Create table
docker exec kalamdb kalam-cli exec "CREATE TABLE test (id INT, name TEXT)"
# Insert data
docker exec kalamdb kalam-cli exec "INSERT INTO test VALUES (1, 'persisted')"
# Restart container
docker-compose restart
# Verify data still exists
docker exec kalamdb kalam-cli exec "SELECT * FROM test"
# Output: 1 | persistedFrom cli/kalam-link directory:
cd cli/kalam-link
wasm-pack build --target web --out-dir pkgOutput (in pkg/ directory):
kalam_link_bg.wasm- WebAssembly binarykalam_link.js- JavaScript bindingskalam_link.d.ts- TypeScript type definitionspackage.json- npm package metadata
Test in Node.js:
// test.mjs
import init, { KalamClient } from './pkg/kalam_link.js';
await init(); // Initialize WASM
const client = new KalamClient(
'ws://localhost:2900',
'550e8400-e29b-41d4-a716-446655440000'
);
await client.connect();
console.log('Connected:', client.isConnected());
await client.disconnect();node test.mjs
# Output: Connected: truecd pkg
npm publishOr use locally:
# In your React app
npm install ../cli/kalam-link/pkgRun setup script:
cd examples/simple-typescript
chmod +x setup.sh
./setup.shsetup.sh script:
#!/bin/bash
set -e
# Check kalam-cli is available
if ! command -v kalam-cli &> /dev/null; then
echo "Error: kalam-cli not found"
exit 1
fi
# Test connection
echo "Testing connection to KalamDB..."
kalam-cli exec "SELECT 1" || {
echo "Error: Cannot connect to KalamDB server"
exit 1
}
# Load schema from todo-app.sql
echo "Creating TODO table..."
kalam-cli load todo-app.sql
echo "Setup complete!"todo-app.sql:
CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
completed BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);npm installpackage.json:
{
"name": "kalamdb-todo-example",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"test": "vitest",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"kalam-link": "file:../../cli/kalam-link/pkg"
},
"devDependencies": {
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"@vitejs/plugin-react": "^4.0.0",
"typescript": "^5.0.0",
"vite": "^4.4.0",
"vitest": "^0.34.0",
"@testing-library/react": "^14.0.0",
"@testing-library/jest-dom": "^6.0.0"
}
}Create .env file:
echo "VITE_KALAMDB_URL=ws://localhost:2900" > .env
echo "VITE_KALAMDB_API_KEY=550e8400-e29b-41d4-a716-446655440000" >> .envImportant: Add .env to .gitignore!
npm run devOutput:
VITE v4.4.0 ready in 250 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
Open browser: http://localhost:5173
Features to test:
- Connection Status: Green "Connected" badge should appear
- Add TODO: Type "Buy groceries" → Click Add → Appears in list
- Multi-tab sync: Open another tab → Add TODO in first tab → Appears in second tab instantly
- localStorage cache: Close tab → Reopen → TODOs load instantly from cache
- Delete TODO: Click delete → Removed from all tabs
- Offline mode: Disconnect server → "Disconnected" badge → Add button disabled
npm testTest coverage:
- Connection status display
- TODO add/delete operations
- localStorage persistence
- Subscription event handling
- Error handling (connection failure)
Container won't start:
# Check logs
docker-compose logs kalamdb
# Common issues:
# - Port 2900 already in use: Change KALAMDB_SERVER_PORT
# - Volume permission errors: Check Docker volume permissionsData not persisting:
# Verify volume exists
docker volume ls | grep kalamdb_data
# Inspect volume
docker volume inspect kalamdb_dataBuild fails:
# Ensure wasm target installed
rustup target add wasm32-unknown-unknown
# Clean and rebuild
cargo clean
wasm-pack build --target webModule won't load in browser:
- Check browser console for MIME type errors
- Ensure server sends
Content-Type: application/wasmfor .wasm files - Use
await init()before creating KalamClient
Connection fails:
# Verify server is running
curl http://localhost:2900/health
# Check API key is correct
echo $VITE_KALAMDB_API_KEY
# Check browser console for errorslocalStorage not working:
- Check browser privacy settings (localStorage might be disabled)
- Clear localStorage:
localStorage.clear()in browser console - Check for localStorage quota errors (5-10MB limit)
Tabs not syncing:
- Verify WebSocket connection in both tabs (check connection badge)
- Check browser console for subscription errors
- Ensure both tabs use same API key
-
Explore the code: Review
examples/simple-typescript/src/to understand WASM client usage -
Extend the example: Add features (edit TODO, filters, search)
-
Deploy to production:
- Use WSS (WebSocket Secure) instead of WS
- Configure CORS properly
- Use environment-specific API keys
- Enable HTTPS for web server
-
Read the docs:
What you've set up:
- ✅ API key authentication for KalamDB
- ✅ Soft delete for user tables
- ✅ Dockerized KalamDB server with config override
- ✅ WASM-compiled kalam-link client
- ✅ React TODO app with real-time sync
Time to complete: ~30 minutes (matches SC-012)
Key files created:
backend/Dockerfilebackend/docker-compose.ymlcli/kalam-link/pkg/*(WASM artifacts)examples/simple-typescript/*(React app)