Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ FHIR Package → TypeSchema Generator → TypeSchema Format → Code Generators
- If a change is a direct fix for a specific previous commit, place it immediately after that commit with a `fix:` prefix in the message.
- Typical commit order: source changes → test changes → regenerated examples. Example updates should be the last commit in the branch.

## Pull Request Style

- PR body should be a bullet list summarizing changes — no section headers, no test plan.
- Use two-level nesting to group related items when the list is long; keep it flat when short.
- Keep bullets concise and focused on what changed, not why.
- When a PR changes generated code or user-facing API, include before/after code examples.
- Add a short motivation line before each example explaining why the change was made.

## Development Guidelines

### TypeScript Configuration
Expand Down Expand Up @@ -198,6 +206,29 @@ Located in `src/api/writer-generator/`:
- Each writer traverses TypeSchema index and generates code
- Maintains language-specific idioms and conventions

## Static Assets for Generators

Static files that are copied verbatim into generated output live in `assets/api/writer-generator/<language>/`. Each language writer has a resolver function (e.g., `resolveTsAssets`, `resolvePyAssets`) that handles path resolution for both dev (`src/`) and dist (`dist/`) builds.

**Pattern:**
```
assets/api/writer-generator/
├── typescript/profile-helpers.ts # Runtime helpers for TS profile classes
└── python/
├── requirements.txt
├── fhirpy_base_model.py
└── resource_family_validator.py
```

**How it works:**
1. Asset files are authored/maintained directly in `assets/` (included in biome linting)
2. Writers copy them to output via `this.cp("filename", "filename")` — uses `Writer.cp()` which resolves via `resolveAssets`
3. Each language writer sets `resolveAssets` in its constructor (e.g., TypeScript writer defaults to `resolveTsAssets`)

**When to use assets vs programmatic generation:**
- Use assets for static runtime code shared across all generated profiles (helpers, validators, base models)
- Use programmatic generation (`w.lineSM()`, `w.curlyBlock()`) for code that varies per schema/profile

## Common Development Patterns

### Adding a New Generator Feature
Expand Down Expand Up @@ -235,10 +266,11 @@ Located in `src/api/writer-generator/`:

### Generators
- `src/api/writer-generator/introspection.ts` - TypeSchema introspection generation
- `src/api/writer-generator/typescript.ts` - TypeScript code generation
- `src/api/writer-generator/typescript/writer.ts` - TypeScript type generation
- `src/api/writer-generator/typescript/profile.ts` - TypeScript profile class generation
- `src/api/writer-generator/python.ts` - Python/Pydantic generation
- `src/api/writer-generator/csharp.ts` - C# generation
- `src/api/writer-generator/base.ts` - Common writer utilities
- `src/api/writer-generator/csharp/csharp.ts` - C# generation
- `src/api/writer-generator/writer.ts` - Base Writer class (I/O, indentation, `cp()` for assets)

### FHIR Processing
- `src/typeschema/register.ts` - Package registration and canonical resolution
Expand Down
53 changes: 26 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

