JavaScript / WASM
The @jeswr/sparq RDF/JS API — the Rust engine compiled to a single ~886 KB wasm artifact.
Try it: drive the API in your tab
Engine loading…One seeded Store of six people; each panel below calls a different part of the @jeswr/sparq surface against it — the real Rust engine, compiled to wasm, running here.
queryCursor()Pull the result in self-contained batches of batchSize rows — the consumer never holds more than one batch at a time. Lower the batch size to watch more pulls arrive.
match() / countQuads()A triple-pattern lookup: leave a position blank for a wildcard, or paste an N-Triples term (<iri> or "literal"). countQuads() reads the count from the index without materialising the terms.
count()Count a SELECT's solutions without building any JS-side Bindings — read straight from the index where possible. Query: SELECT * WHERE { ?p foaf:knows ?o }
applyDelta()Mutate the store in place with a quad-level delta — O(batch), no index rebuild. Watch the size and person count change; the lookup and count panels above re-derive from the same live store.
Dataset from a <script type="module">Dataset export is an RDF/JS DatasetCore over the engine — importable directly in a browser module script from this project's self-hosted bundle (no third-party CDN). The async factories (Dataset.fromString / .create / .fromQuads) instantiate the wasm engine on first use, so the ~MB binary loads lazily — never on import.<script type="module">
// Self-hosted: this project's OWN GitHub Pages origin — no third-party CDN. The
// ~MB engine wasm is fetched LAZILY by the first `await Dataset.fromString(...)`
// below — NOT by this import line — so it never blocks the page paint.
import { Dataset, DataFactory as DF } from "https://sparq.jeswr.org/wasm/sparq.js";
const ds = await Dataset.fromString(
'<http://ex/a> <http://ex/name> "Alice" .',
"ntriples",
);
console.log(ds.size); // 1 (DatasetCore: size, add, delete, has, match, iterate)
ds.add(DF.quad(
DF.namedNode("http://ex/b"), DF.namedNode("http://ex/name"), DF.literal("Bob"),
));
for (const q of ds.match(null, DF.namedNode("http://ex/name"), null)) {
console.log(q.subject.value, "→", q.object.value);
}
// Drop to the full SPARQL engine when DatasetCore is not enough:
console.log(ds.store.queryBoolean("ASK { ?s ?p ?o }")); // true
ds.free();
</script>sparq.js is a single self-contained ESM file published into this site at /wasm/sparq.js — the engine .wasm stays out of it, fetched lazily by the first await. The same named entry is also on an ESM CDN (the @jeswr/sparq npm package):
<script type="module">
// Alternative: the same named entry from an ESM CDN (the published @jeswr/sparq npm package).
import { Dataset } from "https://esm.sh/@jeswr/sparq";
</script>Prefer Dataset (or SparqStore) in an app — the cold start is memoised, so it is paid at most once per page. The lower-level engine handle is also importable: the wasm-pack glue is itself an ESM module.
<script type="module">
// Low-level: the wasm-pack `--target web` glue is itself a real ESM module.
import init, { Store } from "https://sparq.jeswr.org/wasm/sparq_wasm.js";
await init(); // lazily fetches + instantiates sparq_wasm_bg.wasm
const store = Store.load("<a> <b> <c> .", "ntriples");
</script>@jeswr/sparq wraps the Rust triplestore + SPARQL engine — compiled to a single ~886 KB (≈314 KB gzipped) wasm artifact — in an idiomatic RDF/JS surface that runs unchanged in Node ≥ 18 and the browser; this very site uses it for every live demo, and the panels below run against one seeded store in your tab.
What it does
- SparqStore (RDF/JS) — fromString / fromCompressed, query() yielding Map-like Bindings, idiomatic terms, plus the raw Store class for SPARQL-JSON strings.
- Dataset — RDF/JS DatasetCore — Named ESM entry: add / delete / has / match / size / iterate, lazily wasm-initialised; .store drops to the full SPARQL surface.
- Streaming cursors — Iterate large SELECT results in batches without materialising the whole table.
- RDF/JS match() / countQuads() / count() — The standard Source interface, plus a solution count read from the index without building every binding.
- applyDelta / SPARQL Update — Apply quad-level deltas or SPARQL Update to mutate the store in place.
This is the engine — every live demo on this site calls this API; in Node it loads the same wasm binary, and in the browser it streams it on first use, never on import.
Reproduce: npm i @jeswr/sparq
Caveats & limitations
The SparqStore.query() wrapper covers SELECT/ASK; CONSTRUCT / DESCRIBE come via queryQuads() (RDF/JS quads), queryQuadsString() (N-Triples) and queryQuadsStream() — drop to the raw Store only to skip term materialisation. The lean bundle omits REGEX/REPLACE and the wall-clock query budget (see the SPARQL surface), trading a smaller download for those native-only features.