npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cooljapan/oxirs

v0.3.2

Published

WebAssembly bindings for OxiRS - Run RDF/SPARQL in the browser

Readme

oxirs-wasm

WebAssembly bindings for OxiRS - Run RDF/SPARQL in the browser

Crates.io docs.rs npm

Lightweight RDF and SPARQL implementation compiled to WebAssembly for browser, Node.js, and edge deployment.

Features

  • In-memory RDF Store: Subject/predicate/object hash-indexed triple storage; pattern and property-path evaluation looks up matches in the index instead of scanning every triple in the store
  • RDF Parsing: Turtle, N-Triples, N-Quads, TriG, plus a streaming/incremental chunk-based parser
  • SPARQL 1.1 Queries: SELECT, ASK, CONSTRUCT with OPTIONAL, UNION, FILTER (LANG/STR/DATATYPE/BOUND/regex/isIRI/isLiteral/isBlank/STRSTARTS/STRENDS/CONTAINS/STRLEN, &&/||/!), FILTER EXISTS/NOT EXISTS, property paths (/ | * + ? ^ !()), subqueries, GROUP BY + aggregates, ORDER BY, LIMIT/OFFSET
  • SPARQL UPDATE: INSERT DATA, DELETE DATA, INSERT/DELETE ... WHERE, CLEAR, DROP
  • PREFIX/BASE Prologues: queries may declare PREFIX/BASE and use prefixed names, expanded before parsing
  • Solution Budget: cap intermediate join solutions per query so an unselective join fails fast instead of running to completion
  • Named Graphs: multi-graph (quad) storage with GRAPH pattern queries
  • RDFS Inference: forward-chaining subClassOf/subPropertyOf/domain/range entailment
  • SHACL Validation (core subset): NodeShape/PropertyShape constraint checking
  • TypeScript Support: type definitions, plus React/Vue/Svelte adapters (js/react, js/vue, js/svelte)
  • Zero Server Dependencies: No Tokio, runs in single-threaded WASM
  • Lightweight: ~300KB optimized binary

Installation

NPM (Browser/Node.js)

npm install oxirs-wasm

Cargo (Rust WASM Project)

[dependencies]
oxirs-wasm = "0.3.2"

Quick Start

JavaScript/TypeScript

import { initialize, createStore } from 'oxirs-wasm';

// Initialize WASM module
await initialize();

// Create RDF store
const store = await createStore();

// Load Turtle data
const turtle = `
    @prefix : <http://example.org/> .
    :alice :knows :bob .
    :bob :name "Bob" .
`;
const count = await store.loadTurtle(turtle);
console.log(`Loaded ${count} triples`);

// Execute SPARQL query — PREFIX/BASE prologues are expanded before parsing
const results = await store.query(`
    PREFIX : <http://example.org/>
    SELECT ?person ?name WHERE {
        ?person :name ?name .
    }
`);
console.log(results);
// [{ person: "http://example.org/bob", name: "\"Bob\"" }]

// ASK query
const exists = await store.ask(`
    PREFIX : <http://example.org/>
    ASK { :alice :knows :bob }
`);
console.log('Alice knows Bob:', exists); // true

// Export to N-Triples
const ntriples = store.toNTriples();
console.log(ntriples);

Bounding Query Cost

A join is evaluated left to right, so an unselective pattern early in a WHERE clause can build a huge intermediate result before a later pattern cuts it back down — LIMIT cannot bound this because it only applies at the end. setSolutionBudget caps the number of intermediate solutions a single query may produce, so a runaway join fails fast with a query error instead of running to completion:

// Cap intermediate solutions (useful when answering queries under a
// time/CPU budget, e.g. a serverless endpoint).
store.setSolutionBudget(50_000);

try {
    await store.query('SELECT * WHERE { ?a ?p ?x . ?b ?p ?y }');
} catch (e) {
    console.error('Query exceeded its solution budget:', e);
}

// Remove the cap — queries go back to being unbounded.
store.clearSolutionBudget();

HTML Integration

<!DOCTYPE html>
<html>
<head>
    <title>RDF in Browser</title>
</head>
<body>
    <script type="module">
        // Loading the raw wasm-pack output directly (no npm wrapper): use
        // the generated `init` loader and the `OxiRSStore` constructor.
        import init, { OxiRSStore } from './pkg/oxirs_wasm.js';

        async function run() {
            await init();
            const store = new OxiRSStore();

            await store.loadTurtle(`
                @prefix : <http://example.org/> .
                :alice :knows :bob .
            `);

            const results = await store.query(
                'PREFIX : <http://example.org/>\nSELECT ?s ?o WHERE { ?s :knows ?o }'
            );

            console.log('Results:', results);
        }

        run();
    </script>
