A utility module for downloading, indexing, caching, and managing FHIR packages from the FHIR Package Registry and Simplifier
npm install fhir-package-installerhl7.fhir.uv.sdc@3.0.0)
latest versions
.fpi.index.json) of all FHIR JSON files in the package
package.json manifest and dependencies
bash
npm install fhir-package-installer
`
---
Quick Start (Default Usage)
`ts
import fpi from 'fhir-package-installer';
await fpi.install('hl7.fhir.r4.core@4.0.1');
const index = await fpi.getPackageIndexFile({ id: 'hl7.fhir.r4.core', version: '4.0.1' });
`
---
Dual Module Usage (ESM & CommonJS)
Starting with version 1.4.1, this package ships a dual build that supports both ESM and CommonJS consumers without the ERR_REQUIRE_ESM error.
$3
`js
import { FhirPackageInstaller } from 'fhir-package-installer';
const fpiClassInstance = new FhirPackageInstaller();
await fpiClassInstance.install('hl7.fhir.r4.core@4.0.1');
`
$3
`js
const { FhirPackageInstaller } = require('fhir-package-installer');
const fpiClassInstance = new FhirPackageInstaller();
fpiClassInstance.install('hl7.fhir.r4.core@4.0.1').then(() => console.log('Installed'));
`
$3
For convenience, a default instance (fpi) is still exported:
`js
import fpi from 'fhir-package-installer'; // ESM
// or
const fpi = require('fhir-package-installer').default; // CJS
`
Advanced Usage (Custom Configurations)
Use the FhirPackageInstaller class directly to customize behavior:
`ts
import { FhirPackageInstaller } from 'fhir-package-installer';
const customFpi = new FhirPackageInstaller({
logger: {
info: msg => console.log('[INFO]', msg),
warn: msg => console.warn('[WARN]', msg),
error: msg => console.error('[ERROR]', msg)
},
registryUrl: 'https://packages.fhir.org',
registryToken: 'your-registry-token-here', // For private registries / artifactories
cachePath: './my-fhir-cache'
});
await customFpi.install('hl7.fhir.r4.core');
`
$3
- logger – Optional. Custom logger implementing the Logger interface (from @outburn/types).
- registryUrl – Optional. Custom package registry base URL (e.g., JFrog Artifactory).
- registryToken – Optional. Authentication token for private registries.
- cachePath – Optional. Directory where packages will be cached.
- skipExamples – Optional. Don't install dependencies that have examples in the package name
---
Public API Methods
$3
Downloads and installs a package and all its dependencies.
Accepts either a package identifier object ({ id, version } from @outburn/types) or a string ('name@version', 'name#version', or 'name').
---
$3
Downloads a package tarball and optionally extracts it to a destination directory.
---
$3
Installs a package from a local file or directory.
The package can be a tarball file or a directory containing the package files.
---
$3
Fetches the package.json manifest of an installed package.
---
$3
Returns the .fpi.index.json content for the package.
If the file doesn't exist, it will be generated automatically.
---
$3
Returns the direct dependencies of a package, including both explicit dependencies defined in package.json and automatic implicit dependencies (for core FHIR packages).
---
$3
Looks up the latest published version for a given package name (string only).
---
$3
Parses name, name@version, or name#version into an object with id and version.
If no version is provided, resolves to the latest.
---
$3
Returns true if the package is already present in the local cache.
---
$3
Returns the root cache directory used by this installer.
---
$3
Returns the logger instance used by this installer.
---
$3
Returns the path to a specific package folder in the cache.
---
Implicit Dependency Management
FHIR Package Installer automatically manages implicit dependencies for core FHIR packages. When you install a base FHIR package (like hl7.fhir.r4.core), the system automatically includes essential terminology and extension packages that are commonly required.
$3
When installing core FHIR packages, these implicit dependencies are automatically added:
| Core Package | Implicit Dependencies |
|--------------|----------------------|
| hl7.fhir.r3.core | hl7.terminology.r3, hl7.fhir.uv.extensions.r3 |
| hl7.fhir.r4.core | hl7.terminology.r4, hl7.fhir.uv.extensions.r4 |
| hl7.fhir.r5.core | hl7.terminology.r5, hl7.fhir.uv.extensions.r5 |
$3
The implicit dependency resolver uses an online-first, cache-fallback strategy:
1. Online Resolution: Attempts to resolve the latest versions from the registry
2. Cache Fallback: If online resolution fails, uses the latest cached versions
3. Graceful Degradation: Logs warnings but continues installation if implicit packages can't be resolved
---
FHIR Package Latest Version Caching
To prevent HTTP 429 rate limiting errors when installing multiple FHIR packages or resolving many "latest" versions, FHIR Package Installer caches registry package metadata on disk and reuses it across processes:
$3
- Automatic caching: Registry package documents are cached on disk under .fpi.cache/metadata/
- Shared across processes: Multiple FhirPackageInstaller instances (and separate Node processes) reuse the same cached metadata when using the same cachePath
- Cache file format: One file per package keyed by a stable hash, containing { expiresAt, data } where data['dist-tags'].latest is used for "latest" resolution
- TTL: Entries expire after 30 minutes by default (configurable via registryTtlMs; best-effort)
FHIR Package Cache Directory
$3
Location of the default global package cache differs per operating system.
Windows:
`
C:\Users\\.fhir\packages
`
Unix/Linux:
`
~/.fhir/packages
`
$3
Windows:
`
%ProgramData%\.fhir\packages
`
(typically C:\ProgramData\.fhir\packages)
Note: The package cache uses the location indicated by the ProgramData environment variable.
Unix/Linux:
`
/var/lib/.fhir/packages
`
$3
The automatic detection of user vs. system service context can be overridden via the FHIR_PACKAGE_CACHE_MODE environment variable:
- FHIR_PACKAGE_CACHE_MODE=system - Force use of system service paths
- FHIR_PACKAGE_CACHE_MODE=user - Force use of user paths
This is useful in containerized environments or when the automatic detection doesn't match your deployment scenario.
$3
The package cache root folder contains a folder per package where the folder name is the package name, a pound and the package version:
- package-cache-folder
- hl7.fhir.us.core#0.1.1
- hl7.fhir.r4.core#4.0.1
- hl7.fhir.uv.sdc#3.0.0
---
JFrog Artifactory & Private Registry Support
FHIR Package Installer supports JFrog Artifactory and other private NPM registries that act as secure proxies or mirrors of the public FHIR Package Registry. Artifactory is commonly used by enterprises to provide cached, controlled access to FHIR packages through their internal infrastructure, along with other solutions like Nexus Repository and Azure DevOps Artifacts.
$3
`ts
import { FhirPackageInstaller } from 'fhir-package-installer';
const artifactoryFpi = new FhirPackageInstaller({
registryUrl: 'https://your-artifactory.example.com/artifactory/api/npm/fhir-npm-remote',
registryToken: 'cmVmdGtuOjAxOjE3ODQ5Nzc0OTI6NU83WE9JTkFrOVJtVWxxSmpzcXZsYWVaeHpL', // Do not include 'Bearer' prefix
cachePath: './custom-cache'
});
// Install public FHIR packages through your Artifactory registry
await artifactoryFpi.install('hl7.fhir.r4.core@4.0.1');
await artifactoryFpi.install('hl7.fhir.us.core@6.1.0');
`
$3
⚠️ Critical Configuration: When setting up your JFrog Artifactory repository for FHIR packages, you must:
1. Repository Type: Create an npm remote repository (not generic)
2. Remote URL: Set to https://packages.simplifier.net
- ⚠️ Use Simplifier URL, not packages.fhir.org (which is just an alias)
- The actual package metadata and tarball URLs always reference Simplifier
3. in Advanced Settings: ✅ Check "Bypass HEAD Request" option
- This is essential because the FHIR Package Registry doesn't fully comply with npm protocol expectations
- Without this setting, package installation will fail
Why this matters: The FHIR Package Registry behaves differently from standard npm registries. The "Bypass HEAD Request" option tells Artifactory to skip certain npm protocol checks that would otherwise cause failures when proxying FHIR packages.
$3
- JFrog Artifactory: npm remote repositories (most common enterprise solution)
- Sonatype Nexus: npm proxy repositories
- Azure DevOps Artifacts: npm feeds
- GitHub Packages: npm package registry
- Custom npm registries: Any npm-compatible registry with Bearer token authentication
---
Index Format:
.fpi.index.json
Each installed package is scanned for JSON files in the package/ subdirectory (excluding package.json and any [*].index.json files). A generated index is written to:
`bash
/package/.fpi.index.json
`
Sample structure:
`json
{
"index-version": 2,
"files": [
{
"filename": "StructureDefinition-something.json",
"resourceType": "StructureDefinition",
"id": "something",
"url": "http://...",
"kind": "resource",
"name": "Something",
"version": "1.0.0",
"type": "Observation",
"supplements": "http://...",
"content": "complete",
"baseDefinition": "http://...",
"derivation": "constraint",
"date": "2020-01-01"
}
]
}
`
Notes:
- All fields are optional and, with the exception of filename, populated directly from the original JSON resource.
- This index is an enhanced alternative to the .index.json` format in the FHIR NPM spec.