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

@pedigree-fhir/core

v0.1.0

Published

Headless, framework-agnostic core for FHIR-driven pedigree charts: parsing, model, layout, state, validation.

Readme

@pedigree-fhir/core

Framework-agnostic core for FHIR-driven pedigree graphs: parsing, relationship inference, PSC semantics, layout, state, editing, history, and validation.

Responsibilities

@pedigree-fhir/core owns the domain and state model for the library. It does not depend on React and does not render anything. Instead, it gives consumers:

  • FHIR parsing from Patient and FamilyMemberHistory
  • relationship inference for common pedigree topology
  • PSC-aware semantics and layout geometry
  • a headless store with selection, layout options, edits, and history
  • validation rules and registry composition

Public surface

The package currently exports these main areas:

  • fhir/*
    • parsePedigree
    • serializePedigree
    • explicit R4* type aliases for Patient, FamilyMemberHistory, and related FHIR datatypes
    • genetics extension helpers
    • relationship-code helpers and display-label resolvers
  • model/*
    • graph and individual/couple types
    • ID helpers
    • inferRelationships
  • psc/*
    • pedigree semantics such as sex, vital state, carrier state, twins, and adoption
  • layout/*
    • layout types
    • computeLayout
  • state/*
    • createPedigreeStore
    • individual, graph, and couple edits
    • history helpers
  • validation/*
    • defaultRegistry
    • validateFhirInput
    • custom registry composition
    • diagnostic/rule types

See src/index.ts for the actual export list.

Core workflow

For most consumers, the canonical flow is:

import {
  createPedigreeStore,
  defaultRegistry,
  inferRelationships,
  parsePedigree,
} from '@pedigree-fhir/core';

const inputDiagnostics = validateFhirInput(patient, familyHistory);
const parsed = parsePedigree(patient, familyHistory);
const graph = inferRelationships(parsed);

const store = createPedigreeStore({
  graph,
  layoutOptions: {},
});

const graphDiagnostics = defaultRegistry().validate(store.getState().graph);

Parsing and inference

The package currently makes its FHIR wire contract explicit via exported R4* type aliases such as R4Patient and R4FamilyMemberHistory. That keeps the library aligned to the current R4 runtime behavior while leaving room for a future R5 strategy to be added intentionally rather than through ambient globals.

parsePedigree(patient, familyHistory) performs the deterministic FHIR-to-graph conversion:

  • constructs the proband from Patient
  • turns FamilyMemberHistory records into individuals
  • reads genetics-parent and genetics-sibling extension data
  • creates explicit couples and child-of relationships when the source is clear
  • groups twin declarations transitively

inferRelationships(graph) then fills in structural relationships from pedigree evidence such as:

  • direct mother/father/sibling relationships
  • maternal and paternal grandparent sides
  • fabricated parents or grandparents where the topology is strongly implied

This split is deliberate: parsing handles explicit source data, while inference handles predictable pedigree structure recovery.

Relationship-code helpers can also drive consumer labels. For example, resolveIndividualDisplayLabel(individual, { preferRelationshipLabel: true }) lets a renderer prefer readable relative labels like "mother" or "natural sister" while still falling back to individual.name when needed.

Layout

computeLayout(graph, options) returns headless geometry rather than a rendered chart. The important outputs are:

  • nodes: individual positions
  • partnerEdges: partner-line SVG path strings, including consanguinity handling
  • parentDrops: sibship drop geometry and twin-junction metadata
  • bounds: overall chart bounds

That geometry is what downstream renderers consume. The current layout is still proband-centered, but it now supports visible descendant rows for gen-0 couples in addition to the ancestor structure above the proband.

Store and edits

createPedigreeStore produces a framework-agnostic external store with:

  • getState()
  • dispatch(action)
  • subscribe(listener)

The store keeps:

  • the current graph
  • layoutOptions
  • selected individual ID
  • edit history

The action surface includes:

  • selection changes
  • layout option updates
  • individual semantic edits
  • graph edits such as adding/removing relatives
  • couple edits such as consanguinity and twin state
  • undo/redo

Validation

Validation is split into two layers:

  1. validateFhirInput(patient, familyHistory) catches raw source-data issues that parsing may otherwise skip or normalize, such as missing IDs, duplicate IDs, dangling genetics references, malformed parent/sibling extensions, and patient-reference mismatches.
  2. defaultRegistry().validate(graph) runs graph-level pedigree rules after parsing and inference.

The built-in validation registry currently includes:

  • completeness checks
  • sex/relationship consistency checks
  • cycle detection
  • unknown code detection
  • broken structural reference checks
  • twin-group consistency checks

Use defaultRegistry() for the standard graph rule set, or createRegistry() to customize the active rules.

Design constraints

The core package is intentionally:

  • headless: no UI assumptions
  • pure-data-first: graph and geometry are explicit outputs
  • editable: state mutations happen through a typed action surface
  • test-heavy: the repo’s package coverage bar is 100%

See also