{"id":50103100,"url":"https://github.com/dnlbox/fhir-capability-analyzer","last_synced_at":"2026-05-23T08:35:49.214Z","repository":{"id":352446985,"uuid":"1215123192","full_name":"dnlbox/fhir-capability-analyzer","owner":"dnlbox","description":"CLI and library for fetching, analyzing, and comparing FHIR server CapabilityStatements. Profile detection for US Core, UK Core, AU Core, IPS, ISiK and more.","archived":false,"fork":false,"pushed_at":"2026-05-20T20:51:05.000Z","size":320,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-20T21:47:46.320Z","etag":null,"topics":["capability-statement","cli","fhir","fhir-r4","fhir-r4b","fhir-r5","health-interoperability","healthcare","hl7","ips","r4b","typescript","us-core"],"latest_commit_sha":null,"homepage":"https://dnlbox.github.io/fhir-capability-analyzer/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dnlbox.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T14:09:45.000Z","updated_at":"2026-05-20T20:51:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dnlbox/fhir-capability-analyzer","commit_stats":null,"previous_names":["dnlbox/fhir-capability-analyzer"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/dnlbox/fhir-capability-analyzer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnlbox%2Ffhir-capability-analyzer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnlbox%2Ffhir-capability-analyzer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnlbox%2Ffhir-capability-analyzer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnlbox%2Ffhir-capability-analyzer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dnlbox","download_url":"https://codeload.github.com/dnlbox/fhir-capability-analyzer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnlbox%2Ffhir-capability-analyzer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33389227,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["capability-statement","cli","fhir","fhir-r4","fhir-r4b","fhir-r5","health-interoperability","healthcare","hl7","ips","r4b","typescript","us-core"],"created_at":"2026-05-23T08:35:48.535Z","updated_at":"2026-05-23T08:35:49.208Z","avatar_url":"https://github.com/dnlbox.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fhir-capability-analyzer\n\n[![CI](https://github.com/dnlbox/fhir-capability-analyzer/actions/workflows/ci.yml/badge.svg)](https://github.com/dnlbox/fhir-capability-analyzer/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/dnlbox/fhir-capability-analyzer/actions/workflows/codeql.yml/badge.svg)](https://github.com/dnlbox/fhir-capability-analyzer/actions/workflows/codeql.yml)\n[![npm](https://img.shields.io/npm/v/fhir-capability-analyzer)](https://www.npmjs.com/package/fhir-capability-analyzer)\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n\nA TypeScript CLI and library that answers the question: **\"What does this FHIR server actually support?\"**\n\n- Fetch a CapabilityStatement from any FHIR server URL or local JSON file\n- Summarize resources, interactions, operations, and security in a readable format\n- Detect conformance to international profiles: US Core, UK Core, AU Core, IPS, IPA, SMART App Launch, ISiK, and more\n- Generate a structured analysis report with warnings for common configuration issues\n- Compare two servers' capabilities side by side\n- Output as human-readable text, JSON (CI-friendly), or Markdown\n\nThe browser-safe core works in Node.js, Deno, Cloudflare Workers, and browser bundles. The CLI wraps the same core with file I/O and exit codes.\n\n## Why this exists\n\nEvery FHIR server exposes a CapabilityStatement at `/metadata` describing every resource, interaction, search parameter, and security mechanism it supports. Reading one by hand is painful: a typical document runs 1,000 to 3,000 lines of deeply nested JSON.\n\n`fhir-capability-analyzer` does that reading for you: fetch, parse, summarize, and compare, all from the command line. It also detects which international profiles a server declares support for, which is useful when integrating with servers in different countries or healthcare systems.\n\n## Quick start\n\n```bash\n# Analyze a live server\nnpx fhir-capability-analyzer analyze https://hapi.fhir.org/baseR4\n\n# Analyze a local file\nnpx fhir-capability-analyzer analyze ./capability.json\n\n# JSON output (CI-friendly, stable schema)\nnpx fhir-capability-analyzer analyze https://hapi.fhir.org/baseR4 --format json\n\n# Markdown output\nnpx fhir-capability-analyzer analyze https://hapi.fhir.org/baseR4 --format markdown\n\n# Compare two servers\nnpx fhir-capability-analyzer compare https://server-a.example.com https://server-b.example.com\n\n# Compare and fail CI if differences found\nnpx fhir-capability-analyzer compare ./baseline.json https://server.example.com --exit-on-diff\n```\n\n## Sample output\n\n```txt\nServer: HAPI FHIR R4 Test Server\nFHIR Version: 4.0.1\nStatus: active\nFormats: application/fhir+json, application/fhir+xml, json, xml\n\nResources (3)\n-------------\nPatient                        read, vread, update, patch, delete, history-instance, history-type, create, search-type [7 search params]\nObservation                    read, create, update, delete, search-type [4 search params]\nCondition                      read, create, update, search-type [3 search params]\n\nOperations (2)\n--------------\n  $everything\n  $validate\n\nProfile Conformance\n-------------------\n  (No known profiles detected)\n\nSecurity\n--------\n  CORS: enabled\n  Auth: (none declared)\n```\n\n## Installation\n\n```bash\n# Global CLI\nnpm install -g fhir-capability-analyzer\n\n# Project dependency (library use)\nnpm install fhir-capability-analyzer\n```\n\n## CLI reference\n\n### `analyze \u003csource\u003e`\n\nAnalyze a CapabilityStatement from a URL or local JSON file.\n\n```bash\nArguments:\n  source              FHIR server URL or path to local JSON file\n\nOptions:\n  -f, --format        Output format: text | json | markdown  (default: text)\n  --bearer-token      Bearer token for OAuth 2.0 protected servers\n  -v, --version       Print version\n  -h, --help          Show help\n\nExit codes:\n  0  Success, no warnings\n  1  Success, but warnings were found (text and markdown modes only)\n  2  Fetch or parse error\n```\n\n### `compare \u003csourceA\u003e \u003csourceB\u003e`\n\nCompare two FHIR servers' capabilities.\n\n```bash\nArguments:\n  sourceA             FHIR server URL or local JSON file (baseline)\n  sourceB             FHIR server URL or local JSON file (target)\n\nOptions:\n  -f, --format        Output format: text | json | markdown  (default: text)\n  --exit-on-diff      Exit with code 1 when differences are found\n  --bearer-token      Bearer token for OAuth 2.0 protected servers\n  -h, --help          Show help\n```\n\n### Authentication\n\nFor OAuth 2.0 protected servers, pass the token via flag or environment variable:\n\n```bash\n# Via flag\nfhir-capability-analyzer analyze https://secure.example.com --bearer-token \"$TOKEN\"\n\n# Via environment variable (preferred for CI — keeps the token out of shell history)\nFHIR_TOKEN=eyJ... fhir-capability-analyzer analyze https://secure.example.com\n\n# Compare two secured servers (same token used for both)\nFHIR_TOKEN=eyJ... fhir-capability-analyzer compare https://server-a.example.com https://server-b.example.com\n```\n\nThe `--bearer-token` flag takes precedence over `FHIR_TOKEN`. Tokens are never written to stdout or included in any output format.\n\n## TypeScript library API\n\n```typescript\nimport {\n  fetchCapabilityStatement,\n  parseFromJson,\n  analyze,\n  compare,\n} from \"fhir-capability-analyzer\";\n\nimport { detectProfiles } from \"fhir-capability-analyzer/registry\";\n\n// Fetch from a live server\nconst result = await fetchCapabilityStatement(\"https://hapi.fhir.org/baseR4\");\n\n// Fetch from an OAuth 2.0 protected server\nconst result = await fetchCapabilityStatement(\"https://secure.example.com\", {\n  headers: { Authorization: `Bearer ${token}` },\n});\nif (!result.success) throw new Error(result.error);\n\n// Analyze\nconst report = analyze(result.capability);\nconsole.log(report.summary.resourceCount); // number of resources\nconsole.log(report.conformance.detectedProfiles); // ProfileConformance[]\nconsole.log(report.warnings); // string[]\n\n// Parse from local JSON (e.g., after fs.readFileSync)\nconst localResult = parseFromJson(JSON.parse(rawJson));\n\n// Compare two capabilities\nconst diff = compare(capA, capB);\n// diff.added, diff.removed, diff.changed — ComparisonDifference[]\n\n// Profile detection only\nconst profiles = detectProfiles([\n  \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-patient\",\n]);\n// [{ url, name, country, standard }]\n```\n\n## Profile detection\n\nDetects conformance to known international and national FHIR profiles by matching profile URLs declared in `instantiates`, `implementationGuide`, and per-resource `profile`/`supportedProfile` fields.\n\n| Standard         | Country          | Canonical URL prefix                                                               |\n| ---------------- | ---------------- | ---------------------------------------------------------------------------------- |\n| US Core          | 🇺🇸 us            | `http://hl7.org/fhir/us/core/`                                                     |\n| UK Core          | 🇬🇧 uk            | `https://fhir.hl7.org.uk/`, `https://fhir.nhs.uk/`                                 |\n| AU Core          | 🇦🇺 au            | `http://hl7.org.au/fhir/core/`                                                     |\n| AU Base          | 🇦🇺 au            | `http://hl7.org.au/fhir/`                                                          |\n| CA Baseline      | 🇨🇦 ca            | `http://hl7.org/fhir/ca/baseline/`                                                 |\n| IPS              | 🌍 international | `http://hl7.org/fhir/uv/ips/`                                                      |\n| IPA              | 🌍 international | `http://hl7.org/fhir/uv/ipa/`                                                      |\n| SMART App Launch | 🌍 international | `http://fhir-registry.smarthealthit.org/`, `http://hl7.org/fhir/smart-app-launch/` |\n| ISiK             | 🇩🇪 de            | `https://gematik.de/fhir/isik/`, `https://gematik.de/fhir/ISiK/`                   |\n| FR Core          | 🇫🇷 fr            | `http://hl7.org/fhir/fr/core/`, `https://hl7.fr/ig/fhir/`                          |\n| NL Nictiz        | 🇳🇱 nl            | `http://nictiz.nl/fhir/`                                                           |\n| IHE              | 🌍 international | `https://profiles.ihe.net/`                                                        |\n\nThese are FHIR canonical identifiers. Some canonical URL hosts do not resolve in a browser,\nbut the identifiers still need to be matched exactly when they appear in a CapabilityStatement.\n\n## Architecture\n\n```md\nsrc/core/        browser-safe functional core\n  types.ts       all shared TypeScript interfaces\n  parse.ts       CapabilityStatement → ServerCapability\n  fetch.ts       fetch from URL, parse from JSON\n  analyze.ts     ServerCapability → AnalysisReport\n  compare.ts     ServerCapability × ServerCapability → ComparisonReport\n\nsrc/registry/    browser-safe profile registry\n  profiles.ts    known profile URL patterns\n  detect.ts      detectProfiles(urls[]) → ProfileConformance[]\n\nsrc/formatters/  browser-safe output renderers\n  text.ts        human-readable text\n  json.ts        stable JSON\n  markdown.ts    Markdown tables\n\nsrc/cli/         Node.js adapter (thin shell over core)\n  commands/      analyze.ts, compare.ts\n```\n\nNo code under `src/core/`, `src/registry/`, or `src/formatters/` imports Node.js APIs. This is enforced by TypeScript and tested.\n\n## What this tool does NOT do\n\n- Full StructureDefinition / profile conformance validation — use the [HL7 FHIR Validator](https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator)\n- Profile evaluation beyond URL pattern matching (only checks declared URLs, not resource content)\n- OAuth 2.0 authorization flows — you need to obtain a bearer token separately and pass it via `--bearer-token` or `FHIR_TOKEN`\n- IG package resolution or download\n- XML to JSON conversion — use the [`fhir`](https://www.npmjs.com/package/fhir) package\n\n## Supported FHIR versions\n\nR4 (4.0.1), R4B (4.3.0), R5 (5.0.0) — auto-detected from the `fhirVersion` field.\n\n## The FHIR TypeScript ecosystem\n\n`fhir-capability-analyzer` is part of a small family of tools for FHIR developer workflows:\n\n| Tool | Purpose |\n|---|---|\n| [`fhir-resource-diff`](https://github.com/dnlbox/fhir-resource-diff) | Validate, diff, and compare individual FHIR JSON resources |\n| [`fhir-test-data`](https://github.com/dnlbox/fhir-test-data) | Generate valid FHIR test data with country-aware identifiers (14 locales) |\n| `fhir-capability-analyzer` (this package) | Fetch, analyze, and compare FHIR server CapabilityStatements |\n\n**Using them together:**\n\n```bash\n# Check what a server supports before running integration tests\nfhir-capability-analyzer analyze https://your-fhir-server.example.com\n\n# Generate test patients and validate them against the FHIR spec\nfhir-test-data generate patient --locale uk --seed 42 | \\\n  fhir-resource-diff validate - --fhir-version R4\n\n# Compare two servers to find differences before a migration\nfhir-capability-analyzer compare https://old-server.example.com https://new-server.example.com \\\n  --exit-on-diff\n```\n\n## Development\n\n### Prerequisites\n\n- Node.js \u003e= 20\n- pnpm \u003e= 9\n\n### Setup\n\n```bash\ngit clone https://github.com/dnlbox/fhir-capability-analyzer.git\ncd fhir-capability-analyzer\npnpm install\n```\n\n### Common scripts\n\n| Script | Purpose |\n|--------|---------|\n| `pnpm cli -- analyze \u003curl\u003e` | Run CLI from source |\n| `pnpm test` | Run tests |\n| `pnpm test:watch` | Run tests in watch mode |\n| `pnpm typecheck` | TypeScript type checking |\n| `pnpm lint` | ESLint |\n| `pnpm build` | Production build (tsup) |\n\n## Roadmap\n\n- [x] Authentication support for secured FHIR servers (OAuth 2.0 token injection)\n- [ ] `--assert` flag for CI: fail if a specific profile is not detected\n\n## Links\n\n- [Documentation](https://dnlbox.github.io/fhir-capability-analyzer/)\n- [npm](https://www.npmjs.com/package/fhir-capability-analyzer)\n- [GitHub](https://github.com/dnlbox/fhir-capability-analyzer)\n- [FHIR specification](https://hl7.org/fhir/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnlbox%2Ffhir-capability-analyzer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdnlbox%2Ffhir-capability-analyzer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnlbox%2Ffhir-capability-analyzer/lists"}