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

@fhirschema/codegen

v0.0.24

Published

Code generator for FHIR Schema

Downloads

94

Readme

fhir-schema codegen

NPM Version fscg py-sdk ts-sdk

Library that generates language-specific models from FHIR StructureDefinition using type-schema (Github), enabling developers to work with strongly-typed FHIR resources in their preferred programming language.

How does it work?

fhir-schema-codegen uses a two-step process:

  1. Type-Schema Transformation: Converts FHIR StructureDefinition into type-schema format, which provides a flat and denormalized representation for easier data access.

  2. Template-Based Generation: Uses generators to transform the type-schema into language-specific models for each supported language (TypeScript, C#, Python, etc.).

Supports custom template-based generators allowing you to add new language support, customize the output format of available generators, and implement language-specific features.

Join our community at FHIR Chat to learn more and contribute!

Installation

# Install globally
npm install -g @fhirschema/codegen

# Or use with npx
npx @fhirschema/codegen [command] [options]

Usage

The fhir-schema codegen provides several commands to work with FHIR definitions and generate code:

# Generate code
fscg generate -g typescript -o ./fhir.r4.sdk -p [email protected]

# List all available (built in) generators
fscg generators

Command Reference

generate

Generates code from core FHIR Implementation Guide:

fscg generate -g <generator> -o <output-dir> -p <fhir.package@version>

Options:

  • -g, --generator <generator> - Generator to use (typescript, csharp, python)
  • -o, --output <directory> - Output directory
  • -p, --packages <packages...> - Available published FHIR IGs
  • -f, --files <files...> - TypeSchema source *.ndjson files
  • --custom-generator <path> - Path to your custom generator template
  • --with-debug-comment - Enable debug comments in generated code
  • --profile - Enable profile generation

Example:

fscg generate -g typescript -o ./fhir.r4.sdk -p [email protected]

Create a custom generator template

generators

Lists of the available generators:

fscg generators

create-generator

Creates a new custom generator template:

fscg create-generator -o <output-directory>

Options:

  • -o, --output <directory> - Output directory (default: ./fhirschema-generators)

Example:

fscg create-generator -o ./my-generator

Supported Generators

The library supports multiple language generators, each providing type-safe FHIR resource handling. Below are the currently supported generators with examples and implementation details:

TypeScript Generator

The TypeScript generator creates a fully typed SDK with interfaces for all FHIR resources. Example implementation in ./example/typescript/:

import { Patient } from './aidbox/types/hl7-fhir-r4-core';

const patient: Patient = {
  identifier: [{ system: 'http://org.io/id', value: '0000-0000' }],
  name: [{ given: ['John'], family: 'Doe' }],
  gender: 'male',
  birthDate: '1990-01-01',
};

Generate TypeScript SDK:

fscg generate -g typescript -o ./ts-sdk -p [email protected]

# With debug comments:
fscg generate -g typescript -o ./ts-sdk -p [email protected] --with-debug-comment

C# Generator

The C# generator produces strongly-typed C# classes for FHIR resources. Example implementation in ./example/csharp/:

using Aidbox.FHIR.R4.Core;

var patient = new Patient
{
    Identifier = [new Identifier { System = "http://hl7.org/fhir/us/CodeSystem/identity", Value = "0000-0000" }],
    Name = [new HumanName { Given = ["John"], Family = "Doe" }],
    Gender = "male",
    BirthDate = "1990-01-01",
};

Generate C# SDK:

fscg generate -g csharp -o ./csharp-sdk -p [email protected]

Python Generator

The Python generator creates Python classes. Example implementation in ./example/python/:

from aidbox.hl7_fhir_r4_core.base import HumanName, Identifier
from aidbox.hl7_fhir_r4_core import Patient

patient = Patient(
    identifier=[Identifier(system="http://org.io/id", value="0000-0000")],
    name=[HumanName(given=["John"], family="Doe")],
    gender="male",
    birth_date="1990-01-01",
)

Generate Python SDK:

fscg generate -g python -o ./python-sdk -p [email protected]

# With options:
fscg generate -g python -o ./python-sdk -p [email protected] --py-sdk-package my_package --py-allow-extra-fields

Custom Generators

You can create custom generators to support additional languages or specialized formats. The generator system is extensible and allows you to:

  • Create generators for new languages
  • Customize the output format
  • Add language-specific features

Generator inherits from base Generator class and implements generate() method to produce target language code based on type-schema (see ./src/generators/typescript/index.ts)

For more information on creating and using custom generators, see the Generators Registry documentation.

TypeScript Example

import { Generator, type GeneratorOptions, NestedTypeSchema, TypeSchema } from '@fhirschema/codegen';
import path from 'node:path';

export interface CustomGeneratorOptions extends GeneratorOptions {
    // Add custom options here
}

const typeMap :  Record<string, string> = {
    'boolean': 'boolean',
    'integer': 'number',
    'decimal': 'number',
    'positiveInt': 'number',
    'number': 'number'
}

export class CustomGenerator extends Generator {
    constructor(opts: CustomGeneratorOptions) {
        super({
            ...opts,
            staticDir: path.resolve(__dirname, '../static'),
        });
    }

    generateType(schema: TypeSchema | NestedTypeSchema) {
        let base = schema.base ? 'extends ' + schema.base.name : '';
        this.curlyBlock(['export', 'interface', schema.identifier.name, base], () => {
            if (schema.fields) {
                for (const [fieldName, field] of Object.entries(schema.fields)) {
                    if ('choices' in field) continue;
                    let fieldSymbol = fieldName;
                    if (!field.required) {
                        fieldSymbol += '?';
                    }
                    if (field.type.kind == 'primitive-type') {
                        type = typeMap[field.type.name] || 'string'
                    } else {
                        type = field.type.name;
                    }
                    this.lineSM(fieldSymbol, ':', type + (field.array ? '[]' : ''));
                }
            }
        });
        this.line();
    }

    generate() {
        this.dir('src', async () => {
            this.file('types.ts', () => {
                for (let schema of this.loader.complexTypes()) {
                    this.generateType(schema);
                }
            });

            for (let schema of this.loader.resources()) {
                this.file(schema.identifier.name + ".ts", () => {
                    if (schema.dependencies) {
                        for (let dep of schema.dependencies.filter(d => d.kind == 'complex-type')) {
                            this.lineSM('import', '{', dep.name, '}', 'from', '"./types.ts"');
                        }

                        for (let dep of schema.dependencies.filter(d => d.kind == 'resource')) {
                            this.lineSM('import', '{', dep.name, '}', 'from', '"./' + dep.name + '.ts"');
                        }
                    }

                    this.line();

                    if (schema.nested) {
                        for (let subtype of schema.nested) {
                            this.generateType(subtype);
                        }
                    }

                    this.line();

                    this.generateType(schema);
                });
            }
        })
    }
}

export function createGenerator(options: GeneratorOptions): Generator {
    return new CustomGenerator(options);
}

This will produce something like this:

import { CodeableConcept } from "./types.ts";
import { Reference } from "./types.ts";
import { HumanName } from "./types.ts";
import { Address } from "./types.ts";
import { Identifier } from "./types.ts";
import { Attachment } from "./types.ts";
import { BackboneElement } from "./types.ts";
import { ContactPoint } from "./types.ts";
import { Period } from "./types.ts";
import { DomainResource } from "./DomainResource.ts";

export interface PatientLink extends BackboneElement {
  other : Reference;
  type : string;
}

export interface PatientCommunication extends BackboneElement {
  language : CodeableConcept;
  preferred? : boolean;
}

export interface PatientContact extends BackboneElement {
  address? : Address;
  gender? : string;
  name? : HumanName;
  organization? : Reference;
  period? : Period;
  relationship? : CodeableConcept[];
  telecom? : ContactPoint[];
}


export interface Patient extends DomainResource {
  active? : boolean;
  address? : Address[];
  birthDate? : string;
  communication? : PatientCommunication[];
  contact? : PatientContact[];
  deceasedBoolean? : boolean;
  deceasedDateTime? : string;
  gender? : string;
  generalPractitioner? : Reference[];
  identifier? : Identifier[];
  link? : PatientLink[];
  managingOrganization? : Reference;
  maritalStatus? : CodeableConcept;
  multipleBirthBoolean? : boolean;
  multipleBirthInteger? : number;
  name? : HumanName[];
  photo? : Attachment[];
  telecom? : ContactPoint[];
}

Contributing

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

Development Setup

  1. Clone the repository

    git clone https://github.com/fhir-schema/fhir-schema-codegen.git
    cd fhir-schema-codegen
  2. Install dependencies

    npm install
  3. Build the project

    npm run build
  4. Run tests

    npm test

Creating a New Generator

To create a new generator for a language:

  1. Create a new directory in src/generators/ for your language
  2. Create an index.ts file that exports a createGenerator function
  3. Implement your generator by extending the base Generator class
  4. Add your generator to the choices in the CLI in src/cli.ts

Alternatively, you can use the create-generator command to create a custom generator outside the main codebase.