npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-lib

Or 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 ePI
  • context.epi - ePI FHIR Bundle
  • context.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 bundle
  • resolveReference() - Resolve FHIR references
  • extractCodes() - Extract codes from CodeableConcepts
  • matchCodes() - 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

  1. Fork & Branch: Create feature branch from main
  2. Implement: Add function to appropriate module (src/fhir/, src/html/, etc.)
  3. Test: Write tests with real FHIR fixtures (see test/fixtures/)
  4. Document: Add JSDoc + example in docs/API.md
  5. PR: Open pull request with clear description of use case
  6. 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.