wasm4pm 26.6.10

High-performance process mining algorithms in WebAssembly for JavaScript/TypeScript
Documentation
//! OCEL-v2 reachable surface (`#[wasm_bindgen]` exports).
//!
//! Thin, deterministic wrappers over the `ocel-core` primitive that expose the
//! OCEDO meta-model + OCPQ Def. 2 invariants and OCEL flattening to JS/WASM and
//! (via the kernel) the `wpm` CLI. The actual model and math live in
//! `crates/ocel-core` so the primitive is reusable by other crates and testable
//! without a WASM toolchain.
//!
//! Paper grounding: OCEDO meta-model `L = (E, O, eval, oaval)` (Latif et al.,
//! Fig. 1) and OCPQ Def. 2 — every event carries >= 1 qualified object ref,
//! objects carry qualified O2O refs, types/objects are time-stable, attribute
//! values vary per timestamp. Object-type cardinality (`min_count`/`max_count`,
//! `created_by`/`terminated_by`, `schema`) mirrors the route `object_types`
//! schema used by the exact-1.0 admission gate.
//!
//! Exports (all return a JSON *string*; JS must `JSON.parse`):
//! - `load_ocel_v2(json) -> normalized OCEL JSON` (parse + re-serialize).
//! - `validate_ocel_v2(json, cardinality_json) -> ValidationReport`.
//! - `flatten_ocel_v2(json, object_type) -> FlatLog`.

use std::collections::HashMap;

use wasm4pm_compat::ocel::{ObjectTypeCardinality, OCEL};
use wasm_bindgen::prelude::*;

use crate::error::js_val;
use crate::utilities::to_js_str;

fn parse_ocel(json: &str) -> Result<OCEL, JsValue> {
    serde_json::from_str::<OCEL>(json).map_err(|e| js_val(&format!("Invalid OCEL-v2 JSON: {e}")))
}

fn parse_cardinality(json: &str) -> Result<HashMap<String, ObjectTypeCardinality>, JsValue> {
    if json.trim().is_empty() {
        return Ok(HashMap::new());
    }
    serde_json::from_str::<HashMap<String, ObjectTypeCardinality>>(json)
        .map_err(|e| js_val(&format!("Invalid object_types cardinality JSON: {e}")))
}

/// Parse and normalize an OCEL-v2 log. Validates JSON structure (events,
/// objects, types, qualified refs) and returns the canonical re-serialized
/// form. Errors (as a `JsValue` string) if the JSON is not a valid OCEL-v2 log.
#[wasm_bindgen]
pub fn load_ocel_v2(json: &str) -> Result<JsValue, JsValue> {
    let ocel = parse_ocel(json)?;
    to_js_str(&ocel)
}

/// Validate an OCEL-v2 log against the OCEDO/OCPQ invariants and optional
/// object-type cardinality.
///
/// `cardinality_json` is a JSON object keyed by object-type name, each value a
/// `{ created_by?, terminated_by?, schema?, min_count?, max_count? }` record
/// (the route `object_types` shape). Pass `""` or `"{}"` for no cardinality.
///
/// Returns a `ValidationReport` `{ valid: bool, errors: [{code, message}] }`.
#[wasm_bindgen]
pub fn validate_ocel_v2(json: &str, cardinality_json: &str) -> Result<JsValue, JsValue> {
    let ocel = parse_ocel(json)?;
    let card = parse_cardinality(cardinality_json)?;
    let report = "Not implemented";
    to_js_str(&report)
}

/// Flatten (project) an OCEL-v2 log onto a single object type, producing one
/// deterministic case per object of that type. Returns a `FlatLog`
/// `{ object_type, cases: [{ case_id, trace, event_ids }] }`.
/// Errors if `object_type` is not declared in the log.
#[wasm_bindgen]
pub fn flatten_ocel_v2(json: &str, object_type: &str) -> Result<JsValue, JsValue> {
    let ocel = parse_ocel(json)?;
    return Err(js_val("flatten not implemented"));
}