WASM Bindings - Entrenar - Training & Optimization Library
Description: A comprehensive guide to building neural network training systems with autograd, optimizers, LoRA/QLoRA, and quantization using EXTREME TDD methodology

# WASM Bindings

The dashboard module provides WebAssembly bindings for browser-based training dashboards.

## Feature Flag

Enable WASM support in your `Cargo.toml`:

    [dependencies]
    entrenar = { version = "0.2", features = ["wasm"] }

## IndexedDbStorage

Browser-compatible storage backend that implements `ExperimentStorage`:

    #![allow(unused)]
    fn main() {
    pub struct IndexedDbStorage {
        // In-memory implementation mimicking IndexedDB behavior
    }

    impl ExperimentStorage for IndexedDbStorage {
        fn create_experiment(&mut self, name: &str, config: Option<Value>) -> Result<String>;
        fn create_run(&mut self, experiment_id: &str) -> Result<String>;
        fn start_run(&mut self, run_id: &str) -> Result<()>;
        fn complete_run(&mut self, run_id: &str, status: RunStatus) -> Result<()>;
        fn log_metric(&mut self, run_id: &str, key: &str, step: u64, value: f64) -> Result<()>;
        fn log_artifact(&mut self, run_id: &str, key: &str, data: &[u8]) -> Result<String>;
        fn get_metrics(&self, run_id: &str, key: &str) -> Result<Vec<MetricPoint>>;
        fn get_run_status(&self, run_id: &str) -> Result<RunStatus>;
        fn set_span_id(&mut self, run_id: &str, span_id: &str) -> Result<()>;
        fn get_span_id(&self, run_id: &str) -> Result<Option<String>>;
    }
    }

### Additional Methods

    #![allow(unused)]
    fn main() {
    impl IndexedDbStorage {
        /// List all experiments
        pub fn list_experiments(&self) -> Vec<String>;

        /// List all runs for an experiment
        pub fn list_runs(&self, experiment_id: &str) -> Vec<String>;

        /// List all metric keys for a run
        pub fn list_metric_keys(&self, run_id: &str) -> Vec<String>;
    }
    }

## WasmRun

JavaScript-friendly training run wrapper with `wasm_bindgen`:

    #![allow(unused)]
    fn main() {
    #[wasm_bindgen]
    pub struct WasmRun {
        run_id: String,
        experiment_id: String,
        storage: Arc<Mutex<IndexedDbStorage>>,
        step_counters: HashMap<String, u64>,
        finished: bool,
    }
    }

### JavaScript API

    // Create a new run
    const run = await WasmRun.new('my-experiment');

    // Log metrics (auto-incrementing step)
    run.log_metric('loss', 0.5);
    run.log_metric('loss', 0.4);
    run.log_metric('accuracy', 0.85);

    // Log at specific step
    run.log_metric_at('learning_rate', 100, 0.001);

    // Get all metrics as JSON
    const metrics = JSON.parse(run.get_metrics_json());
    // {
    //   "loss": [
    //     {"step": 0, "value": 0.5, "timestamp": "..."},
    //     {"step": 1, "value": 0.4, "timestamp": "..."}
    //   ],
    //   "accuracy": [
    //     {"step": 0, "value": 0.85, "timestamp": "..."}
    //   ]
    // }

    // Subscribe to metric updates
    run.subscribe_metrics((key, value) => {
        console.log(`${key}: ${value}`);
    });

    // Get run info
    console.log(run.run_id());        // "run-0"
    console.log(run.experiment_id()); // "exp-0"
    console.log(run.current_step('loss')); // 2
    console.log(run.is_finished());   // false

    // Finish the run
    run.finish();  // Success status
    // or
    run.fail();    // Failed status

## Building for WASM

### Prerequisites

    # Install wasm-pack
    cargo install wasm-pack

    # Install wasm32 target
    rustup target add wasm32-unknown-unknown

### Build

    # Build for bundler (webpack, etc.)
    wasm-pack build --target bundler --features wasm

    # Build for web (no bundler)
    wasm-pack build --target web --features wasm

    # Build for Node.js
    wasm-pack build --target nodejs --features wasm

### Output

    pkg/
    ├── entrenar.js           # JavaScript bindings
    ├── entrenar.d.ts         # TypeScript definitions
    ├── entrenar_bg.wasm      # WebAssembly module
    ├── entrenar_bg.wasm.d.ts # WASM TypeScript defs
    └── package.json          # npm package

## Usage in Web Applications

### With a Bundler (Webpack/Vite)

    // Install: npm install ./pkg
    import init, { WasmRun } from 'entrenar';

    async function main() {
        await init();

        const run = WasmRun.new('training-session');

        // Training loop
        for (let epoch = 0; epoch < 100; epoch++) {
            const loss = trainEpoch();
            run.log_metric('loss', loss);

            updateChart(JSON.parse(run.get_metrics_json()));
        }

        run.finish();
    }

    main();

### Without a Bundler

    <script type="module">
        import init, { WasmRun } from './pkg/entrenar.js';

        async function main() {
            await init();

            const run = WasmRun.new('browser-training');
            run.log_metric('loss', 0.5);

            document.getElementById('metrics').textContent =
                run.get_metrics_json();
        }

        main();
    </script>

### React Example

    import { useEffect, useState, useRef } from 'react';
    import init, { WasmRun } from 'entrenar';

    function TrainingDashboard() {
        const [metrics, setMetrics] = useState({});
        const runRef = useRef(null);

        useEffect(() => {
            async function setup() {
                await init();
                runRef.current = WasmRun.new('react-training');
            }
            setup();

            return () => {
                if (runRef.current && !runRef.current.is_finished()) {
                    runRef.current.finish();
                }
            };
        }, []);

        const logMetric = (key, value) => {
            if (runRef.current) {
                runRef.current.log_metric(key, value);
                setMetrics(JSON.parse(runRef.current.get_metrics_json()));
            }
        };

        return (
            <div>
                <button onClick={() => logMetric('loss', Math.random())}>
                    Log Random Loss
                </button>
                <pre>{JSON.stringify(metrics, null, 2)}</pre>
            </div>
        );
    }

## Error Handling

WASM methods return `Result<T, JsValue>` which throws on error:

    try {
        const run = WasmRun.new('my-experiment');
        run.log_metric('loss', 0.5);
    } catch (error) {
        console.error('WASM error:', error);
    }

## Limitations

- No real IndexedDB - Current implementation uses in-memory storage
- Single-threaded - WebAssembly runs on the main thread
- No persistence - Data is lost on page refresh
- Subscribe placeholder - `subscribe_metrics` is a placeholder API

## See Also

- Dashboard Overview
- DashboardSource Trait