@gravitate-health/lens-tool-lib
v1.0.0
Published
Helper library for developing Gravitate Health lens components
Readme
Gravitate Health Lens Toolkit
A comprehensive helper library for developing Gravitate Health lens components. This toolkit eliminates 70-80% of boilerplate code and provides standardized, tested functions for common lens operations.
🎯 Purpose
The Gravitate Health Lens Toolkit simplifies lens development by providing:
- FHIR Resource Extraction: Easy access to IPS data (conditions, medications, observations, etc.)
- ePI Processing: Parse extensions, match identifiers, find annotated sections
- HTML DOM Manipulation: DOM manipulation with environment detection (Node.js/browser)
- Internationalization: Language detection and multi-language messages
- Utilities: Common functions (date calculations, deep equality, validation helpers, etc.)
📦 Installation
npm install @gravitate-health/lens-tool-libOr include the library in your lens project directory.
🚀 Quick Start
Simple Function-Based Approach
Just export enhance() and getSpecification() functions. Import only what you need:
const { getConditions } = require('@gravitate-health/lens-tool-lib');
const { findSectionsByCode } = require('@gravitate-health/lens-tool-lib');
const { addClasses } = require('@gravitate-health/lens-tool-lib');
// Or import multiple functions at once:
const {
getConditions,
findSectionsByCode,
addClasses
} = require('@gravitate-health/lens-tool-lib');
/**
* Main enhance function - receives validated context
* @param {Object} context - Contains pv, html, epi, ips (already validated)
* @returns {Promise<string>} Enhanced HTML
*/
async function enhance(context) {
// Extract data from IPS
const conditions = getConditions(context.ips);
// Find matching ePI sections
const categories = findSectionsByCode(
context.epi,
conditions.flatMap(c => c.codes)
);
// Add CSS classes to matching sections
return await addClasses(
context.html,
categories,
'highlight',
'my-lens'
);
}
function getSpecification() {
return "1.0.0";
}
async function explanation(context, lang = "en") {
return "Explanation text";
}
// Export lens interface
module.exports = {
enhance,
getSpecification,
explanation
};📚 Core Modules
Lens Context
Your lens functions receive a context object that is already validated and contains:
context.pv- Persona Vector (patient preferences)context.html- HTML content from ePIcontext.epi- ePI FHIR Bundlecontext.ips- IPS FHIR Bundle
No need to validate or create context - it's ready to use!
FHIR Functions
The library provides four main FHIR modules:
Common FHIR Functions (from fhir/common.js)
Low-level helpers for working with FHIR resources:
getResourcesByType()- Get resources by type from any bundleresolveReference()- Resolve FHIR referencesextractCodes()- Extract codes from CodeableConceptsmatchCodes()- Match codes with optional system matching
IPS Functions (from fhir/ips.js)
Extract and parse FHIR resources from IPS bundles:
const {
getConditions,
getMedications,
getObservationsByCode,
getPatientInfo
} = require('@gravitate-health/lens-tool-lib');
// Get all conditions
const conditions = getConditions(context.ips);
// Get all medications (handles references and ingredients)
const medications = getMedications(context.ips);
// Get observations with filters
const lowPotassium = getObservationsByCode(
context.ips,
["2823-3"],
{ valueFilter: (obs) => obs.value < 3.5 }
);
// Get patient info with calculated age
const patient = getPatientInfo(context.ips);ePI Functions (from fhir/epi.js)
Parse ePI bundles and extensions (ePI IS FHIR).
const {
findSectionsByCode,
matchProductIdentifier,
getLanguage
} = require('@gravitate-health/lens-tool-lib');
// Find sections by code
const categories = findSectionsByCode(
context.epi,
["77386006", "69840006"]
);
// Match product identifiers
const isMatch = matchProductIdentifier(
context.epi,
["CIT-204447"]
);
// Get language
const lang = getLanguage(context.epi);Persona Vector Functions (from fhir/pv.js)
Extract and analyze persona dimensions from Persona Vector collections:
const {
getHealthLiteracy,
getDigitalLiteracy,
getAllDimensions,
getDimensionsSummary,
DIMENSION_CODES
} = require('@gravitate-health/lens-tool-lib');
// Get specific dimensions
const healthLit = getHealthLiteracy(context.pv);
const digitalLit = getDigitalLiteracy(context.pv);
// Check literacy level and adapt content
if (healthLit && healthLit.value.includes('low')) {
// Simplify medical terminology
}
// Get all dimensions
const dimensions = getAllDimensions(context.pv);
// Get summary
const summary = getDimensionsSummary(context.pv);
console.log(`Total dimensions: ${summary.totalDimensions}`);
console.log(`Available: ${summary.dimensionCodes.join(', ')}`);
// Use dimension constants
const employment = getDimensionByCode(context.pv, DIMENSION_CODES.EMPLOYMENT);
// Find dimensions with numeric values > 5
const highValues = findDimensionsByValue(context.pv,
(value) => typeof value === 'number' && value > 5
);HTML Functions (from html/dom.js)
DOM manipulation and HTML processing.
const { addClasses, insertBanner, traverseDOM } = require('@gravitate-health/lens-tool-lib');
// Add CSS classes to elements
const result = await addClasses(
context.html,
['section-4.4', 'contraindications'],
'highlight',
'my-lens'
);
// Insert banner
const result = await insertBanner(
context.html,
'<div>Warning message</div>',
'top',
'banner-class'
);
// Traverse DOM with custom visitor
const result = await traverseDOM(context.html, (element, doc) => {
if (element.tagName === 'DIV' && element.classList.contains('warning')) {
element.classList.add('highlight');
}
});Language Functions (from i18n/language.js)
Language detection and internationalization.
const {
getLanguage, // from fhir/epi
getStandardMessages,
getLangKey,
translate
} = require('@gravitate-health/lens-tool-lib');
// Detect language (use getLanguage from fhir/epi module)
const lang = getLanguage(context.epi);
// Get translated messages
const messages = getStandardMessages(lang);Utility Functions (from utils/common.js)
General utility functions including validation helpers.
const {
deepEqual,
calculateAge,
addMonths,
isDateInRange,
unique,
groupBy,
ensureArray,
isEmpty,
validateRequiredFields,
safeGet
} = require('@gravitate-health/lens-tool-lib');
// Deep equality
if (deepEqual(obj1, obj2)) { }
// Age calculation
const age = calculateAge("1990-05-15");
// Date utilities
const futureDate = addMonths(new Date(), 10);
const isInRange = isDateInRange(date, start, end);
// Array utilities
const uniqueValues = unique([1, 2, 2, 3]);
const grouped = groupBy(items, 'type');
// Validation helpers
const arr = ensureArray(value);
if (isEmpty(arr)) { }
const validation = validateRequiredFields(obj, ['field1', 'field2']);
const value = safeGet(obj, 'nested.path.value', defaultValue);📖 Examples
See the examples/ directory for complete working examples:
- simple-condition-lens.js: Highlight sections based on patient conditions
- pregnancy-lens.js: Pregnancy/breastfeeding warnings with age checks
- medication-interaction-lens.js: Drug interaction warnings
- literacy-lens.js: Adapt content based on health and digital literacy levels
All examples use the functional approach with enhance(), getSpecification(), and explanation().
📄 Documentation
Full API documentation is available in docs/API.md.
🔧 Development
Project Structure
@gravitate-health/lens-tool-lib/
├── src/
│ ├── fhir/
│ │ ├── common.js # Common FHIR helpers
│ │ ├── ips.js # IPS-specific functions
│ │ ├── epi.js # ePI-specific functions (ePI IS FHIR)
│ │ └── pv.js # Persona Vector functions
│ ├── html/
│ │ └── dom.js # DOM manipulation utilities
│ ├── i18n/
│ │ └── language.js # Translations and i18n
│ ├── utils/
│ │ └── common.js # Utility functions
│ └── index.js
├── examples/
│ ├── simple-condition-lens.js
│ ├── pregnancy-lens.js
│ ├── medication-interaction-lens.js
│ └── literacy-lens.js
├── docs/
│ └── API.md
├── package.json
└── README.md🎯 Benefits for Developers
- 70-80% Less Code: Eliminate repetitive boilerplate
- Consistency: All lenses follow same patterns
- Tested: Pre-tested, reliable functions
- Type Safety: Clear function signatures
- Documentation: Comprehensive API docs and examples
- Maintainability: Bug fixes benefit all lenses
- Faster Development: Focus on business logic, not infrastructure
- No Classes: Pure functional approach - just import and use functions
📝 License
Apache 2.0
🤝 Contributing
This library collects common functions used across multiple lenses. The contribution process is intentionally open, lean, and simple.
When to Add Functions
- Function is needed by 2+ lenses (avoid one-off utilities)
- Eliminates significant boilerplate (aim for 70-80% code reduction)
- Handles common FHIR/ePI patterns consistently
- Improves performance or reliability across lenses
Contribution Workflow
- Fork & Branch: Create feature branch from
main - Implement: Add function to appropriate module (
src/fhir/,src/html/, etc.) - Test: Write tests with real FHIR fixtures (see
test/fixtures/) - Document: Add JSDoc + example in
docs/API.md - PR: Open pull request with clear description of use case
- Review: Maintainers will review for correctness, performance, and fit
PR Guidelines
- Keep PRs focused (one function or related set)
- Include test coverage for new functions
- Follow existing patterns (JSDoc, early returns, error handling)
- Demonstrate value across multiple lens use cases
- Ensure both Node.js and browser compatibility for DOM functions
Code Review Focus
- Correctness with FHIR R4 spec
- Performance impact (remember 1-second timeout)
- API clarity and consistency
- Test coverage and edge cases
By integrating validation and version control, this group of tools helps mitigate risks associated with code migration, ultimately leading to a smoother transition to new technologies.
📧 Support
For questions or issues, please open an issue on the GitHub repository.