</body>
</html>

Building from Source

# Install wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# Build WASM package
cd platforms/oxirs-wasm
wasm-pack build --target web --release

# The output will be in pkg/
# - oxirs_wasm.js (ES module)
# - oxirs_wasm_bg.wasm (binary)
# - oxirs_wasm.d.ts (TypeScript types)

API Reference

Store Operations

class OxiRSStore {
    constructor();

    // Load RDF data
    loadTurtle(turtle: string): Promise<number>;
    loadNTriples(ntriples: string): Promise<number>;

    // Triple operations
    insert(subject: string, predicate: string, object: string): boolean;
    delete(subject: string, predicate: string, object: string): boolean;
    contains(subject: string, predicate: string, object: string): boolean;
    size(): number;
    clear(): void;

    // SPARQL queries (PREFIX/BASE prologues are supported)
    query(sparql: string): Promise<QueryResult[]>;
    ask(sparql: string): Promise<boolean>;
    construct(sparql: string): Promise<Triple[]>;

    // Query cost control
    setSolutionBudget(budget: number): void;
    clearSolutionBudget(): void;

    // RDFS forward-chaining inference
    inferRdfs(): { added: number };

    // Export
    toTurtle(): string;
    toNTriples(): string;

    // Indexes
    subjects(): string[];
    predicates(): string[];
    objects(): string[];

    // Namespaces
    addPrefix(prefix: string, uri: string): void;
}

Deployment Targets

Browser

<script type="module">
    import init, { OxiRSStore } from './pkg/oxirs_wasm.js';
    await init();
    const store = new OxiRSStore();
</script>

Node.js

The web build target produces an ES module, so import it rather than require() it (Node.js cannot require() an ES module):

import { initialize, createStore } from 'oxirs-wasm';

(async () => {
    await initialize();
    const store = await createStore();
    // ...
})();

Cloudflare Workers

import { initialize, createStore } from 'oxirs-wasm';

export default {
    async fetch(request: Request): Promise<Response> {
        await initialize();
        const store = await createStore();

        // Process RDF data
        const { rdf, sparql } = await request.json();
        await store.loadTurtle(rdf);
        const results = await store.query(sparql);

        return new Response(JSON.stringify(results));
    }
};

Deno Deploy

import { initialize, createStore } from 'https://esm.sh/oxirs-wasm';

Deno.serve(async (req) => {
    await initialize();
    const store = await createStore();
    // ...
});

Limitations

  • ❌ No persistent storage (in-memory only)
  • ❌ No SPARQL DESCRIBE
  • ❌ No OWL reasoning (RDFS forward-chaining entailment — subClassOf/subPropertyOf/domain/range — is supported via inferRdfs())
  • ❌ SHACL validation covers a core subset only (NodeShape/PropertyShape with minCount, maxCount, datatype, pattern, minInclusive/maxInclusive, class, nodeKind, in, hasValue — not the full SHACL-AF/SPARQL-based constraint set)
  • ❌ No federated queries (SPARQL SERVICE)

For full SPARQL 1.1 and complete SHACL support, use the server-side oxirs-fuseki / oxirs-shacl crates.

Performance

  • WASM binary size: ~300KB (optimized with wasm-opt)
  • Initialization: ~100ms (first load, cached)
  • Parsing: 10K triples/sec (Turtle)
  • Query execution: 1K queries/sec (simple patterns)
  • Memory: ~200KB per 1K triples
  • Indexed evaluation: triple pattern and property-path matching go through the store's subject/predicate/object hash indexes rather than scanning every triple, so a join costs a hash lookup per solution instead of a full graph scan

Use Cases

  • Browser RDF Editors: Client-side validation and editing
  • Offline Applications: Local knowledge graphs without server
  • Edge Computing: IoT devices, embedded systems
  • Privacy-Preserving: Process sensitive data locally
  • Developer Tools: RDF/SPARQL playground in browser
  • Static Sites: Jamstack with client-side queries

Dependencies

  • wasm-bindgen - JavaScript interop
  • js-sys - JavaScript standard library bindings
  • web-sys - Web APIs (console, performance)
  • console_error_panic_hook - Readable panic messages in the browser console
  • serde, serde_json - Serialization
  • thiserror - Error types

License

Licensed under the Apache License, Version 2.0.