@slatedb/uniffi
v0.14.1
Published
Node.js bindings for SlateDB generated from UniFFI and packaged with native libraries.
Readme
SlateDB Node Binding
bindings/node contains the official Node.js package for SlateDB.
Install
Package:
@slatedb/uniffiRequirements:
- Node.js 20 or newer
Install from npm:
npm install @slatedb/uniffiAPI Model
ObjectStore.resolve(...)opens an object store from a URL such asmemory:///orfile:///...DbBuilderopens a writable database andDbReaderBuilderopens a read-only reader- keys and values are binary; pass
BufferorUint8Array - most database operations are async and should be awaited
- builders are single-use;
DbandDbReaderstay open untilshutdown()resolves - native-backed handles also expose
dispose()for deterministic cleanup aftershutdown()or when abandoning a builder
Quick Start
import assert from "node:assert/strict";
import { DbBuilder, ObjectStore } from "@slatedb/uniffi";
async function main() {
const store = ObjectStore.resolve("memory:///");
let db;
try {
const builder = new DbBuilder("demo-db", store);
try {
db = await builder.build();
} finally {
builder.dispose();
}
const key = Buffer.from("hello");
const value = Buffer.from("world");
await db.put(key, value);
const read = await db.get(key);
assert.deepEqual(read, value);
console.log(Buffer.from(read).toString("utf8"));
} finally {
if (db != null) {
await db.shutdown();
db.dispose();
}
store.dispose();
}
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});Replace memory:/// with any object store URL supported by Rust's object_store crate.
Metrics
The Node binding exposes both application-provided metrics recorders and the built-in
DefaultMetricsRecorder:
DbBuilder.with_metrics_recorder(...)DbReaderBuilder.with_metrics_recorder(...)DefaultMetricsRecorder.snapshot()DefaultMetricsRecorder.metrics_by_name(...)DefaultMetricsRecorder.metric_by_name_and_labels(...)
Example:
import { DbBuilder, DefaultMetricsRecorder, ObjectStore } from "@slatedb/uniffi";
const store = ObjectStore.resolve("memory:///");
const recorder = new DefaultMetricsRecorder();
const builder = new DbBuilder("metrics-demo", store);
try {
builder.with_metrics_recorder(recorder);
const db = await builder.build();
try {
await db.put(Buffer.from("hello"), Buffer.from("world"));
const metric = recorder.metric_by_name_and_labels("slatedb.db.write_ops", []);
if (metric?.value.tag === "Counter") {
console.log(metric.value[""]);
}
} finally {
await db.shutdown();
db.dispose();
}
} finally {
builder.dispose();
recorder.dispose();
store.dispose();
}Local Development
The package is generated from the UniFFI slatedb-uniffi cdylib using uniffi-bindgen-node-js.
You only need these tools when regenerating bindings, running tests from this repository, or packing the npm artifact locally:
- Node.js 20 or newer
- Rust toolchain for this repository
uniffi-bindgen-node-jsonPATH
Install the generator with:
cargo install uniffi-bindgen-node-js --version 0.0.13Install the package dependency used by the generated bindings with:
npm --prefix bindings/node installRegenerate Bindings
From the repository root:
npm --prefix bindings/node run buildThis command:
- builds the host
slatedb-uniffilibrary - runs
uniffi-bindgen-node-js - copies the generated package files into
bindings/node - stages the host native library under
bindings/node/prebuilds/<target>/
Generated API files are written into bindings/node and are not committed. package.json, build.mjs, and this README.md are maintained by hand.
Run Tests
From the repository root:
npm --prefix bindings/node testThe test script rebuilds the package and then runs node --test inside bindings/node.
Reproduce The PR CI Flow
From the repository root, this mirrors the Node validation done in .github/workflows/pr.yaml:
npm --prefix bindings/node ci
npm --prefix bindings/node run build
(cd bindings/node && node --test)
git diff --exit-code -- bindings/node
rm -rf /tmp/slatedb-node-pack
mkdir -p /tmp/slatedb-node-pack
(cd bindings/node && npm pack --pack-destination /tmp/slatedb-node-pack)
TARBALL="$(find /tmp/slatedb-node-pack -maxdepth 1 -name '*.tgz' | head -n 1)"
test -n "${TARBALL}"
tar -tf "${TARBALL}" | grep -Fx 'package/index.js'
tar -tf "${TARBALL}" | grep -Fx 'package/index.d.ts'
tar -tf "${TARBALL}" | grep -Fx 'package/slatedb.js'
tar -tf "${TARBALL}" | grep -Fx 'package/slatedb.d.ts'
tar -tf "${TARBALL}" | grep -Fx 'package/slatedb-ffi.js'
tar -tf "${TARBALL}" | grep -Fx 'package/slatedb-ffi.d.ts'
tar -tf "${TARBALL}" | grep -Fx 'package/runtime/ffi-types.js'
tar -tf "${TARBALL}" | grep -Fx 'package/prebuilds/linux-x64-gnu/libslatedb_uniffi.so'Packaging And Runtime Notes
The published @slatedb/uniffi tarball contains generated JavaScript and TypeScript bindings plus bundled native libraries. Consumers install one npm package; there is no separate Rust build step or native download in normal usage.
Writable databases and readers enter a dedicated multi-threaded Tokio runtime while opening so SlateDB's long-lived background tasks capture a multi-threaded Tokio handle. Foreground binding calls are still awaited through the normal JavaScript async API. By default, the runtime uses the host's available parallelism. Set SLATEDB_UNIFFI_RUNTIME_THREADS to a positive integer before the first DbBuilder.build() or DbReaderBuilder.build() call to override the worker thread count for the lifetime of the process.
At runtime, the package loads the native library that matches the current host from prebuilds/<target>/. The published package currently includes:
linux-x64-gnulinux-arm64-gnudarwin-x64darwin-arm64win32-x64win32-arm64
Linux musl targets are not packaged today. Local builds stage only the host native library; release builds stage all supported targets into the published npm package.
When assembling a release package from a prebuilt native directory, run:
npm --prefix bindings/node run build -- --prebuilt-dir <dir>The generated API files stay the same; only the packaged native libraries change between local and release builds.
