Skip to content

Commit 602075d

Browse files
committed
chore: progress with profile generation
1 parent 774c4ba commit 602075d

32 files changed

Lines changed: 25817 additions & 1032 deletions

atomic-codegen.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export default defineConfig({
1414
typescript: {
1515
includeDocuments: true,
1616
namingConvention: "PascalCase",
17-
includeProfiles: false,
17+
includeProfiles: true,
1818
includeExtensions: false,
1919
generateIndex: true,
2020
strictMode: true,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fhir-types
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/**
2+
* FHIR R4 Resource Creation Demo
3+
*
4+
* This file demonstrates how to:
5+
* 1. Create a Patient resource
6+
* 2. Create an Observation resource
7+
* 3. Create a body weight observation with profiles
8+
* 4. Use attach and extract functions for FHIR profiles
9+
* 5. Bundle them together in a FHIR Bundle
10+
*/
11+
12+
import type { Bundle, BundleEntry } from "./fhir-types/hl7-fhir-r4-core/Bundle";
13+
import type { CodeableConcept } from "./fhir-types/hl7-fhir-r4-core/CodeableConcept";
14+
import type { Coding } from "./fhir-types/hl7-fhir-r4-core/Coding";
15+
import type { Observation, ObservationReferenceRange } from "./fhir-types/hl7-fhir-r4-core/Observation";
16+
import type { Address, ContactPoint, HumanName, Identifier, Patient } from "./fhir-types/hl7-fhir-r4-core/Patient";
17+
import type { Quantity } from "./fhir-types/hl7-fhir-r4-core/Quantity";
18+
import type { Reference } from "./fhir-types/hl7-fhir-r4-core/Reference";
19+
20+
function createPatient(): Patient {
21+
const identifier: Identifier = {
22+
system: "http://hospital.example.org/identifiers/patient",
23+
value: "12345",
24+
use: "official",
25+
};
26+
27+
const name: HumanName = {
28+
family: "Smith",
29+
given: ["John", "Jacob"],
30+
use: "official",
31+
prefix: ["Mr."],
32+
};
33+
34+
const telecom: ContactPoint[] = [
35+
{
36+
system: "phone",
37+
value: "555-555-5555",
38+
use: "home",
39+
},
40+
{
41+
system: "email",
42+
value: "john.smith@example.com",
43+
use: "work",
44+
},
45+
];
46+
47+
const address: Address = {
48+
line: ["123 Main St"],
49+
city: "Anytown",
50+
state: "CA",
51+
postalCode: "12345",
52+
country: "USA",
53+
use: "home",
54+
};
55+
56+
const patient: Patient = {
57+
resourceType: "Patient",
58+
id: "pt-1",
59+
identifier: [identifier],
60+
active: true,
61+
name: [name],
62+
telecom: telecom,
63+
gender: "male",
64+
birthDate: "1974-12-25",
65+
address: [address],
66+
};
67+
68+
return patient;
69+
}
70+
71+
function createObservation(patientId: string): Observation {
72+
const glucoseCoding: Coding = {
73+
system: "http://loinc.org",
74+
code: "15074-8",
75+
display: "Glucose [Moles/volume] in Blood",
76+
};
77+
78+
const glucoseConcept: CodeableConcept = {
79+
coding: [glucoseCoding],
80+
text: "Blood glucose measurement",
81+
};
82+
83+
const referenceRange: ObservationReferenceRange = {
84+
low: {
85+
value: 3.1,
86+
unit: "mmol/L",
87+
system: "http://unitsofmeasure.org",
88+
code: "mmol/L",
89+
},
90+
high: {
91+
value: 6.2,
92+
unit: "mmol/L",
93+
system: "http://unitsofmeasure.org",
94+
code: "mmol/L",
95+
},
96+
text: "3.1 to 6.2 mmol/L",
97+
};
98+
99+
const glucoseValue: Quantity = {
100+
value: 6.3,
101+
unit: "mmol/L",
102+
system: "http://unitsofmeasure.org",
103+
code: "mmol/L",
104+
};
105+
106+
const patientReference: Reference<"Patient"> = {
107+
reference: `Patient/${patientId}`,
108+
display: "John Smith",
109+
};
110+
111+
const observation: Observation = {
112+
resourceType: "Observation",
113+
id: "glucose-obs-1",
114+
status: "final",
115+
category: [
116+
{
117+
coding: [
118+
{
119+
system: "http://terminology.hl7.org/CodeSystem/observation-category",
120+
code: "laboratory",
121+
display: "Laboratory",
122+
},
123+
],
124+
text: "Laboratory",
125+
},
126+
],
127+
code: glucoseConcept,
128+
subject: patientReference,
129+
effectiveDateTime: "2023-03-15T09:30:00Z",
130+
issued: "2023-03-15T10:15:00Z",
131+
valueQuantity: glucoseValue,
132+
referenceRange: [referenceRange],
133+
};
134+
135+
return observation;
136+
}
137+
138+
function createBodyWeightObservation(patientId: string): Observation {
139+
const baseObservation: Observation = {
140+
resourceType: "Observation",
141+
id: "example-genetics-1",
142+
status: "final",
143+
code: {
144+
coding: [
145+
{
146+
code: "29463-7",
147+
system: "http://loinc.org",
148+
display: "Body weight",
149+
},
150+
],
151+
},
152+
};
153+
154+
const bodyweightProfile: observation_bodyweight = {
155+
__profileUrl: "http://hl7.org/fhir/StructureDefinition/bodyweight",
156+
status: baseObservation.status,
157+
category: [
158+
{
159+
coding: [
160+
{
161+
system: "http://terminology.hl7.org/CodeSystem/observation-category",
162+
code: "vital-signs",
163+
display: "Vital Signs",
164+
},
165+
],
166+
text: "Vital Signs",
167+
},
168+
],
169+
code: {
170+
coding: [
171+
{
172+
code: "29463-7",
173+
system: "http://loinc.org",
174+
display: "Body weight",
175+
},
176+
],
177+
},
178+
subject: {
179+
reference: `Patient/${patientId}`,
180+
display: "John Smith",
181+
},
182+
effectiveDateTime: "2023-03-15T09:30:00Z",
183+
valueQuantity: {
184+
value: 75.5,
185+
unit: "kg",
186+
system: "http://unitsofmeasure.org",
187+
code: "kg",
188+
},
189+
};
190+
191+
console.log("Original observation:", JSON.stringify(baseObservation, null, 2));
192+
console.log("Body weight observation:", JSON.stringify(bodyweightProfile, null, 2));
193+
194+
const bodyweightObservation = attach_observation_bodyweight_to_Observation(baseObservation, bodyweightProfile);
195+
console.log("Body weight observation with profile:", JSON.stringify(bodyweightObservation, null, 2));
196+
197+
console.log("Validate bodyweight observation with attached profile");
198+
const isStatusCorrect = bodyweightObservation.status === "final";
199+
const isCodeCorrect =
200+
bodyweightObservation.code?.coding?.[0]?.code === "29463-7" &&
201+
bodyweightObservation.code?.coding?.[0]?.system === "http://loinc.org";
202+
const hasValueQuantity = bodyweightObservation.valueQuantity !== undefined;
203+
const isValueQuantityCorrect =
204+
bodyweightObservation.valueQuantity?.value === 75.5 &&
205+
bodyweightObservation.valueQuantity?.unit === "kg" &&
206+
bodyweightObservation.valueQuantity?.system === "http://unitsofmeasure.org";
207+
208+
console.log("✓ Status is 'final':", isStatusCorrect);
209+
console.log("✓ Code is LOINC 29463-7 (Body weight):", isCodeCorrect);
210+
console.log("✓ Has valueQuantity:", hasValueQuantity);
211+
console.log("✓ ValueQuantity is correct (75.5 kg):", isValueQuantityCorrect);
212+
213+
if (!isStatusCorrect || !isCodeCorrect || !hasValueQuantity || !isValueQuantityCorrect)
214+
throw new Error("Bodyweight observation is not valid");
215+
216+
const extractedProfile = extract_observation_bodyweight_from_Observation(bodyweightObservation);
217+
console.log("Extracted bodyweight profile:", JSON.stringify(extractedProfile, null, 2));
218+
219+
console.log("\n--- Validation: extractedProfile correctness ---");
220+
221+
const isProfileUrlCorrect = extractedProfile.__profileUrl === "http://hl7.org/fhir/StructureDefinition/bodyweight";
222+
const isExtractedStatusCorrect = extractedProfile.status === "final";
223+
const isExtractedCodeCorrect = extractedProfile.code?.coding?.[0]?.code === "29463-7";
224+
const isExtractedValueCorrect =
225+
extractedProfile.valueQuantity?.value === 75.5 && extractedProfile.valueQuantity?.unit === "kg";
226+
227+
const profilesMatch = JSON.stringify(bodyweightProfile) === JSON.stringify(extractedProfile);
228+
229+
console.log("✓ Profile URL is correct:", isProfileUrlCorrect);
230+
console.log("✓ Extracted status matches:", isExtractedStatusCorrect);
231+
console.log("✓ Extracted code matches:", isExtractedCodeCorrect);
232+
console.log("✓ Extracted value matches:", isExtractedValueCorrect);
233+
console.log("✓ Original and extracted profiles match:", profilesMatch);
234+
235+
if (!profilesMatch) throw new Error("Profile mismatch");
236+
237+
return bodyweightObservation;
238+
}
239+
240+
function createBundle(patient: Patient, observation: Observation, bodyweightObs: Observation): Bundle {
241+
const patientEntry: BundleEntry = {
242+
fullUrl: `urn:uuid:${patient.id}`,
243+
resource: patient,
244+
};
245+
246+
const observationEntry: BundleEntry = {
247+
fullUrl: `urn:uuid:${observation.id}`,
248+
resource: observation,
249+
};
250+
251+
const bodyweightEntry: BundleEntry = {
252+
fullUrl: `urn:uuid:${bodyweightObs.id}`,
253+
resource: bodyweightObs,
254+
};
255+
256+
const bundle: Bundle = {
257+
resourceType: "Bundle",
258+
id: "bundle-1",
259+
type: "collection",
260+
entry: [patientEntry, observationEntry, bodyweightEntry],
261+
};
262+
263+
return bundle;
264+
}
265+
266+
function runDemo() {
267+
console.log("=".repeat(60));
268+
console.log("Creating FHIR R4 resources demo with bodyweight profile...");
269+
console.log("=".repeat(60));
270+
271+
const patient = createPatient();
272+
console.log("✓ Created patient:", patient.id);
273+
274+
const observation = createObservation(patient.id!);
275+
console.log("✓ Created glucose observation:", observation.id);
276+
277+
console.log(`\n${"=".repeat(60)}`);
278+
console.log("Bodyweight profile attach/extract demo:");
279+
console.log("=".repeat(60));
280+
281+
const bodyweightObs = createBodyWeightObservation(patient.id!);
282+
console.log("✓ Created body weight observation with profile:", bodyweightObs.id);
283+
284+
const bundle = createBundle(patient, observation, bodyweightObs);
285+
console.log("\n✓ Created bundle with", bundle.entry?.length, "resources");
286+
287+
console.log(`\n${"=".repeat(60)}`);
288+
console.log("Final Bundle JSON:");
289+
console.log("=".repeat(60));
290+
console.log(JSON.stringify(bundle, null, 2));
291+
}
292+
293+
runDemo();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Run this script using Bun CLI with:
2+
// bun run examples/typescript-us-core/generate.ts
3+
4+
import { APIBuilder } from "../../src/api/builder";
5+
6+
if (require.main === module) {
7+
console.log("📦 Generating FHIR R4 Core Types...");
8+
9+
const builder = new APIBuilder()
10+
.verbose()
11+
.throwException()
12+
.fromPackage("hl7.fhir.us.core", "6.1.0")
13+
.typescript({ withDebugComment: false, withProfiles: true })
14+
.outputTo("./examples/typescript-us-core/fhir-types")
15+
.writeTypeTree("./examples/typescript-us-core/type-tree.yaml")
16+
.cleanOutput(true);
17+
18+
const report = await builder.generate();
19+
20+
console.log(report);
21+
22+
if (report.success) {
23+
console.log("✅ FHIR R4 types generated successfully!");
24+
} else {
25+
console.error("❌ FHIR R4 types generation failed.");
26+
process.exit(1);
27+
}
28+
}

0 commit comments

Comments
 (0)