@atomic-ehr/codegen 0.0.4 → 0.0.5-canary.20251229160950.1f6114f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +210 -260
- package/assets/api/writer-generator/csharp/Client.cs +333 -0
- package/assets/api/writer-generator/csharp/Helper.cs +19 -0
- package/assets/api/writer-generator/python/requirements.txt +5 -0
- package/assets/api/writer-generator/python/resource_family_validator.py +92 -0
- package/dist/cli/index.js +15 -13
- package/dist/index.d.ts +120 -29
- package/dist/index.js +2172 -577
- package/dist/index.js.map +1 -1
- package/package.json +18 -12
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Atomic EHR Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,26 +1,60 @@
|
|
|
1
|
-
# Atomic
|
|
1
|
+
# Atomic EHR Codegen
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@atomic-ehr/codegen/v/canary)
|
|
4
4
|
[](https://badge.fury.io/js/%40atomic-ehr%2Fcodegen)
|
|
5
5
|
[](https://github.com/atomic-ehr/codegen/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/atomic-ehr/codegen/actions/workflows/sdk-tests.yml)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
|
|
9
|
+
**Table of Contents**
|
|
10
|
+
|
|
11
|
+
- [Atomic EHR Codegen](#atomic-ehr-codegen)
|
|
12
|
+
- [Features](#features)
|
|
13
|
+
- [Versions & Release Cycle](#versions--release-cycle)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Quick Start](#quick-start)
|
|
16
|
+
- [Usage Examples](#usage-examples)
|
|
17
|
+
- [Architecture](#architecture)
|
|
18
|
+
- [Input - FHIR packages & resolves canonicals](#input---fhir-packages--resolves-canonicals)
|
|
19
|
+
- [Load Local StructureDefinitions & TGZ Archives](#load-local-structuredefinitions--tgz-archives)
|
|
20
|
+
- [Intermediate - Type Schema](#intermediate---type-schema)
|
|
21
|
+
- [Tree Shaking](#tree-shaking)
|
|
22
|
+
- [Field-Level Tree Shaking](#field-level-tree-shaking)
|
|
23
|
+
- [Generation](#generation)
|
|
24
|
+
- [1. Writer-Based Generation (Programmatic)](#1-writer-based-generation-programmatic)
|
|
25
|
+
- [2. Mustache Template-Based Generation (Declarative)](#2-mustache-template-based-generation-declarative)
|
|
26
|
+
- [Roadmap](#roadmap)
|
|
27
|
+
- [Support](#support)
|
|
28
|
+
- [Footnotes](#footnotes)
|
|
29
|
+
|
|
30
|
+
<!-- markdown-toc end -->
|
|
31
|
+
|
|
32
|
+
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.
|
|
33
|
+
|
|
34
|
+
Guides:
|
|
35
|
+
|
|
36
|
+
- **[Writer Generator Guide](docs/guides/writer-generator.md)** - Build custom code generators with the Writer base class
|
|
37
|
+
- **[Mustache Generator Guide](docs/guides/mustache-generator.md)** - Template-based code generation for any language
|
|
38
|
+
- **[TypeSchemaIndex Guide](docs/guides/typeschema-index.md)** - Type Schema structure and utilities
|
|
39
|
+
- **[Testing Generators Guide](docs/guides/testing-generators.md)** - Unit tests, snapshot testing, and best practices
|
|
40
|
+
- **[Contributing Guide](CONTRIBUTING.md)** - Development setup and workflow
|
|
9
41
|
|
|
10
42
|
## Features
|
|
11
43
|
|
|
12
44
|
- 🚀 **High-Performance** - Built with Bun runtime for blazing-fast generation
|
|
13
|
-
- 🔧 **Extensible Architecture** - Three-stage pipeline
|
|
14
|
-
-
|
|
45
|
+
- 🔧 **Extensible Architecture** - Three-stage pipeline:
|
|
46
|
+
- FHIR package management & canonical resolution
|
|
47
|
+
- Optimized intermediate FHIR data entities representation via Type Schema
|
|
48
|
+
- Generation for different programming languages
|
|
49
|
+
- 📦 **Multi-Package Support** - Generate from a list of FHIR packages
|
|
15
50
|
- 🎯 **Type-Safe** - Generates fully typed interfaces with proper inheritance
|
|
16
|
-
-
|
|
17
|
-
- 🛠️ **Developer Friendly** - Fluent API, CLI, and configuration file support
|
|
51
|
+
- 🛠️ **Developer Friendly** - Fluent API
|
|
18
52
|
|
|
19
|
-
## Versions
|
|
53
|
+
## Versions & Release Cycle
|
|
20
54
|
|
|
21
55
|
- `canary` channel - Latest development version from `main` branch
|
|
22
|
-
- `latest` channel - Latest stable version (
|
|
23
|
-
-
|
|
56
|
+
- `latest` channel - Latest stable version, changelog: [Releases](https://github.com/atomic-ehr/codegen/releases)
|
|
57
|
+
- All versions: [NPM: @atomic-ehr/codegen](https://www.npmjs.com/package/@atomic-ehr/codegen?activeTab=versions)
|
|
24
58
|
|
|
25
59
|
## Installation
|
|
26
60
|
|
|
@@ -37,312 +71,200 @@ yarn add @atomic-ehr/codegen
|
|
|
37
71
|
|
|
38
72
|
## Quick Start
|
|
39
73
|
|
|
40
|
-
|
|
74
|
+
1. Write SDK generation script (`generate-types.ts`):
|
|
41
75
|
|
|
42
|
-
```typescript
|
|
43
|
-
import { APIBuilder } from '@atomic-ehr/codegen';
|
|
44
|
-
|
|
45
|
-
const builder = new APIBuilder()
|
|
46
|
-
.fromPackage("hl7.fhir.r4.core", "4.0.1")
|
|
47
|
-
.typescript({})
|
|
48
|
-
.outputTo("./examples/typescript-r4/fhir-types");
|
|
49
|
-
|
|
50
|
-
const report = await builder.generate();
|
|
51
|
-
console.log(report);
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Run the script with:
|
|
76
|
+
```typescript
|
|
77
|
+
import { APIBuilder, prettyReport } from '@atomic-ehr/codegen';
|
|
55
78
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
79
|
+
const builder = new APIBuilder()
|
|
80
|
+
.fromPackage("hl7.fhir.r4.core", "4.0.1")
|
|
81
|
+
.typescript({})
|
|
82
|
+
.outputTo("./examples/typescript-r4/fhir-types");
|
|
59
83
|
|
|
60
|
-
|
|
84
|
+
const report = await builder.generate();
|
|
85
|
+
console.log(prettyReport(report));
|
|
86
|
+
```
|
|
61
87
|
|
|
62
|
-
|
|
63
|
-
# Generate using configuration file
|
|
64
|
-
bunx atomic-codegen generate
|
|
88
|
+
2. Run the script with:
|
|
65
89
|
|
|
66
|
-
|
|
67
|
-
|
|
90
|
+
- `npm exec tsx generate-types.ts`
|
|
91
|
+
- `bun run generate-types.ts`
|
|
92
|
+
- `pnpm exec tsx generate-types.ts`
|
|
68
93
|
|
|
69
|
-
|
|
70
|
-
bunx atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson
|
|
71
|
-
```
|
|
94
|
+
### Usage Examples
|
|
72
95
|
|
|
73
|
-
|
|
96
|
+
See the [examples/](examples/) directory for working demonstrations:
|
|
74
97
|
|
|
75
|
-
|
|
98
|
+
- **[typescript-r4/](examples/typescript-r4/)** - FHIR R4 type generation with resource creation demo and profile usage
|
|
99
|
+
- **[typescript-ccda/](examples/typescript-ccda/)** - C-CDA on FHIR type generation
|
|
100
|
+
- **[typescript-sql-on-fhir/](examples/typescript-sql-on-fhir/)** - SQL on FHIR ViewDefinition with tree shaking
|
|
101
|
+
- **[python/](examples/python/)** - Python/Pydantic model generation with configurable field formats
|
|
102
|
+
- **[csharp/](examples/csharp/)** - C# class generation with namespace configuration
|
|
103
|
+
- **[mustache/](examples/mustache/)** - Java generation with Mustache templates and post-generation hooks
|
|
104
|
+
- **[local-package-folder/](examples/local-package-folder/)** - Loading unpublished local FHIR packages
|
|
76
105
|
|
|
77
|
-
|
|
78
|
-
import { defineConfig } from "@atomic-ehr/codegen";
|
|
79
|
-
|
|
80
|
-
export default defineConfig({
|
|
81
|
-
outputDir: "./generated",
|
|
82
|
-
overwrite: true,
|
|
83
|
-
validate: true,
|
|
84
|
-
cache: true,
|
|
85
|
-
packages: ["hl7.fhir.r4.core@4.0.1"],
|
|
86
|
-
typescript: {
|
|
87
|
-
includeDocuments: true,
|
|
88
|
-
namingConvention: "PascalCase",
|
|
89
|
-
includeProfiles: false,
|
|
90
|
-
includeExtensions: false,
|
|
91
|
-
generateIndex: true,
|
|
92
|
-
strictMode: true,
|
|
93
|
-
generateValueSets: true,
|
|
94
|
-
includeValueSetHelpers: true,
|
|
95
|
-
valueSetStrengths: ["required", "preferred"],
|
|
96
|
-
valueSetMode: "custom"
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
Then run:
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
bunx atomic-codegen generate
|
|
105
|
-
```
|
|
106
|
+
For detailed documentation, see [examples/README.md](examples/README.md).
|
|
106
107
|
|
|
107
108
|
## Architecture
|
|
108
109
|
|
|
109
110
|
The toolkit uses a three-stage architecture (details: [link](https://www.health-samurai.io/articles/type-schema-a-pragmatic-approach-to-build-fhir-sdk)):
|
|
110
111
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
1. **Input Layer** - Parses FHIR packages and profiles, resolves canonicals, and transforms them into TypeSchema format
|
|
116
|
-
2. **Intermediate Format** - TypeSchema provides a universal representation for FHIR data entities
|
|
117
|
-
3. **Output Generators** - Generate code for TypeScript, Python, and other languages
|
|
118
|
-
|
|
119
|
-
## Usage Examples
|
|
112
|
+
1. **Input** - FHIR packages & resolves canonicals
|
|
113
|
+
2. **Intermediate representation** - TypeSchema provides a universal representation for FHIR data entities and processing utilities
|
|
114
|
+
3. **Generation** - Generate code for TypeScript, Python, etc.
|
|
120
115
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
- `demo.ts` - a simple script that creates resources and demonstrates how to work with profiles
|
|
124
|
-
- `generate.ts` - script to generate types
|
|
125
|
-
|
|
126
|
-
### Generate Types for a Custom Profile (Draft)
|
|
116
|
+
The `APIBuilder` provides a fluent interface for configuring and generating code:
|
|
127
117
|
|
|
128
118
|
```typescript
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
119
|
+
const builder = new APIBuilder()
|
|
120
|
+
|
|
121
|
+
// Input sources (choose one or combine)
|
|
122
|
+
.fromPackage("hl7.fhir.r4.core", "4.0.1") // NPM registry package
|
|
123
|
+
.fromPackageRef("https://...package.tgz") // Remote TGZ file
|
|
124
|
+
.localStructureDefinitions({ ... }) // Loose JSON files
|
|
125
|
+
|
|
126
|
+
// Type Schema processing
|
|
127
|
+
.treeShake({ ... }) // Include only specified types
|
|
128
|
+
|
|
129
|
+
// Code generator (choose one)
|
|
130
|
+
.typescript({ // TypeScript generator
|
|
131
|
+
generateProfile?: boolean,
|
|
132
|
+
withDebugComment?: boolean,
|
|
133
|
+
openResourceTypeSet?: boolean,
|
|
134
|
+
})
|
|
135
|
+
.python({ // Python generator
|
|
136
|
+
allowExtraFields?: boolean,
|
|
137
|
+
fieldFormat?: "snake_case" | "camelCase",
|
|
138
|
+
staticDir?: string,
|
|
139
|
+
})
|
|
140
|
+
.csharp("NameSpace", "staticFilesPath") // C# generator
|
|
141
|
+
|
|
142
|
+
// Output configuration
|
|
143
|
+
.outputTo("./generated/types") // Output directory
|
|
144
|
+
.cleanOutput(true) // Clean before generation
|
|
145
|
+
|
|
146
|
+
// Optional: Optimization & debugging
|
|
147
|
+
.throwException() // Throw on errors (optional)
|
|
148
|
+
.writeTypeSchemas("./schemas") // Export TypeSchema files
|
|
149
|
+
.writeTypeTree("./tree.yaml") // Export dependency tree
|
|
150
|
+
|
|
151
|
+
// Execute generation
|
|
152
|
+
.generate(); // Returns GenerationReport
|
|
142
153
|
```
|
|
143
154
|
|
|
144
|
-
|
|
155
|
+
Each method returns the builder instance, allowing method chaining. The `generate()` method executes the pipeline and returns a report with success status and generated file details.
|
|
145
156
|
|
|
146
|
-
|
|
147
|
-
import { APIBuilder } from '@atomic-ehr/codegen';
|
|
157
|
+
### Input - FHIR packages & resolves canonicals
|
|
148
158
|
|
|
149
|
-
|
|
159
|
+
The input stage leverages [Canonical Manager](https://github.com/atomic-ehr/canonical-manager) to handle FHIR package management and dependency resolution. It processes FHIR packages from multiple sources (registry, local files, TGZ archives) and resolves all canonical URLs to their concrete definitions, ensuring all references between resources are properly linked before transformation.
|
|
150
160
|
|
|
151
|
-
|
|
152
|
-
.fromPackage('hl7.fhir.r4.core', '4.0.1')
|
|
153
|
-
.withTemplate('./templates/custom-interface.hbs')
|
|
154
|
-
.typescript({
|
|
155
|
-
outputDir: './generated',
|
|
156
|
-
customHelpers: {
|
|
157
|
-
upperCase: (str) => str.toUpperCase()
|
|
158
|
-
}
|
|
159
|
-
})
|
|
160
|
-
.generate();
|
|
161
|
-
```
|
|
161
|
+
The [`Register`](src/typeschema/register.ts) component wraps Canonical Manager specifically for codegen purposes, providing:
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
- **Multi-package indexing** for fast canonical URL lookups across package boundaries
|
|
164
|
+
- **Package-aware resolution** with automatic dependency tree traversal
|
|
165
|
+
- **FHIR-to-TypeSchema conversion** using the `@atomic-ehr/fhirschema` translator
|
|
166
|
+
- **Element snapshot generation** that merges inherited properties from base resources
|
|
164
167
|
|
|
165
|
-
|
|
166
|
-
import { APIBuilder } from '@atomic-ehr/codegen';
|
|
167
|
-
|
|
168
|
-
const builder = new APIBuilder();
|
|
169
|
-
|
|
170
|
-
// Parse once, generate multiple formats
|
|
171
|
-
const schemas = await builder
|
|
172
|
-
.fromPackage('hl7.fhir.r4.core', '4.0.1')
|
|
173
|
-
.parse();
|
|
174
|
-
|
|
175
|
-
// Generate TypeScript
|
|
176
|
-
await builder
|
|
177
|
-
.fromSchemas(schemas)
|
|
178
|
-
.typescript({ outputDir: './ts-types' })
|
|
179
|
-
.generate();
|
|
180
|
-
|
|
181
|
-
// Generate Python (coming soon)
|
|
182
|
-
await builder
|
|
183
|
-
.fromSchemas(schemas)
|
|
184
|
-
.python({ outputDir: './py-types' })
|
|
185
|
-
.generate();
|
|
186
|
-
```
|
|
168
|
+
#### Load Local StructureDefinitions & TGZ Archives
|
|
187
169
|
|
|
188
|
-
|
|
170
|
+
Use the new `localPackage` helper to point the builder at an on-disk FHIR package folder (for example, an unpublished implementation guide). If you only have loose StructureDefinition JSON files, group them under a folder and pass it to `localStructureDefinitions`. Canonical Manager handles copying, indexing, and dependency installation in both scenarios, so the API builder only needs to describe where the files live and what upstream packages they depend on.
|
|
189
171
|
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson
|
|
198
|
-
atomic-codegen typeschema validate schemas.ndjson
|
|
199
|
-
|
|
200
|
-
# Help and debugging
|
|
201
|
-
atomic-codegen --help # Show help
|
|
202
|
-
atomic-codegen --debug generate # Debug mode
|
|
172
|
+
```typescript
|
|
173
|
+
.localStructureDefinitions({
|
|
174
|
+
package: { name: "example.local.structures", version: "0.0.1" },
|
|
175
|
+
path: "./custom-profiles",
|
|
176
|
+
dependencies: [{ name: "hl7.fhir.r4.core", version: "4.0.1" }],
|
|
177
|
+
})
|
|
178
|
+
.localTgzPackage("./packages/my-custom-ig.tgz")
|
|
203
179
|
```
|
|
204
180
|
|
|
205
|
-
|
|
181
|
+
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.
|
|
206
182
|
|
|
207
|
-
###
|
|
183
|
+
### Intermediate - Type Schema
|
|
208
184
|
|
|
209
|
-
|
|
210
|
-
|--------|------|---------|-------------|
|
|
211
|
-
| `outputDir` | `string` | `./generated` | Base output directory for all generated files |
|
|
212
|
-
| `overwrite` | `boolean` | `false` | Overwrite existing files without prompting |
|
|
213
|
-
| `validate` | `boolean` | `true` | Validate generated TypeSchema before processing |
|
|
214
|
-
| `cache` | `boolean` | `true` | Enable caching for improved performance |
|
|
215
|
-
| `packages` | `string[]` | `[]` | FHIR packages to process (e.g., `"hl7.fhir.r4.core@4.0.1"`) |
|
|
185
|
+
Type Schema serves as a universal intermediate representation that bridges FHIR's complex hierarchical structure with programming language constructs. It transforms FHIR StructureDefinitions into a flattened, code-generation-friendly format that:
|
|
216
186
|
|
|
217
|
-
|
|
187
|
+
- **Unifies** all FHIR elements (Resources, Types, ValueSets) into a consistent structure
|
|
188
|
+
- **Flattens** nested paths for direct field access without complex traversal
|
|
189
|
+
- **Enriches** definitions with resolved references, value set expansions, and type dependencies
|
|
190
|
+
- **Simplifies** FHIR concepts like choice types and extensions for easier code generation
|
|
218
191
|
|
|
219
|
-
|
|
220
|
-
|--------|------|---------|-------------|
|
|
221
|
-
| `outputDir` | `string` | `./generated` | Output directory for generated files |
|
|
222
|
-
| `moduleFormat` | `'esm' \| 'cjs'` | `'esm'` | Module format |
|
|
223
|
-
| `generateIndex` | `boolean` | `true` | Generate index file with exports |
|
|
224
|
-
| `includeDocuments` | `boolean` | `true` | Include JSDoc documentation |
|
|
225
|
-
| `namingConvention` | `'PascalCase' \| 'camelCase'` | `'PascalCase'` | Type naming convention |
|
|
226
|
-
| `includeExtensions` | `boolean` | `false` | Include FHIR extensions |
|
|
227
|
-
| `includeProfiles` | `boolean` | `false` | Include FHIR profiles |
|
|
228
|
-
| `generateValueSets` | `boolean` | `false` | Generate strongly-typed value sets from FHIR bindings |
|
|
229
|
-
| `valueSetStrengths` | `string[]` | `['required']` | Which binding strengths to generate |
|
|
230
|
-
| `includeValueSetHelpers` | `boolean` | `false` | Include validation helper functions |
|
|
231
|
-
| `valueSetDirectory` | `string` | `'valuesets'` | Output directory for value set files |
|
|
192
|
+
This approach enables generating idiomatic code for any programming language while preserving FHIR semantics and constraints. Learn more: [Type Schema specification](https://www.health-samurai.io/articles/type-schema-a-pragmatic-approach-to-build-fhir-sdk).
|
|
232
193
|
|
|
233
|
-
|
|
194
|
+
#### Tree Shaking
|
|
234
195
|
|
|
235
|
-
|
|
196
|
+
Tree shaking optimizes the generated output by including only the resources you explicitly need and their dependencies. Instead of generating types for an entire FHIR package (which can contain hundreds of resources), you can specify exactly which resources to include:
|
|
236
197
|
|
|
237
198
|
```typescript
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
includeValueSetHelpers: true,
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
});
|
|
199
|
+
.treeShake({
|
|
200
|
+
"hl7.fhir.r4.core#4.0.1": {
|
|
201
|
+
"http://hl7.org/fhir/StructureDefinition/Patient": {},
|
|
202
|
+
"http://hl7.org/fhir/StructureDefinition/Observation": {},
|
|
203
|
+
}
|
|
204
|
+
})
|
|
248
205
|
```
|
|
249
206
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
- **generateValueSets**: Enable value set generation
|
|
253
|
-
- **valueSetStrengths**: Control which binding strengths generate types (`'required'`, `'preferred'`, `'extensible'`, `'example'`)
|
|
254
|
-
- **includeValueSetHelpers**: Include runtime validation functions
|
|
255
|
-
- **valueSetDirectory**: Customize output directory name
|
|
207
|
+
This feature automatically resolves and includes all dependencies (referenced types, base resources, nested types) while excluding unused resources, significantly reducing the size of generated code and improving compilation times.
|
|
256
208
|
|
|
257
|
-
|
|
209
|
+
##### Field-Level Tree Shaking
|
|
258
210
|
|
|
259
|
-
|
|
211
|
+
Beyond resource-level filtering, tree shaking supports fine-grained field selection using `selectFields` (whitelist) or `ignoreFields` (blacklist):
|
|
260
212
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
213
|
+
```typescript
|
|
214
|
+
.treeShake({
|
|
215
|
+
"hl7.fhir.r4.core#4.0.1": {
|
|
216
|
+
"http://hl7.org/fhir/StructureDefinition/Patient": {
|
|
217
|
+
selectFields: ["id", "name", "birthDate", "gender"]
|
|
218
|
+
},
|
|
219
|
+
"http://hl7.org/fhir/StructureDefinition/Observation": {
|
|
220
|
+
ignoreFields: ["performer", "note"]
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
```
|
|
265
225
|
|
|
266
|
-
|
|
226
|
+
**Configuration Rules:**
|
|
227
|
+
- `selectFields`: Only includes the specified fields (whitelist approach)
|
|
228
|
+
- `ignoreFields`: Removes specified fields, keeps everything else (blacklist approach)
|
|
229
|
+
- These options are **mutually exclusive** - you cannot use both in the same rule
|
|
267
230
|
|
|
268
|
-
|
|
269
|
-
# Clone repository
|
|
270
|
-
git clone https://github.com/your-org/atomic-codegen
|
|
271
|
-
cd atomic-codegen
|
|
231
|
+
**Polymorphic Field Handling:**
|
|
272
232
|
|
|
273
|
-
|
|
274
|
-
bun install
|
|
233
|
+
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.
|
|
275
234
|
|
|
276
|
-
|
|
277
|
-
bun test
|
|
235
|
+
### Generation
|
|
278
236
|
|
|
279
|
-
|
|
280
|
-
bun run build
|
|
281
|
-
```
|
|
237
|
+
The generation stage transforms Type Schema into target language code using two complementary approaches:
|
|
282
238
|
|
|
283
|
-
|
|
239
|
+
#### 1. Writer-Based Generation (Programmatic)
|
|
284
240
|
|
|
285
|
-
|
|
241
|
+
For languages with built-in support (TypeScript, Python, C#), extend the `Writer` class to implement language-specific generators:
|
|
286
242
|
|
|
287
|
-
|
|
243
|
+
- **FileSystemWriter**: Base class providing file I/O, directory management, and buffer handling (both disk and in-memory modes)
|
|
244
|
+
- **Writer**: Extends FileSystemWriter with code formatting utilities (indentation, blocks, comments, line management)
|
|
245
|
+
- **Language Writers** (`TypeScript`, `Python`[^py], `CSharp`): Implement language-specific generation logic by traversing TypeSchema index and generating corresponding types, interfaces, or classes
|
|
288
246
|
|
|
289
|
-
|
|
247
|
+
[^py]: For details on [Type Schema: Python SDK for FHIR](https://www.health-samurai.io/articles/type-schema-python-sdk-for-fhir)
|
|
290
248
|
|
|
291
|
-
|
|
249
|
+
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.
|
|
292
250
|
|
|
293
|
-
-
|
|
294
|
-
- 🐛 [Issue Tracker](https://github.com/atomic-ehr/codegen/issues)
|
|
251
|
+
**When to use**: Full control needed, complex generation logic, performance-critical, language has a dedicated writer, production-grade output
|
|
295
252
|
|
|
296
|
-
|
|
253
|
+
#### 2. Mustache Template-Based Generation (Declarative)
|
|
297
254
|
|
|
298
|
-
|
|
255
|
+
For custom languages or formats, use Mustache templates to define code generation rules without programming:
|
|
299
256
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
await builder
|
|
304
|
-
.fromPackage('hl7.fhir.r4.core', '4.0.1')
|
|
305
|
-
.restClient({
|
|
306
|
-
clientName: 'MyFHIRClient',
|
|
307
|
-
baseUrl: 'https://api.example.com/fhir',
|
|
308
|
-
authType: 'oauth2'
|
|
309
|
-
})
|
|
310
|
-
.generate();
|
|
311
|
-
|
|
312
|
-
// Use generated client
|
|
313
|
-
const client = new MyFHIRClient();
|
|
314
|
-
const patient = await client.Patient.read('123');
|
|
315
|
-
const bundle = await client.Patient.search({ name: 'Smith' });
|
|
316
|
-
```
|
|
257
|
+
- **Template Files**: Declarative Mustache templates that describe output structure
|
|
258
|
+
- **Configuration**: JSON config file controlling type filtering, naming, and post-generation hooks
|
|
259
|
+
- **ViewModels**: Type Schema automatically transformed into template-friendly data structures
|
|
317
260
|
|
|
318
|
-
|
|
319
|
-
```typescript
|
|
320
|
-
// Intelligent search builders
|
|
321
|
-
const results = await client.Patient
|
|
322
|
-
.search()
|
|
323
|
-
.name().contains('Smith')
|
|
324
|
-
.birthdate().greaterThan('2000-01-01')
|
|
325
|
-
.address().city().equals('Boston')
|
|
326
|
-
.include('Patient:organization')
|
|
327
|
-
.sort('birthdate', 'desc')
|
|
328
|
-
.execute();
|
|
329
|
-
```
|
|
261
|
+
Templates enable flexible code generation for any language or format (Go, Rust, GraphQL, documentation, configs) by describing the output format rather than implementing generation logic.
|
|
330
262
|
|
|
331
|
-
|
|
332
|
-
```typescript
|
|
333
|
-
// Type-safe FHIR operations
|
|
334
|
-
const result = await client.Patient
|
|
335
|
-
.operation('$match')
|
|
336
|
-
.withParameters({
|
|
337
|
-
resource: patient,
|
|
338
|
-
onlyCertainMatches: true
|
|
339
|
-
})
|
|
340
|
-
.execute();
|
|
341
|
-
```
|
|
263
|
+
**When to use**: Custom language support, quick prototyping, template-driven customization, non-code output
|
|
342
264
|
|
|
343
|
-
|
|
265
|
+
---
|
|
344
266
|
|
|
345
|
-
##
|
|
267
|
+
## Roadmap
|
|
346
268
|
|
|
347
269
|
- [x] TypeScript generation
|
|
348
270
|
- [x] FHIR R4 core package support
|
|
@@ -351,17 +273,45 @@ See our detailed [**ROADMAP.md**](ROADMAP.md) for the complete development plan.
|
|
|
351
273
|
- [x] **Value Set Generation** - Strongly-typed enums from FHIR bindings
|
|
352
274
|
- [~] **Profile & Extension Support** - Basic parsing (US Core in development)
|
|
353
275
|
- [ ] **Complete Multi-Package Support** - Custom packages and dependencies
|
|
354
|
-
- [ ] **REST Client Generation** - Fetch-based FHIR clients
|
|
355
276
|
- [ ] **Smart Chained Search** - Intelligent search builders
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// Intelligent search builders
|
|
280
|
+
const results = await client.Patient
|
|
281
|
+
.search()
|
|
282
|
+
.name().contains('Smith')
|
|
283
|
+
.birthdate().greaterThan('2000-01-01')
|
|
284
|
+
.address().city().equals('Boston')
|
|
285
|
+
.include('Patient:organization')
|
|
286
|
+
.sort('birthdate', 'desc')
|
|
287
|
+
.execute();
|
|
288
|
+
```
|
|
289
|
+
|
|
356
290
|
- [ ] **Operation Generation** - Type-safe FHIR operations
|
|
357
|
-
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
// Type-safe FHIR operations
|
|
294
|
+
const result = await client.Patient
|
|
295
|
+
.operation('$match')
|
|
296
|
+
.withParameters({
|
|
297
|
+
resource: patient,
|
|
298
|
+
onlyCertainMatches: true
|
|
299
|
+
})
|
|
300
|
+
.execute();
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
- [x] **Python generation**
|
|
304
|
+
- [x] **C# generation**
|
|
358
305
|
- [ ] **Rust generation**
|
|
359
306
|
- [ ] **GraphQL schema generation**
|
|
360
307
|
- [ ] **OpenAPI specification generation**
|
|
361
308
|
- [ ] **Validation functions**
|
|
362
309
|
- [ ] **Mock data generation**
|
|
363
|
-
|
|
310
|
+
|
|
311
|
+
## Support
|
|
312
|
+
|
|
313
|
+
- 🐛 [Issue Tracker](https://github.com/atomic-ehr/codegen/issues)
|
|
364
314
|
|
|
365
315
|
---
|
|
366
316
|
|
|
367
|
-
Built with ❤️
|
|
317
|
+
Built with ❤️ by the Atomic Healthcare team
|