@atomic-ehr/codegen 0.0.7 → 0.0.8-canary.20260304203134.178662b

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/README.md CHANGED
@@ -23,7 +23,6 @@
23
23
  - [Generation](#generation)
24
24
  - [1. Writer-Based Generation (Programmatic)](#1-writer-based-generation-programmatic)
25
25
  - [2. Mustache Template-Based Generation (Declarative)](#2-mustache-template-based-generation-declarative)
26
- - [Roadmap](#roadmap)
27
26
  - [Support](#support)
28
27
  - [Footnotes](#footnotes)
29
28
 
@@ -41,14 +40,32 @@ Guides:
41
40
 
42
41
  ## Features
43
42
 
44
- - 🚀 **High-Performance** - Built with Bun runtime for blazing-fast generation
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
50
- - 🎯 **Type-Safe** - Generates fully typed interfaces with proper inheritance
51
- - 🛠️ **Developer Friendly** - Fluent API
43
+ - [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/)
44
+ - Tested with hl7.fhir.r4.core, US Core, C-CDA, SQL on FHIR, etc.
45
+ - [x] **Resources & Complex Types** — Generates typed definitions with proper inheritance
46
+ - [x] **Value Set Bindings** Strongly-typed enums from FHIR terminology bindings
47
+ - [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/))
48
+ - Extensions flat typed accessors (e.g. `setRace()` on US Core Patient), [standalone extension profiles](examples/typescript-r4/extension-profile.test.ts)
49
+ - Slicing typed get/set accessors with discriminator matching
50
+ - Validation runtime `validate()` for required fields, fixed values, slice cardinality, enums, references
51
+ - [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
52
+ - TypeSchema is a universal intermediate representation — add a new language by writing only the final generation stage
53
+ - Built-in generators: TypeScript, Python/Pydantic, C#, and Mustache templates
54
+ - [x] **TypeSchema Transformations**:
55
+ - [x] Tree Shaking — include only the resources and fields you need; automatically resolves dependencies
56
+ - [x] Logical Model Promotion — promote FHIR logical models (e.g. CDA ClinicalDocument) to first-class resources
57
+ - [ ] Renaming — custom naming conventions for generated types, fields, packages, etc.
58
+ - [ ] **Search Builders** — type-safe FHIR search query construction
59
+ - [ ] **Operation Generation** — type-safe FHIR operation calls
60
+
61
+ | Feature | TypeSchema | TypeScript | Python | C# | Mustache |
62
+ |---|---|---|---|---|---|
63
+ | Resources & Complex Types | yes | yes | yes | yes | template |
64
+ | Value Set Bindings | yes | inline | inline | enum | template |
65
+ | Profiles & Extensions | yes | yes | no | no | no |
66
+ | Tree Shaking | yes | 〃 | 〃 | 〃 | 〃 |
67
+ | Logical Model Promotion | yes | 〃 | 〃 | 〃 | 〃 |
68
+
52
69
 
53
70
  ## Versions & Release Cycle
54
71
 
@@ -298,107 +315,61 @@ Templates enable flexible code generation for any language or format (Go, Rust,
298
315
 
299
316
  ### Profile Classes
300
317
 
301
- When generating TypeScript with `generateProfile: true`, the generator creates profile wrapper classes that provide a fluent API for working with FHIR profiles (US Core, etc.). These classes handle complex profile constraints like slicing and extensions automatically.
318
+ When generating TypeScript with `generateProfile: true`, the generator creates profile wrapper classes that provide a fluent API for working with FHIR profiles. These classes handle complex profile constraints like slicing and extensions automatically.
302
319
 
303
320
  ```typescript
304
- import { Patient } from "./fhir-types/hl7-fhir-r4-core/Patient";
305
- import { USCorePatientProfileProfile } from "./fhir-types/hl7-fhir-us-core/profiles/UscorePatientProfile";
306
-
307
- // Wrap a FHIR resource with a profile class
308
- const resource: Patient = { resourceType: "Patient" };
309
- const profile = new USCorePatientProfileProfile(resource);
321
+ import { observation_bpProfile as bpProfile } from "./profiles/Observation_observation_bp";
310
322
 
311
- // Set extensions using flat API - complex extensions are simplified
312
- profile.setRace({
313
- ombCategory: { system: "urn:oid:2.16.840.1.113883.6.238", code: "2106-3", display: "White" },
314
- text: "White",
323
+ // create() auto-sets fixed values (code, meta.profile) and required slice stubs
324
+ const bp = bpProfile.create({
325
+ status: "final",
326
+ subject: { reference: "Patient/pt-1" },
315
327
  });
316
328
 
317
- // Set simple extensions directly
318
- profile.setSex({ system: "http://hl7.org/fhir/administrative-gender", code: "male" });
319
-
320
- // Get extension values - flat API returns simplified object
321
- const race = profile.getRace();
322
- console.log(race?.ombCategory?.display); // "White"
329
+ // Slice setters discriminator values (LOINC codes) applied automatically
330
+ // Single-variant choice types (value[x] → valueQuantity) are flattened:
331
+ bp.setVSCat({ text: "Vital Signs" })
332
+ .setSystolicBP({ value: 120, unit: "mmHg" })
333
+ .setDiastolicBP({ value: 80, unit: "mmHg" })
334
+ .setEffectiveDateTime("2024-06-15");
323
335
 
324
- // Get raw FHIR Extension when needed
325
- const raceExtension = profile.getRaceExtension();
326
- console.log(raceExtension?.url); // "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race"
336
+ bp.validate(); // [] valid
327
337
 
328
- // Get the underlying resource
329
- const patientResource = profile.toResource();
338
+ // Get plain FHIR JSON — ready for API calls, storage, etc.
339
+ const obs = bp.toResource();
340
+ // obs.component[0].valueQuantity.value === 120
341
+ // obs.component[0].code.coding[0].code === "8480-6"
330
342
  ```
331
343
 
332
- **Slicing Support:**
333
-
334
- Profile classes also handle FHIR slicing, automatically applying discriminator values:
344
+ **Slicing & Choice Type Flattening:**
335
345
 
336
346
  ```typescript
337
- import { Observation } from "./fhir-types/hl7-fhir-r4-core/Observation";
338
- import { USCoreBloodPressureProfileProfile } from "./fhir-types/hl7-fhir-us-core/profiles/UscoreBloodPressureProfile";
339
-
340
- const obs: Observation = { resourceType: "Observation", status: "final", code: {} };
341
- const bp = new USCoreBloodPressureProfileProfile(obs);
347
+ // Simplified getter discriminator stripped, choice type flattened
348
+ bp.getSystolicBP(); // { value: 120, unit: "mmHg" }
342
349
 
343
- // Set slices - discriminator is applied automatically
344
- // No input needed when all fields are part of the discriminator
345
- bp.setSystolic({ valueQuantity: { value: 120, unit: "mmHg" } });
346
- bp.setDiastolic({ valueQuantity: { value: 80, unit: "mmHg" } });
347
-
348
- // Get simplified slice (without discriminator fields)
349
- const systolic = bp.getSystolic();
350
- console.log(systolic?.valueQuantity?.value); // 120
351
-
352
- // Get raw slice (includes discriminator)
353
- const systolicRaw = bp.getSystolicRaw();
354
- console.log(systolicRaw?.code?.coding?.[0]?.code); // "8480-6" (LOINC code for systolic BP)
350
+ // Raw getter full FHIR element including discriminator values
351
+ bp.getSystolicBPRaw(); // { code: { coding: [...] }, valueQuantity: { value: 120, ... } }
355
352
  ```
356
353
 
357
- See [examples/typescript-us-core/](examples/typescript-us-core/) for complete profile usage examples.
358
-
359
- ## Roadmap
360
-
361
- - [x] TypeScript generation
362
- - [x] FHIR R4 core package support
363
- - [x] Configuration file support
364
- - [x] Comprehensive test suite (72+ tests)
365
- - [x] **Value Set Generation** - Strongly-typed enums from FHIR bindings
366
- - [x] **Profile & Extension Support** - Basic parsing (US Core in development)
367
- - [ ] **Complete Multi-Package Support** - Custom packages and dependencies
368
- - [ ] **Smart Chained Search** - Intelligent search builders
354
+ **Wrapping Existing Resources:**
369
355
 
370
- ```typescript
371
- // Intelligent search builders
372
- const results = await client.Patient
373
- .search()
374
- .name().contains('Smith')
375
- .birthdate().greaterThan('2000-01-01')
376
- .address().city().equals('Boston')
377
- .include('Patient:organization')
378
- .sort('birthdate', 'desc')
379
- .execute();
380
- ```
356
+ ```typescript
357
+ // Wrap any resource to read slices
358
+ const bp2 = bpProfile.from(existingObservation);
359
+ bp2.getSystolicBP(); // { value: 120, unit: "mmHg" }
360
+ bp2.getVSCat(); // { text: "Vital Signs" }
361
+ bp2.getEffectiveDateTime(); // "2024-06-15"
362
+ ```
381
363
 
382
- - [ ] **Operation Generation** - Type-safe FHIR operations
364
+ **Validation:**
383
365
 
384
- ```typescript
385
- // Type-safe FHIR operations
386
- const result = await client.Patient
387
- .operation('$match')
388
- .withParameters({
389
- resource: patient,
390
- onlyCertainMatches: true
391
- })
392
- .execute();
393
- ```
366
+ ```typescript
367
+ const errors = bp.validate();
368
+ // [] empty means valid
369
+ // ["effective: at least one of effectiveDateTime, effectivePeriod is required"]
370
+ ```
394
371
 
395
- - [x] **Python generation**
396
- - [x] **C# generation**
397
- - [ ] **Rust generation**
398
- - [ ] **GraphQL schema generation**
399
- - [ ] **OpenAPI specification generation**
400
- - [ ] **Validation functions**
401
- - [ ] **Mock data generation**
372
+ See [examples/typescript-r4/](examples/typescript-r4/) for R4 profile tests and [examples/typescript-us-core/](examples/typescript-us-core/) for US Core profile examples.
402
373
 
403
374
  ## Support
404
375
 
@@ -1,4 +1,4 @@
1
- from typing import Any, Union, Optional, Iterator, Tuple, Dict
1
+ from typing import Any, ClassVar, Type, Union, Optional, Iterator, Tuple, Dict
2
2
  from pydantic import BaseModel, Field
3
3
  from typing import Protocol
4
4
 
@@ -8,20 +8,23 @@ class ResourceProtocol(Protocol):
8
8
  id: Union[str, None]
9
9
 
10
10
 
11
+ class ResourceTypeDescriptor:
12
+ def __get__(self, instance: Optional[BaseModel], owner: Type[BaseModel]) -> str:
13
+ field = owner.model_fields.get("resource_type")
14
+ if field is None:
15
+ raise ValueError("resource_type field not found")
16
+ if field.default is None:
17
+ raise ValueError("resource_type field default value is not set")
18
+ return str(field.default)
19
+
20
+
11
21
  class FhirpyBaseModel(BaseModel):
12
22
  """
13
23
  This class satisfies ResourceProtocol
14
24
  """
15
- resource_type: str = Field(alias="resourceType")
16
25
  id: Optional[str] = Field(None, alias="id")
17
26
 
18
- @property
19
- def resourceType(self) -> str:
20
- return self.resource_type
21
-
22
- @resourceType.setter
23
- def resourceType(self, value: str) -> None:
24
- self.resource_type = value
27
+ resourceType: ClassVar[ResourceTypeDescriptor] = ResourceTypeDescriptor()
25
28
 
26
29
  def __iter__(self) -> Iterator[Tuple[str, Any]]: # type: ignore[override]
27
30
  data = self.model_dump(mode='json', by_alias=True, exclude_none=True)
@@ -0,0 +1,23 @@
1
+ from typing import Any, Union, Optional, Iterator, Tuple, Dict
2
+ from pydantic import BaseModel, Field
3
+ from typing import Protocol
4
+
5
+
6
+ class ResourceProtocol(Protocol):
7
+ resourceType: Any
8
+ id: Union[str, None]
9
+
10
+
11
+ class FhirpyBaseModel(BaseModel):
12
+ """
13
+ This class satisfies ResourceProtocol
14
+ """
15
+ id: Optional[str] = Field(None, alias="id")
16
+
17
+ def __iter__(self) -> Iterator[Tuple[str, Any]]: # type: ignore[override]
18
+ data = self.model_dump(mode='json', by_alias=True, exclude_none=True)
19
+ return iter(data.items())
20
+
21
+ def serialize(self) -> Dict[str, Any]:
22
+ """Serialize to dict (compatible with fhirpy's serialize method)"""
23
+ return self.model_dump(mode='json', by_alias=True, exclude_none=True)
package/dist/cli/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import x from'picocolors';import et from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {createHash}from'crypto';import Te from'assert';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as ge from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var D=class e{options;dryWarnSet=new Set;constructor(t={}){this.options={timestamp:false,level:1,...t};}shouldLog(t){let o=this.options.level??1;return t>=o}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(t,o,i){let n=this.options.timestamp?`${x.gray(new Date().toLocaleTimeString())} `:"",r=this.options.prefix?`${x.cyan(`[${this.options.prefix}]`)} `:"";return `${n}${i(t)} ${r}${o}`}isSuppressed(t){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(t)||false}tryWriteToConsole(t,o){if(this.isSuppressed(t)||!this.shouldLog(t))return;(e.consoleLevelsMap[t]||console.log)(o);}success(t){this.tryWriteToConsole(1,this.formatMessage("",t,x.green));}error(t,o){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",t,x.red));let i=this.options.level===0;o&&i&&(console.error(x.red(` ${o.message}`)),o.stack&&console.error(x.gray(o.stack)));}warn(t){this.tryWriteToConsole(2,this.formatMessage("!",t,x.yellow));}dryWarn(t){this.dryWarnSet.has(t)||(this.warn(t),this.dryWarnSet.add(t));}info(t){this.tryWriteToConsole(1,this.formatMessage("i",t,x.blue));}debug(t){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",t,x.magenta));}step(t){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",t,x.cyan));}progress(t){this.tryWriteToConsole(1,this.formatMessage("\u23F3",t,x.blue));}plain(t,o=i=>i){let i=this.options.timestamp?`${x.gray(new Date().toLocaleTimeString())} `:"",n=this.options.prefix?`${x.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${i}${n}${o(t)}`);}dim(t){this.plain(t,x.gray);}child(t){return new e({...this.options,prefix:this.options.prefix?`${this.options.prefix}:${t}`:t})}configure(t){this.options={...this.options,...t};}getLevel(){return this.options.level??1}setLevel(t){this.options.level=t;}},v=new D;function Ce(e){v.success(e);}function k(e,t){v.error(e,t);}function V(e){v.info(e);}function ke(e){v.dim(e);}function K(e){v.configure(e);}function J(e={}){return new D(e)}function Q(e){console.log(),console.log(x.cyan(x.bold(`\u2501\u2501\u2501 ${e} \u2501\u2501\u2501`)));}function X(e,t,o){let i=e;t&&(i+=` ${x.gray(`(${t}ms)`)}`),Ce(i),o&&Object.entries(o).forEach(([n,r])=>{ke(` ${n}: ${r}`);});}function b(e,t="\u2022"){e.forEach(o=>{console.log(x.gray(` ${t} ${o}`));});}var F="Use CodeableReference which is not provided by FHIR R4.",be="Use Availability which is not provided by FHIR R4.",O={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":be,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":F,"http://hl7.org/fhir/StructureDefinition/specimen-additive":F,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":F,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":F,"http://hl7.org/fhir/StructureDefinition/workflow-reason":F},"hl7.fhir.r5.core#5.0.0":{"http://hl7.org/fhir/StructureDefinition/shareablecodesystem":"FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now.","http://hl7.org/fhir/StructureDefinition/publishablecodesystem":"Uses R5-only base types not available in R4 generation."}};function I(e,t){let o=`${e.name}#${e.version}`,i=O[o]?.[t];if(i)return {shouldSkip:true,reason:i};let n=O[e.name]?.[t];return n?{shouldSkip:true,reason:n}:{shouldSkip:false}}var S=e=>`${e.name}#${e.version}`,Y=e=>`${e.name}@${e.version}`;var Z=e=>{let t=JSON.stringify(e);return createHash("sha256").update(t).digest("hex").slice(0,16)},ee=(e,t)=>({...e,package_meta:e.package_meta||t,name:e.name,url:e.url,base:e.base});var te=e=>e?.kind==="nested",ne=e=>e?.kind==="profile";var ie=(e,t)=>{if(!e.url)throw new Error("ValueSet must have a URL");if(!e.name)throw new Error("ValueSet must have a name");return {...e,package_meta:e.package_meta||t,name:e.name,url:e.url}};function M(e){let t=e.split("|")[0];return t||e}function ve(e){return e.split("|")[1]}function Fe(e){return e.derivation==="constraint"?"profile":e.kind==="primitive-type"?"primitive-type":e.kind==="complex-type"?"complex-type":e.kind==="resource"?"resource":e.kind==="logical"?"logical":"resource"}function C(e){return {kind:Fe(e),package:e.package_meta.name,version:e.package_meta.version,name:e.name,url:e.url}}var Ee=e=>{let t=e.split("/"),o=t[t.length-1];return o&&o.length>0?o.split(/[-_]/).map(i=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join(""):e};function L(e,t,o){let i=M(o),n=Ee(i),r={package_meta:{name:"missing_valuesets",version:ve(i)||"0.0.0"},id:o},s=e.resolveVs(t,i)||r,c=s?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(s.id)?s.id:n;return {kind:"value-set",package:s.package_meta.name,version:s.package_meta.version,name:c,url:i}}function P(e,t,o){let i=o.binding?.bindingName,n=t.join("."),[r,s,c]=i?[{name:"shared",version:"1.0.0"},i,`urn:fhir:binding:${i}`]:[e.package_meta,`${e.name}.${n}_binding`,`${e.url}#${n}_binding`];return {kind:"binding",package:r.name,version:r.version,name:s,url:c}}function B(e,t,o,i){let n=M(o)||o,r=e.resolveVs(t,n);if(r)return De(e,r)}function De(e,t,o){if(t.expansion?.contains)return t.expansion.contains.filter(n=>n.code!==void 0).map(n=>(Te(n.code),{code:n.code,display:n.display,system:n.system}));let i=[];if(t.compose?.include){for(let n of t.compose.include)if(n.concept)for(let r of n.concept)i.push({system:n.system,code:r.code,display:r.display});else if(n.system&&!n.filter)try{let r=e.resolveAny(n.system);if(r?.concept){let s=(c,a)=>{for(let l of c)i.push({system:a,code:l.code,display:l.display}),l.concept&&s(l.concept,a);};s(r.concept,n.system);}}catch{}}return i.length>0?i:void 0}var oe=100,j=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function _(e,t,o,i){if(!o.binding)return;let n=o.binding.strength,r=o.binding.valueSet;if(!r)return;if(!j.has(o.type??"")){i?.dryWarn(`eld-11: Binding on non-bindable type '${o.type}' (valueSet: ${r})`);return}if(!(n==="required"||n==="extensible"||n==="preferred"))return;let c=B(e,t.package_meta,r);if(!c||c.length===0)return;let a=c.map(l=>l.code).filter(l=>l&&typeof l=="string"&&l.trim().length>0);if(a.length>oe){i?.dryWarn(`Value set ${r} has ${a.length} which is more than ${oe} codes, which may cause issues with code generation.`);return}if(a.length!==0)return {isOpen:n!=="required",values:a}}function Le(e,t,o,i,n){if(!i.binding?.valueSet)return;let r=P(t,o,i),s=L(e,t.package_meta,i.binding.valueSet),c=_(e,t,i,n);return {identifier:r,valueset:s,strength:i.binding.strength,enum:c,dependencies:[s]}}function re(e,t,o){let i=new Set;if(!t.elements)return [];let n=[];function r(a,l){for(let[u,m]of Object.entries(a)){let h=[...l,u],p=h.join("."),d=e.resolveElementSnapshot(t,h);if(!i.has(p)){if(i.add(p),d.binding){let f=Le(e,t,h,d,o);f&&n.push(f);}m.elements&&r(m.elements,h);}}}r(t.elements,[]),n.sort((a,l)=>a.identifier.name.localeCompare(l.identifier.name));let s=[],c=new Set;for(let a of n)c.has(a.identifier.url)||(c.add(a.identifier.url),s.push(a));return s}function w(e,t,o,i){let n={};if(t.derivation==="constraint"){let m=e.resolveFsSpecializations(t.package_meta,t.url).map(h=>A(e,h,i)).filter(h=>h!==void 0).flat();for(let h of m.reverse())n[h.identifier.name]=h.identifier.url;}let r=o.join("."),s=n[r]??`${t.url}#${r}`,c=s.split("#")[0],l=e.resolveFs(t.package_meta,c)?.package_meta??t.package_meta;return {kind:"nested",package:l.name,version:l.version,name:r,url:s}}function se(e,t,o){let i=[];for(let[n,r]of Object.entries(o)){let s=[...t,n];E(r)&&i.push([s,r]),r.elements&&i.push(...se(e,s,r.elements));}return i}function Pe(e,t,o,i,n){let r={};for(let[s,c]of Object.entries(i)){let a=[...o,s],l=e.resolveElementSnapshot(t,a);E(l)?r[s]=U(e,t,a,l,n):r[s]=N(e,t,a,l,n);}return r}function A(e,t,o){if(!t.elements)return;let i=se(t,[],t.elements).filter(([r,s])=>s.elements&&Object.keys(s.elements).length>0),n=[];for(let[r,s]of i){let c=w(e,t,r,o),a;s.type==="BackboneElement"||!s.type?a="BackboneElement":a=s.type;let l=e.ensureSpecializationCanonicalUrl(a),u=e.resolveFs(t.package_meta,l);if(!u)throw new Error(`Could not resolve base type ${a}`);let m={kind:"complex-type",package:u.package_meta.name,version:u.package_meta.version,name:a,url:l},h=Pe(e,t,r,s.elements??{},o),p={identifier:c,base:m,fields:h};n.push(p);}return n.sort((r,s)=>r.identifier.url.localeCompare(s.identifier.url)),n.length===0?void 0:n}function ae(e){let t=[];for(let o of e){o.base&&t.push(o.base);for(let i of Object.values(o.fields||{}))"type"in i&&i.type&&t.push(i.type),"binding"in i&&i.binding&&t.push(i.binding);}return t}function ce(e,t,o){let i=o[o.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${o.join("/")}`);let n=o.slice(0,-1),r=e.resolveFsGenealogy(t.package_meta,t.url).flatMap(s=>{if(n.length===0)return s.required||[];if(!s.elements)return [];let c=s;for(let a of n)c=c?.elements?.[a];return c?.required||[]});return new Set(r).has(i)}function le(e,t,o){let i=o[o.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${o.join("/")}`);let n=o.slice(0,-1),r=e.resolveFsGenealogy(t.package_meta,t.url).flatMap(s=>{if(n.length===0)return s.excluded||[];if(!s.elements)return [];let c=s;for(let a of n)c=c?.elements?.[a];return c?.excluded||[]});return new Set(r).has(i)}var we=(e,t,o)=>{if(o.refers)return o.refers.map(i=>{let n=e.ensureSpecializationCanonicalUrl(i),r=e.resolveFs(t.package_meta,n);if(!r)throw new Error(`Failed to resolve fs for ${n}`);return C(r)})},Ne=e=>{let t=new Set,o=new Set;if(e.required)for(let i of e.required)t.add(i);if(e.excluded)for(let i of e.excluded)o.add(i);if(e.elements)for(let[i,n]of Object.entries(e.elements))n.min!==void 0&&n.min>0&&t.add(i);return {required:t.size>0?Array.from(t):void 0,excluded:o.size>0?Array.from(o):void 0}},pe=e=>{let t=e.slicing;if(!t)return;let o={};for(let[i,n]of Object.entries(t.slices??{})){if(!n)continue;let{required:r,excluded:s}=n.schema?Ne(n.schema):{};o[i]={min:n.min,max:n.max,match:n.match,required:r,excluded:s};}return {discriminator:t.discriminator,rules:t.rules,ordered:t.ordered,slices:Object.keys(o).length>0?o:void 0}};function $(e,t,o,i,n){if(i.elementReference){let r=i.elementReference.slice(1).filter((s,c)=>c%2===1);return w(e,t,r,n)}else if(i.type){let r=e.ensureSpecializationCanonicalUrl(i.type),s=e.resolveFs(t.package_meta,r);if(!s)throw new Error(`Could not resolve field type: <${t.url}>.${o.join(".")}: <${i.type}> (pkg: '${S(t.package_meta)}'))`);return C(s)}else {if(i.choices)return;if(t.derivation==="constraint")return;n?.dryWarn(`Can't recognize element type: <${t.url}>.${o.join(".")} (pkg: '${S(t.package_meta)}'): missing type info`);return}}var N=(e,t,o,i,n)=>{let r,s;i.binding&&(r=P(t,o,i),j.has(i.type??"")&&(s=_(e,t,i,n)));let c=$(e,t,o,i,n);return c||n?.dryWarn(`Field type not found for '${t.url}#${o.join(".")}' (${t.derivation})`),{type:c,required:ce(e,t,o),excluded:le(e,t,o),reference:we(e,t,i),array:i.array||false,min:i.min,max:i.max,slicing:pe(i),choices:i.choices,choiceOf:i.choiceOf,binding:r,enum:s}};function E(e){let t=e.type==="BackboneElement",o=e.type==="Element"&&e.elements!==void 0&&Object.keys(e.elements).length>0,i=e.type===void 0&&e.choiceOf===void 0&&e.elements!==void 0&&Object.keys(e.elements).length>0;return t||o||i}function U(e,t,o,i,n){return {type:w(e,t,o,n),array:i.array||false,required:ce(e,t,o),excluded:le(e,t,o),slicing:pe(i)}}function Ue(e,t,o,i,n){if(!i)return;let r={};for(let s of e.getAllElementKeys(i)){let c=[...o,s],a=e.resolveElementSnapshot(t,c),l=a.type?e.ensureSpecializationCanonicalUrl(a.type):void 0;if(l&&I(t.package_meta,l).shouldSkip){n?.warn(`Skipping field ${c} for ${l} due to skip hack ${I(t.package_meta,l).reason}`);continue}E(a)?r[s]=U(e,t,c,a,n):r[s]=N(e,t,c,a,n);}return r}function $e(e){let t=[];for(let o of Object.values(e))"type"in o&&o.type&&t.push(o.type),"binding"in o&&o.binding&&t.push(o.binding);return t}function He(e,t){return !!(e.base==="Extension"||e.base==="http://hl7.org/fhir/StructureDefinition/Extension"||e.url?.includes("/extension/")||e.url?.includes("-extension")||e.name?.toLowerCase().includes("extension")||e.type==="Extension")}async function de(e,t,o){if(!t.url)throw new Error("ValueSet URL is required");let i=L(e,t.package_meta,t.url),n=B(e,t.package_meta,t.url);return {identifier:i,description:t.description,concept:n,compose:n?void 0:t.compose}}function Ve(e,t,o,i){let n=[];t&&n.push(t),o&&n.push(...$e(o)),i&&n.push(...ae(i));let r={};for(let a of n)a.url!==e.url&&(r[a.url]=a);let s=new Set(i?.map(a=>a.identifier.url)),c=Object.values(r).filter(a=>ne(e)||!te(a)?true:!s.has(a.url)).sort((a,l)=>a.url.localeCompare(l.url));return c.length>0?c:void 0}function Oe(e,t,o){let i=C(t),n;if(t.base&&t.type!=="Element"){let p=e.resolveFs(t.package_meta,e.ensureSpecializationCanonicalUrl(t.base));if(!p)throw new Error(`Base resource not found '${t.base}' for <${t.url}> from ${S(t.package_meta)}`);n=C(p);}let r=Ue(e,t,[],t.elements,o),s=A(e,t,o),c=t.derivation==="constraint"?Ae(e,t,o):void 0,a=Ve(i,n,r,s),l=c?.flatMap(p=>p.valueTypes??[])??[],u=(()=>{if(!a&&l.length===0)return a;let p={};for(let d of a??[])p[d.url]=d;for(let d of l)p[d.url]=d;return Object.values(p)})(),m={identifier:i,base:n,fields:r,nested:s,description:t.description,dependencies:u,...c&&c.length>0?{extensions:c}:{}},h=re(e,t,o);return [m,...h]}function Me(e,t,o,i){let n=e.resolveFs(t.package_meta,o);if(!n?.elements)return;let r=[];for(let[c,a]of Object.entries(n.elements)){if(a.choiceOf!=="value"&&!c.startsWith("value"))continue;let l=$(e,n,[c],a,i);l&&r.push(l);}if(r.length===0)return;let s=new Map(r.map(c=>[c.url,c]));return Array.from(s.values())}var Be=(e,t,o)=>{let i=[];if(!t.elements)return i;for(let[n,r]of Object.entries(t.elements)){if(!n.startsWith("extension:"))continue;let s=n.split(":")[1];if(!s)continue;let c;for(let[a,l]of Object.entries(r.elements??{}))if(!(l.choiceOf!=="value"&&!a.startsWith("value"))&&(c=$(e,t,[n,a],l,o),c))break;i.push({name:s,url:r.url??s,valueType:c,min:r.min,max:r.max!==void 0?String(r.max):void 0});}return i},je=e=>{let t=[],i=e.elements?.extension?.slicing?.slices;if(!i||typeof i!="object")return t;for(let[n,r]of Object.entries(i)){let s=r,c=s.schema;if(!c)continue;let a;for(let[l,u]of Object.entries(c.elements??{})){let m=u;if(!(m.choiceOf!=="value"&&!l.startsWith("value"))&&m.type){a={kind:"complex-type",package:e.package_meta.name,version:e.package_meta.version,name:m.type,url:`http://hl7.org/fhir/StructureDefinition/${m.type}`};break}}t.push({name:n,url:s.match?.url??n,valueType:a,min:c._required?1:c.min??0,max:c.max!==void 0?String(c.max):c.array?"*":"1"});}return t},_e=(e,t,o,i)=>{let n=e.resolveFs(t.package_meta,o);if(!n?.elements)return;let r=Be(e,n,i),s=je(n),c=[...r,...s];return c.length>0?c:void 0};function Ae(e,t,o){let i=[],n=(s,c,a)=>{let l=a.url,u=l?Me(e,t,l,o):void 0,m=l?_e(e,t,l,o):void 0,h=m!==void 0&&m.length>0;i.push({name:c,path:[...s,"extension"].join("."),url:l,min:a.min,max:a.max!==void 0?String(a.max):void 0,mustSupport:a.mustSupport,valueTypes:u,subExtensions:m,isComplex:h});},r=(s,c)=>{if(c.extensions)for(let[a,l]of Object.entries(c.extensions))n(s,a,l);if(c.elements)for(let[a,l]of Object.entries(c.elements))r([...s,a],l);};if(t.extensions)for(let[s,c]of Object.entries(t.extensions))n([],s,c);if(t.elements)for(let[s,c]of Object.entries(t.elements))r([s],c);return i}async function ue(e,t,o){let i=Oe(e,t,o);if(He(t,C(t))){let n=i[0];if(!n)throw new Error("Expected schema to be defined");n.metadata={isExtension:true};}return i}var Ge=(e,t)=>{let o={};for(let r of e){let s=`${r.schema.identifier.url}|${r.schema.identifier.package}`,c=Z(r.schema);o[s]??={},o[s][c]??={typeSchema:r.schema,sources:[]},o[s][c].sources.push(r);}let i=[],n={};for(let r of Object.values(o)){let s=Object.values(r).sort((a,l)=>l.sources.length-a.sources.length),c=s[0];if(c&&(i.push(c.typeSchema),s.length>1)){let a=c.typeSchema.identifier.package,l=c.typeSchema.identifier.url;t?.dryWarn(`'${l}' from '${a}'' has ${s.length} versions`),n[a]??={},n[a][l]=s.flatMap(u=>u.sources.map(m=>({typeSchema:u.typeSchema,sourcePackage:m.sourcePackage,sourceCanonical:m.sourceCanonical})));}}return {schemas:i,collisions:n}},me=async(e,t)=>{let o=[];for(let i of e.allFs()){let n=S(i.package_meta),r=I(i.package_meta,i.url);if(r.shouldSkip){t?.dryWarn(`Skip ${i.url} from ${n}. Reason: ${r.reason}`);continue}for(let s of await ue(e,i,t))o.push({schema:s,sourcePackage:n,sourceCanonical:i.url});}for(let i of e.allVs())o.push({schema:await de(e,i),sourcePackage:S(i.package_meta),sourceCanonical:i.url});return Ge(o,t)};var G=e=>e!==null&&typeof e=="object"&&e.resourceType==="CodeSystem";var H=e=>e!==null&&typeof e=="object"&&e.resourceType==="ValueSet";var qe=async(e,t)=>{let o=await e.packageJson(t.name);if(!o)return [];let i=o.dependencies;return i!==void 0?Object.entries(i).map(([n,r])=>({name:n,version:r})):[]},he=e=>({pkg:e,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),ye=async(e,t,o,i,n)=>{let r=S(t);if(n?.info(`${" ".repeat(o*2)}+ ${r}`),i[r])return i[r];let s=he(t);for(let a of await e.search({package:t})){let l=a.url;if(!l||!(isStructureDefinition(a)||H(a)||G(a)))continue;let u=l;s.canonicalResolution[u]&&n?.dryWarn(`Duplicate canonical URL: ${u} at ${r}.`),s.canonicalResolution[u]=[{deep:o,pkg:t,pkgId:r,resource:a}];}let c=await qe(e,t);for(let a of c){let{canonicalResolution:l}=await ye(e,a,o+1,i,n);for(let[u,m]of Object.entries(l)){let h=u;s.canonicalResolution[h]=[...s.canonicalResolution[h]||[],...m];}}for(let a of Object.values(s.canonicalResolution))a.sort((l,u)=>l.deep-u.deep);return i[r]=s,s},fe=(e,t)=>{for(let{pkg:o,canonicalResolution:i}of Object.values(e)){let n=S(o);if(!e[n])throw new Error(`Package ${n} not found`);for(let[s,c]of Object.entries(i)){let a=c[0];if(!a)throw new Error("Resource not found");let l=a.resource,u=a.pkg;if(isStructureDefinition(l)){let m=ge.translate(l),h=ee(m,u);e[n].fhirSchemas[h.url]=h;}if(H(l)){let m=ie(l,u);e[n].valueSets[m.url]=m;}}}},ze=(e,t,o)=>{let i=Object.values(e).flatMap(n=>n.canonicalResolution[t]);if(!i)throw new Error(`No canonical resolution found for ${t} in any package`);return i[0]?.resource},Ke=async(e,{logger:t,focusedPackages:o})=>{let i=o??await e.packages(),n={};for(let p of i)await ye(e,p,0,n,t);fe(n);let r=(p,d)=>{let f=n[S(p)];if(f){let g=f.canonicalResolution[d]?.[0];if(g)return n[g.pkgId]?.fhirSchemas[d]}for(let g of Object.values(n)){let y=g.fhirSchemas[d];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(n)){let y=g.fhirSchemas[d];if(y)return y}},s=(p,d)=>{let f=n[S(p)];if(f){let g=f.canonicalResolution[d]?.[0];if(g)return n[g.pkgId]?.valueSets[d]}for(let g of Object.values(n)){let y=g.valueSets[d];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(n)){let y=g.valueSets[d];if(y)return y}},c=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),a=(p,d)=>{let f=r(p,d);if(f===void 0)throw new Error(`Failed to resolve FHIR Schema: '${d}'`);let g=[f];for(;f?.base;){let y=f.package_meta,R=c(f.base);if(f=r(y,R),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${d}'. Problem: '${R}' from '${S(y)}'`);g.push(f);}return g},l=(p,d)=>a(p,d).filter(f=>f.derivation==="specialization"),u=(p,d)=>{let f=a(p.package_meta,p.url),g=Je(f,d);return Qe(g)},m=p=>{let d=new Set;for(let[f,g]of Object.entries(p)){d.add(f);for(let y of g?.choices||[])p[y]||d.add(y);}return Array.from(d)},h;return {testAppendFs(p){let d=S(p.package_meta);n[d]||(n[d]=he(p.package_meta)),n[d].fhirSchemas[p.url]=p,h=void 0;},resolveFs:r,resolveFsGenealogy:a,resolveFsSpecializations:l,ensureSpecializationCanonicalUrl:c,resolveSd:(p,d)=>{let f=n[S(p)]?.canonicalResolution[d]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(n).flatMap(p=>Object.values(p.canonicalResolution).flatMap(d=>d.map(f=>{let g=f.resource;return g.package_name?g:{...g,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,d)=>p.url.localeCompare(d.url)),patchSd:p=>{Object.values(n).flatMap(d=>Object.values(d.canonicalResolution).forEach(f=>{f.forEach(g=>{if(isStructureDefinition(g.resource)){let y=g.resource,R=p(d.pkg,y);if(y.url!==R.url)throw new Error(`Patch update StructureDefinition URL: ${y.url} !== ${R.url}`);g.resource=R;}});})),fe(n),h=void 0;},allFs:()=>Object.values(n).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(n).flatMap(p=>Object.values(p.valueSets)),resolveVs:s,resolveAny:p=>ze(n,p),resolveElementSnapshot:u,getAllElementKeys:m,resolver:n,resolutionTree:()=>{if(h)return h;let p={};for(let[d,f]of Object.entries(n)){let g=f.pkg.name;p[g]={};for(let[y,R]of Object.entries(f.canonicalResolution)){let q=y;p[g][q]=[];for(let z of R)p[g][q].push({deep:z.deep,pkg:z.pkg});}}return h=p,p}}},xe=async(e,t)=>{let o=e.map(Y);t?.logger?.step(`Loading FHIR packages: ${o.join(", ")}`);let i=CanonicalManager({packages:o,workingDir:"tmp/fhir",registry:t.registry||void 0});return await i.init(),await Ke(i,{...t,focusedPackages:e})},Je=(e,t)=>{let[o,...i]=t;return o===void 0?[]:e.map(n=>{if(!n.elements)return;let r=n.elements?.[o];for(let s of i)r=r?.elements?.[s];return r}).filter(n=>n!==void 0)};function Qe(e){let t=e.reverse(),o=Object.assign({},...t);return o.elements=void 0,o}var Se={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async e=>{let t=J({prefix:"TypeSchema"});try{t.step("Generating TypeSchema from FHIR packages"),t.info(`Packages: ${e.packages.join(", ")}`),t.info(`Output: ${e.output}`);let o=e.singleFile?"ndjson":e.format;t.debug(`Format: ${o}${e.singleFile&&e.format==="json"?" (forced from json due to singleFile)":""}`),e.treeshake&&e.treeshake.length>0&&t.info(`Treeshaking enabled for ResourceTypes: ${e.treeshake.join(", ")}`),e.singleFile&&t.info("Single file output enabled (NDJSON format)"),e.registry&&t.info(`Using custom registry: ${e.registry}`);let i=Date.now(),n=e.packages.map(u=>{if(u.includes("@")){let m=u.lastIndexOf("@");return {name:u.slice(0,m),version:u.slice(m+1)||"latest"}}return {name:u,version:"latest"}});t.progress(`Processing packages: ${n.map(u=>`${u.name}@${u.version}`).join(", ")}`);let r=await xe(n,{logger:t,registry:e.registry,focusedPackages:n}),{schemas:s}=await me(r,t);if(s.length===0)throw new Error("No schemas were generated from the specified packages");let c=e.output;if(!c)throw new Error("Output format not specified");await mkdir(dirname(c),{recursive:!0});let a;o==="json"?a=JSON.stringify(s,null,2):a=s.map(u=>JSON.stringify(u)).join(`
3
- `),await writeFile(c,a,"utf-8");let l=Date.now()-i;if(X(`Generated ${s.length} TypeSchema definitions`,l,{schemas:s.length}),t.dim(`Output: ${c}`),e.verbose){t.debug("Generated schemas:");let u=s.map(m=>`${m.identifier?.name||"Unknown"} (${m.identifier?.kind||"unknown"})`);b(u);}}catch(o){t.error("Failed to generate TypeSchema",o instanceof Error?o:new Error(String(o))),process.exit(1);}}};var Re={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:e=>e.command(Se).help().example("$0 typeschema generate hl7.fhir.r4.core@4.0.1","Generate TypeSchema from FHIR R4 core package"),handler:e=>{if(!e.subcommand&&e._.length===1){V("Available typeschema subcommands:"),b(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
2
+ import S from'picocolors';import at from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {createHash}from'crypto';import Ue from'assert';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as pe from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var T=class t{options;dryWarnSet=new Set;constructor(e={}){this.options={timestamp:false,level:1,...e};}shouldLog(e){let i=this.options.level??1;return e>=i}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(e,i,n){let o=this.options.timestamp?`${S.gray(new Date().toLocaleTimeString())} `:"",r=this.options.prefix?`${S.cyan(`[${this.options.prefix}]`)} `:"";return `${o}${n(e)} ${r}${i}`}isSuppressed(e){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(e)||false}tryWriteToConsole(e,i){if(this.isSuppressed(e)||!this.shouldLog(e))return;(t.consoleLevelsMap[e]||console.log)(i);}success(e){this.tryWriteToConsole(1,this.formatMessage("",e,S.green));}error(e,i){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",e,S.red));let n=this.options.level===0;i&&n&&(console.error(S.red(` ${i.message}`)),i.stack&&console.error(S.gray(i.stack)));}warn(e){this.tryWriteToConsole(2,this.formatMessage("!",e,S.yellow));}dryWarn(e){this.dryWarnSet.has(e)||(this.warn(e),this.dryWarnSet.add(e));}info(e){this.tryWriteToConsole(1,this.formatMessage("i",e,S.blue));}debug(e){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",e,S.magenta));}step(e){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",e,S.cyan));}progress(e){this.tryWriteToConsole(1,this.formatMessage("\u23F3",e,S.blue));}plain(e,i=n=>n){let n=this.options.timestamp?`${S.gray(new Date().toLocaleTimeString())} `:"",o=this.options.prefix?`${S.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${n}${o}${i(e)}`);}dim(e){this.plain(e,S.gray);}child(e){return new t({...this.options,prefix:this.options.prefix?`${this.options.prefix}:${e}`:e})}configure(e){this.options={...this.options,...e};}getLevel(){return this.options.level??1}setLevel(e){this.options.level=e;}},I=new T;function Ee(t){I.success(t);}function R(t,e){I.error(t,e);}function $(t){I.info(t);}function Te(t){I.dim(t);}function Y(t){I.configure(t);}function Z(t={}){return new T(t)}function ee(t){console.log(),console.log(S.cyan(S.bold(`\u2501\u2501\u2501 ${t} \u2501\u2501\u2501`)));}function te(t,e,i){let n=t;e&&(n+=` ${S.gray(`(${e}ms)`)}`),Ee(n),i&&Object.entries(i).forEach(([o,r])=>{Te(` ${o}: ${r}`);});}function k(t,e="\u2022"){t.forEach(i=>{console.log(S.gray(` ${e} ${i}`));});}var v="Use CodeableReference which is not provided by FHIR R4.",De="Use Availability which is not provided by FHIR R4.",j={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":De,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":v,"http://hl7.org/fhir/StructureDefinition/specimen-additive":v,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":v,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":v,"http://hl7.org/fhir/StructureDefinition/workflow-reason":v},"hl7.fhir.r5.core#5.0.0":{"http://hl7.org/fhir/StructureDefinition/shareablecodesystem":"FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now.","http://hl7.org/fhir/StructureDefinition/publishablecodesystem":"Uses R5-only base types not available in R4 generation."}};function C(t,e){let i=`${t.name}#${t.version}`,n=j[i]?.[e];if(n)return {shouldSkip:true,reason:n};let o=j[t.name]?.[e];return o?{shouldSkip:true,reason:o}:{shouldSkip:false}}var x=t=>`${t.name}#${t.version}`,ne=t=>`${t.name}@${t.version}`;var ie=t=>{let e=JSON.stringify(t);return createHash("sha256").update(e).digest("hex").slice(0,16)},oe=(t,e)=>({...t,package_meta:t.package_meta||e,name:t.name,url:t.url,base:t.base});var re=t=>t?.kind==="nested",se=t=>t?.kind==="profile",F=(...t)=>{let e=t.filter(n=>n!==void 0).flatMap(n=>n.map(o=>[o.url,o]));return e.length===0?void 0:Object.values(Object.fromEntries(e)).sort((n,o)=>n.url.localeCompare(o.url))};var ae=(t,e)=>{if(!t.url)throw new Error("ValueSet must have a URL");if(!t.name)throw new Error("ValueSet must have a name");return {...t,package_meta:t.package_meta||e,name:t.name,url:t.url}};function M(t){let e=t.split("|")[0];return e||t}function we(t){return t.split("|")[1]}function Pe(t){return t.derivation==="constraint"?"profile":t.kind==="primitive-type"?"primitive-type":t.kind==="complex-type"?"complex-type":t.kind==="resource"?"resource":t.kind==="logical"?"logical":"resource"}function b(t){return {kind:Pe(t),package:t.package_meta.name,version:t.package_meta.version,name:t.name,url:t.url}}var Ne=t=>{let e=t.split("/"),i=e[e.length-1];return i&&i.length>0?i.split(/[-_]/).map(n=>n.charAt(0).toUpperCase()+n.slice(1).toLowerCase()).join(""):t};function D(t,e,i){let n=M(i),o=Ne(n),r={package_meta:{name:"missing_valuesets",version:we(n)||"0.0.0"},id:i},s=t.resolveVs(e,n)||r,a=s?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(s.id)?s.id:o;return {kind:"value-set",package:s.package_meta.name,version:s.package_meta.version,name:a,url:n}}function L(t,e,i){let n=i.binding?.bindingName,o=e.join("."),[r,s,a]=n?[{name:"shared",version:"1.0.0"},n,`urn:fhir:binding:${n}`]:[t.package_meta,`${t.name}.${o}_binding`,`${t.url}#${o}_binding`];return {kind:"binding",package:r.name,version:r.version,name:s,url:a}}function B(t,e,i,n){let o=M(i)||i,r=t.resolveVs(e,o);if(r)return He(t,r)}function He(t,e,i){if(e.expansion?.contains)return e.expansion.contains.filter(o=>o.code!==void 0).map(o=>(Ue(o.code),{code:o.code,display:o.display,system:o.system}));let n=[];if(e.compose?.include){for(let o of e.compose.include)if(o.concept)for(let r of o.concept)n.push({system:o.system,code:r.code,display:r.display});else if(o.system&&!o.filter)try{let r=t.resolveAny(o.system);if(r?.concept){let s=(a,c)=>{for(let l of a)n.push({system:c,code:l.code,display:l.display}),l.concept&&s(l.concept,c);};s(r.concept,o.system);}}catch{}}return n.length>0?n:void 0}var ce=100,_=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function A(t,e,i,n){if(!i.binding)return;let o=i.binding.strength,r=i.binding.valueSet;if(!r)return;if(!_.has(i.type??"")){n?.dryWarn(`eld-11: Binding on non-bindable type '${i.type}' (valueSet: ${r})`);return}if(!(o==="required"||o==="extensible"||o==="preferred"))return;let a=B(t,e.package_meta,r);if(!a||a.length===0)return;let c=a.map(l=>l.code).filter(l=>l&&typeof l=="string"&&l.trim().length>0);if(c.length>ce){n?.dryWarn(`Value set ${r} has ${c.length} which is more than ${ce} codes, which may cause issues with code generation.`);return}if(c.length!==0)return {isOpen:o!=="required",values:c}}function Ve(t,e,i,n,o){if(!n.binding?.valueSet)return;let r=L(e,i,n),s=D(t,e.package_meta,n.binding.valueSet),a=A(t,e,n,o);return {identifier:r,valueset:s,strength:n.binding.strength,enum:a,dependencies:[s]}}function le(t,e,i){let n=new Set;if(!e.elements)return [];let o=[];function r(c,l){for(let[d,m]of Object.entries(c)){let y=[...l,d],p=y.join("."),u=t.resolveElementSnapshot(e,y);if(!n.has(p)){if(n.add(p),u.binding){let f=Ve(t,e,y,u,i);f&&o.push(f);}m.elements&&r(m.elements,y);}}}r(e.elements,[]),o.sort((c,l)=>c.identifier.name.localeCompare(l.identifier.name));let s=[],a=new Set;for(let c of o)a.has(c.identifier.url)||(a.add(c.identifier.url),s.push(c));return s}var G=t=>t!==null&&typeof t=="object"&&t.resourceType==="CodeSystem";var w=t=>t!==null&&typeof t=="object"&&t.resourceType==="ValueSet";var $e=async(t,e)=>{let i=await t.packageJson(e.name);if(!i)return [];let n=i.dependencies;return n!==void 0?Object.entries(n).map(([o,r])=>({name:o,version:r})):[]},de=t=>({pkg:t,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),ue=async(t,e,i,n,o)=>{let r=x(e);if(o?.info(`${" ".repeat(i*2)}+ ${r}`),n[r])return n[r];let s=de(e);for(let c of await t.search({package:e})){let l=c.url;if(!l||!(isStructureDefinition(c)||w(c)||G(c)))continue;let d=l;s.canonicalResolution[d]&&o?.dryWarn(`Duplicate canonical URL: ${d} at ${r}.`),s.canonicalResolution[d]=[{deep:i,pkg:e,pkgId:r,resource:c}];}let a=await $e(t,e);for(let c of a){let{canonicalResolution:l}=await ue(t,c,i+1,n,o);for(let[d,m]of Object.entries(l)){let y=d;s.canonicalResolution[y]=[...s.canonicalResolution[y]||[],...m];}}for(let c of Object.values(s.canonicalResolution))c.sort((l,d)=>l.deep-d.deep);return n[r]=s,s},je=(t,e)=>{for(let{pkg:i,canonicalResolution:n}of Object.values(t)){let o=x(i);if(!t[o])throw new Error(`Package ${o} not found`);for(let[s,a]of Object.entries(n)){let c=a[0];if(!c)throw new Error("Resource not found");let l=c.resource,d=c.pkg;if(isStructureDefinition(l)){let m=pe.translate(l),y=oe(m,d);t[o].fhirSchemas[y.url]=y;}if(w(l)){let m=ae(l,d);t[o].valueSets[m.url]=m;}}}},Me=(t,e,i)=>{let n=Object.values(t).flatMap(o=>o.canonicalResolution[e]);if(!n)throw new Error(`No canonical resolution found for ${e} in any package`);return n[0]?.resource},Be=async(t,{logger:e,focusedPackages:i})=>{let n=i??await t.packages(),o={};for(let p of n)await ue(t,p,0,o,e);je(o);let r=(p,u)=>{let f=o[x(p)];if(f){let g=f.canonicalResolution[u]?.[0];if(g)return o[g.pkgId]?.fhirSchemas[u]}for(let g of Object.values(o)){let h=g.fhirSchemas[u];if(h&&h.package_meta.name===p.name)return h}for(let g of Object.values(o)){let h=g.fhirSchemas[u];if(h)return h}},s=(p,u)=>{let f=o[x(p)];if(f){let g=f.canonicalResolution[u]?.[0];if(g)return o[g.pkgId]?.valueSets[u]}for(let g of Object.values(o)){let h=g.valueSets[u];if(h&&h.package_meta.name===p.name)return h}for(let g of Object.values(o)){let h=g.valueSets[u];if(h)return h}},a=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),c=(p,u)=>{let f=r(p,u);if(f===void 0)throw new Error(`Failed to resolve FHIR Schema: '${u}'`);let g=[f];for(;f?.base;){let h=f.package_meta,E=a(f.base);if(f=r(h,E),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${u}'. Problem: '${E}' from '${x(h)}'`);g.push(f);}return g},l=(p,u)=>c(p,u).filter(f=>f.derivation==="specialization"),d=(p,u)=>{let f=c(p.package_meta,p.url),g=N(f,u);return W(g)},m=p=>{let u=new Set;for(let[f,g]of Object.entries(p)){u.add(f);for(let h of g?.choices||[])p[h]||u.add(h);}return Array.from(u)},y;return {testAppendFs(p){let u=x(p.package_meta);o[u]||(o[u]=de(p.package_meta)),o[u].fhirSchemas[p.url]=p,y=void 0;},resolveFs:r,resolveFsGenealogy:c,resolveFsSpecializations:l,ensureSpecializationCanonicalUrl:a,resolveSd:(p,u)=>{let f=o[x(p)]?.canonicalResolution[u]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(o).flatMap(p=>Object.values(p.canonicalResolution).flatMap(u=>u.map(f=>{let g=f.resource;return g.package_name?g:{...g,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,u)=>p.url.localeCompare(u.url)),allFs:()=>Object.values(o).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(o).flatMap(p=>Object.values(p.valueSets)),resolveVs:s,resolveAny:p=>Me(o,p),resolveElementSnapshot:d,getAllElementKeys:m,resolver:o,resolutionTree:()=>{if(y)return y;let p={};for(let[u,f]of Object.entries(o)){let g=f.pkg.name;p[g]={};for(let[h,E]of Object.entries(f.canonicalResolution)){let Q=h;p[g][Q]=[];for(let X of E)p[g][Q].push({deep:X.deep,pkg:X.pkg});}}return y=p,p}}},me=async(t,e)=>{let i=t.map(ne);e?.logger?.step(`Loading FHIR packages: ${i.join(", ")}`);let n=CanonicalManager({packages:i,workingDir:"tmp/fhir",registry:e.registry||void 0});return await n.init(),await Be(n,{...e,focusedPackages:t})},N=(t,e)=>{let[i,...n]=e;return i===void 0?[]:t.map(o=>{if(!o.elements)return;let r=o.elements?.[i];for(let s of n)r=r?.elements?.[s];return r}).filter(o=>o!==void 0)};function W(t){let e=t.reverse(),i=Object.assign({},...e);return i.elements=void 0,i}var fe=(t,e,i)=>{let n=t.resolveFsSpecializations(e.package_meta,e.url),o=N(n,i),r=W(o).type,s;if(r){let a=t.ensureSpecializationCanonicalUrl(r),l=t.resolveFsGenealogy(e.package_meta,a).flatMap(d=>Object.keys(d.elements??{}));l.length>0&&(s=new Set(l));}for(let a of o)if(!(!a.elements||Object.keys(a.elements).length===0)&&!(s&&!Object.keys(a.elements).some(c=>!s.has(c))))return true;return false},q=(t,e,i,n,o)=>n.type==="BackboneElement"?true:!o?.elements||o.choiceOf!==void 0?false:fe(t,e,i),_e=t=>t.elements?new Set(z(t,[],t.elements).filter(([e,i])=>i.elements&&Object.keys(i.elements).length>0).map(([e])=>e.join("."))):new Set;function U(t,e,i){let n={},o=e.derivation==="constraint"?t.resolveFsSpecializations(e.package_meta,e.url):t.resolveFsGenealogy(e.package_meta,e.url);for(let d of [...o].reverse()){let m=_e(d);for(let y of m)n[y]=`${d.url}#${y}`;}let r=i.join("."),s=n[r]??`${e.url}#${r}`,a=s.split("#")[0],l=t.resolveFs(e.package_meta,a)?.package_meta??e.package_meta;return {kind:"nested",package:l.name,version:l.version,name:r,url:s}}function z(t,e,i){let n=[];for(let[o,r]of Object.entries(i)){let s=[...e,o];r.elements&&r.choiceOf===void 0&&n.push([s,r]),r.elements&&n.push(...z(t,s,r.elements));}return n}function Ae(t,e,i,n,o){let r={},s=t.resolveFsGenealogy(e.package_meta,e.url),a=N(s,i),c=new Set;for(let l of a)if(l.elements)for(let d of Object.keys(l.elements))c.add(d);for(let l of c){let d=[...i,l],m=t.resolveElementSnapshot(e,d);q(t,e,d,m,n[l])?r[l]=V(t,e,d,m):r[l]=H(t,e,d,m,o);}return r}function ge(t,e,i){if(!e.elements)return;let n=z(e,[],e.elements).filter(([r,s])=>!s.elements||Object.keys(s.elements).length===0?false:s.type!=="BackboneElement"?fe(t,e,r):true),o=[];for(let[r,s]of n){let a=U(t,e,r),c;s.type==="BackboneElement"||!s.type?c="BackboneElement":c=s.type;let l=t.ensureSpecializationCanonicalUrl(c),d=t.resolveFs(e.package_meta,l);if(!d)throw new Error(`Could not resolve base type ${c}`);let m={kind:"complex-type",package:d.package_meta.name,version:d.package_meta.version,name:c,url:l},y=Ae(t,e,r,s.elements??{},i),p={identifier:a,base:m,fields:y};o.push(p);}return o.sort((r,s)=>r.identifier.url.localeCompare(s.identifier.url)),o.length===0?void 0:o}function ye(t){let e=[];for(let i of t){i.base&&e.push(i.base);for(let n of Object.values(i.fields||{}))"type"in n&&n.type&&e.push(n.type),"binding"in n&&n.binding&&e.push(n.binding);}return e}function he(t,e,i){let n=i[i.length-1];if(!n)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let o=i.slice(0,-1),r=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(s=>{if(o.length===0)return s.required||[];if(!s.elements)return [];let a=s;for(let c of o)a=a?.elements?.[c];return a?.required||[]});return new Set(r).has(n)}function Se(t,e,i){let n=i[i.length-1];if(!n)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let o=i.slice(0,-1),r=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(s=>{if(o.length===0)return s.excluded||[];if(!s.elements)return [];let a=s;for(let c of o)a=a?.elements?.[c];return a?.excluded||[]});return new Set(r).has(n)}var Ge=(t,e,i)=>{if(i.refers)return i.refers.map(n=>{let o=t.ensureSpecializationCanonicalUrl(n),r=t.resolveFs(e.package_meta,o);if(!r)throw new Error(`Failed to resolve fs for ${o}`);return b(r)})},We=t=>{let e=new Set,i=new Set;if(t.required)for(let o of t.required)e.add(o);if(t.excluded)for(let o of t.excluded)i.add(o);if(t.elements)for(let[o,r]of Object.entries(t.elements))r.min!==void 0&&r.min>0&&e.add(o);let n=t.elements?Object.keys(t.elements):void 0;return {required:e.size>0?Array.from(e):void 0,excluded:i.size>0?Array.from(i):void 0,elements:n&&n.length>0?n:void 0}},qe=t=>!t||typeof t=="object"&&Object.keys(t).length===0,K=(t,e,i)=>{let n=t;for(let r=0;r<e.length-1;r++){let s=e[r];(!n[s]||typeof n[s]!="object")&&(n[s]={}),n=n[s];}let o=e[e.length-1];n[o]=i;},ze=(t,e)=>{let i=t;for(let n of e)if(i&&typeof i=="object"&&!Array.isArray(i))i=i[n];else return;return i},xe=(t,e,i,n)=>{if(i>=e.length||!t.elements)return;let o=e[i],r=t.elements[o];if(r){if(i===e.length-1&&r.fixed?.value!==void 0){K(n,e,r.fixed.value);return}if(r.slicing?.slices){let s=e.slice(i+1);for(let a of Object.values(r.slicing.slices)){if(!a.min||a.min<1||!a.match||typeof a.match!="object")continue;let c=a.match;if(Object.keys(c).length!==0)if(s.length>0){let l=ze(c,s);l!==void 0&&K(n,e,l);}else K(n,e.slice(0,i+1),c);}return}xe(r,e,i+1,n);}},Ke=(t,e)=>{if(!e?.elements||!t||t.length===0)return;let i={};for(let n of t){let o=n.path.split(".");xe(e,o,0,i);}return Object.keys(i).length>0?i:void 0},Re=t=>{let e=t.slicing;if(!e)return;let i={};for(let[n,o]of Object.entries(e.slices??{})){if(!o)continue;let{required:r,excluded:s,elements:a}=o.schema?We(o.schema):{};i[n]={min:o.min,max:o.max,match:qe(o.match)?Ke(e.discriminator??[],o.schema):o.match,required:r,excluded:s,elements:a};}return {discriminator:e.discriminator,rules:e.rules,ordered:e.ordered,slices:Object.keys(i).length>0?i:void 0}};function O(t,e,i,n,o){if(n.elementReference){let r=n.elementReference.slice(1).filter((s,a)=>a%2===1);return U(t,e,r)}else if(n.type){let r=t.ensureSpecializationCanonicalUrl(n.type),s=t.resolveFs(e.package_meta,r);if(!s)throw new Error(`Could not resolve field type: <${e.url}>.${i.join(".")}: <${n.type}> (pkg: '${x(e.package_meta)}'))`);return b(s)}else {if(n.choices)return;if(e.derivation==="constraint")return;o?.dryWarn(`Can't recognize element type: <${e.url}>.${i.join(".")} (pkg: '${x(e.package_meta)}'): missing type info`);return}}var H=(t,e,i,n,o,r)=>{let s,a;n.binding&&(s=L(e,i,n),_.has(n.type??"")&&(a=A(t,e,n,o)));let c=O(t,e,i,n,o);c||o?.dryWarn(`Field type not found for '${e.url}#${i.join(".")}' (${e.derivation})`);let l;n.pattern?l={kind:"pattern",type:n.pattern.type,value:n.pattern.value}:n.fixed&&(l={kind:"fixed",type:n.fixed.type,value:n.fixed.value});let d=r??n;if(!l&&d.elements?.coding?.slicing?.slices){let m=d.elements.coding.slicing.slices,y=Object.values(m);if(y.length>0&&y.every(u=>u.min!==void 0&&u.min>=1&&u.match&&typeof u.match=="object"&&Object.keys(u.match).length>0)){let u=y.map(f=>f.match);l={kind:"fixed",type:"CodeableConcept",value:{coding:u.length===1?[u[0]]:u}};}}return {type:c,required:he(t,e,i),excluded:Se(t,e,i),reference:Ge(t,e,n),array:n.array||false,min:n.min,max:n.max,slicing:Re(n),choices:n.choices,choiceOf:n.choiceOf,binding:s,enum:a,valueConstraint:l}};function V(t,e,i,n){return {type:U(t,e,i),array:n.array||false,required:he(t,e,i),excluded:Se(t,e,i),slicing:Re(n)}}var Je=(t,e,i,n)=>{let o=t.resolveFs(e.package_meta,i);if(!o?.elements)return;let r=[];for(let[s,a]of Object.entries(o.elements)){if(a.choiceOf!=="value"&&!s.startsWith("value"))continue;let c=O(t,o,[s],a,n);c&&r.push(c);}return F(r)},Qe=(t,e,i)=>{let n=[];if(!e.elements)return n;for(let[o,r]of Object.entries(e.elements)){if(!o.startsWith("extension:"))continue;let s=o.split(":")[1];if(!s)continue;let a;for(let[c,l]of Object.entries(r.elements??{}))if(!(l.choiceOf!=="value"&&!c.startsWith("value"))&&(a=O(t,e,[o,c],l,i),a))break;n.push({name:s,url:r.url??s,valueType:a,min:r.min,max:r.max!==void 0?String(r.max):void 0});}return n},Xe=t=>{let e=[],n=t.elements?.extension?.slicing?.slices;if(!n||typeof n!="object")return e;for(let[o,r]of Object.entries(n)){let s=r,a=s.schema;if(!a)continue;let c;for(let[l,d]of Object.entries(a.elements??{})){let m=d;if(!(m.choiceOf!=="value"&&!l.startsWith("value"))&&m.type){c={kind:"complex-type",package:t.package_meta.name,version:t.package_meta.version,name:m.type,url:`http://hl7.org/fhir/StructureDefinition/${m.type}`};break}}e.push({name:o,url:s.match?.url??o,valueType:c,min:a._required?1:a.min??0,max:a.max!==void 0?String(a.max):a.array?"*":"1"});}return e},Ye=(t,e,i,n)=>{let o=t.resolveFs(e.package_meta,i);if(!o?.elements)return;let r=Qe(t,o,n),s=Xe(o),a=[...r,...s];return a.length>0?a:void 0},ke=(t,e,i)=>{let n=[],o=(s,a,c)=>{let l=c.url,d=l?Je(t,e,l,i):void 0,m=l?Ye(t,e,l,i):void 0;if(!l){let p=e.elements?.extension?.slicing?.slices?.[a]?.schema;if(p){l=p.elements?.url?.fixed?.value??a;for(let[u,f]of Object.entries(p.elements??{})){let g=f;if(g.choiceOf==="value"&&g.type){d=[{kind:"complex-type",package:e.package_meta.name,version:e.package_meta.version,name:g.type,url:`http://hl7.org/fhir/StructureDefinition/${g.type}`}];break}}}}let y=m&&m.length>0;n.push({name:a,path:[...s,"extension"].join("."),url:l,min:c.min,max:c.max!==void 0?String(c.max):void 0,mustSupport:c.mustSupport,valueTypes:d,subExtensions:m,isComplex:y});},r=(s,a)=>{if(a.extensions)for(let[c,l]of Object.entries(a.extensions))o(s,c,l);if(a.elements)for(let[c,l]of Object.entries(a.elements))r([...s,c],l);};return r([],e),n.length===0?void 0:n};function Ze(t,e,i,n,o){if(!n)return;let r={};for(let s of t.getAllElementKeys(n)){let a=[...i,s],c=t.resolveElementSnapshot(e,a),l=c.type?t.ensureSpecializationCanonicalUrl(c.type):void 0;if(l&&C(e.package_meta,l).shouldSkip){o?.warn(`Skipping field ${a} for ${l} due to skip hack ${C(e.package_meta,l).reason}`);continue}q(t,e,a,c,n[s])?r[s]=V(t,e,a,c):r[s]=H(t,e,a,c,o,n[s]);}return r}function et(t){let e=[];for(let i of Object.values(t))"type"in i&&i.type&&e.push(i.type),"binding"in i&&i.binding&&e.push(i.binding);return e}async function Ce(t,e,i){if(!e.url)throw new Error("ValueSet URL is required");let n=D(t,e.package_meta,e.url),o=B(t,e.package_meta,e.url);return {identifier:n,description:e.description,concept:o,compose:o?void 0:e.compose}}function tt(t,e,i,n){let o=[];e&&o.push(e),i&&o.push(...et(i)),n&&o.push(...ye(n));let r=new Set(n?.map(a=>a.identifier.url)),s=o.filter(a=>a.url===t.url?false:se(t)||!re(a)?true:!r.has(a.url));return F(s)}function nt(t,e,i){let n=b(e),o;if(e.base){let y=t.resolveFs(e.package_meta,t.ensureSpecializationCanonicalUrl(e.base));if(!y)throw new Error(`Base resource not found '${e.base}' for <${e.url}> from ${x(e.package_meta)}`);o=b(y);}let r=Ze(t,e,[],e.elements,i),s=ge(t,e,i),a=e.derivation==="constraint"?ke(t,e,i):void 0,c=a?.flatMap(y=>y.valueTypes??[])??[],l=tt(n,o,r,s),d={identifier:n,base:o,fields:r,nested:s,description:e.description,dependencies:F(l,c),extensions:a},m=le(t,e,i);return [d,...m]}async function be(t,e,i){return nt(t,e,i)}var it=(t,e)=>{let i={};for(let r of t){let s=`${r.schema.identifier.url}|${r.schema.identifier.package}`,a=ie(r.schema);i[s]??={},i[s][a]??={typeSchema:r.schema,sources:[]},i[s][a].sources.push(r);}let n=[],o={};for(let r of Object.values(i)){let s=Object.values(r).sort((c,l)=>l.sources.length-c.sources.length),a=s[0];if(a&&(n.push(a.typeSchema),s.length>1)){let c=a.typeSchema.identifier.package,l=a.typeSchema.identifier.url;e?.dryWarn(`'${l}' from '${c}'' has ${s.length} versions`),o[c]??={},o[c][l]=s.flatMap(d=>d.sources.map(m=>({typeSchema:d.typeSchema,sourcePackage:m.sourcePackage,sourceCanonical:m.sourceCanonical})));}}return {schemas:n,collisions:o}},Ie=async(t,e)=>{let i=[];for(let n of t.allFs()){let o=x(n.package_meta),r=C(n.package_meta,n.url);if(r.shouldSkip){e?.dryWarn(`Skip ${n.url} from ${o}. Reason: ${r.reason}`);continue}for(let s of await be(t,n,e))i.push({schema:s,sourcePackage:o,sourceCanonical:n.url});}for(let n of t.allVs())i.push({schema:await Ce(t,n),sourcePackage:x(n.package_meta),sourceCanonical:n.url});return it(i,e)};var ve={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async t=>{let e=Z({prefix:"TypeSchema"});try{e.step("Generating TypeSchema from FHIR packages"),e.info(`Packages: ${t.packages.join(", ")}`),e.info(`Output: ${t.output}`);let i=t.singleFile?"ndjson":t.format;e.debug(`Format: ${i}${t.singleFile&&t.format==="json"?" (forced from json due to singleFile)":""}`),t.treeshake&&t.treeshake.length>0&&e.info(`Treeshaking enabled for ResourceTypes: ${t.treeshake.join(", ")}`),t.singleFile&&e.info("Single file output enabled (NDJSON format)"),t.registry&&e.info(`Using custom registry: ${t.registry}`);let n=Date.now(),o=t.packages.map(d=>{if(d.includes("@")){let m=d.lastIndexOf("@");return {name:d.slice(0,m),version:d.slice(m+1)||"latest"}}return {name:d,version:"latest"}});e.progress(`Processing packages: ${o.map(d=>`${d.name}@${d.version}`).join(", ")}`);let r=await me(o,{logger:e,registry:t.registry,focusedPackages:o}),{schemas:s}=await Ie(r,e);if(s.length===0)throw new Error("No schemas were generated from the specified packages");let a=t.output;if(!a)throw new Error("Output format not specified");await mkdir(dirname(a),{recursive:!0});let c;i==="json"?c=JSON.stringify(s,null,2):c=s.map(d=>JSON.stringify(d)).join(`
3
+ `),await writeFile(a,c,"utf-8");let l=Date.now()-n;if(te(`Generated ${s.length} TypeSchema definitions`,l,{schemas:s.length}),e.dim(`Output: ${a}`),t.verbose){e.debug("Generated schemas:");let d=s.map(m=>`${m.identifier?.name||"Unknown"} (${m.identifier?.kind||"unknown"})`);k(d);}}catch(i){e.error("Failed to generate TypeSchema",i instanceof Error?i:new Error(String(i))),process.exit(1);}}};var Fe={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:t=>t.command(ve).help().example("$0 typeschema generate hl7.fhir.r4.core@4.0.1","Generate TypeSchema from FHIR R4 core package"),handler:t=>{if(!t.subcommand&&t._.length===1){$("Available typeschema subcommands:"),k(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
4
4
  Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),console.log(`
5
- Examples:`),b(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}e.subcommand&&!["generate","validate","merge"].includes(e.subcommand)&&(k(`Unknown typeschema subcommand: ${e.subcommand}
6
- `),V("Available typeschema subcommands:"),b(["generate Generate TypeSchema files from FHIR packages","validate Validate TypeSchema files for correctness and consistency","merge Merge multiple TypeSchema files into a single file"]),console.log(`
7
- Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};function nt(e){return e?{debug:0,info:1,warn:2,error:3,silent:4}[e.toLowerCase()]:void 0}async function it(e){let t=nt(e.logLevel);t===void 0&&(e.debug||e.verbose?t=0:t=1),K({timestamp:e.debug,level:t});}function ot(){return et(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(it).command(Re).option("verbose",{alias:"v",type:"boolean",description:"Enable verbose output",default:false,global:true}).option("debug",{alias:"d",type:"boolean",description:"Enable debug output with detailed logging",default:false,global:true}).option("log-level",{alias:"l",type:"string",choices:["debug","info","warn","error","silent"],description:"Set the log level (default: info)",global:true}).demandCommand(0).middleware(e=>{e._.length===0&&(Q("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
5
+ Examples:`),k(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}t.subcommand&&!["generate","validate","merge"].includes(t.subcommand)&&(R(`Unknown typeschema subcommand: ${t.subcommand}
6
+ `),$("Available typeschema subcommands:"),k(["generate Generate TypeSchema files from FHIR packages","validate Validate TypeSchema files for correctness and consistency","merge Merge multiple TypeSchema files into a single file"]),console.log(`
7
+ Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};function lt(t){return t?{debug:0,info:1,warn:2,error:3,silent:4}[t.toLowerCase()]:void 0}async function pt(t){let e=lt(t.logLevel);e===void 0&&(t.debug||t.verbose?e=0:e=1),Y({timestamp:t.debug,level:e});}function dt(){return at(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(pt).command(Fe).option("verbose",{alias:"v",type:"boolean",description:"Enable verbose output",default:false,global:true}).option("debug",{alias:"d",type:"boolean",description:"Enable debug output with detailed logging",default:false,global:true}).option("log-level",{alias:"l",type:"string",choices:["debug","info","warn","error","silent"],description:"Set the log level (default: info)",global:true}).demandCommand(0).middleware(t=>{t._.length===0&&(ee("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
8
8
  Use 'atomic-codegen <command> --help' for more information about a command.`),console.log(`
9
9
  Quick examples:`),console.log(" atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson"),console.log(`
10
- Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((e,t,o)=>{t?k(t.message,t):k(e),k(`
11
- Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function W(){await ot().parseAsync();}import.meta.main&&W().catch(e=>{e("Unexpected error:",e),process.exit(1);});W().catch(e=>{console.error("CLI Error:",e instanceof Error?e.message:e),process.exit(1);});
10
+ Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((t,e,i)=>{e?R(e.message,e):R(t),R(`
11
+ Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function J(){await dt().parseAsync();}import.meta.main&&J().catch(t=>{t("Unexpected error:",t),process.exit(1);});J().catch(t=>{console.error("CLI Error:",t instanceof Error?t.message:t),process.exit(1);});
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as FS from '@atomic-ehr/fhirschema';
2
2
  import { FHIRSchema, StructureDefinition as StructureDefinition$1, FHIRSchemaElement } from '@atomic-ehr/fhirschema';
3
- import { CanonicalManager } from '@atomic-ehr/fhir-canonical-manager';
3
+ import { CanonicalManager, PreprocessContext } from '@atomic-ehr/fhir-canonical-manager';
4
4
 
5
5
  /**
6
6
  * CodeGen Logger
@@ -800,7 +800,6 @@ type Register = {
800
800
  resolveFsGenealogy(pkg: PackageMeta, canonicalUrl: CanonicalUrl): RichFHIRSchema[];
801
801
  resolveFsSpecializations(pkg: PackageMeta, canonicalUrl: CanonicalUrl): RichFHIRSchema[];
802
802
  allSd(): RichStructureDefinition[];
803
- patchSd(fn: (pkg: PackageMeta, sd: StructureDefinition$1) => StructureDefinition$1): void;
804
803
  /** Returns all FHIRSchemas from all packages in the resolver */
805
804
  allFs(): RichFHIRSchema[];
806
805
  /** Returns all ValueSets from all packages in the resolver */
@@ -991,6 +990,7 @@ declare class APIBuilder {
991
990
  constructor(userOpts?: Partial<APIBuilderOptions> & {
992
991
  manager?: ReturnType<typeof CanonicalManager>;
993
992
  register?: Register;
993
+ preprocessPackage?: (context: PreprocessContext) => PreprocessContext;
994
994
  logger?: CodegenLogger;
995
995
  });
996
996
  fromPackage(packageName: string, version?: string): APIBuilder;