Every live cell in this series so far has quietly gone through one
door: npm/factoidal,
the JavaScript package this project ships from its F*-extracted
engine. This post makes that door explicit — the full function list,
and a live look at which of those functions the engine bundle backing
this page actually supports.
npm/factoidal/index.js's public API, each function paired with the
post in this series that already exercises it:
| Function | Does | Seen in |
|---|---|---|
parse(text, {format}) |
text → Dataset |
post 1, post 11 |
query(data, sparql, {entail}) |
SELECT/ASK/CONSTRUCT, with an entail: 'RDFS'|'OWL-RL' option |
post 2, post 3 |
update(data, updateText) |
SPARQL Update (INSERT/DELETE) | — |
serialize(data, {format}) / canonicalize(data) |
Dataset → text, the second RDFC-1.0-canonical |
— |
shaclValidate(data, shapes) |
SHACL Core validation report | post 5 |
shexValidate(data, schema, focus, shape) |
ShEx shape-expression validation | post 6 |
owlClosure(data, mode) |
RDFS/OWL 2 RL forward closure | post 3 |
rmlMap(mapping, sourceData, kind) |
RML source-to-triples mapping | — |
csvwToRdf(csvText, metadataJson, options) |
CSVW csv2rdf conversion | post 13 |
jsonldToRdf(jsonldText, options) |
JSON-LD-specific parsing options | — |
rifEval(data, rifRulesXml) |
RIF Core forward-chaining saturation | post 10 |
capabilities() |
feature probe — which of the above the loaded engine bundle actually supports | this post |
Every function past query needs the npm-entry ABI bundle
(factoidal-npm-entry.js) rather than just the CLI-shaped bundle —
capabilities() exists precisely because that's an optional extra,
not a given.
parse then query — the same two calls under almost every other
live cell in this series, spelled out plainly this once:
const turtle = `
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix ex: <http://example.org/> .
ex:alice a foaf:Person ; foaf:name "Alice" ; foaf:knows ex:bob .
ex:bob a foaf:Person ; foaf:name "Bob" .
`;
const dataset = await fn.parse(turtle);
const rows = await fn.query(
dataset,
`# Every foaf:name in the graph, in alphabetical order.
PREFIX foaf: <http://xmlns.com/foaf/0.1/> SELECT ?name WHERE { ?p foaf:name ?name } ORDER BY ?name`
);
return rows.map((row) => row.get("name").value);
["Alice", "Bob"] — a Dataset in, Map<string, Term>[] rows out,
same shape whether the query is a five-line SELECT or (as in post 3)
an entail: 'OWL-RL' closure running underneath it.
npm/factoidal's own capabilities() (server-side, Node-only) walks
the loaded ABI object and reports a typeof entry.X === 'function'
check per feature. fn.capabilities() is the browser-side mirror
(docs/_includes/hub.njk's fn adapter) — it hides the ABI lookup
entirely and returns the same shape:
const caps = await fn.capabilities();
return { available: caps.entry, caps };
If every value in caps is true, the engine bundle this page loaded
is current enough for every live cell in this series to actually run
— including the RIF and CSVW cells two posts either side of this one.
A stale bundle would show false for whichever feature it predates,
which is exactly what capabilities()'s own doc comment ({entry: boolean, ..., rif: boolean} — see
npm/factoidal/lib/api.js)
promises server-side: a per-feature probe, not a blanket
version check.
npm/factoidal ships two engines side by side: require('factoidal')
(js_of_ocaml) and require('factoidal/wasm') (wasm_of_ocaml, Node
≥ 22 / WasmGC). Both expose the identical function list above, and —
measured directly against this repository's current wasm build —
factoidal/wasm's capabilities() now reports:
{
entry: true, construct: true, update: true,
canonicalize: true, graphs: true, canonicalHash: true,
shacl: true, shex: true, owlClosure: true,
rml: true, csvw: true, jsonld: true, rif: true
}
Two things make this work: the npm-entry ABI bundle
(factoidal-npm-entry.wasm.js) includes every export the js_of_ocaml
build ships, and a require.main-path bug in wasm.js's entry loader
is fixed — the loader
resolved the bundle's .wasm.assets/ directory relative to
require.main.filename, which is wrong for any caller whose own main
module lives somewhere else (any test/ file, any downstream
consumer), so the asset read threw deep inside wasm init and was
silently swallowed, misreporting entry: false and every function
built on it even when the bundle genuinely had the export. This whole
series' live cells still run against the plain js engine per
docs/web/hub/README.md's "Constraints every cell must
respect" — a separate, still-current constraint (the wasm CLI-bundle
lags newer CLI surfaces like --dump-nq byte-for-byte parity), unrelated
to the npm-entry ABI capability gap this section used to describe.
The previous post parsed one graph five ways. The next post covers the two newest arrivals behind this door — Verifiable Credentials and CSVW — including one capability this whole series' "live cell" convention can't reach at all.
Every live cell above is pinned in
tests/hub/post12_test.mjs —
the exact same source, executed against the real npm/factoidal
typed API instead of the in-browser fn/Factoidal adapters.