Examples
Five small programs that run for real. Each one does the same work in Go, Ruby, TypeScript and curl, and prints the same text. The code on these pages is imported from the files in examples/, so what you read is what runs.
| Example | Shows | Languages |
|---|---|---|
| CRUD | insert, get, update with if_version, delete, count | Go, Ruby, Rails, TypeScript, curl |
| Logs (direct mode) | files written by other processes: filters, $regex, cursor pages | Go, Ruby, TypeScript, curl |
| Reports (aggregate) | $match, $group, $dateTrunc by hour, $sum, $avg, $sort | Go, Ruby, TypeScript, curl |
| Outbox (watch and ack) | a consumer with a where filter that resumes after a restart | Go, Ruby, TypeScript, curl |
| Expiring sessions | expire_in, ttl, expire, persist: expired documents disappear | Go, Ruby, TypeScript, curl |
Run them
You need Go, Ruby 3.2 or newer with bundler, Node 24 with pnpm, curl and jq.
git clone https://github.com/thadeu/ndb && cd ndb/examples
make run-crud LANG=go # LANG is go, ruby, ts or curl (crud also has rails)
make run-logs # no LANG: every language
make check # all examples, all languages, output must matchIf no daemon answers, make starts bin/ndb with examples/ndb.yml: data in examples/.data, socket /tmp/ndb-examples.sock (a unix socket path must stay under 104 bytes on macOS). Every program reads NDB_URL and NDB_TOKEN, so this also works with a TCP daemon:
NDB_URL=tcp://127.0.0.1:7070 NDB_TOKEN=secret make run-crud LANG=tsA program can run again and again. It removes what it created, or it checks first.
The curl helper
Every curl.sh loads one small helper, examples/lib/ndb.sh. It reads NDB_URL and NDB_TOKEN, picks --unix-socket or TCP, and adds the bearer token. jq formats the answers.
#!/usr/bin/env bash
# Shared by every curl.sh. Reads NDB_URL and NDB_TOKEN, like the SDKs do.
#
# ndb POST /v1/c/users/find '{"where":{"plan":"pro"}}' prints the answer
# ndb_status POST /v1/c/users/delete '{...}' prints only the HTTP status
# ndb_header X-Ndb-Next POST /v1/c/users/find '{...}' prints one response header
#
# unix:///path is sent with --unix-socket. tcp://host:port is plain HTTP, and
# NDB_TOKEN becomes a bearer token (the unix socket never needs one).
NDB_URL="${NDB_URL:-unix:///tmp/ndb-examples.sock}"
NDB_BODY="$(mktemp)"
NDB_ARGS=(-sS -H 'Content-Type: application/json')
trap 'rm -f "$NDB_BODY"' EXIT
case "$NDB_URL" in
unix://*)
NDB_ARGS+=(--unix-socket "${NDB_URL#unix://}")
NDB_BASE="http://ndb"
;;
tcp://*)
NDB_BASE="http://${NDB_URL#tcp://}"
;;
*)
echo "NDB_URL must start with unix:// or tcp://" >&2
exit 1
;;
esac
if [[ -n "${NDB_TOKEN:-}" ]]; then
NDB_ARGS+=(-H "Authorization: Bearer $NDB_TOKEN")
fi
ndb() {
local method="$1" path="$2" body="${3-}"
local extra=()
shift $(($# < 3 ? $# : 3))
if [[ -n "$body" ]]; then
extra=(-d "$body")
fi
curl "${NDB_ARGS[@]}" -X "$method" ${extra[@]+"${extra[@]}"} "$@" "$NDB_BASE$path"
}
# ndb_header NAME METHOD PATH BODY prints one response header, for example X-Ndb-Total.
ndb_header() {
local name="$1"
shift
ndb "$@" -D - -o /dev/null | tr -d '\r' | awk -F': ' -v n="$name" 'tolower($1) == tolower(n) { print $2 }'
}
# The answer body of the last ndb_status call stays in $NDB_BODY.
ndb_status() {
local method="$1" path="$2" body="${3-}"
local extra=()
if [[ -n "$body" ]]; then
extra=(-d "$body")
fi
curl "${NDB_ARGS[@]}" -o "$NDB_BODY" -w '%{http_code}' -X "$method" ${extra[@]+"${extra[@]}"} "$NDB_BASE$path"
}What each SDK can do
The examples do not hide a missing feature. Where an SDK lacks one, the page says so.
| Feature | Go | Ruby | Rails | TypeScript | curl |
|---|---|---|---|---|---|
insert, update, delete, if_version | yes | yes | yes | yes | yes |
| find, sort, cursor pages, count | yes | yes | yes | yes | yes |
$regex | yes | yes (also Regexp) | yes | yes | yes |
| aggregate | yes | yes | yes (and group/sum) | yes | yes |
watch with where, ack | yes | yes | client only | yes | yes |
declare expires_field from code, expire_in, ttl, expire, persist | yes | yes | yes | yes | yes |
| blobs | yes | yes | yes | no | yes |
There is no blobs example because the TypeScript SDK has no blobs.
See also: Clients for the SDK guides, Query language for the JSON the programs send.