Skip to content

Commit c268c4b

Browse files
authored
Merge pull request #46 from atomic-ehr/actualize-documentation
Actualize documentation & add GenerationReport prettifier
2 parents a5813d1 + 4e042cd commit c268c4b

37 files changed

Lines changed: 2017 additions & 5000 deletions

‎.github/ISSUE_TEMPLATE/blank.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
name: Blank issue
3+
about: Create a blank issue
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---

‎.github/ISSUE_TEMPLATE/config.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
blank_issues_enabled: false
1+
blank_issues_enabled: true
22
contact_links:
33
- name: 🗣️ Chat
44
url: https://discord.gg/rumCG3dwgF

‎CLAUDE.md‎

Lines changed: 137 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@ This is a FHIR code generation toolkit with a **three-stage pipeline**:
3737

3838
### 2. High-Level API (`src/api/`)
3939
- **APIBuilder** (`builder.ts`): Fluent interface for chaining operations
40-
- **Generators** (`generators/`): Language-specific code generators
40+
- **Generators** (`writer-generator/`): Language-specific code generators
4141
- `typescript.ts`: Generates TypeScript interfaces and types
42+
- `python.ts`: Generates Python/Pydantic models
43+
- `csharp.ts`: Generates C# classes
4244

4345
### 3. CLI Interface (`src/cli/`)
4446
- **Commands** (`commands/`):
4547
- `typeschema`: Generate and validate TypeSchema from FHIR packages
46-
- `generate`: Generate code from TypeSchema (TypeScript)
48+
- `generate`: Generate code from TypeSchema (TypeScript, Python, C#)
4749
- **Main entry** (`index.ts`): CLI setup with yargs
4850

4951
### Key Data Flow
@@ -89,26 +91,152 @@ FHIR Package → TypeSchema Generator → TypeSchema Format → Code Generators
8991
## Important Implementation Details
9092

9193
### FHIR Package Processing
92-
- Supports FHIR R4 packages (R5 planned)
94+
- Supports FHIR R4 packages (R5 in progress)
9395
- Handles profiles and extensions (US Core in development)
9496
- Caches parsed schemas for performance
95-
- Multi-package dependency resolution
97+
- Multi-package dependency resolution via Canonical Manager
9698

9799
### TypeSchema Format
98100
- Intermediate representation between FHIR and target languages
99101
- Enables multi-language code generation
100102
- Supports field validation and constraints
101103
- Handles nested types and references
104+
- Flattens FHIR's hierarchical structure for easier generation
102105

103106
### Code Generation
104-
- Modular generator system
107+
- Modular generator system via APIBuilder
108+
- Language-specific writers in `src/api/writer-generator/`
105109
- TypeScript generator creates interfaces with proper inheritance
106-
- Extensible for future languages (Python, Rust planned)
110+
- Extensible architecture for new languages
107111
- Supports custom naming conventions and output formats
108112

113+
## APIBuilder Flow
114+
115+
The `APIBuilder` class (`src/api/builder.ts`) provides the fluent API for the three-stage pipeline:
116+
117+
```typescript
118+
// Input stage - Choose one or combine:
119+
.fromPackage("hl7.fhir.r4.core", "4.0.1") // NPM registry
120+
.fromPackageRef("https://example.com/package.tgz") // Remote TGZ
121+
.localStructureDefinitions({...}) // Local files
122+
.fromSchemas(array) // TypeSchema objects
123+
124+
// Processing stage - Optional:
125+
.treeShake({...}) // Filter types
126+
.writeTypeSchemas("./schemas") // Debug output
127+
128+
// Output stage - Choose one:
129+
.typescript({...}) // TypeScript
130+
.python({...}) // Python
131+
.csharp("Namespace", "./path") // C#
132+
133+
// Finalize:
134+
.outputTo("./output") // Output directory
135+
.cleanOutput(true) // Clean before generation
136+
.generate() // Execute
137+
```
138+
139+
## Core Concepts
140+
141+
### TypeSchema
142+
- Universal intermediate format for FHIR data
143+
- Defined in `src/typeschema/types.ts`
144+
- Contains: identifier, description, fields, dependencies, base type
145+
- Fields include type, required flag, array flag, binding info
146+
- Supports enums for constrained value sets
147+
148+
### Transformers
149+
Located in `src/typeschema/core/`:
150+
- `transformer.ts`: Main conversion logic from FHIR to TypeSchema
151+
- Handles different FHIR element types
152+
- Processes inheritance and choice types
153+
- Manages field flattening and snapshot generation
154+
155+
### Writers
156+
Located in `src/api/writer-generator/`:
157+
- Base `Writer` class: Handles I/O, indentation, formatting
158+
- Language writers: TypeScript, Python, C#, Mustache
159+
- Each writer traverses TypeSchema index and generates code
160+
- Maintains language-specific idioms and conventions
161+
162+
## Common Development Patterns
163+
164+
### Adding a New Generator Feature
165+
1. Extend the transformer in `src/typeschema/core/transformer.ts` to produce TypeSchema data
166+
2. Add logic to the language writer in `src/api/writer-generator/[language].ts`
167+
3. Add tests in `test/unit/typeschema/` and `test/unit/api/`
168+
4. Document in design docs if it's a major feature
169+
170+
### Debugging TypeSchema Generation
171+
1. Use `builder.writeTypeSchemas("./debug-schemas")` to inspect intermediate output
172+
2. Check `src/typeschema/types.ts` for TypeSchema structure
173+
3. Review `src/typeschema/core/transformer.ts` for transformation logic
174+
4. Enable verbose logging with `builder.setLogLevel("DEBUG")`
175+
176+
### Testing Generated Code
177+
1. Use `builder.build()` instead of `generate()` to avoid file I/O
178+
2. Tests are organized by component in `test/unit/`
179+
3. Run `bun test:coverage` to see coverage metrics
180+
4. Use `bun test --watch` for development
181+
182+
### Working with Tree Shaking
183+
- Configured via `builder.treeShake({...})`
184+
- Specify which resources and fields to include
185+
- Automatically resolves dependencies
186+
- Reference format: `"hl7.fhir.r4.core#4.0.1"`
187+
188+
## Key File Locations
189+
190+
### Core Logic
191+
- `src/index.ts` - Main entry point and exports
192+
- `src/config.ts` - Configuration type definitions
193+
- `src/api/builder.ts` - APIBuilder implementation
194+
- `src/typeschema/types.ts` - TypeSchema type definitions
195+
- `src/typeschema/generator.ts` - TypeSchema generation orchestration
196+
197+
### Generators
198+
- `src/api/writer-generator/typescript.ts` - TypeScript code generation
199+
- `src/api/writer-generator/python.ts` - Python/Pydantic generation
200+
- `src/api/writer-generator/csharp.ts` - C# generation
201+
- `src/api/writer-generator/base.ts` - Common writer utilities
202+
203+
### FHIR Processing
204+
- `src/typeschema/register.ts` - Package registration and canonical resolution
205+
- `src/typeschema/core/transformer.ts` - FHIR → TypeSchema conversion
206+
- `src/typeschema/core/field-builder.ts` - Field extraction logic
207+
- `src/typeschema/core/binding.ts` - Value set and binding handling
208+
209+
### Testing
210+
- `test/unit/typeschema/` - TypeSchema processor tests
211+
- `test/unit/api/` - Generator and builder tests
212+
- `test/assets/` - Test fixtures and sample data
213+
214+
## Known Limitations & Gotchas
215+
216+
1. **R5 Support**: Limited, still in development
217+
2. **Profile Extensions**: Basic parsing only, US Core in progress
218+
3. **Choice Types**: Supported but representation differs by language
219+
4. **Circular References**: Handled but may affect tree shaking
220+
5. **Large Packages**: May require increased Node.js memory (`--max-old-space-size`)
221+
222+
## Performance Optimization Tips
223+
224+
1. Use tree shaking to reduce schema count
225+
2. Enable caching in APIBuilder
226+
3. Process large packages in batches
227+
4. Use `build()` instead of `generate()` for testing
228+
5. Run `bun run quality` before committing (combines typecheck, lint, test:unit)
229+
109230
## Roadmap Context
110231

111232
This toolkit focuses on type generation and code generation:
112-
- **Current**: TypeScript interface generation from FHIR schemas
113-
- **Next**: Profile/extension support and expanded TypeScript generator capabilities
114-
- **Future**: Multi-language support, GraphQL schemas, validation functions
233+
- **Current**: TypeScript, Python, C# interface/class generation from FHIR R4
234+
- **In Progress**: R5 support, profile/extension enhancements
235+
- **Planned**: Rust, GraphQL, OpenAPI, validation functions, mock data generation
236+
237+
## Useful External Resources
238+
239+
- [FHIR Specification](https://www.hl7.org/fhir/)
240+
- [Canonical Manager](https://github.com/atomic-ehr/canonical-manager)
241+
- [FHIR Schema](https://github.com/fhir-schema/fhir-schema)
242+
- [TypeSchema Spec](https://www.health-samurai.io/articles/type-schema-a-pragmatic-approach-to-build-fhir-sdk)

‎CONTRIBUTING.md‎

Lines changed: 5 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -110,38 +110,9 @@ bun test --coverage
110110

111111
## Testing
112112

113-
### Test Structure
113+
For comprehensive guidance on writing and running tests, see the [Testing Generators Guide](./docs/guides/testing-generators.md).
114114

115-
```
116-
test/
117-
├── unit/ # Unit tests
118-
│ ├── typeschema/ # TypeSchema tests
119-
│ └── api/ # API tests
120-
├── integration/ # Integration tests
121-
└── e2e/ # End-to-end tests
122-
```
123-
124-
### Writing Tests
125-
126-
```typescript
127-
import { describe, expect, it } from "bun:test";
128-
129-
describe("YourFeature", () => {
130-
it("should do something specific", async () => {
131-
// Arrange
132-
const input = createTestInput();
133-
134-
// Act
135-
const result = await yourFunction(input);
136-
137-
// Assert
138-
expect(result).toBeDefined();
139-
expect(result.property).toBe(expectedValue);
140-
});
141-
});
142-
```
143-
144-
### Running Tests
115+
Quick reference:
145116

146117
```bash
147118
# Run all tests
@@ -155,6 +126,9 @@ bun test --coverage
155126

156127
# Run in watch mode
157128
bun test --watch
129+
130+
# Update snapshots after intentional changes
131+
bun test -- --update-snapshots
158132
```
159133

160134
## Submitting Changes
@@ -308,44 +282,6 @@ export { helperFunction };
308282

309283
## Adding New Features
310284

311-
### Adding a New Generator
312-
313-
1. Create generator file: `src/generators/[language].ts`
314-
315-
```typescript
316-
import type { TypeSchema } from "../typeschema/types";
317-
318-
export interface GeneratorOptions {
319-
outputDir: string;
320-
// Add language-specific options
321-
}
322-
323-
export class LanguageGenerator {
324-
constructor(private options: GeneratorOptions) {}
325-
326-
async generate(schemas: TypeSchema[]): Promise<void> {
327-
// Implementation
328-
}
329-
}
330-
```
331-
332-
2. Add to API builder: `src/api/builder.ts`
333-
334-
```typescript
335-
generateLanguage(options: LanguageGeneratorOptions): this {
336-
this.operations.push({
337-
type: 'generate',
338-
generator: 'language',
339-
options
340-
});
341-
return this;
342-
}
343-
```
344-
345-
3. Add CLI command: `src/cli/commands/generate/[language].ts`
346-
347-
4. Add tests: `test/unit/generators/[language].test.ts`
348-
349285
### Adding a New FHIR Package
350286

351287
1. Update package resolver

‎README.md‎

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,24 @@
1919
- [Load Local StructureDefinitions & TGZ Archives](#load-local-structuredefinitions--tgz-archives)
2020
- [Intermediate - Type Schema](#intermediate---type-schema)
2121
- [Tree Shaking](#tree-shaking)
22+
- [Field-Level Tree Shaking](#field-level-tree-shaking)
2223
- [Generation](#generation)
24+
- [1. Writer-Based Generation (Programmatic)](#1-writer-based-generation-programmatic)
2325
- [Roadmap](#roadmap)
2426
- [Support](#support)
27+
- [Footnotes](#footnotes)
2528

2629
<!-- markdown-toc end -->
2730

2831
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.
2932

33+
Guides:
34+
35+
- **[Writer Generator Guide](docs/guides/writer-generator.md)** - Build custom code generators with the Writer base class
36+
- **[TypeSchemaIndex Guide](docs/guides/typeschema-index.md)** - Type Schema structure and utilities
37+
- **[Testing Generators Guide](docs/guides/testing-generators.md)** - Unit tests, snapshot testing, and best practices
38+
- **[Contributing Guide](CONTRIBUTING.md)** - Development setup and workflow
39+
3040
## Features
3141

3242
- 🚀 **High-Performance** - Built with Bun runtime for blazing-fast generation
@@ -62,15 +72,15 @@ yarn add @atomic-ehr/codegen
6272
1. Write SDK generation script (`generate-types.ts`):
6373

6474
```typescript
65-
import { APIBuilder } from '@atomic-ehr/codegen';
75+
import { APIBuilder, prettyReport } from '@atomic-ehr/codegen';
6676

6777
const builder = new APIBuilder()
6878
.fromPackage("hl7.fhir.r4.core", "4.0.1")
6979
.typescript({})
7080
.outputTo("./examples/typescript-r4/fhir-types");
7181

7282
const report = await builder.generate();
73-
console.log(report);
83+
console.log(prettyReport(report));
7484
```
7585

7686
2. Run the script with:
@@ -221,14 +231,21 @@ FHIR choice types (like `multipleBirth[x]` which can be boolean or integer) are
221231

222232
### Generation
223233

224-
The generation stage uses a `WriterGenerator` system that transforms Type Schema into target language code. The architecture consists of:
234+
The generation stage transforms Type Schema into target language code using two complementary approaches:
235+
236+
#### 1. Writer-Based Generation (Programmatic)
237+
238+
For languages with built-in support (TypeScript, Python, C#), extend the `Writer` class to implement language-specific generators:
239+
240+
- **FileSystemWriter**: Base class providing file I/O, directory management, and buffer handling (both disk and in-memory modes)
241+
- **Writer**: Extends FileSystemWriter with code formatting utilities (indentation, blocks, comments, line management)
242+
- **Language Writers** (`TypeScript`, `Python`[^py], `CSharp`): Implement language-specific generation logic by traversing TypeSchema index and generating corresponding types, interfaces, or classes
225243

226-
- **Base Writer** (`Writer`): Handles file I/O, indentation, and code formatting primitives
227-
- **Language Writers** (e.g., `TypeScript`): Implement language-specific generation logic
244+
[^py]: For details on [Type Schema: Python SDK for FHIR](https://www.health-samurai.io/articles/type-schema-python-sdk-for-fhir)
228245

229-
Writers provide high-level abstractions for common code patterns (blocks, imports, type definitions) while maintaining full control over output formatting. Each language writer traverses the Type Schema index and generates corresponding types, interfaces, or classes following that language's idioms and best practices.
246+
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.
230247

231-
- [Type Schema: Python SDK for FHIR](https://www.health-samurai.io/articles/type-schema-python-sdk-for-fhir)
248+
**When to use**: Full control needed, complex generation logic, performance-critical, language has a dedicated writer, production-grade output
232249

233250
## Roadmap
234251

@@ -266,7 +283,8 @@ Writers provide high-level abstractions for common code patterns (blocks, import
266283
.execute();
267284
```
268285
269-
- [ ] **Python generation**
286+
- [x] **Python generation**
287+
- [x] **C# generation**
270288
- [ ] **Rust generation**
271289
- [ ] **GraphQL schema generation**
272290
- [ ] **OpenAPI specification generation**

0 commit comments

Comments
 (0)