@atomic-ehr/fhir-canonical-manager

中文文档
0.0.29发布于 2026/10/14MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 9350

npm canary [![npm version](https://img.shields.io/npm/v/@atomic-ehr/fhir-canonical-man

原始使用文档
文档目录51 节
  1. Features
  2. Installation
  3. Quick Start
  4. CLI Usage
  5. Installation
  6. Getting Started
  7. Commands
  8. CLI Examples
  9. Quick Reference
  10. Core Concepts
  11. Package Management
  12. Resource Resolution
  13. API Reference
  14. CanonicalManager(config)
  15. Patches & defect handling
  16. init(): Promise<void>
  17. resolve(url, options?): Promise<Resource>
  18. resolveEntry(url, options?): Promise<IndexEntry>
  19. read(reference): Promise<Resource>
  20. search(params): Promise<Resource[]>
  21. searchEntries(params): Promise<IndexEntry[]>
  22. packages(): Promise<PackageId[]>
  23. addPackages(packages: string[]): Promise<void>
  24. getSearchParametersForResource(resourceType): Promise<Searc…
  25. destroy(): Promise<void>
  26. CLI Reference
  27. Command Overview
  28. Global Options
  29. Search Options
  30. Prefix Search
  31. Filter Combinations
  32. Output Formats
  33. Directory Structure
  34. Cache Format
  35. Advanced Usage
  36. Working with Multiple Packages
  37. Custom Registry Configuration
  38. Building a FHIR Validator
  39. Analyzing Package Dependencies
  40. Performance Considerations
  41. Startup Performance
  42. Memory Usage
  43. Best Practices
  44. Error Handling
  45. TypeScript Types
  46. Development
  47. Project Structure
  48. Requirements
  49. License
  50. Contributing
  51. Development Guidelines

@atomic-ehr/fhir-canonical-manager

npm canary npm version CI

A TypeScript package manager for FHIR resources that provides canonical URL resolution. This library helps you discover, resolve, and manage FHIR packages and their resources through a simple, functional API.

Features

  • 🚀 Automatic Package Management - Automatically installs and manages FHIR packages
  • 💾 Persistent Caching - Caches package metadata to disk for fast subsequent loads
  • 🔍 Canonical URL Resolution - Resolve canonical URLs to specific resource versions
  • 📦 Multiple Package Support - Work with multiple FHIR packages simultaneously
  • 🎯 Flexible Search - Search resources by type, kind, URL, version, or package
  • ⚡ Performance Optimized - In-memory cache with disk persistence
  • 🛠️ TypeScript First - Full TypeScript support with comprehensive types
  • 🩹 Package Defect Handling - Composable patches, canonical exclusion, index recovery, and a diagnostics report
  • 🖥️ CLI Tool - Command-line interface for package management and resource discovery

Installation

bun install @atomic-ehr/fhir-canonical-manager
# or
npm install @atomic-ehr/fhir-canonical-manager

Quick Start

import { CanonicalManager } from '@atomic-ehr/fhir-canonical-manager';

// Create and initialize the manager
const manager = CanonicalManager({
    packages: ["hl7.fhir.r4.core"],
    workingDir: "tmp/fhir",
    registry: "https://fs.get-ig.org/pkgs/" // optional, default registry
});

await manager.init();

// Resolve and read a resource
const resource = await manager.resolve('http://hl7.org/fhir/StructureDefinition/Patient');
console.log(resource.url); // http://hl7.org/fhir/StructureDefinition/Patient

CLI Usage

The package includes a powerful command-line interface (fcm) for managing FHIR packages and searching resources without writing code.

Installation

# Install globally
npm install -g @atomic-ehr/fhir-canonical-manager

# Or use with npx
npx @atomic-ehr/fhir-canonical-manager

# Or run directly with bunx
bunx @atomic-ehr/fhir-canonical-manager

Getting Started

# Create a new project and initialize with FHIR packages
mkdir my-fhir-project && cd my-fhir-project
fcm init hl7.fhir.r4.core

# Search for resources
fcm search Patient

# Get a specific resource
fcm resolve http://hl7.org/fhir/StructureDefinition/Patient

Commands

fcm init

Initialize FHIR packages in the current directory.

# Initialize with packages
fcm init hl7.fhir.r4.core [email protected]

# With custom registry
fcm init hl7.fhir.r4.core --registry https://packages.simplifier.net

# Initialize from existing package.json
fcm init

Configuration is stored in package.json:

{
  "fcm": {
    "packages": ["hl7.fhir.r4.core", "[email protected]"],
    "registry": "https://fs.get-ig.org/pkgs/"
  }
}

fcm list

List installed packages or resources.

# List all packages
fcm list

# List resources in a package
fcm list hl7.fhir.r4.core

# Filter by type
fcm list hl7.fhir.r4.core --type StructureDefinition

# Output as JSON
fcm list --json

Search for resources with advanced filtering and prefix matching capabilities.

Basic Usage:

# Search by URL pattern
fcm search Patient

# Prefix search - space-separated terms match URL components
fcm search str def pat  # Matches: StructureDefinition/Patient

Resource Type Shortcuts:

fcm search -sd          # All StructureDefinitions
fcm search -cs          # All CodeSystems
fcm search -vs          # All ValueSets
fcm search -sd patient  # Patient-related StructureDefinitions

Advanced Filtering:

# Filter by type (-t)
fcm search -t Extension              # All Extensions
fcm search -t Patient                # Resources with type="Patient"
fcm search -sd -t Patient            # Patient StructureDefinition specifically

# Filter by kind (-k)
fcm search -k resource               # All resources (Patient, Observation, etc.)
fcm search -k complex-type           # All complex types (HumanName, Address, etc.)
fcm search -k primitive-type         # All primitive types (string, boolean, etc.)

# Combine filters
fcm search -t Extension -k complex-type  # All Extension complex types
fcm search -sd pat -t Extension          # Patient-related Extensions

# Filter by package
fcm search allergy --package hl7.fhir.us.core

# Output as JSON
fcm search Patient --json

Output Format: By default, results are displayed one per line in the format:

url, {"resourceType":"...", "kind":"...", "type":"..."}

Example output:

http://hl7.org/fhir/StructureDefinition/Patient, {"resourceType":"StructureDefinition","kind":"resource","type":"Patient"}

fcm resolve

Get a resource by its canonical URL.

# Display resource
fcm resolve http://hl7.org/fhir/StructureDefinition/Patient

# Save to file
fcm resolve http://hl7.org/fhir/ValueSet/administrative-gender > gender.json

# Show only specific fields
fcm resolve http://hl7.org/fhir/StructureDefinition/Patient --fields url,type,kind

fcm searchparam

Display search parameters for a specific FHIR resource type.

# Display search parameters for Patient resource
fcm searchparam Patient

# Output as JSON
fcm searchparam Observation --format json

# Export as CSV for spreadsheet analysis
fcm searchparam Encounter --format csv > encounter-params.csv

Output Formats:

  • table (default): Displays each parameter in a multiline format with full data
  • json: Outputs as JSON array with code, type, expression, and url fields
  • csv: Exports as CSV for spreadsheet analysis

Example output (table format):

Code:       active
Type:       token
Expression: Patient.active
URL:        http://hl7.org/fhir/SearchParameter/Patient-active
---
Code:       address
Type:       string
Expression: Patient.address | Person.address | Practitioner.address |
            RelatedPerson.address
URL:        http://hl7.org/fhir/SearchParameter/individual-address
---
Code:       identifier
Type:       token
Expression: Patient.identifier
URL:        http://hl7.org/fhir/SearchParameter/Patient-identifier
---

Total: 29 search parameters

CLI Examples

# Set up a new FHIR project
mkdir my-fhir-project && cd my-fhir-project
fcm init hl7.fhir.r4.core

# Search for Observation-related resources
fcm search observation

# Get a specific resource and save it
fcm resolve http://hl7.org/fhir/StructureDefinition/Observation > observation.json

# List all ValueSets in JSON format
fcm search --type ValueSet --json > valuesets.json

Quick Reference

TaskCommand
Initialize projectfcm init hl7.fhir.r4.core
List packagesfcm list
List package resourcesfcm list hl7.fhir.r4.core
Search all resourcesfcm search
Search by namefcm search Patient
Search with prefixfcm search str def pat
All StructureDefinitionsfcm search -sd
All CodeSystemsfcm search -cs
All ValueSetsfcm search -vs
Filter by typefcm search -t Extension
Filter by kindfcm search -k resource
Combine filtersfcm search -sd -t Patient
Get resourcefcm resolve <url>
Get search parametersfcm searchparam Patient
Export as JSONfcm search --json
Export params as CSVfcm searchparam Patient --format csv
Helpfcm --help

Core Concepts

Package Management

The manager automatically handles FHIR package installation:

  1. Creates a working directory if it doesn't exist
  2. Initializes a package.json for dependency management
  3. Installs specified FHIR packages using npm
  4. Scans packages for .index.json files
  5. Builds an in-memory index of all resources
  6. Persists cache to .fcm/cache/index.json

Resource Resolution

Resources are identified by:

  • Canonical URL: The unique identifier for a FHIR resource
  • Reference ID: An opaque, deterministic hash based on package and file path
  • Package Context: Optional package name/version constraints

API Reference

CanonicalManager(config)

Creates a new instance of the canonical manager.

interface Config {
  packages: string[];               // FHIR packages to install (e.g., ["hl7.fhir.r4.core"])
  workingDir: string;               // Directory for packages and cache
  registry?: string;                // NPM registry URL (optional)
  dropCache?: boolean;              // Rebuild the cache instead of loading it from disk
  patches?: Partial<Patches>;       // Per-phase handler lists (see "Patches & defect handling")
  packageIndex?: PackageIndexMode;  // How to treat shipped .index.json files (default "use")
  /** @deprecated use `patches` — equivalent to package/resource handlers */
  preprocessPackage?: (ctx: PreprocessContext) => PreprocessContext;
  /** @deprecated use `packageIndex` */
  ignorePackageIndex?: boolean;
}

Example:

const manager = CanonicalManager({
    packages: [
        "hl7.fhir.r4.core",
        "[email protected]"
    ],
    workingDir: "./fhir-packages",
    registry: "https://fs.get-ig.org/pkgs/"
});

Patches & defect handling

Real-world FHIR packages ship defects (missing dependencies, canonical URL typos, unavailable ValueSet bindings, cross-version type references, corrupt .index.json). CanonicalManager exposes three knobs to work around them.

packageIndex — how to treat shipped .index.json

type PackageIndexMode = "use" | "recover" | "regenerate";
  • "use" (default): trust the shipped index; scan the directory only if it's absent. A corrupt index is warned about but not worked around (matches prior behavior).
  • "recover": use the index, but fall back to a per-package directory scan when it's corrupt or incomplete (unparseable, or references files missing on disk).
  • "regenerate": ignore shipped indexes and always scan.

ignorePackageIndex is a deprecated alias (true → "regenerate", false → "use"); setting both it and packageIndex throws.

patches — composable transforms and exclusions

patches is a single Patches object with an optional list of handlers per phase, keyed by the value each handler transforms — packageJson, indexEntry, and fhirResource. Each handler receives its package id, that value, and a diagnostics sink, and returns a transformed value or undefined to no-op; the handlers in a phase run left-to-right. The indexEntry handlers may also return null to drop the canonical (it never enters the index). Provide only the phases you need; the deprecated preprocessPackage is appended after your packageJson/fhirResource handlers.

import type { PackagePatch } from "@atomic-ehr/fhir-canonical-manager";

// A handler is (pkg, value, report) => transformedValue | undefined.
// Fix a package's declared version at the package phase:
const fixVersion: PackagePatch = (pkg, packageJson) => ({ ...packageJson, version: "1.2.3" });

// patches: { packageJson: [fixVersion] }

The bundled patch helpers are exported from the @atomic-ehr/fhir-canonical-manager/patch subpath:

  • Scoping combinators — inPackage(match, [handlers]) applies handlers only to matching packages (name, {name, version}, or predicate) and nests; inResource(url, [handlers]) scopes resource handlers to one canonical.
  • Manifest fixes (packageJson phase) — ensureDependency(deps) makes a package declare each dependency at the given version (adds missing ones, adjusts mismatched ones, never adds a package to itself); renamePackage(from, to) fixes a typo'd manifest name.
  • Resource fixes (fhirResource phase) — replaceText(from, to) substitutes a string throughout the serialized body (typo'd canonicals, wrong reference targets, unavailable ValueSet bindings — scope it!); ensureCodes(url, codes) appends missing codes to a CodeSystem without touching existing concepts; patchElement(elementId, (element) => element) rewrites one StructureDefinition element (snapshot and differential) — e.g. widen or narrow its reference targets; scope it with inResource(url, [...]).
  • Index fixes (indexEntry phase) — excludeCanonical({package?, url, reason}) drops a canonical from the index (output and resolution), recording the reason in report().
  • Plumbing — applyPatches, matchPackage.

For example, excludeCanonical dropping a canonical (e.g. an R4 extension that references an R5-only type):

import { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
import { excludeCanonical } from "@atomic-ehr/fhir-canonical-manager/patch";

const manager = CanonicalManager({
    packages: ["hl7.fhir.uv.extensions.r4"],
    workingDir: "./fhir-packages",
    patches: {
        indexEntry: [
            excludeCanonical({
                url: "http://hl7.org/fhir/StructureDefinition/specimen-additive",
                reason: "Uses CodeableReference, not available in R4",
            }),
        ],
    },
});

Caching note: the on-disk index records what the packages ship, so managers with different patches can share a working directory.

  • indexEntry and fhirResource run per load and per read — change them freely.
  • packageJson also runs at install and scan time and is part of the cached package metadata, so changing it still needs dropCache: true (or a cleared working dir).

report() — why you see what you see

const report = manager.report(); // ReportEntry[]
//   { kind: "index-recovery"; package; reason; recovered }
//   | { kind: "exclusion"; package; url; reason }
//   | { kind: "deprecation"; message }

Returns a record of every defect-handling action taken (index recoveries, exclusions, deprecation notices), so downstream tools can explain why a canonical is missing or changed.

Cached-run caveat: exclusion entries are recorded on every run, cached or not, because the indexEntry phase runs on every load. index-recovery entries are only produced while building the index, so a cached run reports nothing for them — use dropCache: true to rebuild if you need to see why a package's index was repaired.

init(): Promise<void>

Initializes the manager. This method:

  • Ensures working directory exists
  • Creates .fcm/cache directory
  • Checks for existing cache
  • If no cache: installs packages and builds index
  • If cache exists: loads from disk (fast startup)
await manager.init();

resolve(url, options?): Promise<Resource>

Resolves a canonical URL directly to a FHIR resource.

// Simple resolution
const patient = await manager.resolve(
    'http://hl7.org/fhir/StructureDefinition/Patient'
);

// With package constraint
const patient = await manager.resolve(
    'http://hl7.org/fhir/StructureDefinition/Patient',
    { package: 'hl7.fhir.r4.core' }
);

// With version constraint
const patient = await manager.resolve(
    'http://hl7.org/fhir/StructureDefinition/Patient',
    { version: '4.0.1' }
);

resolveEntry(url, options?): Promise<IndexEntry>

Resolves a canonical URL to an index entry (metadata only).

const entry = await manager.resolveEntry(
    'http://hl7.org/fhir/StructureDefinition/Patient'
);

console.log(entry);
// {
//   id: "opaque-reference-id",
//   resourceType: "StructureDefinition",
//   url: "http://hl7.org/fhir/StructureDefinition/Patient",
//   version: "4.0.1",
//   kind: "resource",
//   type: "Patient",
//   package: { name: "hl7.fhir.r4.core", version: "4.0.1" }
// }

read(reference): Promise<Resource>

Reads a resource using its reference.

const entry = await manager.resolveEntry(url);
const resource = await manager.read(entry);

search(params): Promise<Resource[]>

Searches and returns full resources matching criteria.

// Get all StructureDefinitions
const structures = await manager.search({
    type: 'StructureDefinition'
});

// Get all resources of kind "resource"
const resources = await manager.search({
    kind: 'resource'
});

// Complex search
const valuesets = await manager.search({
    type: 'ValueSet',
    package: { name: 'hl7.fhir.r4.core', version: '4.0.1' }
});

searchEntries(params): Promise<IndexEntry[]>

Searches and returns index entries (metadata only).

// Find all CodeSystems
const entries = await manager.searchEntries({
    type: 'CodeSystem'
});

// Find by URL
const entries = await manager.searchEntries({
    url: 'http://hl7.org/fhir/StructureDefinition/Patient'
});

Search parameters:

  • kind?: string - Resource kind (e.g., 'resource', 'datatype', 'primitive')
  • url?: string - Canonical URL (exact match)
  • type?: string - Resource type (e.g., 'StructureDefinition', 'ValueSet')
  • version?: string - Resource version
  • package?: PackageId - Filter by package name and version

packages(): Promise<PackageId[]>

Lists all loaded packages.

const packages = await manager.packages();
// [
//   { name: "hl7.fhir.r4.core", version: "4.0.1" },
//   { name: "hl7.fhir.us.core", version: "5.0.1" }
// ]

addPackages(packages: string[]): Promise<void>

Add (and install if needed) extra FHIR packages at runtime.

await manager.addPackages(
    "[email protected]",
    "hl7.fhir.us.davinci-drug-formulary"
);
  • Accepts one or more package specifiers: name or name@version
  • If manager not yet initialised, they are appended and normal init() flow handles install
  • Already present packages are skipped (idempotent)
  • New ones are installed, node_modules re‑scanned, cache persisted
  • Resources become immediately available to resolve, search, CLI commands

Returns: Promise<void> (resolves when indexing is updated)

getSearchParametersForResource(resourceType): Promise<SearchParameter[]>

Gets all search parameters applicable to a specific FHIR resource type.

// Get search parameters for Patient resource
const searchParams = await manager.getSearchParametersForResource('Patient');

// Each parameter contains FHIR SearchParameter fields
searchParams.forEach(param => {
    console.log(`${param.code}: ${param.type} - ${param.expression}`);
});

// Example output:
// identifier: token - Patient.identifier
// name: string - Patient.name
// birthdate: date - Patient.birthDate
// gender: token - Patient.gender

Returns an array of SearchParameter resources with all FHIR fields preserved, including:

  • url: Canonical URL of the search parameter
  • code: Search parameter name used in queries
  • type: Parameter type (token, string, date, reference, etc.)
  • expression: FHIRPath expression
  • base: Array of resource types this parameter applies to
  • Additional FHIR SearchParameter fields

destroy(): Promise<void>

Cleans up resources and clears cache from memory (disk cache persists).

await manager.destroy();

CLI Reference

The fcm command-line interface provides comprehensive FHIR resource management capabilities.

Command Overview

CommandDescription
fcm init [packages...]Initialize FHIR packages in current directory
fcm list [package]List packages or resources
fcm search [terms...]Search resources with advanced filtering
fcm resolve <url>Get a resource by canonical URL
fcm searchparam <resourceType>Display search parameters for a resource type

Global Options

  • --help, -h - Show help information
  • --version, -v - Show version number
  • --json - Output results as JSON (available for list, search, resolve)

Search Options

OptionDescriptionExample
-sdFilter to StructureDefinitionsfcm search -sd
-csFilter to CodeSystemsfcm search -cs
-vsFilter to ValueSetsfcm search -vs
-t <type>Filter by type fieldfcm search -t Extension
-k <kind>Filter by kind fieldfcm search -k resource
--type <resourceType>Filter by resourceTypefcm search --type ValueSet
--package <name>Filter by packagefcm search --package hl7.fhir.us.core

The search command supports intelligent prefix matching. When you provide multiple space-separated terms, each term is matched as a prefix against URL components:

# Search for "str" AND "def" AND "pat" as prefixes
fcm search str def pat

# This matches URLs like:
# - http://hl7.org/fhir/StructureDefinition/Patient
# - http://hl7.org/fhir/StructureDefinition/PatientContact

Filter Combinations

Filters can be combined for precise searching:

# Find all Extension complex types
fcm search -t Extension -k complex-type

# Find Patient-related Extensions
fcm search -sd pat -t Extension

# Find all primitive types in US Core
fcm search -k primitive-type --package hl7.fhir.us.core

Output Formats

Default (Single-line):

http://hl7.org/fhir/StructureDefinition/Patient, {"resourceType":"StructureDefinition","kind":"resource","type":"Patient"}

JSON Format:

fcm search Patient --json

Returns full IndexEntry objects as JSON array.

Directory Structure

After initialization, your working directory will contain:

workingDir/
├── package.json          # NPM package file
├── node_modules/         # Installed FHIR packages
│   ├── hl7.fhir.r4.core/
│   │   ├── package.json
│   │   ├── .index.json   # FHIR resource index
│   │   └── *.json        # FHIR resources
│   └── .../
└── .fcm/
    └── cache/
        └── index.json    # Cached index for fast startup

Cache Format

The cache is stored as a JSON file with the following structure:

{
  entries: {
    "http://hl7.org/fhir/StructureDefinition/Patient": [
      {
        id: "hash-based-id",
        resourceType: "StructureDefinition",
        url: "http://hl7.org/fhir/StructureDefinition/Patient",
        version: "4.0.1",
        kind: "resource",
        type: "Patient",
        package: { name: "hl7.fhir.r4.core", version: "4.0.1" }
      }
    ]
  },
  packages: {
    "hl7.fhir.r4.core": {
      id: { name: "hl7.fhir.r4.core", version: "4.0.1" },
      path: "/path/to/node_modules/hl7.fhir.r4.core",
      canonical: "http://hl7.org/fhir",
      fhirVersions: ["4.0.1"]
    }
  },
  references: {
    "hash-based-id": {
      packageName: "hl7.fhir.r4.core",
      packageVersion: "4.0.1",
      filePath: "/path/to/resource.json",
      resourceType: "StructureDefinition",
      url: "http://hl7.org/fhir/StructureDefinition/Patient",
      version: "4.0.1"
    }
  }
}

Advanced Usage

Working with Multiple Packages

const manager = CanonicalManager({
    packages: [
        "hl7.fhir.r4.core",
        "[email protected]",
        "hl7.fhir.us.davinci-drug-formulary"
    ],
    workingDir: "./fhir-packages"
});

await manager.init();

// Search across all packages
const allValueSets = await manager.search({ type: 'ValueSet' });

// Search in specific package
const usCoreProfiles = await manager.search({
    type: 'StructureDefinition',
    package: { name: 'hl7.fhir.us.core', version: '5.0.1' }
});

Custom Registry Configuration

// Use the default FHIR package registry
const manager = CanonicalManager({
    packages: ["hl7.fhir.r4.core"],
    workingDir: "./fhir-packages",
    registry: "https://fs.get-ig.org/pkgs/"
});

// Use a custom NPM registry
const manager = CanonicalManager({
    packages: ["hl7.fhir.r4.core"],
    workingDir: "./fhir-packages",
    registry: "https://my-private-registry.com"
});

Building a FHIR Validator

async function validateResource(resource: any, manager: CanonicalManager) {
    // Get the profile URL from the resource
    const profileUrl = resource.meta?.profile?.[0];
    if (!profileUrl) {
        throw new Error('No profile specified');
    }

    // Resolve the StructureDefinition
    const profile = await manager.resolve(profileUrl);

    // Validate resource against profile
    // ... validation logic ...
}

Analyzing Package Dependencies

async function analyzeValueSetDependencies(manager: CanonicalManager) {
    // Get all ValueSets
    const valueSets = await manager.search({ type: 'ValueSet' });

    const dependencies = new Map<string, Set<string>>();

    for (const vs of valueSets) {
        const vsPackage = vs.package?.name || 'unknown';

        // Check compose.include for external code systems
        if (vs.compose?.include) {
            for (const include of vs.compose.include) {
                if (include.system) {
                    try {
                        const cs = await manager.resolve(include.system);
                        const csPackage = cs.package?.name || 'unknown';

                        if (csPackage !== vsPackage) {
                            if (!dependencies.has(vsPackage)) {
                                dependencies.set(vsPackage, new Set());
                            }
                            dependencies.get(vsPackage)!.add(csPackage);
                        }
                    } catch {
                        // External code system not in our packages
                    }
                }
            }
        }
    }

    return dependencies;
}

Performance Considerations

Startup Performance

  • First run: Slower due to package installation and index building
  • Subsequent runs: Fast startup by loading from disk cache
  • Cache invalidation: Delete .fcm/cache to force rebuild

Memory Usage

  • All index entries are kept in memory for fast lookup
  • Resource content is loaded on-demand
  • For large package sets, consider memory requirements

Best Practices

  1. Reuse manager instances: Create once, use many times
  2. Use searchEntries() for metadata: Faster than search() when you don't need full resources
  3. Specify package constraints: Faster resolution when package is known
  4. Cache working directory: Share between application instances

Error Handling

The manager throws errors for:

  • Not initialized: Call init() before other methods
  • Resource not found: Canonical URL doesn't exist
  • Invalid reference: Reference ID is invalid
  • Package installation failures: Network or registry issues
try {
    const resource = await manager.resolve('http://invalid.url/Resource');
} catch (error) {
    console.error('Failed to resolve:', error.message);
}

TypeScript Types

interface Reference {
    id: string;              // Opaque identifier
    resourceType: string;    // FHIR resource type
}

interface PackageId {
    name: string;           // Package name
    version: string;        // Package version
}

interface IndexEntry extends Reference {
    indexVersion: number;   // Index format version
    kind?: string;         // resource, datatype, primitive, etc.
    url?: string;          // Canonical URL
    type?: string;         // Specific type (e.g., "Patient")
    version?: string;      // Resource version
    package?: PackageId;   // Source package
}

interface Resource extends Reference {
    url?: string;          // Canonical URL
    version?: string;      // Resource version
    [key: string]: any;    // Other FHIR properties
}

interface SourceContext {
    id?: string;
    package?: PackageId;
    url?: string;
    path?: string;
}

Development

To install dependencies:

bun install

To run tests:

bun test

To run the example:

bun run example.ts

Project Structure

fhir-canonical-manager/
├── src/
│   ├── index.ts          # Core library implementation
│   ├── compat.ts         # Bun/Node.js compatibility layer
│   └── cli/              # CLI implementation
│       ├── index.ts      # CLI entry point
│       ├── init.ts       # Init command
│       ├── list.ts       # List command
│       ├── search.ts     # Search command
│       └── resolve.ts    # Resolve command
├── test/
│   ├── index.test.ts     # Core library tests
│   ├── cli.test.ts       # CLI unit tests
│   └── cli-integration.test.ts # CLI integration tests
├── dist/                 # Compiled output (generated)
├── example.ts            # Usage example
├── package.json
├── tsconfig.json
└── README.md

Requirements

  • Node.js 18+ or Bun 1.0+
  • TypeScript 5.0+
  • Network access for package installation

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Guidelines

  1. All code in single file: src/index.ts
  2. Functional programming style
  3. No external dependencies except Node.js built-ins
  4. Comprehensive tests in test/index.test.ts
  5. Update README.md with API changes

版本与发布记录

@atomic-ehr/fhir-canonical-manager 共发布 98 个版本,首次发布于 2025/07/31;过去 12 个月发布了 69 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.0.29latest2026/10/1424 天前
0.0.29-canary.20261014123756.2929e7dcanary2026/10/1424 天前
0.0.28-canary.20261014111502.f48d9d02026/10/1424 天前
0.0.282026/09/251 个月前
0.0.28-canary.20260925083515.c7f09842026/09/251 个月前
0.0.27-canary.20260925083243.c157bdb2026/09/251 个月前

关于 @atomic-ehr/fhir-canonical-manager 的常见问题

@atomic-ehr/fhir-canonical-manager 是什么?

[![npm version](https://img.shields.io/npm/v/@atomic-ehr/fhir-canonical-man

如何安装 @atomic-ehr/fhir-canonical-manager?

在项目目录运行 npm install @atomic-ehr/fhir-canonical-manager,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:typescript(^5)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 fcm,可以用 npx fcm 直接运行。

@atomic-ehr/fhir-canonical-manager 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@atomic-ehr/fhir-canonical-manager 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@atomic-ehr/fhir-canonical-manager 可以商用吗?

@atomic-ehr/fhir-canonical-manager 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@atomic-ehr/fhir-canonical-manager 的下载量有多少?

根据 npm 官方下载统计,@atomic-ehr/fhir-canonical-manager 在 2026/10/07 – 2026/11/05 这 30 天内被下载 9,350 次,日均约 312 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@atomic-ehr/fhir-canonical-manager 还在维护吗?

最新版本 0.0.29 发布于 2026/10/14(24 天前);至今共发布 98 个版本,其中过去 12 个月发布了 69 个;首次发布于 2025/07/31。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。