oxirs_wasm/lib.rs
1//! # OxiRS WASM
2//!
3//! [](https://github.com/cool-japan/oxirs/releases)
4//!
5//! **Status**: Development Release (v0.4.1)
6//!
7//! WebAssembly bindings for OxiRS - Run RDF/SPARQL in the browser.
8//!
9//! ## Features
10//!
11//! - **Streaming RDF Parser**: Turtle, N-Triples, N-Quads (incremental chunk processing)
12//! - **Compact Triple Store**: Dictionary-based, 12 bytes per triple, dual sorted indexes
13//! - **JS/TS API**: Clean `wasm_bindgen` surface via `OxiRSStore` and `WasmSparqlStore`
14//! - **SPARQL Queries**: SELECT, ASK, CONSTRUCT (triple-pattern based)
15//! - **SPARQL UPDATE**: INSERT DATA, DELETE DATA, INSERT/DELETE WHERE, CLEAR, DROP
16//! - **SPARQL Enhancements**: OPTIONAL, UNION, FILTER expressions
17//! - **RDFS Inference**: subClassOf/subPropertyOf transitivity, domain/range typing
18//! - **Named Graphs**: Multi-graph storage with GRAPH pattern queries
19//! - **Memory Efficient**: Optimized for WASM's 4 GB address space limit
20//!
21//! ## Example (JavaScript)
22//!
23//! ```javascript
24//! import init, { OxiRSStore } from 'oxirs-wasm';
25//!
26//! await init();
27//!
28//! const store = new OxiRSStore();
29//! await store.loadTurtle(`
30//! @prefix : <http://example.org/> .
31//! :alice :knows :bob .
32//! :bob :name "Bob" .
33//! `);
34//!
35//! const results = store.query('SELECT ?name WHERE { ?person :name ?name }');
36//! console.log(results);
37//! ```
38
39pub mod api;
40pub mod error;
41pub mod inference;
42pub mod named_graph;
43pub mod parser;
44pub mod query;
45pub mod store;
46pub mod update;
47
48// v1.1.0 SPARQL Results CSV/TSV serializer
49pub mod results_csv;
50
51// v1.1.0 round 5: GeoJSON serialization/deserialization for SPARQL geo results
52pub mod geojson_support;
53
54// v1.1.0 round 6: SPARQL query pretty-printer and formatter
55pub mod sparql_formatter;
56
57// v1.1.0 round 7: Namespace/prefix management for RDF serializers
58pub mod prefix_manager;
59
60// v1.1.0 round 11: Streaming / incremental chunk-based RDF document parser
61pub mod streaming_parser;
62
63// v1.1.0 round 12: WASM/JS interop bridge type conversions
64pub mod wasm_bridge;
65
66// v1.1.0 round 13: Client-side SPARQL query validation (syntax/semantic checks)
67pub mod query_validator;
68
69// v1.1.0 round 11: RDF graph visualization with Fruchterman-Reingold layout
70pub mod graph_visualizer;
71
72// v1.1.0 round 12: In-memory indexed triple store for WASM
73pub mod triple_store;
74
75// v1.1.0 round 13: In-memory SPARQL executor (SELECT/ASK/CONSTRUCT/DESCRIBE + FILTER)
76pub mod sparql_executor;
77
78// v1.1.0 round 14: WASM storage abstraction layer (key-value with namespace isolation + TTL)
79pub mod storage_adapter;
80
81// v1.1.0 round 15: WASM event dispatching system (pub/sub for browser events)
82pub mod event_dispatcher;
83
84// v1.1.0 round 16: RDF namespace prefix management for WASM bindings
85pub mod namespace_manager;
86
87// v0.3.0: Web Workers for parallel execution
88pub mod web_worker;
89
90// v0.3.0: ServiceWorker offline cache
91pub mod offline_cache;
92
93// v0.3.0: SHACL validation subset
94pub mod shacl;
95
96// Fluent, programmatic SPARQL SELECT/ASK/COUNT query builder
97pub mod query_builder;
98
99// Structured WASM error codes and an error-history handler
100pub mod error_handler;
101
102// Multi-format (JSON/XML/CSV/TSV/Markdown/HTML) SPARQL result set formatter
103pub mod sparql_result_formatter;
104
105// A deterministic, in-memory *mock* SPARQL endpoint client — no network I/O.
106// Off by default; see the `mock-endpoint-client` feature doc in Cargo.toml.
107#[cfg(feature = "mock-endpoint-client")]
108pub mod endpoint_client;
109
110use wasm_bindgen::prelude::*;
111
112pub use api::WasmSparqlStore;
113pub use error::WasmError;
114pub use store::OxiRSStore;
115
116// Initialize panic hook for better error messages in browser DevTools
117#[wasm_bindgen(start)]
118pub fn init() {
119 console_error_panic_hook::set_once();
120}
121
122/// RDF Triple representation for JavaScript
123#[wasm_bindgen]
124#[derive(Debug, Clone)]
125pub struct Triple {
126 subject: String,
127 predicate: String,
128 object: String,
129}
130
131#[wasm_bindgen]
132impl Triple {
133 #[wasm_bindgen(constructor)]
134 pub fn new(subject: &str, predicate: &str, object: &str) -> Self {
135 Self {
136 subject: subject.to_string(),
137 predicate: predicate.to_string(),
138 object: object.to_string(),
139 }
140 }
141
142 #[wasm_bindgen(getter)]
143 pub fn subject(&self) -> String {
144 self.subject.clone()
145 }
146
147 #[wasm_bindgen(getter)]
148 pub fn predicate(&self) -> String {
149 self.predicate.clone()
150 }
151
152 #[wasm_bindgen(getter)]
153 pub fn object(&self) -> String {
154 self.object.clone()
155 }
156}
157
158/// Query result for JavaScript
159#[wasm_bindgen]
160pub struct QueryResult {
161 bindings: Vec<JsValue>,
162}
163
164#[wasm_bindgen]
165impl QueryResult {
166 #[wasm_bindgen(getter)]
167 pub fn bindings(&self) -> Vec<JsValue> {
168 self.bindings.clone()
169 }
170
171 #[wasm_bindgen(getter)]
172 pub fn length(&self) -> usize {
173 self.bindings.len()
174 }
175}
176
177/// Get OxiRS WASM version
178#[wasm_bindgen]
179pub fn version() -> String {
180 env!("CARGO_PKG_VERSION").to_string()
181}
182
183/// Log a message to the browser console
184#[wasm_bindgen]
185pub fn log(message: &str) {
186 web_sys::console::log_1(&message.into());
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 #[test]
194 fn test_triple() {
195 let triple = Triple::new("http://a", "http://b", "http://c");
196 assert_eq!(triple.subject(), "http://a");
197 assert_eq!(triple.predicate(), "http://b");
198 assert_eq!(triple.object(), "http://c");
199 }
200}