- [Atomic EHR Codegen](#atomic-ehr-codegen)
- [Features](#features)
- [Guides](#guides)
- [Versions & Release Cycle](#versions--release-cycle)
- [Installation](#installation)
- [Quick Start](#quick-start)
Expand All @@ -20,52 +21,52 @@
- [Intermediate - Type Schema](#intermediate---type-schema)
- [Tree Shaking](#tree-shaking)
- [Field-Level Tree Shaking](#field-level-tree-shaking)
- [Logical Model Promotion](#logical-model-promotion)
- [Generation](#generation)
- [1. Writer-Based Generation (Programmatic)](#1-writer-based-generation-programmatic)
- [2. Mustache Template-Based Generation (Declarative)](#2-mustache-template-based-generation-declarative)
- [Profile Classes](#profile-classes)
- [Support](#support)
- [Footnotes](#footnotes)

<!-- markdown-toc end -->

A powerful, extensible code generation toolkit for FHIR ([Fast Healthcare Interoperability Resources](https://www.hl7.org/fhir/)) that transforms FHIR specifications into strongly-typed code for multiple programming languages.

Guides:

- **[Writer Generator Guide](docs/guides/writer-generator.md)** - Build custom code generators with the Writer base class
- **[Mustache Generator Guide](docs/guides/mustache-generator.md)** - Template-based code generation for any language
- **[TypeSchemaIndex Guide](docs/guides/typeschema-index.md)** - Type Schema structure and utilities
- **[Testing Generators Guide](docs/guides/testing-generators.md)** - Unit tests, snapshot testing, and best practices
- **[Contributing Guide](CONTRIBUTING.md)** - Development setup and workflow

## Features

- [x] **Multi-Package Support** — Load packages from the [FHIR registry](examples/typescript-r4/), [remote TGZ files](examples/typescript-sql-on-fhir/), or a [local folder with custom StructureDefinitions](examples/local-package-folder/)
- Tested with hl7.fhir.r4.core, US Core, C-CDA, SQL on FHIR, etc.
- [x] **Resources & Complex Types** — Generates typed definitions with proper inheritance
- [x] **Value Set Bindings** — Strongly-typed enums from FHIR terminology bindings
- [x] **Profiles & Extensions** — Factory methods with auto-populated fixed values and required slices ([R4 profiles](examples/typescript-r4/profile-bp.test.ts), [US Core](examples/typescript-us-core/))
- [x] **Profiles** — Factory methods with auto-populated fixed values and required slices ([R4 profiles](examples/typescript-r4/profile-bp.test.ts), [US Core](examples/typescript-us-core/))
- Extensions — flat typed accessors (e.g. `setRace()` on US Core Patient), [standalone extension profiles](examples/typescript-r4/extension-profile.test.ts)
- Slicing — typed get/set accessors with discriminator matching
- Validation — runtime `validate()` for required fields, fixed values, slice cardinality, enums, references
- [x] **Extensible Architecture** — Three-stage pipeline: FHIR packages → [TypeSchema](https://www.health-samurai.io/articles/type-schema-a-pragmatic-approach-to-build-fhir-sdk) IR → code generation
- TypeSchema is a universal intermediate representation — add a new language by writing only the final generation stage
- Built-in generators: TypeScript, Python/Pydantic, C#, and Mustache templates
- [x] **TypeSchema Transformations**:
- [x] Tree Shaking — include only the resources and fields you need; automatically resolves dependencies
- [x] Logical Model Promotion — promote FHIR logical models (e.g. CDA ClinicalDocument) to first-class resources
- [ ] Renaming — custom naming conventions for generated types, fields, packages, etc.
- [x] **Tree Shaking** — include only the resources and fields you need; automatically resolves dependencies
- [x] **Logical Model Promotion** — promote FHIR logical models to first-class resources
- [ ] Renaming — custom naming conventions for generated types and fields
- [ ] **Search Builders** — type-safe FHIR search query construction
- [ ] **Operation Generation** — type-safe FHIR operation calls

| Feature | TypeSchema | TypeScript | Python | C# | Mustache |
|---|---|---|---|---|---|
| Resources & Complex Types | yes | yes | yes | yes | template |
| Value Set Bindings | yes | inline | inline | enum | template |
| Profiles & Extensions | yes | yes | no | no | no |
| Tree Shaking | yes | 〃 | 〃 | 〃 | 〃 |
| Logical Model Promotion | yes | 〃 | 〃 | 〃 | 〃 |
| Feature | TypeScript | Python | C# | Mustache |
|---------------------------|------------|---------|------|----------|
| Resources & Complex Types | yes | yes | yes | template |
| Value Set Bindings | inline | limited | enum | template |
| Primitive Extensions | yes | no | no | no |
| Profiles | yes | no | no | no |
| Profile Validation | yes | no | no | no |

## Guides

- **[Writer Generator Guide](docs/guides/writer-generator.md)** - Build custom code generators with the Writer base class
- **[Mustache Generator Guide](docs/guides/mustache-generator.md)** - Template-based code generation for any language
- **[TypeSchemaIndex Guide](docs/guides/typeschema-index.md)** - Type Schema structure and utilities
- **[Testing Generators Guide](docs/guides/testing-generators.md)** - Unit tests, snapshot testing, and best practices
- **[Contributing Guide](CONTRIBUTING.md)** - Development setup and workflow

## Versions & Release Cycle

Expand Down Expand Up @@ -204,7 +205,7 @@ Use the new `localPackage` helper to point the builder at an on-disk FHIR packag
.localTgzPackage("./packages/my-custom-ig.tgz")
```

The example above points Canonical Manager at `./custom-profiles`, installs the HL7 R4 core dependency automatically, and then limits generation to the custom `ExampleNotebook` logical model plus the standard R4 `Patient` resource via tree shaking. The `localTgzPackage` helper registers `.tgz` artifacts that Canonical Manager already knows how to unpack.
The example above points Canonical Manager at `./custom-profiles` and installs the HL7 R4 core dependency automatically. The `localTgzPackage` helper registers `.tgz` artifacts that Canonical Manager already knows how to unpack.

### Intermediate - Type Schema

Expand Down Expand Up @@ -263,7 +264,7 @@ Beyond resource-level filtering, tree shaking supports fine-grained field select

FHIR choice types (like `multipleBirth[x]` which can be boolean or integer) are handled intelligently. Selecting/ignoring the base field affects all variants, while targeting specific variants only affects those types.

##### Logical Promotion
#### Logical Model Promotion

Some implementation guides expose logical models (logical-kind StructureDefinitions) that are intended to be used like resources in generated SDKs. The code generator supports promoting selected logical models to behave as resources during generation.

Expand Down Expand Up @@ -291,9 +292,7 @@ For languages with built-in support (TypeScript, Python, C#), extend the `Writer

- **FileSystemWriter**: Base class providing file I/O, directory management, and buffer handling (both disk and in-memory modes)
- **Writer**: Extends FileSystemWriter with code formatting utilities (indentation, blocks, comments, line management)
- **Language Writers** (`TypeScript`, `Python`[^py], `CSharp`): Implement language-specific generation logic by traversing TypeSchema index and generating corresponding types, interfaces, or classes

[^py]: For details on [Type Schema: Python SDK for FHIR](https://www.health-samurai.io/articles/type-schema-python-sdk-for-fhir)
- **Language Writers** (`TypeScript`, `Python`, `CSharp`): Implement language-specific generation logic by traversing TypeSchema index and generating corresponding types, interfaces, or classes (see also: [Type Schema: Python SDK for FHIR](https://www.health-samurai.io/articles/type-schema-python-sdk-for-fhir))

Each language writer maintains full control over output formatting while leveraging high-level abstractions for common code patterns. Writers follow language idioms and best practices, with optimized output for production use.

Expand Down Expand Up @@ -373,8 +372,8 @@ See [examples/typescript-r4/](examples/typescript-r4/) for R4 profile tests and

## Support

- 🐛 [Issue Tracker](https://github.com/atomic-ehr/codegen/issues)
- [Issue Tracker](https://github.com/atomic-ehr/codegen/issues)

---

Built with ❤️ by the Atomic Healthcare team
Built by the Atomic Healthcare team
Loading