WebAssembly Integration
The OctoFHIR FHIRPath WebAssembly bindings provide high-performance FHIRPath evaluation directly in web browsers without requiring a server.
Installation
Section titled “Installation”Using npm
Section titled “Using npm”# Install the WASM packagenpm install fhirpath-wasm
# Or install from local buildcd fhirpath-wasmnpm installnpm run build
Direct Usage
Section titled “Direct Usage”You can also use the WASM module directly by including the generated files in your web project:
fhirpath_wasm.js
- JavaScript bindingsfhirpath_wasm_bg.wasm
- WebAssembly binaryfhirpath_wasm.d.ts
- TypeScript definitions (if using TypeScript)
Basic Usage
Section titled “Basic Usage”Module Initialization
Section titled “Module Initialization”import init, { evaluate_fhirpath, validate_fhirpath, get_fhirpath_version} from './pkg/fhirpath_wasm.js';
// Initialize the WASM moduleasync function initFHIRPath() { try { await init(); console.log('FHIRPath WASM initialized'); console.log('Version:', get_fhirpath_version()); } catch (error) { console.error('Failed to initialize WASM:', error); }}
// Call initializationinitFHIRPath();
Expression Evaluation
Section titled “Expression Evaluation”// Sample FHIR Patient resourceconst patient = { resourceType: "Patient", name: [ { given: ["John", "Michael"], family: "Smith" } ], gender: "male", birthDate: "1990-01-15"};
// Convert to JSON string (required by WASM interface)const resourceJson = JSON.stringify(patient);
// Evaluate FHIRPath expressiontry { const result = evaluate_fhirpath("Patient.name.given", resourceJson); const parsedResult = JSON.parse(result);
if (parsedResult.error) { console.error('Evaluation error:', parsedResult.error); } else { console.log('Given names:', parsedResult); // Output: ["John", "Michael"] }} catch (error) { console.error('Unexpected error:', error);}
Expression Validation
Section titled “Expression Validation”// Validate FHIRPath expression syntaxtry { const result = validate_fhirpath("Patient.name.family"); const validation = JSON.parse(result);
if (validation.valid) { console.log('✅ Expression is valid'); } else { console.log('❌ Expression is invalid:', validation.error); }} catch (error) { console.error('Validation error:', error);}
Advanced Usage
Section titled “Advanced Usage”Complete Web Application Example
Section titled “Complete Web Application Example”<!DOCTYPE html><html><head> <title>FHIRPath WASM Demo</title></head><body> <div> <h1>FHIRPath Evaluator</h1> <textarea id="resource" placeholder="Enter FHIR resource JSON..."></textarea> <input id="expression" placeholder="Enter FHIRPath expression..." /> <button onclick="evaluateExpression()">Evaluate</button> <pre id="result"></pre> </div>
<script type="module"> import init, { evaluate_fhirpath, get_fhirpath_version } from './pkg/fhirpath_wasm.js';
let wasmInitialized = false;
async function initializeWasm() { try { await init(); wasmInitialized = true; console.log('WASM initialized, version:', get_fhirpath_version()); } catch (error) { console.error('WASM initialization failed:', error); } }
window.evaluateExpression = function() { if (!wasmInitialized) { document.getElementById('result').textContent = 'WASM not initialized yet'; return; }
const resource = document.getElementById('resource').value; const expression = document.getElementById('expression').value;
try { const result = evaluate_fhirpath(expression, resource); const parsed = JSON.parse(result);
if (parsed.error) { document.getElementById('result').textContent = 'Error: ' + parsed.error; } else { document.getElementById('result').textContent = JSON.stringify(parsed, null, 2); } } catch (error) { document.getElementById('result').textContent = 'Error: ' + error.message; } };
// Initialize on page load initializeWasm(); </script></body></html>
Error Handling
Section titled “Error Handling”function safeEvaluate(expression, resourceJson) { try { // Validate JSON first JSON.parse(resourceJson);
// Evaluate expression const result = evaluate_fhirpath(expression, resourceJson); const parsed = JSON.parse(result);
if (parsed.error) { return { success: false, error: parsed.error, type: 'evaluation' }; }
return { success: true, data: parsed }; } catch (error) { if (error instanceof SyntaxError) { return { success: false, error: 'Invalid JSON in resource', type: 'json' }; }
return { success: false, error: error.message, type: 'unexpected' }; }}
TypeScript Support
Section titled “TypeScript Support”// Type definitions for the WASM moduledeclare module 'fhirpath-wasm' { export default function init(): Promise<void>; export function evaluate_fhirpath(expression: string, resource: string): string; export function validate_fhirpath(expression: string): string; export function get_fhirpath_version(): string;}
// Usage with typesimport init, { evaluate_fhirpath, validate_fhirpath } from 'fhirpath-wasm';
interface EvaluationResult { success: boolean; data?: any; error?: string;}
async function evaluateWithTypes(expression: string, resource: object): Promise<EvaluationResult> { try { const resourceJson = JSON.stringify(resource); const result = evaluate_fhirpath(expression, resourceJson); const parsed = JSON.parse(result);
if (parsed.error) { return { success: false, error: parsed.error }; }
return { success: true, data: parsed }; } catch (error) { return { success: false, error: (error as Error).message }; }}
Common FHIRPath Expressions
Section titled “Common FHIRPath Expressions”Here are some commonly used FHIRPath expressions you can try:
Patient Resource
Section titled “Patient Resource”// Get patient's given names"Patient.name.given"
// Get patient's family name"Patient.name.family"
// Get patient's gender"Patient.gender"
// Get patient's birth date"Patient.birthDate"
// Get patient's phone numbers"Patient.telecom.where(system='phone').value"
// Get patient's email addresses"Patient.telecom.where(system='email').value"
// Get patient's city"Patient.address.city"
Observation Resource
Section titled “Observation Resource”// Get observation value"Observation.value"
// Get observation code"Observation.code.coding.code"
// Get observation status"Observation.status"
// Get observation date"Observation.effectiveDateTime"
Performance Considerations
Section titled “Performance Considerations”- Initialization: WASM module initialization is asynchronous and should be done once per application
- Memory: Large FHIR resources may require more memory; consider chunking for very large datasets
- Caching: Cache frequently used expressions and resources when possible
- Error Handling: Always handle both WASM errors and FHIRPath evaluation errors
Browser Compatibility
Section titled “Browser Compatibility”The WASM module works in all modern browsers that support:
- WebAssembly (WASM)
- ES6 Modules
- Async/Await
Supported browsers:
- Chrome 61+
- Firefox 60+
- Safari 11+
- Edge 16+
Deployment
Section titled “Deployment”When deploying your application:
- Ensure WASM files are served with correct MIME types
- Configure your web server to serve
.wasm
files withapplication/wasm
content type - Consider using a CDN for better performance
- Enable gzip compression for WASM files
Example server configuration (nginx):
Section titled “Example server configuration (nginx):”location ~* \.wasm$ { add_header Content-Type application/wasm; add_header Cache-Control "public, max-age=31536000";}
Interactive Playground
Section titled “Interactive Playground”Try the FHIRPath Playground to experiment with expressions interactively in your browser.