Skip to content

Node.js

@veristamp/nqql-edge is the edge-enabled Node.js package: N-API bindings for the QQL runtime plus in-process HNSW storage and optional local ONNX embeddings. No Qdrant server and no network at inference time.

nqql-edge

Node.js >= 18. Prebuilt binaries are published for Linux x86-64, macOS arm64 (Apple Silicon), and Windows x86-64 — not macOS Intel (ONNX Runtime publishes no artifact for it; see models).

npm
npm install @veristamp/nqql-edge
const {
localExecutor, listEmbeddingModels, parse, injectFilter, version,
} = require("@veristamp/nqql-edge");
const client = localExecutor("./qql-data", {
model: "bge-small-en-v1.5",
onDiskPayload: true,
});
await client.execute("CREATE COLLECTION docs HYBRID");
await client.execute('UPSERT INTO docs VALUES {id: 1, text: "hello from edge"}');
const report = await client.execute(
"QUERY TEXT 'hello' FROM docs USING dense LIMIT 5"
);
console.log(report.results[0].data);
await client.close(); // flush before deleting ./qql-data
console.log(version, listEmbeddingModels().length);

Fully offline FastEmbed-backed executor. dataDir is the storage path. options is an object (a bare boolean is accepted for backward compatibility and maps to onDiskPayload):

OptionDefaultPurpose
onDiskPayloadtrueStore payloads on disk instead of memory
modelBGESmallENV15Dense ONNX model name, HF code, or alias (bge-small-en-v1.5)
sparseModelnullOffline sparse model (e.g. "splade")
multiModelnullOffline multivector model (e.g. "bge-m3")
imageModelnullOffline CLIP vision model (e.g. "clip-vision")
rerankerModelnullOffline cross-encoder model (e.g. "bge-reranker-base")
cacheDirfastembed defaultDirectory for downloaded models
showDownloadProgressfalseShow Hugging Face progress bars

Models are locked at construction. A USING MODEL '…' clause naming a different model fails loudly instead of switching silently — see models.

httpExecutor(dataDir, url, embedKey, embedModel, embedDim, onDiskPayload?)

Section titled “httpExecutor(dataDir, url, embedKey, embedModel, embedDim, onDiskPayload?)”

Local storage and search, remote OpenAI-compatible embeddings (Ollama, OpenAI, Cohere, Together, Mistral):

const client = httpExecutor(
"./qql-data",
"http://localhost:11434/v1/embeddings",
"",
"nomic-embed-text",
768,
true,
);

localExecutor and httpExecutor return a Client:

MethodPurpose
client.execute(query, options?)Execute a query string, Stmt, or array of either; options.onError is "stop" or "continue"
client.explain(query)Human-readable plan for a string
client.explainStmt(stmt)Human-readable plan for a pre-parsed Stmt
client.compile(query)Non-executing {stmt_type, method, path, payload} route
client.close()Flush and release edge storage. Idempotent

execute returns an ExecutionReport:

{
ok: true,
results: [
{
ok: true,
operation: "QUERY",
message: "Found 10 hits",
data: { result: { points: [{ id: 1, score: 0.75, payload: { text: "hello" } }] } },
},
],
succeeded: 1,
failed: 0,
}

Stmt objects come from parse() and support stmt.injectFilter(field, op, value) and stmt.toJson(). injectFilter is the supported tenant-scoping mechanism. Edge has no custom SHARD routing, so a SHARD '…' clause fails at execution with QQL-EDGE-UNSUPPORTED-SHARD — see capabilities.

ExportPurpose
parse(query)Parse one statement or a script into Stmt[]
parseJson(query)Raw AST JSON string (avoids V8 object allocation)
isValid(query)Boolean parse check
injectFilter(query, field, op, value)Return a filtered statement
tokenize(query)Token list {kind, text, pos}
compileQuery(query)Non-executing route
explain(query) / explainStmt(stmt)Plan rendering
listEmbeddingModels()Catalog of loadable ONNX models
versionPackage version string
execute(query, options?)One-shot execution with a temporary client (loads the model every call — prefer a long-lived Client)
executeStmt(stmt, options?)One-shot execution of a pre-parsed Stmt

Supported injected operators: =, >, >=, <, <= (!= is rejected by design; wrap equality and negate instead).

Unsupported features throw with a stable code embedded in the message, e.g. QQL-EDGE-UNSUPPORTED-GROUP-BY, always with a reason and a "use remote Qdrant" hint. Errors are never silent no-ops.

See the Rust page for the underlying engine and models for embedding configuration.