@atomic-ehr/codegen 0.0.5 → 0.0.6
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 +117 -25
- package/assets/api/writer-generator/python/fhirpy_base_model.py +32 -0
- package/dist/cli/index.js +8 -36
- package/dist/index.d.ts +720 -424
- package/dist/index.js +1750 -885
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,9 +43,9 @@ Guides:
|
|
|
43
43
|
|
|
44
44
|
- 🚀 **High-Performance** - Built with Bun runtime for blazing-fast generation
|
|
45
45
|
- 🔧 **Extensible Architecture** - Three-stage pipeline:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
- FHIR package management & canonical resolution
|
|
47
|
+
- Optimized intermediate FHIR data entities representation via Type Schema
|
|
48
|
+
- Generation for different programming languages
|
|
49
49
|
- 📦 **Multi-Package Support** - Generate from a list of FHIR packages
|
|
50
50
|
- 🎯 **Type-Safe** - Generates fully typed interfaces with proper inheritance
|
|
51
51
|
- 🛠️ **Developer Friendly** - Fluent API
|
|
@@ -79,7 +79,8 @@ yarn add @atomic-ehr/codegen
|
|
|
79
79
|
const builder = new APIBuilder()
|
|
80
80
|
.fromPackage("hl7.fhir.r4.core", "4.0.1")
|
|
81
81
|
.typescript({})
|
|
82
|
-
.outputTo("./examples/typescript-r4/fhir-types")
|
|
82
|
+
.outputTo("./examples/typescript-r4/fhir-types")
|
|
83
|
+
.introspection({ typeTree: "./type-tree.yaml" });
|
|
83
84
|
|
|
84
85
|
const report = await builder.generate();
|
|
85
86
|
console.log(prettyReport(report));
|
|
@@ -98,7 +99,8 @@ See the [examples/](examples/) directory for working demonstrations:
|
|
|
98
99
|
- **[typescript-r4/](examples/typescript-r4/)** - FHIR R4 type generation with resource creation demo and profile usage
|
|
99
100
|
- **[typescript-ccda/](examples/typescript-ccda/)** - C-CDA on FHIR type generation
|
|
100
101
|
- **[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
|
|
102
|
+
- **[python/](examples/python/)** - Python/Pydantic model generation with simple requests-based client
|
|
103
|
+
- **[python-fhirpy/](examples/python-fhirpy/)** - Python/Pydantic model generation with fhirpy async client
|
|
102
104
|
- **[csharp/](examples/csharp/)** - C# class generation with namespace configuration
|
|
103
105
|
- **[mustache/](examples/mustache/)** - Java generation with Mustache templates and post-generation hooks
|
|
104
106
|
- **[local-package-folder/](examples/local-package-folder/)** - Loading unpublished local FHIR packages
|
|
@@ -120,11 +122,14 @@ const builder = new APIBuilder()
|
|
|
120
122
|
|
|
121
123
|
// Input sources (choose one or combine)
|
|
122
124
|
.fromPackage("hl7.fhir.r4.core", "4.0.1") // NPM registry package
|
|
123
|
-
.fromPackageRef("https://...package.tgz")
|
|
124
|
-
.localStructureDefinitions({ ... })
|
|
125
|
+
.fromPackageRef("https://...package.tgz") // Remote TGZ file
|
|
126
|
+
.localStructureDefinitions({ ... }) // Loose JSON files
|
|
125
127
|
|
|
126
128
|
// Type Schema processing
|
|
127
|
-
.
|
|
129
|
+
.typeSchema({
|
|
130
|
+
treeShake: { ... }, // Include only specified types
|
|
131
|
+
promoteLogical: { ... }, // Process logical models as resources
|
|
132
|
+
})
|
|
128
133
|
|
|
129
134
|
// Code generator (choose one)
|
|
130
135
|
.typescript({ // TypeScript generator
|
|
@@ -143,10 +148,14 @@ const builder = new APIBuilder()
|
|
|
143
148
|
.outputTo("./generated/types") // Output directory
|
|
144
149
|
.cleanOutput(true) // Clean before generation
|
|
145
150
|
|
|
146
|
-
// Optional:
|
|
151
|
+
// Optional: Introspection & debugging
|
|
147
152
|
.throwException() // Throw on errors (optional)
|
|
148
|
-
.
|
|
149
|
-
|
|
153
|
+
.introspection({
|
|
154
|
+
typeSchemas: "./schemas", // Export TypeSchemas
|
|
155
|
+
typeTree: "./tree.yaml", // Export type tree
|
|
156
|
+
fhirSchemas: "./fhir-schemas", // Export FHIR schemas
|
|
157
|
+
structureDefinitions: "./sd" // Export StructureDefinitions
|
|
158
|
+
})
|
|
150
159
|
|
|
151
160
|
// Execute generation
|
|
152
161
|
.generate(); // Returns GenerationReport
|
|
@@ -196,11 +205,13 @@ This approach enables generating idiomatic code for any programming language whi
|
|
|
196
205
|
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:
|
|
197
206
|
|
|
198
207
|
```typescript
|
|
199
|
-
.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
.typeSchema({
|
|
209
|
+
treeShake: {
|
|
210
|
+
"hl7.fhir.r4.core#4.0.1": {
|
|
211
|
+
"http://hl7.org/fhir/StructureDefinition/Patient": {},
|
|
212
|
+
"http://hl7.org/fhir/StructureDefinition/Observation": {}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
204
215
|
})
|
|
205
216
|
```
|
|
206
217
|
|
|
@@ -211,19 +222,22 @@ This feature automatically resolves and includes all dependencies (referenced ty
|
|
|
211
222
|
Beyond resource-level filtering, tree shaking supports fine-grained field selection using `selectFields` (whitelist) or `ignoreFields` (blacklist):
|
|
212
223
|
|
|
213
224
|
```typescript
|
|
214
|
-
.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
225
|
+
.typeSchema({
|
|
226
|
+
treeShake: {
|
|
227
|
+
"hl7.fhir.r4.core#4.0.1": {
|
|
228
|
+
"http://hl7.org/fhir/StructureDefinition/Patient": {
|
|
229
|
+
selectFields: ["id", "name", "birthDate", "gender"]
|
|
230
|
+
},
|
|
231
|
+
"http://hl7.org/fhir/StructureDefinition/Observation": {
|
|
232
|
+
ignoreFields: ["performer", "note"]
|
|
233
|
+
}
|
|
234
|
+
}
|
|
221
235
|
}
|
|
222
|
-
}
|
|
223
236
|
})
|
|
224
237
|
```
|
|
225
238
|
|
|
226
239
|
**Configuration Rules:**
|
|
240
|
+
|
|
227
241
|
- `selectFields`: Only includes the specified fields (whitelist approach)
|
|
228
242
|
- `ignoreFields`: Removes specified fields, keeps everything else (blacklist approach)
|
|
229
243
|
- These options are **mutually exclusive** - you cannot use both in the same rule
|
|
@@ -232,6 +246,24 @@ Beyond resource-level filtering, tree shaking supports fine-grained field select
|
|
|
232
246
|
|
|
233
247
|
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.
|
|
234
248
|
|
|
249
|
+
##### Logical Promotion
|
|
250
|
+
|
|
251
|
+
Some implementation guides expose logical models (logical-kind StructureDefinitions) that are intended to be used like resources in generated SDKs. The code generator supports promoting selected logical models to behave as resources during generation.
|
|
252
|
+
|
|
253
|
+
Use the programmatic API via `APIBuilder`:
|
|
254
|
+
|
|
255
|
+
```typescript
|
|
256
|
+
const builder = new APIBuilder({})
|
|
257
|
+
.fromPackage("my.custom.pkg", "4.0.1")
|
|
258
|
+
.typeSchema({
|
|
259
|
+
promoteLogical: {
|
|
260
|
+
"my.custom.pkg": [
|
|
261
|
+
"http://example.org/StructureDefinition/MyLogicalModel"
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
})
|
|
265
|
+
```
|
|
266
|
+
|
|
235
267
|
### Generation
|
|
236
268
|
|
|
237
269
|
The generation stage transforms Type Schema into target language code using two complementary approaches:
|
|
@@ -264,6 +296,66 @@ Templates enable flexible code generation for any language or format (Go, Rust,
|
|
|
264
296
|
|
|
265
297
|
---
|
|
266
298
|
|
|
299
|
+
### Profile Classes
|
|
300
|
+
|
|
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.
|
|
302
|
+
|
|
303
|
+
```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);
|
|
310
|
+
|
|
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",
|
|
315
|
+
});
|
|
316
|
+
|
|
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"
|
|
323
|
+
|
|
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"
|
|
327
|
+
|
|
328
|
+
// Get the underlying resource
|
|
329
|
+
const patientResource = profile.toResource();
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Slicing Support:**
|
|
333
|
+
|
|
334
|
+
Profile classes also handle FHIR slicing, automatically applying discriminator values:
|
|
335
|
+
|
|
336
|
+
```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);
|
|
342
|
+
|
|
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)
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
See [examples/typescript-us-core/](examples/typescript-us-core/) for complete profile usage examples.
|
|
358
|
+
|
|
267
359
|
## Roadmap
|
|
268
360
|
|
|
269
361
|
- [x] TypeScript generation
|
|
@@ -271,7 +363,7 @@ Templates enable flexible code generation for any language or format (Go, Rust,
|
|
|
271
363
|
- [x] Configuration file support
|
|
272
364
|
- [x] Comprehensive test suite (72+ tests)
|
|
273
365
|
- [x] **Value Set Generation** - Strongly-typed enums from FHIR bindings
|
|
274
|
-
- [
|
|
366
|
+
- [x] **Profile & Extension Support** - Basic parsing (US Core in development)
|
|
275
367
|
- [ ] **Complete Multi-Package Support** - Custom packages and dependencies
|
|
276
368
|
- [ ] **Smart Chained Search** - Intelligent search builders
|
|
277
369
|
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
resource_type: str = Field(alias="resourceType")
|
|
16
|
+
id: Optional[str] = Field(None, alias="id")
|
|
17
|
+
|
|
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
|
|
25
|
+
|
|
26
|
+
def __iter__(self) -> Iterator[Tuple[str, Any]]: # type: ignore[override]
|
|
27
|
+
data = self.model_dump(mode='json', by_alias=True, exclude_none=True)
|
|
28
|
+
return iter(data.items())
|
|
29
|
+
|
|
30
|
+
def serialize(self) -> Dict[str, Any]:
|
|
31
|
+
"""Serialize to dict (compatible with fhirpy's serialize method)"""
|
|
32
|
+
return self.model_dump(mode='json', by_alias=True, exclude_none=True)
|
package/dist/cli/index.js
CHANGED
|
@@ -1,39 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import C from'picocolors';import Ci from'yargs';import {hideBin}from'yargs/helpers';import*as x from'fs';import x__default,{existsSync}from'fs';import*as N from'path';import N__default,{dirname,resolve}from'path';import*as U from'fs/promises';import {mkdir,writeFile,readFile}from'fs/promises';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import {fileURLToPath}from'url';import se from'assert';import*as Mt from'yaml';import*as Ht from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';import {spawn}from'child_process';import*as Qt from'util';import ei from'mustache';var gt=i=>{switch(i.toUpperCase()){case "DEBUG":return 0;case "INFO":return 1;case "WARN":return 2;case "ERROR":return 3;case "SILENT":return 4;default:throw new Error(`Invalid log level: ${i}`)}},de=class i{options;dryWarnSet=new Set;constructor(e={}){this.options={timestamp:false,level:1,...e};}shouldLog(e){let t=this.options.level??1;return e>=t}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(e,t,r){let n=this.options.timestamp?`${C.gray(new Date().toLocaleTimeString())} `:"",o=this.options.prefix?`${C.cyan(`[${this.options.prefix}]`)} `:"";return `${n}${r(e)} ${o}${t}`}isSuppressed(e){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(e)||false}tryWriteToConsole(e,t){if(this.isSuppressed(e)||!this.shouldLog(e))return;(i.consoleLevelsMap[e]||console.log)(t);}success(e){this.tryWriteToConsole(1,this.formatMessage("",e,C.green));}error(e,t){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",e,C.red));let r=this.options.level===0;t&&r&&(console.error(C.red(` ${t.message}`)),t.stack&&console.error(C.gray(t.stack)));}warn(e){this.tryWriteToConsole(2,this.formatMessage("!",e,C.yellow));}dry_warn(e){this.dryWarnSet.has(e)||(this.warn(e),this.dryWarnSet.add(e));}info(e){this.tryWriteToConsole(1,this.formatMessage("i",e,C.blue));}debug(e){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",e,C.magenta));}step(e){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",e,C.cyan));}progress(e){this.tryWriteToConsole(1,this.formatMessage("\u23F3",e,C.blue));}plain(e,t=r=>r){let r=this.options.timestamp?`${C.gray(new Date().toLocaleTimeString())} `:"",n=this.options.prefix?`${C.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${r}${n}${t(e)}`);}dim(e){this.plain(e,C.gray);}child(e){return new i({...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;}},G=new de;function Ge(i){G.success(i);}function w(i,e){G.error(i,e);}function ft(i){G.warn(i);}function He(i){G.info(i);}function ht(i){G.step(i);}function pr(i){G.dim(i);}function yt(i){G.configure(i);}function L(i={}){return new de(i)}function St(i){console.log(),console.log(C.cyan(C.bold(`\u2501\u2501\u2501 ${i} \u2501\u2501\u2501`)));}function Tt(i,e,t){let r=i;e&&(r+=` ${C.gray(`(${e}ms)`)}`),Ge(r),t&&Object.entries(t).forEach(([n,o])=>{pr(` ${n}: ${o}`);});}function J(i,e="\u2022"){i.forEach(t=>{console.log(C.gray(` ${e} ${t}`));});}var ue=i=>i.split(/(?<=[a-z])(?=[A-Z])|[-_.\s]/).filter(Boolean),me=i=>ue(i).map(e=>e.toLowerCase()).join("-"),bt=i=>{if(i.length===0)throw new Error("Empty string");return i[0]?.toUpperCase()+i.substring(1).toLowerCase()},K=i=>{if(i.length===0)throw new Error("Empty string");let[e,...t]=ue(i);return [e?.toLowerCase(),...t.map(bt)].join("")},k=i=>ue(i).map(bt).join(""),F=i=>ue(i).map(e=>e.toLowerCase()).join("_"),E=i=>!i||i.length===0?i:i.charAt(0).toUpperCase()+i.slice(1),Y=i=>i.map(e=>E(e));var vt=i=>`<${i.identifier.url}> from ${i.identifier.package}#${i.identifier.version}`;var Z=class{opts;currentDir;currentFile;writtenFilesBuffer={};constructor(e){this.opts=e;}setOutputDir(e){if(this.currentDir)throw new Error("Can't change output dir while writing");this.opts.outputDir=e;}logger(){return this.opts.logger}onDiskMkDir(e){this.opts.inMemoryOnly||x.existsSync(e)||x.mkdirSync(e,{recursive:true});}onDiskOpenFile(e){return this.opts.inMemoryOnly?-1:x.openSync(e,"w")}onDiskCloseFile(e){this.opts.inMemoryOnly||(x.fsyncSync(e),x.closeSync(e));}onDiskWrite(e,t){this.opts.inMemoryOnly||x.writeSync(e,t);}cd(e,t){let r=this.currentDir;this.currentDir=e.startsWith("/")?N.join(this.opts.outputDir,e):N.join(this.currentDir??this.opts.outputDir,e),this.onDiskMkDir(this.currentDir),this.logger()?.debug(`cd '${this.currentDir}'`),t(),this.currentDir=r;}cat(e,t){if(this.currentFile)throw new Error("Can't open file when another file is open");if(e.includes("/"))throw new Error(`Change file path separatly: ${e}`);let r=N.normalize(`${this.currentDir}/${e}`);try{let n=this.onDiskOpenFile(r);this.logger()?.debug(`cat > '${r}'`),this.currentFile={descriptor:n,relPath:r},this.writtenFilesBuffer[this.currentFile.relPath]={relPath:r,absPath:N.resolve(r),tokens:[]},t();}finally{this.currentFile&&this.onDiskCloseFile(this.currentFile.descriptor),this.currentFile=void 0;}}write(e){if(!this.currentFile)throw new Error("No file opened");this.onDiskWrite(this.currentFile.descriptor,e);let t=this.writtenFilesBuffer[this.currentFile.relPath];if(!t)throw new Error("No buffer found");t.tokens.push(e);}cp(e,t){if(!this.opts.resolveAssets)throw new Error("resolveAssets is not defined");e=N.resolve(this.opts.resolveAssets(e)),t=N.normalize(`${this.currentDir??this.opts.outputDir}/${t}`);let r=x.readFileSync(e,"utf8");this.writtenFilesBuffer[t]={relPath:t,absPath:N.resolve(t),tokens:[r]},x.cpSync(e,t);}writtenFiles(){return Object.values(this.writtenFilesBuffer).map(({relPath:e,absPath:t,tokens:r})=>({relPath:e,absPath:t,content:r.join("")})).sort((e,t)=>e.relPath.localeCompare(t.relPath))}},V=class extends Z{currentIndent=0;indent(){this.currentIndent+=this.opts.tabSize;}deindent(){this.currentIndent-=this.opts.tabSize;}writeIndent(){this.write(" ".repeat(this.currentIndent));}line(...e){e.length===0?this.write(`
|
|
3
|
-
`)
|
|
4
|
-
`));}lineSM(...e){this.writeIndent(),this.write(`${e.join(" ")};
|
|
5
|
-
`);}comment(...e){let t=e.join(" ").split(`
|
|
6
|
-
`);for(let r of t)this.line(this.opts.commentLinePrefix,r);}debugComment(...e){this.opts.withDebugComment&&(e=e.map(t=>typeof t=="string"?t:JSON.stringify(t,null,2)),this.comment(...e));}disclaimer(){return ["WARNING: This file is autogenerated by @atomic-ehr/codegen.","GitHub: https://github.com/atomic-ehr/codegen","Any manual changes made to this file may be overwritten."]}generateDisclaimer(){this.disclaimer().forEach(e=>{this.comment(e);}),this.line();}indentBlock(e){this.indent(),e(),this.deindent();}curlyBlock(e,t,r){this.line(`${e.filter(Boolean).join(" ")} {`),this.indent(),t(),this.deindent(),this.line(`}${r?.filter(Boolean).join(" ")??""}`);}squareBlock(e,t,r){this.line(`${e.filter(Boolean).join(" ")} [`),this.indent(),t(),this.deindent(),this.line(`]${r?.filter(Boolean).join(" ")??""}`);}};var ge=(i,e=true)=>{let t=i.split("/").pop();if(t&&(e&&t.includes("#")&&(t=t.split("#")[0]),!!t))return /^\d/.test(t)&&(t=`number_${t}`),t};var b=i=>`${i.name}#${i.version}`,fe=i=>`${i.name}@${i.version}`;var ze=(i,e)=>(e||(e={name:"undefined",version:"undefined"}),{...i,package_meta:i.package_meta||e,name:i.name,url:i.url,base:i.base}),We=i=>i?.kind==="resource";var Q=i=>i?.kind==="complex-type",ee=i=>i?.kind==="primitive-type",M=i=>i?.kind==="nested",Ct=i=>i?.kind==="profile";var B=i=>i?.identifier.kind==="resource"||i?.identifier.kind==="complex-type"||i?.identifier.kind==="logical",qe=i=>i?.identifier.kind==="complex-type",O=i=>i?.identifier.kind==="resource",xt=i=>i?.identifier.kind==="primitive-type",j=i=>i?.identifier.kind==="logical",he=i=>i?.identifier.kind==="profile";function Rt(i){return i?.identifier.kind==="binding"}function kt(i){return i?.identifier.kind==="value-set"}var H=i=>i?i.choices===void 0:false,P=i=>i?i.choices!==void 0:false,Je=i=>i?i.choiceOf!==void 0:false,Ft=(i,e)=>{if(!i.url)throw new Error("ValueSet must have a URL");if(!i.name)throw new Error("ValueSet must have a name");return {...i,package_meta:i.package_meta||e,name:i.name,url:i.url}};var It={"!":"Not","<=":"LessOrEqual",">=":"GreaterOrEqual","<":"Less",">":"Greater","=":"Equal","-":"Dash","+":"Plus","*":"Asterisk","/":"Slash","%":"Percent","&":"And","|":"Or","^":"Xor","~":"Tilde","?":"Question",".":"Dot"};function dr(i){return i.split("-").map(e=>E(e)).join("-")}function ur(i){let e=i;for(let t in It)e=e.replaceAll(t,It[t]??"");return e}function mr(i){let e=Number(i[0]);return Number.isInteger(e)&&!Number.isNaN(e)?`_${i}`:i}function wt(i){let e=dr(i);return e=mr(e),e=ur(e),e=E(e),e}function D(i){return E(K(i.replaceAll(".","-")))}var Pt=i=>{let e=fileURLToPath(import.meta.url),t=N__default.dirname(e);return e.endsWith("dist/index.js")?N__default.resolve(t,"..","assets","api","writer-generator","csharp",i):N__default.resolve(t,"../../../..","assets","api","writer-generator","csharp",i)},hr={boolean:"bool",instant:"string",time:"string",date:"string",dateTime:"string",decimal:"decimal",integer:"int",unsignedInt:"long",positiveInt:"long",integer64:"long",base64Binary:"string",uri:"string",url:"string",canonical:"string",oid:"string",uuid:"string",string:"string",code:"string",markdown:"string",id:"string",xhtml:"string"},yr=["Reference","Expression"],Sr=i=>i.required?["required"]:[],Tr=i=>{let e=Et($t(i.identifier));return E(e)},br=i=>i.base?`: ${i.base.name}`:"",vr=(i,e=true)=>{if(!i)return;let t=i.split("/").pop();if(t&&(e&&t.includes("#")&&(t=t.split("#")[0]),!!t))return /^\d/.test(t)&&(t=`number_${t}`),D(t)},$t=i=>{if(i.kind==="nested"){let e=i.url,t=vr(e,false);if(!t)return "";let[r,n]=t.split("#"),o=Y((n??"").split(".")).join("");return D([r,o].join(""))}return D(i.name)},Cr=i=>yr.includes(i),Et=i=>Cr(i)?`Resource${i}`:i,Se=class extends V{enums={};constructor(e){super({tabSize:4,withDebugComment:false,commentLinePrefix:"//",resolveAssets:e.resolveAssets??Pt,...e});}async generate(e){let t=e.collectComplexTypes(),r=e.collectResources(),n=Array.from(new Set(r.map(o=>D(o.identifier.package))));this.generateAllFiles(t,r,n),this.copyStaticFiles();}generateAllFiles(e,t,r){this.generateUsingFile(r),this.generateBaseTypes(e),this.generateResources(t),this.generateEnumFiles(r),this.generateResourceDictionaries(t,r),this.generateHelperFile();}generateType(e,t){let r=Tr(e),n=br(e);this.curlyBlock(["public","class",r,n],()=>{this.generateFields(e,t),this.generateNestedTypes(e,t),this.line(),this.includeHelperMethods();}),this.line();}generateFields(e,t){if(!e.fields)return;let r=Object.entries(e.fields).sort(([n],[o])=>n.localeCompare(o));for(let[n,o]of r)this.generateField(n,o,t);}generateNestedTypes(e,t){if(!(!("nested"in e)||!e.nested)){this.line();for(let r of e.nested)this.generateType(r,t);}}generateField(e,t,r){try{if(P(t))return;let n=this.buildFieldDeclaration(e,t,r);this.line(...n);}catch(n){this.logger()?.error(`Error processing field ${e}: ${n.message}`);}}buildFieldDeclaration(e,t,r){let n=this.determineFieldType(e,t,r),o=Sr(t),s=k(e);return ["public",...o,n,s,"{ get; set; }"].filter(Boolean)}determineFieldType(e,t,r){let n=this.getBaseTypeName(t);"enum"in t&&t.enum&&(n=this.registerAndGetEnumType(e,t,r)),n=Et(n);let o="",s=t.required?"":"?",a=t.array?"[]":"";return `${o}${n}${a}${s}`}getBaseTypeName(e){if("type"in e){let t=e.type.name.toString();return e.type.kind==="nested"?t=$t(e.type):e.type.kind==="primitive-type"&&(t=hr[e.type.name]??"string"),t}return ""}registerAndGetEnumType(e,t,r){let o=`${D(t.binding?.name??e)}Enum`;return this.enums[r]||(this.enums[r]={}),t.enum&&(this.enums[r][o]=t.enum),o}includeHelperMethods(){this.line("public override string ToString() => "),this.line(" JsonSerializer.Serialize(this, Helper.JsonSerializerOptions);"),this.line();}generateUsingFile(e){this.cd("/",async()=>{this.cat("Usings.cs",()=>{this.generateDisclaimer(),this.generateGlobalUsings(e);});});}generateGlobalUsings(e){let t=["CSharpSDK","System.Text.Json","System.Text.Json.Serialization",this.opts.rootNamespace,...e.map(r=>`${this.opts.rootNamespace}.${r}`)];for(let r of t)this.lineSM("global","using",r);}generateBaseTypes(e){this.cd("/",async()=>{this.cat("base.cs",()=>{this.generateDisclaimer(),this.line(),this.lineSM("namespace",this.opts.rootNamespace);for(let t of e){let r=D(t.identifier.package);this.generateType(t,r);}});});}generateResources(e){for(let t of e)this.generateResourceFile(t);}generateResourceFile(e){let t=D(e.identifier.package);this.cd(`/${t}`,async()=>{this.cat(`${e.identifier.name}.cs`,()=>{this.generateDisclaimer(),this.line(),this.lineSM("namespace",`${this.opts.rootNamespace}.${t}`),this.line(),this.generateType(e,t);});});}generateEnumFiles(e){for(let t of e)this.generatePackageEnums(t);}generatePackageEnums(e){let t=this.enums[e];!t||Object.keys(t).length===0||this.cd(`/${e}`,async()=>{this.cat(`${e}Enums.cs`,()=>{this.generateDisclaimer(),this.generateEnumFileContent(e,t);});});}generateEnumFileContent(e,t){this.lineSM("using","System.ComponentModel"),this.line(),this.lineSM(`namespace ${this.opts.rootNamespace}.${e}`);for(let[r,n]of Object.entries(t))this.generateEnum(r,n);}generateEnum(e,t){this.curlyBlock(["public","enum",e],()=>{for(let r of t)this.line(`[Description("${r}")]`),this.line(`${wt(r)},`);}),this.line();}generateResourceDictionaries(e,t){this.cd("/",async()=>{for(let r of t){let n=e.filter(o=>D(o.identifier.package)===r);if(n.length===0)return;this.cat(`${r}ResourceDictionary.cs`,()=>{this.generateDisclaimer(),this.line(),this.lineSM(`namespace ${this.opts.rootNamespace}`),this.generateResourceDictionaryClass(r,n);});}});}generateResourceDictionaryClass(e,t){this.curlyBlock(["public","static","class","ResourceDictionary"],()=>{this.curlyBlock(["public static readonly Dictionary<Type, string> Map = new()"],()=>{for(let r of t){let n=r.identifier.name;this.line(`{ typeof(${e}.${n}), "${n}" },`);}}),this.lineSM();});}copyStaticFiles(){this.cp("Client.cs","Client.cs"),this.cp("Helper.cs","Helper.cs");}generateHelperFile(){if(this.opts.inMemoryOnly)return;let e=Pt("Helper.cs"),t=N__default.join(this.opts.outputDir,"Helper.cs");x__default.copyFileSync(e,t);}};var z=i=>{let e={};for(let t of i){let r=t.identifier.package;e[r]||(e[r]=[]),e[r].push(t);}for(let[t,r]of Object.entries(e)){let n={};for(let s of r)n[JSON.stringify(s.identifier)]=s;let o=Object.values(n);o.sort((s,a)=>s.identifier.name.localeCompare(a.identifier.name)),e[t]=o;}return e},xr=i=>{let e={};for(let r of i)e[r.identifier.name]=r;let t={};for(let r of i){let n=r.identifier.name,o=r.base?.name;t[n]||(t[n]=[]),o&&e[o]&&t[n].push(o);}return t},Rr=i=>{let e=[],t={},r={},n=o=>{if(r[o])throw new Error(`Graph has cycles ${o}`);if(!t[o]){r[o]=true;for(let s of i[o]??[])n(s);r[o]=false,t[o]=true,e.push(o);}};for(let o in i)t[o]||n(o);return e},Ot=i=>{let e=xr(i);return Rr(e).map(r=>i.find(n=>n.identifier.name===r)).filter(Boolean)},kr=i=>{let e=i.filter(o=>O(o)||j(o)||qe(o)),t=[];for(let o of e)o.base&&t.push({parent:o.base,child:o.identifier});let r=[...t],n=o=>{let s=t.filter(c=>c.parent.name===o.name).map(c=>c.child),a=[];for(let c of s)a.push(...n(c));return [...s,...a]};for(let o of t){let s=n(o.child);for(let a of s)t.some(c=>c.parent.name===o.parent.name&&c.child.name===a.name)||r.push({parent:o.parent,child:a});}return r},be=(i,{resolutionTree:e,logger:t})=>{let r={},n=u=>{let m=u.identifier.url,S=u.identifier.package;if(r[m]||(r[m]={}),r[m][u.identifier.package]&&S!=="shared"){let v=JSON.stringify(u.identifier,void 0,2),T=JSON.stringify(r[m][S]?.identifier,void 0,2);if(v!==T)throw new Error(`Duplicate schema: ${v} and ${T}`);return}r[m][S]=u;};for(let u of i)n(u);let o=kr(i),s=u=>r[u.url]?.[u.package],a=(u,m)=>{if(e){let S=e[u]?.[m]?.[0];if(S)return r[m]?.[S.pkg.name]}return r[m]?.[u]},c=u=>o.filter(m=>m.parent.name===u.name).map(m=>m.child),l=u=>{let m=[],S=u;for(;S;){m.push(S);let v=S.base;if(v===void 0)break;let T=s(v);if(!T){t?.warn(`Failed to resolve base type: ${m.map(I=>`${I.identifier.url} (${I.identifier.kind})`).join(", ")}`);return}S=T;}return m},p=u=>{let m=l(u);if(m===void 0)throw new Error(`Failed to resolve base type: ${u.identifier.url} (${u.identifier.kind})`);return m},f=u=>{let m=p(u).find(S=>S.identifier.kind!=="profile");if(!m)throw new Error(`No non-constraint schema found in hierarchy for: ${u.identifier.name}`);return m};return {_schemaIndex:r,_relations:o,collectComplexTypes:()=>i.filter(qe),collectResources:()=>i.filter(O),collectLogicalModels:()=>i.filter(j),collectProfiles:()=>i.filter(he),resolve:s,resolveByUrl:a,resourceChildren:c,tryHierarchy:l,hierarchy:p,findLastSpecialization:f,findLastSpecializationByIdentifier:u=>{let m=s(u);return m?f(m).identifier:u},flatProfile:u=>{let m=p(u),S=m.filter(_=>_.identifier.kind==="profile"),v=m.find(_=>_.identifier.kind!=="profile");if(!v)throw new Error(`No non-constraint schema found in hierarchy for ${u.identifier.name}`);let T={};for(let _ of S.slice().reverse()){let le=_;if(le.fields)for(let[pe,mt]of Object.entries(le.fields))T[pe]?T[pe]={...T[pe],...mt}:T[pe]={...mt};}let I={};for(let _ of S.flatMap(le=>le.dependencies??[]))I[_.url]=_;let A=Object.values(I);return {...u,base:v.identifier,fields:T,dependencies:A}},isWithMetaField:u=>{let m=l(u);return m?m.filter(B).some(S=>S.fields?.meta!==void 0):false},exportTree:async u=>{let m={};for(let[v,T]of Object.entries(z(i))){m[v]={"primitive-type":{},"complex-type":{},resource:{},"value-set":{},nested:{},binding:{},profile:{},logical:{}};for(let I of T)m[v][I.identifier.kind][I.identifier.url]={};}let S=u.endsWith(".yaml")?Mt.stringify(m):JSON.stringify(m,void 0,2);await U.mkdir(N.dirname(u),{recursive:true}),await U.writeFile(u,S);}}};var wr={boolean:"bool",instant:"str",time:"str",date:"str",dateTime:"str",decimal:"float",integer:"int",unsignedInt:"int",positiveInt:"PositiveInt",integer64:"int",base64Binary:"str",uri:"str",url:"str",canonical:"str",oid:"str",uuid:"str",string:"str",code:"str",markdown:"str",id:"str",xhtml:"str"},Ke={snake_case:F,PascalCase:k,camelCase:K},Pr=new Set(["False","None","True","and","as","assert","async","await","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","nonlocal","not","or","pass","raise","return","try","while","with","yield","List"]),_t=100,$r=i=>Pr.has(i)?`${i}_`:i,Er=i=>i==="Resource"||i==="Element"?["BaseModel"]:[],Nr=(i,e=true)=>{if(!i)return;let t=i.split("/").pop();if(t&&(e&&t.includes("#")&&(t=t.split("#")[0]),!!t))return /^\d/.test(t)&&(t=`number_${t}`),F(t)},ve=i=>{if(i.kind==="nested"){let e=i.url,t=Nr(e,false);if(!t)return "";let[r,n]=t.split("#"),o=Y((n??"").split(".")).join("");return k([r,o].join(""))}return k(i.name)},Ye=i=>{let e=N.dirname(fileURLToPath(import.meta.url));return __filename.endsWith("dist/index.js")?N.resolve(e,"..","assets","api","writer-generator","python",i):N.resolve(e,"../../..","assets","api","writer-generator","python",i)},Ce=class extends V{nameFormatFunction;tsIndex;constructor(e){super({...e,resolveAssets:e.resolveAssets??Ye}),this.nameFormatFunction=this.getFieldFormatFunction(e.fieldFormat);}async generate(e){this.tsIndex=e;let t={groupedComplexTypes:z(e.collectComplexTypes()),groupedResources:z(e.collectResources())};this.generateRootPackages(t),this.generateSDKPackages(t);}generateRootPackages(e){this.generateRootInitFile(e),this.cp(Ye("requirements.txt"),"requirements.txt");}generateSDKPackages(e){this.generateComplexTypesPackages(e.groupedComplexTypes),this.generateResourcePackages(e);}generateComplexTypesPackages(e){for(let[t,r]of Object.entries(e))this.cd(`/${F(t)}`,()=>{this.generateBasePy(r);});}generateResourcePackages(e){for(let[t,r]of Object.entries(e.groupedResources))this.cd(`/${F(t)}`,()=>{this.generateResourcePackageContent(t,r,e.groupedComplexTypes[t]||[]);});}generateResourcePackageContent(e,t,r){let n=this.pyFhirPackageByName(e);this.generateResourcePackageInit(n,t,r),this.generateResourceFamilies(t);for(let o of t)this.generateResourceModule(o);}generateRootInitFile(e){this.cd("/",()=>{this.cat("__init__.py",()=>{this.generateDisclaimer();let t=this.collectAndImportAllModels(e);this.generateModelRebuilds(t);});});}collectAndImportAllModels(e){let t=[];for(let r of Object.keys(e.groupedResources)){let n=this.pyFhirPackageByName(r);t.push(...this.importComplexTypes(n,e.groupedComplexTypes[r])),t.push(...this.importResources(n,false,e.groupedResources[r]));}return this.line(),t}generateModelRebuilds(e){for(let t of e.sort())this.line(`${t}.model_rebuild()`);}generateBasePy(e){this.cat("base.py",()=>{this.generateDisclaimer(),this.generateDefaultImports(),this.line(),this.generateComplexTypes(e),this.line();});}generateComplexTypes(e){for(let t of Ot(e))this.generateNestedTypes(t),this.line(),this.generateType(t);}generateResourcePackageInit(e,t,r){this.cat("__init__.py",()=>{this.generateDisclaimer(),this.importComplexTypes(e,r);let n=this.importResources(e,true,t);this.line(),this.generateExportsDeclaration(r,n);});}importComplexTypes(e,t){if(!t||t.length===0)return [];let r=t.map(n=>n.identifier.name).sort();return this.pyImportFrom(`${e}.base`,...r),this.line(),r}buildImportLine(e,t){let r="";for(;e.length>0&&r.length<t;){let n=e.shift();if(!n)throw new Error("Unexpected empty entity");r.length>0&&(r+=", "),r+=n;}return e.length>0&&(r+=", \\"),r}importResources(e,t,r){if(!r||r.length===0)return [];let n=[];for(let o of r){let s=this.importOneResource(o,e);!t&&!o.fields||n.push(...s);}return n}importOneResource(e,t){let r=`${t}.${F(e.identifier.name)}`,n=this.collectResourceImportNames(e);this.pyImportFrom(r,...n);let o=[...n];if(this.shouldImportResourceFamily(e)){let s=`${e.identifier.name}Family`;this.pyImportFrom(`${t}.resource_families`,s);}return o}collectResourceImportNames(e){let t=[ve(e.identifier)];for(let r of e.nested??[]){let n=ve(r.identifier);t.push(n);}return t}shouldImportResourceFamily(e){return se(this.tsIndex!==void 0),e.identifier.kind==="resource"&&this.tsIndex.resourceChildren(e.identifier).length>0}generateExportsDeclaration(e,t){this.squareBlock(["__all__","="],()=>{let r=[...(e||[]).map(n=>n.identifier.name),...t].sort();for(let n of r)this.line(`'${n}',`);});}generateResourceModule(e){this.cat(`${F(e.identifier.name)}.py`,()=>{this.generateDisclaimer(),this.generateDefaultImports(),this.line(),this.generateDependenciesImports(e),this.line(),this.generateNestedTypes(e),this.line(),this.generateType(e);});}generateType(e){let t=ve(e.identifier),r=this.getSuperClasses(e);this.line(`class ${t}(${r.join(", ")}):`),this.indentBlock(()=>{this.generateClassBody(e);}),this.line();}getSuperClasses(e){return [...e.base?[e.base.name]:[],...Er(e.identifier.name)]}generateClassBody(e){if(this.generateModelConfig(),!e.fields){this.line("pass");return}e.identifier.kind==="resource"&&this.generateResourceTypeField(e),this.generateFields(e),e.identifier.kind==="resource"&&this.generateResourceMethods(e);}generateModelConfig(){let e=this.opts.allowExtraFields?"allow":"forbid";this.line(`model_config = ConfigDict(validate_by_name=True, serialize_by_alias=True, extra="${e}")`);}generateResourceTypeField(e){this.line(`${this.nameFormatFunction("resourceType")}: str = Field(`),this.indentBlock(()=>{this.line(`default='${e.identifier.name}',`),this.line("alias='resourceType',"),this.line("serialization_alias='resourceType',"),this.line("frozen=True,"),this.line(`pattern='${e.identifier.name}'`);}),this.line(")");}generateFields(e){let t=Object.entries(e.fields??[]).sort(([r],[n])=>r.localeCompare(n));for(let[r,n]of t){if("choices"in n&&n.choices)continue;let o=this.buildFieldInfo(r,n);this.line(`${o.name}: ${o.type}${o.defaultValue}`);}}buildFieldInfo(e,t){let r=$r(this.nameFormatFunction(e)),n=this.determineFieldType(t),o=this.getFieldDefaultValue(t,e);return {name:r,type:n,defaultValue:o}}determineFieldType(e){let t=e?this.getBaseFieldType(e):"";return "enum"in e&&e.enum&&(t=`Literal[${e.enum.map(n=>`"${n}"`).join(", ")}]`),e.array&&(t=`PyList[${t}]`),e.required||(t=`${t} | None`),t}getBaseFieldType(e){return "type"in e&&e.type.kind==="resource"?`${e.type.name}Family`:"type"in e&&e.type.kind==="nested"?ve(e.type):"type"in e&&e.type.kind==="primitive-type"?wr[e.type.name]??"str":"type"in e?e.type.name:""}getFieldDefaultValue(e,t){let r=`alias="${t}", serialization_alias="${t}"`;return e.required?` = Field(${r})`:` = Field(None, ${r})`}generateResourceMethods(e){let t=e.identifier.name.toString();this.line(),this.line("def to_json(self, indent: int | None = None) -> str:"),this.line(" return self.model_dump_json(exclude_unset=True, exclude_none=True, indent=indent)"),this.line(),this.line("@classmethod"),this.line(`def from_json(cls, json: str) -> ${t}:`),this.line(" return cls.model_validate_json(json)");}generateNestedTypes(e){if(e.nested){this.line();for(let t of e.nested)this.generateType(t);}}generateDefaultImports(){this.pyImportFrom("__future__","annotations"),this.pyImportFrom("pydantic","BaseModel","ConfigDict","Field","PositiveInt"),this.pyImportFrom("typing","List as PyList","Literal");}generateDependenciesImports(e){!e.dependencies||e.dependencies.length===0||(this.importComplexTypeDependencies(e.dependencies),this.importResourceDependencies(e.dependencies));}importComplexTypeDependencies(e){let t=e.filter(n=>n.kind==="complex-type"),r=this.groupDependenciesByPackage(t);for(let[n,o]of Object.entries(r))this.pyImportFrom(n,...o.sort());}importResourceDependencies(e){let t=e.filter(r=>r.kind==="resource");for(let r of t){this.pyImportType(r);let n=`${k(r.name)}Family`,o=`${this.pyFhirPackage(r)}.resource_families`;this.pyImportFrom(o,n);}}groupDependenciesByPackage(e){let t={};for(let r of e){let n=this.pyPackage(r);t[n]||(t[n]=[]),t[n].push(r.name);}return t}pyImportFrom(e,...t){let r=`from ${e} import ${t.join(", ")}`;this.shouldUseSingleLineImport(r,t)?this.line(r):this.writeMultiLineImport(e,t);}shouldUseSingleLineImport(e,t){return e.length<=_t||t.length===1}writeMultiLineImport(e,t){this.line(`from ${e} import (\\`),this.indentBlock(()=>{let r=[...t];for(;r.length>0;){let n=this.buildImportLine(r,_t);this.line(n);}}),this.line(")");}pyImportType(e){this.pyImportFrom(this.pyPackage(e),k(e.name));}generateResourceFamilies(e){se(this.tsIndex!==void 0);let t=Object.keys(z(e)).map(o=>`${this.opts.rootPackageName}.${o.replaceAll(".","_")}`),r={};for(let o of this.tsIndex.collectResources()){let s=this.tsIndex.resourceChildren(o.identifier).map(a=>a.name);if(s.length>0){let a=`${o.identifier.name}Family`;r[a]=s;}}let n=Object.keys(r);n.length!==0&&this.buildResourceFamiliesFile(t,r,n);}buildResourceFamiliesFile(e,t,r){this.cat("resource_families.py",()=>{this.generateDisclaimer(),this.includeResourceFamilyValidator(),this.line(),this.generateFamilyDefinitions(e,t),this.generateFamilyExports(r);});}includeResourceFamilyValidator(){let e=x__default.readFileSync(Ye("resource_family_validator.py"),"utf-8");this.line(e);}generateFamilyDefinitions(e,t){this.line(`packages = [${e.map(r=>`'${r}'`).join(", ")}]`),this.line();for(let[r,n]of Object.entries(t))this.generateFamilyDefinition(r,n);}generateFamilyDefinition(e,t){let r=`${e}_resources`;this.line(`${r} = [${t.map(n=>`'${n}'`).join(", ")}]`),this.line(),this.line(`def validate_and_downcast_${e}(v: Any) -> Any:`),this.line(` return validate_and_downcast(v, packages, ${r})`),this.line(),this.line(`type ${e} = Annotated[Any, BeforeValidator(validate_and_downcast_${e})]`),this.line();}generateFamilyExports(e){this.line(`__all__ = [${e.map(t=>`'${t}'`).join(", ")}]`);}buildPyPackageName(e){return (e?[F(e)]:[""]).join(".")}pyFhirPackage(e){return this.pyFhirPackageByName(e.package)}pyFhirPackageByName(e){return [this.opts.rootPackageName,this.buildPyPackageName(e)].join(".")}pyPackage(e){return e.kind==="complex-type"?`${this.pyFhirPackage(e)}.base`:e.kind==="resource"?[this.pyFhirPackage(e),F(e.name)].join("."):this.pyFhirPackage(e)}getFieldFormatFunction(e){return Ke[e]?Ke[e]:(this.logger()?.warn(`Unknown field format '${e}'. Defaulting to SnakeCase.`),this.logger()?.warn(`Supported formats: ${Object.keys(Ke).join(", ")}`),F)}};function Xe(i){let e=i.split("|")[0];return e||i}function Mr(i){return i.split("|")[1]}function Or(i){return i.derivation==="constraint"?"profile":i.kind==="primitive-type"?"primitive-type":i.kind==="complex-type"?"complex-type":i.kind==="resource"?"resource":i.kind==="logical"?"logical":"resource"}function W(i){return {kind:Or(i),package:i.package_meta.name,version:i.package_meta.version,name:i.name,url:i.url}}var Dr=i=>{let e=i.split("/"),t=e[e.length-1];return t&&t.length>0?t.split(/[-_]/).map(r=>r.charAt(0).toUpperCase()+r.slice(1).toLowerCase()).join(""):i};function xe(i,e,t){let r=Xe(t),n=Dr(r),o={package_meta:{name:"missing_valuesets",version:Mr(r)||"0.0.0"},id:t},s=i.resolveVs(e,r)||o,a=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:a,url:r}}function Re(i,e,t){let r=e.join("."),[n,o,s]=t?[{name:"shared",version:"1.0.0"},t,`urn:fhir:binding:${t}`]:[i.package_meta,`${i.name}.${r}_binding`,`${i.url}#${r}_binding`];return {kind:"binding",package:n.name,version:n.version,name:o,url:s}}function ke(i,e,t,r){let n={};if(e.derivation==="constraint"){let c=i.resolveFsSpecializations(e.package_meta,e.url).map(l=>Ze(i,l,r)).filter(l=>l!==void 0).flat();for(let l of c.reverse())n[l.identifier.name]=l.identifier.url;}let o=t.join("."),s=n[o]??`${e.url}#${o}`;return {kind:"nested",package:e.package_meta.name,version:e.package_meta.version,name:o,url:s}}function Lt(i,e,t){let r=[];for(let[n,o]of Object.entries(t)){let s=[...e,n];re(o)&&r.push([s,o]),o.elements&&r.push(...Lt(i,s,o.elements));}return r}function _r(i,e,t,r,n){let o={};for(let[s,a]of Object.entries(r)){let c=[...t,s],l=i.resolveElementSnapshot(e,c);re(l)?o[s]=Ie(i,e,c,l,n):o[s]=Fe(i,e,c,l,n);}return o}function Ze(i,e,t){if(!e.elements)return;let r=Lt(e,[],e.elements).filter(([o,s])=>s.elements&&Object.keys(s.elements).length>0),n=[];for(let[o,s]of r){let a=ke(i,e,o,t),c;s.type==="BackboneElement"||!s.type?c="BackboneElement":c=s.type;let l=i.ensureSpecializationCanonicalUrl(c),p=i.resolveFs(e.package_meta,l);if(!p)throw new Error(`Could not resolve base type ${c}`);let f={kind:"complex-type",package:p.package_meta.name,version:p.package_meta.version,name:c,url:l},y=_r(i,e,o,s.elements??{},t),d={identifier:a,base:f,fields:y};n.push(d);}return n.sort((o,s)=>o.identifier.url.localeCompare(s.identifier.url)),n.length===0?void 0:n}function Vt(i){let e=[];for(let t of i){t.base&&e.push(t.base);for(let r of Object.values(t.fields||{}))"type"in r&&r.type&&e.push(r.type),"binding"in r&&r.binding&&e.push(r.binding);}return e}function Bt(i,e,t){let r=t[t.length-1];if(!r)throw new Error(`Internal error: fieldName is missing for path ${t.join("/")}`);let n=t.slice(0,-1),o=i.resolveFsGenealogy(e.package_meta,e.url).flatMap(s=>{if(n.length===0)return s.required||[];if(!s.elements)return [];let a=s;for(let c of n)a=a?.elements?.[c];return a?.required||[]});return new Set(o).has(r)}function jt(i,e,t){let r=t[t.length-1];if(!r)throw new Error(`Internal error: fieldName is missing for path ${t.join("/")}`);let n=t.slice(0,-1),o=i.resolveFsGenealogy(e.package_meta,e.url).flatMap(s=>{if(n.length===0)return s.excluded||[];if(!s.elements)return [];let a=s;for(let c of n)a=a?.elements?.[c];return a?.excluded||[]});return new Set(o).has(r)}var Lr=(i,e,t)=>{if(t.refers)return t.refers.map(r=>{let n=i.ensureSpecializationCanonicalUrl(r),o=i.resolveFs(e.package_meta,n);if(!o)throw new Error(`Failed to resolve fs for ${n}`);return W(o)})};function Qe(i,e,t,r,n){if(r.elementReference){let o=r.elementReference.slice(1).filter((s,a)=>a%2===1);return ke(i,e,o,n)}else if(r.type){let o=i.ensureSpecializationCanonicalUrl(r.type),s=i.resolveFs(e.package_meta,o);if(!s)throw new Error(`Could not resolve field type: '${r.type}' (from '${e.url}' in '${b(e.package_meta)}')`);return W(s)}else {if(r.choices)return;if(e.derivation==="constraint")return;throw n?.error(`Can't recognize element type '${e.url}' (${e.derivation}) at '${t.join(".")}': ${JSON.stringify(r,void 0,2)}`),new Error("Unrecognized element type")}}var Fe=(i,e,t,r,n)=>{let o,s;r.binding&&(o=Re(e,t,r.binding.bindingName),r.binding.strength==="required"&&r.type==="code"&&(s=et(i,e,r,n)));let a=Qe(i,e,t,r,n);return a||n?.warn(`Field type not found for '${e.url}#${t.join(".")}' (${e.derivation})`),{type:a,required:Bt(i,e,t),excluded:jt(i,e,t),reference:Lr(i,e,r),array:r.array||false,min:r.min,max:r.max,choices:r.choices,choiceOf:r.choiceOf,binding:o,enum:s}};function re(i){let e=i.type==="BackboneElement",t=i.type==="Element"&&i.elements!==void 0&&Object.keys(i.elements).length>0,r=i.type===void 0&&i.choiceOf===void 0&&i.elements!==void 0&&Object.keys(i.elements).length>0;return e||t||r}function Ie(i,e,t,r,n){return {type:ke(i,e,t,n),array:r.array||false,required:Bt(i,e,t),excluded:jt(i,e,t)}}function tt(i,e,t,r){let n=Xe(t)||t,o=i.resolveVs(e,n);if(o)return Br(i,o)}function Br(i,e,t){if(e.expansion?.contains)return e.expansion.contains.filter(n=>n.code!==void 0).map(n=>(se(n.code),{code:n.code,display:n.display,system:n.system}));let r=[];if(e.compose?.include){for(let n of e.compose.include)if(n.concept)for(let o of n.concept)r.push({system:n.system,code:o.code,display:o.display});else if(n.system&&!n.filter)try{let o=i.resolveAny(n.system);if(o?.concept){let s=(a,c)=>{for(let l of a)r.push({system:c,code:l.code,display:l.display}),l.concept&&s(l.concept,c);};s(o.concept,n.system);}}catch{}}return r.length>0?r:void 0}var Ut=100;function et(i,e,t,r){if(!t.binding)return;let n=t.binding.strength,o=t.binding.valueSet;if(!o||!(n==="required"||n==="extensible"&&(t.type==="code"||t.type==="Coding")||n==="preferred"&&(t.type==="code"||t.type==="Coding")))return;let a=tt(i,e.package_meta,o);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>Ut){r?.dry_warn(`Value set ${o} has ${c.length} which is more than ${Ut} codes, which may cause issues with code generation.`);return}return c.length>0?c:void 0}function jr(i,e,t,r,n){if(!r.binding?.valueSet)return;let o=Re(e,t,r.binding.bindingName),s=Qe(i,e,t,r,n),a=xe(i,e.package_meta,r.binding.valueSet),c=[];s&&c.push(s),c.push(a);let l=et(i,e,r,n);return {identifier:o,type:s,valueset:a,strength:r.binding.strength,enum:l,dependencies:c}}function At(i,e,t){let r=new Set;if(!e.elements)return [];let n=[];function o(c,l){for(let[p,f]of Object.entries(c)){let y=[...l,p],d=y.join(".");if(!r.has(d)){if(r.add(d),f.binding){let g=jr(i,e,y,f,t);g&&n.push(g);}f.elements&&o(f.elements,y);}}}o(e.elements,[]),n.sort((c,l)=>c.identifier.name.localeCompare(l.identifier.name));let s=[],a=new Set;for(let c of n)a.has(c.identifier.url)||(a.add(c.identifier.url),s.push(c));return s}function Ur(i,e,t,r,n){if(!r)return;let o={};for(let s of i.getAllElementKeys(r)){let a=[...t,s],c=i.resolveElementSnapshot(e,a);re(c)?o[s]=Ie(i,e,a,c,n):o[s]=Fe(i,e,a,c,n);}return o}function Ar(i){let e=[];for(let t of Object.values(i))"type"in t&&t.type&&e.push(t.type),"binding"in t&&t.binding&&e.push(t.binding);return e}function Gr(i,e){return !!(i.base==="Extension"||i.base==="http://hl7.org/fhir/StructureDefinition/Extension"||i.url?.includes("/extension/")||i.url?.includes("-extension")||i.name?.toLowerCase().includes("extension")||i.type==="Extension")}async function we(i,e,t){if(!e.url)throw new Error("ValueSet URL is required");let r=xe(i,e.package_meta,e.url),n=tt(i,e.package_meta,e.url);return {identifier:r,description:e.description,concept:n,compose:n?void 0:e.compose}}function rt(i,e,t,r){let n=[];e&&n.push(e),t&&n.push(...Ar(t)),r&&n.push(...Vt(r));let o={};for(let c of n)c.url!==i.url&&(o[c.url]=c);let s=new Set(r?.map(c=>c.identifier.url)),a=Object.values(o).filter(c=>Ct(i)||!M(c)?true:!s.has(c.url)).sort((c,l)=>c.url.localeCompare(l.url));return a.length>0?a:void 0}function Hr(i,e,t){let r=W(e),n;if(e.base&&e.type!=="Element"){let p=i.resolveFs(e.package_meta,i.ensureSpecializationCanonicalUrl(e.base));if(!p)throw new Error(`Base resource not found '${e.base}' for <${e.url}> from ${b(e.package_meta)}`);n=W(p);}let o=Ur(i,e,[],e.elements,t),s=Ze(i,e,t),a=rt(r,n,o,s),c={identifier:r,base:n,fields:o,nested:s,description:e.description,dependencies:a},l=At(i,e,t);return [c,...l]}async function Pe(i,e,t){let r=Hr(i,e,t);if(Gr(e,W(e))){let n=r[0];if(!n)throw new Error("Expected schema to be defined");n.metadata={isExtension:true};}return r}var it=i=>i!==null&&typeof i=="object"&&i.resourceType==="CodeSystem";var $e=i=>i!==null&&typeof i=="object"&&i.resourceType==="ValueSet";var zr=async(i,e)=>{let r=(await i.packageJson(e.name)).dependencies;return r!==void 0?Object.entries(r).map(([n,o])=>({name:n,version:o})):[]},zt=i=>({pkg:i,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),Wt=async(i,e,t,r,n)=>{let o=b(e);if(n?.info(`${" ".repeat(t*2)}+ ${o}`),r[o])return r[o];let s=zt(e);for(let c of await i.search({package:e})){let l=c.url;if(!l||!(isStructureDefinition(c)||$e(c)||it(c)))continue;let p=l;s.canonicalResolution[p]&&n?.dry_warn(`Duplicate canonical URL: ${p} at ${o}.`),s.canonicalResolution[p]=[{deep:t,pkg:e,pkgId:o,resource:c}];}let a=await zr(i,e);for(let c of a){let{canonicalResolution:l}=await Wt(i,c,t+1,r,n);for(let[p,f]of Object.entries(l)){let y=p;s.canonicalResolution[y]=[...s.canonicalResolution[y]||[],...f];}}for(let c of Object.values(s.canonicalResolution))c.sort((l,p)=>l.deep-p.deep);return r[o]=s,s},Gt=(i,e,t)=>{let r=Object.values(i).flatMap(n=>n.canonicalResolution[e]);if(!r)throw new Error(`No canonical resolution found for ${e} in any package`);return r[0]?.resource},ie=async(i,{logger:e,fallbackPackageForNameResolution:t,focusedPackages:r})=>{let n=r??await i.packages(),o={};for(let d of n)await Wt(i,d,0,o,e);for(let{pkg:d,canonicalResolution:g}of Object.values(o)){let h=b(d);if(!o[h])throw new Error(`Package ${h} not found`);let u=0;e?.info(`FHIR Schema conversion for '${b(d)}' begins...`);for(let[m,S]of Object.entries(g)){let v=S[0];if(!v)throw new Error("Resource not found");let T=v.resource,I=v.pkg;if(isStructureDefinition(T)){let A=ze(Ht.translate(T),I);u++,o[h].fhirSchemas[A.url]=A;}if($e(T)){let A=Ft(T,I);o[h].valueSets[A.url]=A;}}e?.info(`FHIR Schema conversion for '${b(d)}' completed: ${u} successful`);}let s=(d,g)=>o[b(d)]?.fhirSchemas[g]||t&&o[b(t)]?.fhirSchemas[g],a=(d,g)=>o[b(d)]?.valueSets[g]||t&&o[b(t)]?.valueSets[g],c=d=>d.match(/^[a-zA-Z0-9]+$/)&&`http://hl7.org/fhir/StructureDefinition/${d}`||d,l=(d,g)=>{let h=s(d,g);if(h===void 0)throw new Error(`Failed to resolve FHIR Schema: '${g}'`);let u=[h];for(;h?.base;){let m=h.package_meta,S=c(h.base);if(h=s(m,S),h===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${g}'. Problem: '${S}' from '${b(m)}'`);u.push(h);}return u};return {...i,testAppendFs(d){let g=ze(d),h=b(g.package_meta);o[h]||(o[h]=zt(g.package_meta)),o[h].fhirSchemas[g.url]=g;},resolveFs:s,resolveFsGenealogy:l,resolveFsSpecializations:(d,g)=>l(d,g).filter(h=>h.derivation==="specialization"),ensureSpecializationCanonicalUrl:c,resolveSd:(d,g)=>{let h=Gt(o,g);if(isStructureDefinition(h))return h},allFs:()=>Object.values(o).flatMap(d=>Object.values(d.fhirSchemas)),allVs:()=>Object.values(o).flatMap(d=>Object.values(d.valueSets)),resolveVs:a,resolveAny:d=>Gt(o,d),resolveElementSnapshot:(d,g)=>{let h=l(d.package_meta,d.url),u=Wr(h,g);return qr(u)},getAllElementKeys:d=>{let g=new Set;for(let[h,u]of Object.entries(d)){g.add(h);for(let m of u?.choices||[])d[m]||g.add(m);}return Array.from(g)},resolver:o,resolutionTree:()=>{let d={};for(let[g,h]of Object.entries(o)){let u=h.pkg.name;d[u]={};for(let[m,S]of Object.entries(h.canonicalResolution)){let v=m;d[u][v]=[];for(let T of S)d[u][v].push({deep:T.deep,pkg:T.pkg});}}return d}}};var Wr=(i,e)=>{let[t,...r]=e;return t===void 0?[]:i.map(n=>{if(!n.elements)return;let o=n.elements?.[t];for(let s of r)o=o?.elements?.[s];return o}).filter(n=>n!==void 0)};function qr(i){let e=i.reverse(),t=Object.assign({},...e);return t.elements=void 0,t}var ne=class{manager;options;logger;constructor(e){this.options={...e},this.manager=e.manager,this.logger=e.logger||L({prefix:"TypeSchema"});}async registerFromPackageMetas(e){let t=e.map(b);return this.logger?.step(`Loading FHIR packages: ${t.join(", ")}`),await this.manager.init(),ie(this.manager,{focusedPackages:e})}generateFhirSchemas(e){this.logger?.progress(`Converting ${e.length} StructureDefinitions to FHIRSchemas`);let t=[],r=0,n=0;for(let o of e)try{let s=Ht.translate(o);t.push(s),r++,this.logger?.debug(`Converted StructureDefinition: ${o.name||o.id} (${o.resourceType})`);}catch(s){n++,this.logger?.warn(`Failed to convert StructureDefinition ${o.name||o.id}: ${s instanceof Error?s.message:String(s)}`);}return this.logger?.success(`FHIR Schema conversion completed: ${r}/${e.length} successful, ${n} failed`),t}async generateValueSetSchemas(e,t){e.length>0&&this.logger?.debug(`${e.length} ValueSets available for enum extraction`);let r=await ie(this.manager,{logger:this.logger}),n=[];if(e.length>0){this.logger?.progress(`Converting ${e.length} ValueSets to TypeSchema`);let o=0,s=0;for(let a of e)try{let c=await we(r,a,t);c&&(n.push(c),o++,this.logger?.debug(`Converted ValueSet: ${a.name||a.id}`));}catch(c){s++,this.logger?.warn(`Failed to convert ValueSet ${a.name||a.id}: ${c instanceof Error?c.message:String(c)}`);}this.logger?.success(`ValueSet conversion completed: ${o}/${e.length} successful, ${s} failed`);}return n}async generateFromPackage(e,t,r){let n={name:e,version:t||"latest"},o=await this.registerFromPackageMetas([n]),s=await this.generateValueSetSchemas(o.allVs(),r);return [...(await Promise.all(o.allFs().map(async l=>await Pe(o,l,r)))).flat(),...s]}};var oe="Use CodeableReference which is not provided by FHIR R4.",Jr="Use Availability which is not provided by FHIR R4.",Jt={"hl7.fhir.uv.extensions.r4#1.0.0":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":Jr,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":oe,"http://hl7.org/fhir/StructureDefinition/specimen-additive":oe,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":oe,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":oe,"http://hl7.org/fhir/StructureDefinition/workflow-reason":oe},"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."}},Kt=async(i,e)=>{let t=[];for(let r of i.allFs()){let n=b(r.package_meta);if(Jt[n]?.[r.url]){e?.dry_warn(`Skip ${r.url} from ${n}. Reason: ${Jt[n]?.[r.url]}`);continue}t.push(...await Pe(i,r,e));}for(let r of i.allVs())t.push(await we(i,r));return t};var Kr=(i,e)=>{let t={},r={};for(let n of e){let o=i.fields?.[n];if(!i.fields||!o)throw new Error(`Field ${n} not found`);if(P(o))r[n]||(r[n]={}),r[n].declaration=o.choices;else if(Je(o)){let s=o.choiceOf;r[s]||(r[s]={}),r[s].instances=[...r[s].instances??[],n];}else t[n]=o;}for(let[n,{declaration:o,instances:s}]of Object.entries(r)){let a=s??o;se(a);for(let l of a){let p=i.fields?.[l];se(p),t[l]=p;}let c=i.fields?.[n];se(c),t[n]={...c,choices:a};}i.fields=t;},Yr=(i,e)=>{for(let t of e){let r=i.fields?.[t];if(!i.fields||!r)throw new Error(`Field ${t} not found`);if(i.fields){if(P(r))for(let n of r.choices)delete i.fields[n];if(Je(r)){let n=i.fields[r.choiceOf];se(P(n)),n.choices=n.choices.filter(o=>o!==t),n.choices.length===0&&delete i.fields[r.choiceOf];}delete i.fields[t];}}},Xr=(i,e,t)=>{if(i=structuredClone(i),xt(i)||kt(i)||Rt(i))return i;if(e.selectFields){if(e.ignoreFields)throw new Error("Cannot use both ignoreFields and selectFields in the same rule");Kr(i,e.selectFields);}if(e.ignoreFields){if(e.selectFields)throw new Error("Cannot use both ignoreFields and selectFields in the same rule");Yr(i,e.ignoreFields);}if(i.nested){let r=new Set,n=o=>{Object.values(o.fields??{}).filter(H).filter(s=>M(s.type)).forEach(s=>{let a=s.type.url;if(!r.has(a)){r.add(a);let c=i.nested?.find(l=>l.identifier.url===a);se(c),n(c);}});};n(i),i.nested=i.nested.filter(o=>r.has(o.identifier.url));}return i.dependencies=rt(i.identifier,i.base,i.fields,i.nested),i},Yt=(i,e,{resolutionTree:t,logger:r})=>{let n=[];for(let[a,c]of Object.entries(e))for(let[l,p]of Object.entries(c)){let f=i.resolveByUrl(a,l);if(!f)throw new Error(`Schema not found for ${a} ${l}`);let y=Xr(f,p);n.push(y);}let o=(a,c)=>{if(a.length===0)return Object.values(c);for(let p of a)c[JSON.stringify(p.identifier)]=p;let l=[];for(let p of a)if(B(p)){if(!p.dependencies)continue;if(p.dependencies.forEach(f=>{let y=i.resolve(f);if(!y)throw new Error(`Dependent schema ${JSON.stringify(f)} not found for ${JSON.stringify(p.identifier)}`);let d=JSON.stringify(y.identifier);c[d]||l.push(y);}),p.nested)for(let f of p.nested){if(M(f.identifier))continue;let y=JSON.stringify(f.identifier);c[y]||l.push(f);}}return o(l,c)},s=o(n,{});return be(s,{resolutionTree:t,logger:r})};var Ee=class{constructor(e){this.mode=e;}apply(e){return this._addDebug(e)}_addDebug(e){if(Array.isArray(e))return e.map(t=>this._addDebug(t));if(e!==null&&typeof e=="object"){let t=e,r={},n=JSON.stringify(t,null,this.mode==="FORMATTED"?2:void 0);for(let[o,s]of Object.entries(t))r[o]=this._addDebug(s);return r.debug=n,r}return e}};var Ne=class{constructor(e){this.nameGenerator=e;this.lambda={saveTypeName:()=>(t,r)=>this.nameGenerator.generateType(r(t)),saveEnumValueName:()=>(t,r)=>this.nameGenerator.generateEnumValue(r(t)),saveFieldName:()=>(t,r)=>this.nameGenerator.generateField(r(t)),camelCase:()=>(t,r)=>K(r(t)),snakeCase:()=>(t,r)=>F(r(t)),pascalCase:()=>(t,r)=>k(r(t)),kebabCase:()=>(t,r)=>me(r(t)),lowerCase:()=>(t,r)=>r(t).toLowerCase(),upperCase:()=>(t,r)=>r(t).toUpperCase()};}lambda;apply(e){return {...e,lambda:this.lambda}}};var Me=class{constructor(e,t,r,n){this.keywords=e;this.typeMap=t;this.nameTransformations=r;this.unsaveCharacterPattern=n;}_replaceUnsaveChars(e){let t=this.unsaveCharacterPattern instanceof RegExp?this.unsaveCharacterPattern:new RegExp(this.unsaveCharacterPattern,"g");return e.replace(t,"_")}_applyNameTransformations(e,t){for(let r of this.nameTransformations.common)e=e.replace(r.pattern instanceof RegExp?r.pattern:new RegExp(r.pattern,"g"),r.format);for(let r of t)e=e.replace(r.pattern instanceof RegExp?r.pattern:new RegExp(r.pattern,"g"),r.format);return e}_generateTypeName(e){if(this.typeMap[e])e=this.typeMap[e];else {if(e=this._applyNameTransformations(e,this.nameTransformations.type),e=e.charAt(0).toUpperCase()+e.slice(1),this.keywords.has(e))return `_${e}`;e=this._replaceUnsaveChars(e);}return e}generateEnumType(e){return this._generateTypeName(e)}_generateTypeFromTypeRef(e){return e.kind==="primitive-type"?this._generateTypeName(e.name):this._generateTypeName(e.url.split("/").pop()?.split("#").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join("")??"<UNKNOWN>")}generateFieldType(e){return e.enum?this.generateEnumType(e.binding?.name??e.type.name):this._generateTypeFromTypeRef(e.type)}generateType(e){return typeof e=="string"?this._generateTypeName(e):"url"in e?this._generateTypeFromTypeRef(e):this._generateTypeFromTypeRef(e.identifier)}generateField(e){return e=this._applyNameTransformations(e,this.nameTransformations.field),this.keywords.has(e)?`_${e}`:(e=this._replaceUnsaveChars(e),e)}generateEnumValue(e){return e=this._applyNameTransformations(e,this.nameTransformations.enumValue),this.keywords.has(e)?`_${e}`:(e=this._replaceUnsaveChars(e).toUpperCase(),e)}};var Oe=class{templateBaseDir;templateCache={};constructor(e){this.templateBaseDir=N__default.resolve(e);}_normalizeName(e){return e.endsWith(".mustache")?e:`${e}.mustache`}read(e){return this.readTemplate(e.source)}readTemplate(e){let t=this._normalizeName(e);return this.templateCache[t]||(this.templateCache[t]=x__default.readFileSync(N__default.join(this.templateBaseDir,t),"utf-8")),this.templateCache[t]}};var De=class i{static _array(e){return Array.isArray(e)?e:Array.from(e)}apply(e){return this._addListElementInformation(e)}_addListElementInformation(e){if(Array.isArray(e)||e instanceof Set)return i._array(e).map((t,r,n)=>typeof t=="object"&&t!==null?{...this._addListElementInformation(t),"-index":r,"-length":n.length,"-first":r===0,"-last":r===n.length-1}:t);if(e!==null&&typeof e=="object"){let t=e,r={};for(let[n,o]of Object.entries(t))r[n]=this._addListElementInformation(o);return r}return e}};var Zt=["boolean","instant","time","date","dateTime","decimal","integer","unsignedInt","positiveInt","integer64","base64Binary","uri","url","canonical","oid","uuid","string","code","markdown","id","xhtml"];var _e=class{constructor(e,t,r){this.tsIndex=e;this.nameGenerator=t;this.filterPred=r;}arrayMixinProvider=new De;createUtility(){return this._createForRoot()}createComplexType(e,t={resourcesByUri:{},complexTypesByUri:{}}){let r=this._createForComplexType(e,t),n=this._createParentsFor(r.schema,t),o=this._createChildrenFor(e,t),s=n.flatMap(a=>a.fields);return this.arrayMixinProvider.apply({...this._createForRoot(),...r,parents:n,children:o,inheritedFields:s,allFields:[...r.fields,...n.flatMap(a=>a.fields)],hasChildren:o.length>0,hasParents:n.length>0,hasInheritedFields:s.length>0})}createResource(e,t={resourcesByUri:{},complexTypesByUri:{}}){let r=this._createForResource(e,t),n=this._createParentsFor(r.schema,t),o=this._createChildrenFor(e,t),s=n.flatMap(a=>a.fields);return this.arrayMixinProvider.apply({...this._createForRoot(),...r,parents:n,children:o,inheritedFields:s,allFields:[...r.fields,...s],hasChildren:o.length>0,hasParents:n.length>0,hasInheritedFields:s.length>0})}_createFor(e,t,r){if(e.kind==="complex-type")return this._createForComplexType(e,t,r);if(e.kind==="resource")return this._createForResource(e,t,r);throw new Error(`Unknown type ${e.kind}`)}_createForComplexType(e,t,r){let n=this.tsIndex.resolve(e);if(!n)throw new Error(`ComplexType ${e.name} not found`);Object.hasOwn(t.complexTypesByUri,n.identifier.url)||(t.complexTypesByUri[n.identifier.url]=this._createTypeViewModel(n,t,r));let o=t.complexTypesByUri[n.identifier.url];if(!o)throw new Error(`ComplexType ${e.name} not found`);return o}_createForResource(e,t,r){let n=this.tsIndex.resolve(e);if(!n)throw new Error(`Resource ${e.name} not found`);Object.hasOwn(t.resourcesByUri,n.identifier.url)||(t.resourcesByUri[n.identifier.url]=this._createTypeViewModel(n,t,r));let o=t.resourcesByUri[n.identifier.url];if(!o)throw new Error(`Resource ${e.name} not found`);return o}_createChildrenFor(e,t,r){return Q(e)?this.tsIndex.resourceChildren(e).filter(Q).filter(this.filterPred).map(n=>this._createFor(n,t,r)):We(e)?this.tsIndex.resourceChildren(e).filter(We).filter(this.filterPred).map(n=>this._createFor(n,t,r)):[]}_createParentsFor(e,t){let r=[],n="base"in e?e.base:void 0;for(;n;){r.push(this._createFor(n,t,void 0));let o=this.tsIndex.resolve(n);n=o&&"base"in o?o.base:void 0;}return r}_createForNestedType(e,t,r){let n=this._createTypeViewModel(e,t,r),o=this._createParentsFor(e,t),s=this._createChildrenFor(e.identifier,t,r),a=o.flatMap(c=>c.fields);return {...n,parents:o,children:s,inheritedFields:a,allFields:[...n.fields,...a],hasChildren:s.length>0,hasParents:o.length>0,hasInheritedFields:a.length>0}}_createTypeViewModel(e,t,r){let n=Object.entries(("fields"in e?e.fields:{})??{}),o=this._collectNestedComplex(e,t),s=this._collectNestedEnums(n),a=this._collectDependencies(e),c={name:e.identifier.name,saveName:this.nameGenerator.generateType(e)};return {nestedComplexTypes:o,nestedEnums:s,dependencies:a,isNested:!!r,schema:e,...c,isResource:this._createIsResource(e.identifier),isComplexType:this._createIsComplexType(e.identifier),hasFields:n.length>0,hasNestedComplexTypes:o.length>0,hasNestedEnums:s.length>0,fields:n.filter(([l,p])=>!!p.type).sort((l,p)=>l[0].localeCompare(p[0])).map(([l,p])=>({owner:c,schema:p,name:l,saveName:this.nameGenerator.generateField(l),typeName:this.nameGenerator.generateFieldType(p),isArray:p.array,isRequired:p.required,isEnum:!!p.enum,isSizeConstrained:p.min!==void 0||p.max!==void 0,min:p.min,max:p.max,isResource:this._createIsResource(p.type),isComplexType:this._createIsComplexType(p.type),isPrimitive:this._createIsPrimitiveType(p.type),isCode:p.type?.name==="code",isIdentifier:p.type?.name==="Identifier",isReference:p.type?.name==="Reference"}))}}_collectDependencies(e){let t={resources:[],complexTypes:[]};return "dependencies"in e&&e.dependencies&&(e.dependencies.filter(r=>r.kind==="complex-type").map(r=>({name:r.name,saveName:this.nameGenerator.generateType(r)})).forEach(r=>{t.complexTypes.push(r);}),e.dependencies.filter(r=>r.kind==="resource").map(r=>({name:r.name,saveName:this.nameGenerator.generateType(r)})).forEach(r=>{t.resources.push(r);})),"nested"in e&&e.nested&&e.nested.map(r=>this._collectDependencies(r)).forEach(r=>{r.complexTypes.filter(n=>!t.complexTypes.some(o=>o.name===n.name)).forEach(n=>{t.complexTypes.push(n);}),r.resources.filter(n=>!t.resources.some(o=>o.name===n.name)).forEach(n=>{t.resources.push(n);});}),t}_createIsResource(e){return e.kind!=="resource"?false:Object.fromEntries(this.tsIndex.collectResources().map(t=>t.identifier).map(t=>[`is${t.name.charAt(0).toUpperCase()+t.name.slice(1)}`,t.url===e.url]))}_createIsComplexType(e){return e.kind!=="complex-type"&&e.kind!=="nested"?false:Object.fromEntries(this.tsIndex.collectComplexTypes().map(t=>t.identifier).map(t=>[`is${t.name.charAt(0).toUpperCase()+t.name.slice(1)}`,t.url===e.url]))}_createIsPrimitiveType(e){return e.kind!=="primitive-type"?false:Object.fromEntries(Zt.map(t=>[`is${t.charAt(0).toUpperCase()}${t.slice(1)}`,e.name===t]))}_collectNestedComplex(e,t){let r=[];return "nested"in e&&e.nested&&e.nested.map(n=>this._createForNestedType(n,t,e)).forEach(n=>{r.push(n);}),r}_collectNestedEnums(e){let t={};return e.forEach(([r,n])=>{if("enum"in n&&n.enum){let o=("binding"in n&&n.binding?.name)??r;typeof o=="string"&&(t[o]=t[o]??new Set,n.enum?.forEach(t[o].add.bind(t[o])));}}),Object.entries(t).map(([r,n])=>({name:r,saveName:this.nameGenerator.generateEnumType(r),values:Array.from(n).map(o=>({name:o,saveName:this.nameGenerator.generateEnumValue(o)}))}))}_createForRoot(){return this.arrayMixinProvider.apply({complexTypes:this.tsIndex.collectComplexTypes().map(e=>e.identifier).map(e=>({name:e.name,saveName:this.nameGenerator.generateType(e)})),resources:this.tsIndex.collectResources().map(e=>e.identifier).map(e=>({name:e.name,saveName:this.nameGenerator.generateType(e)}))})}};function ti(i,e){let t=N.resolve(i,"config.json");try{let r=x.readFileSync(t,"utf-8"),n=JSON.parse(r);if(n&&typeof n=="object")return n}catch{}return {}}var er=(i,e)=>{let t={debug:"OFF",hooks:{},meta:{},keywords:[],unsaveCharacterPattern:/[^a-zA-Z0-9]/g,nameTransformations:{common:[],enumValue:[],type:[],field:[]},renderings:{utility:[],resource:[],complexType:[]},shouldRunHooks:true,primitiveTypeMap:{}},r=ti(i),n={...t,...e,...r,sources:{staticSource:N.resolve(i,"static"),templateSource:N.resolve(i,"templates")}};return new ot(n)};function ri(i,e=[],t={}){return new Promise((r,n)=>{let o=spawn(i,e,{stdio:"inherit",...t});o.on("error",n),o.on("close",s=>{s===0?r(s):n(new Error(`Prozess beendet mit Fehlercode ${s}`));});})}var ot=class extends Z{templateFileCache;nameGenerator;lambdaMixinProvider;debugMixinProvider;constructor(e){super(e),this.nameGenerator=new Me(new Set(e.keywords),e.primitiveTypeMap,e.nameTransformations,e.unsaveCharacterPattern),this.templateFileCache=new Oe(e.sources.templateSource),this.lambdaMixinProvider=new Ne(this.nameGenerator),this.debugMixinProvider=e.debug!=="OFF"?new Ee(e.debug):void 0;}async generate(e){let t=new _e(e,this.nameGenerator,()=>true),r={resourcesByUri:{},complexTypesByUri:{}};e.collectComplexTypes().map(n=>n.identifier).sort((n,o)=>n.url.localeCompare(o.url)).map(n=>t.createComplexType(n,r)).forEach(this._renderComplexType.bind(this)),e.collectResources().map(n=>n.identifier).sort((n,o)=>n.url.localeCompare(o.url)).map(n=>t.createResource(n,r)).forEach(this._renderResource.bind(this)),this._renderUtility(t.createUtility()),this.copyStaticFiles(),this.opts.shouldRunHooks&&await this._runHooks(this.opts.hooks.afterGenerate);}copyStaticFiles(){let e=N.resolve(this.opts.sources.staticSource);if(!e)throw new Error("staticDir must be set in subclass.");x.cpSync(e,this.opts.outputDir,{recursive:true});}async _runHooks(e){for(let t of e??[])console.info(`Running hook (${this.opts.outputDir}): ${t.cmd} ${t.args?.join(" ")}`),await ri(t.cmd,t.args??[],{cwd:this.opts.outputDir}),console.info(`Completed hook: ${t.cmd} ${t.args?.join(" ")}`);}_checkRenderingFilter(e,t){return !t.filter?.whitelist?.length&&!t.filter?.blacklist?.length?true:(t.filter?.blacklist??[]).find(r=>e.name.match(r))?false:(t.filter?.whitelist??[]).find(r=>e.name.match(r))?true:!t.filter.whitelist?.length}_renderUtility(e){this.opts.renderings.utility.forEach(t=>{this.cd(t.path,()=>{this.cat(t.fileNameFormat,()=>{this.write(this._render(e,t));});});});}_renderResource(e){this.opts.renderings.resource.filter(t=>this._checkRenderingFilter(e,t)).forEach(t=>{this.cd(t.path,()=>{this.cat(this._calculateFilename(e,t),()=>{this.write(this._render(e,t));});});});}_renderComplexType(e){this.opts.renderings.complexType.filter(t=>this._checkRenderingFilter(e,t)).forEach(t=>{this.cd(t.path,()=>{this.cat(this._calculateFilename(e,t),()=>{this.write(this._render(e,t));});});});}_calculateFilename(e,t){return Qt.format(t.fileNameFormat,e.saveName)}_render(e,t){let r=this.lambdaMixinProvider.apply({meta:{timestamp:this.opts.meta.timestamp??new Date().toISOString(),generator:this.opts.meta.generator??"@atomic-ehr/codegen mustache generator"},model:e,properties:t.properties??{}});return this.debugMixinProvider&&(r=this.debugMixinProvider.apply(r)),ei.render(this.templateFileCache.read(t),r,n=>this.templateFileCache.readTemplate(n))}};var ni={boolean:"boolean",instant:"string",time:"string",date:"string",dateTime:"string",decimal:"number",integer:"number",unsignedInt:"number",positiveInt:"number",integer64:"number",base64Binary:"string",uri:"string",url:"string",canonical:"string",oid:"string",uuid:"string",string:"string",code:"string",markdown:"string",id:"string",xhtml:"string"},tr=i=>{let e=ni[i];if(e===void 0)throw new Error(`Unknown primitive type ${i}`);return e},ir=i=>me(i),ct=i=>i.kind==="profile"?`${R(i)}_profile`:k(i.name),oi=i=>`${ct(i)}.ts`,Ve=i=>`${ir(i.package)}/${ct(i)}`,st=(i,e=true)=>{if(!i)return;let t=ge(i,e);if(t)return at(t)},R=i=>{if(i.kind==="nested"){let e=i.url,t=st(e,false);if(!t)return "";let[r,n]=t.split("#"),o=Y((n??"").split(".")).join("");return at([r,o].join(""))}return at(i.name)},nr=new Set(["class","function","return","if","for","while","const","let","var","import","export","interface"]),X=i=>nr.has(i)?`"${i}"`:i.includes(" ")||i.includes("-")?`"${i}"`:i,at=i=>(nr.has(i)&&(i=`${i}_`),i.replace(/[- ]/g,"_")),q=(i,e)=>e.startsWith('"')?`${i}[${e}]`:`${i}.${e}`,rr=i=>`(${i.map(e=>`"${e}"`).join(" | ")})`,Be=class extends V{tsImportType(e,...t){this.lineSM(`import type { ${t.join(", ")} } from "${e}"`);}generateFhirPackageIndexFile(e){this.cat("index.ts",()=>{let t=e.flatMap(r=>[{identifier:r.identifier,tsPackageName:ct(r.identifier),resourceName:R(r.identifier),nestedTypes:O(r)&&r.nested||j(r)&&r.nested?r.nested.map(n=>R(n.identifier)):[],helpers:O(r)||j(r)?[`is${R(r.identifier)}`]:[]}]).sort((r,n)=>r.resourceName.localeCompare(n.resourceName));t=Array.from(new Map(t.map(r=>[r.resourceName.toLowerCase(),r])).values()).sort((r,n)=>r.resourceName.localeCompare(n.resourceName));for(let r of t)this.debugComment(r.identifier),this.lineSM(`export type { ${[r.resourceName,...r.nestedTypes].join(", ")} } from "./${r.tsPackageName}"`),r.helpers.length>0&&this.lineSM(`export { ${r.helpers.join(", ")} } from "./${r.tsPackageName}"`);});}generateDependenciesImports(e,t){if(t.dependencies){let r=[],n=[];for(let o of t.dependencies)if(["complex-type","resource","logical"].includes(o.kind))r.push({tsPackage:`../${Ve(o)}`,name:E(o.name),dep:o});else if(M(o)){let s={...o};s.name=st(o.url),r.push({tsPackage:`../${Ve(s)}`,name:R(o),dep:o});}else n.push(o);r.sort((o,s)=>o.name.localeCompare(s.name));for(let o of r)this.debugComment(o.dep),this.tsImportType(o.tsPackage,o.name);for(let o of n)this.debugComment("skip:",o);if(this.line(),this.withPrimitiveTypeExtension(t)&&t.identifier.name!=="Element"&&t.dependencies.find(o=>o.name==="Element")===void 0){let o="http://hl7.org/fhir/StructureDefinition/Element",s=e.resolveByUrl(t.identifier.package,o);if(!s)throw new Error(`'${o}' not found for ${t.identifier.package}.`);this.tsImportType(`../${Ve(s.identifier)}`,"Element");}}}generateComplexTypeReexports(e){let t=e.dependencies?.filter(Q).map(r=>({tsPackage:`../${Ve(r)}`,name:E(r.name)}));if(t&&t.length>0){for(let r of t)this.lineSM(`export type { ${r.name} } from "${r.tsPackage}"`);this.line();}}addFieldExtension(e){let t=X(`_${e}`);this.lineSM(`${t}?: Element`);}generateType(e,t){let r;t.identifier.name==="Reference"?r="Reference<T extends string = string>":(t.identifier.kind,r=R(t.identifier));let n;if(t.base&&(n=`extends ${st(t.base.url)}`),this.debugComment(t.identifier),!t.fields&&!n&&!O(t)){this.lineSM(`export type ${r} = object`);return}this.curlyBlock(["export","interface",r,n],()=>{if(O(t)||j(t)){let s=[t.identifier];s.push(...e.resourceChildren(t.identifier));let a=this.opts.openResourceTypeSet&&s.length>1?" | string":"";this.lineSM(`resourceType: ${s.sort((c,l)=>c.name.localeCompare(l.name)).map(c=>`"${c.name}"`).join(" | ")}${a}`),this.line();}if(!t.fields)return;let o=Object.entries(t.fields).sort((s,a)=>s[0].localeCompare(a[0]));for(let[s,a]of o){if(P(a))continue;this.debugComment(s,":",a);let c=X(s),l;a.enum?l=rr(a.enum):t.identifier.name==="Reference"&&c==="reference"?l="`${T}/${string}`":a.reference&&a.reference.length>0?l=`Reference<${a.reference.map(d=>`"${d.name}"`).join(" | ")}>`:ee(a.type)?l=tr(a.type.name):M(a.type)?l=R(a.type):l=a.type.name;let p=a.required?"":"?",f=a.array?"[]":"";this.lineSM(`${c}${p}: ${l}${f}`),this.withPrimitiveTypeExtension(t)&&ee(a.type)&&this.addFieldExtension(s);}});}withPrimitiveTypeExtension(e){if(!this.opts.primitiveTypeExtension||!B(e))return false;for(let t of Object.values(e.fields??{}))if(!P(t)&&ee(t.type))return true;return false}generateResourceTypePredicate(e){if(!O(e)&&!j(e))return;let t=R(e.identifier);this.curlyBlock(["export","const",`is${t}`,"=",`(resource: unknown): resource is ${t}`,"=>"],()=>{this.lineSM(`return resource !== null && typeof resource === "object" && (resource as {resourceType: string}).resourceType === "${e.identifier.name}"`);});}generateNestedTypes(e,t){if(t.nested)for(let r of t.nested)this.generateType(e,r),this.line();}generateProfileType(e,t){this.debugComment("flatProfile",t);let r=R(t.identifier);this.debugComment("identifier",t.identifier),this.debugComment("base",t.base),this.curlyBlock(["export","interface",r],()=>{this.lineSM(`__profileUrl: "${t.identifier.url}"`),this.line();for(let[n,o]of Object.entries(t.fields??{})){if(P(o))continue;this.debugComment(n,o);let s=X(n),a;if(o.enum)a=rr(o.enum);else if(o.reference&&o.reference.length>0){let c=e.findLastSpecialization(t);if(!B(c))throw new Error(`Invalid specialization for ${t.identifier}`);let l=c.fields?.[n];if(l===void 0||P(l)||l.reference===void 0)throw new Error(`Invalid field declaration for ${n}`);let p=l.reference.map(y=>y.name),f=o.reference.map(y=>{let d=e.findLastSpecializationByIdentifier(y);return d.name!==y.name?`"${d.name}" /*${y.name}*/`:`'${y.name}'`}).join(" | ");p.length===1&&p[0]==="Resource"&&f!=='"Resource"'?a=`Reference<"Resource" /* ${f} */ >`:a=`Reference<${f}>`;}else if(M(o.type))a=R(o.type);else if(ee(o.type))a=tr(o.type.name);else {if(o.type===void 0)throw new Error(`Undefined type for '${n}' field at ${vt(t)}`);a=o.type.name;}this.lineSM(`${s}${o.required?"":"?"}: ${a}${o.array?"[]":""}`);}}),this.line();}generateAttachProfile(e){let t=R(e.base),r=R(e.identifier),n=Object.entries(e.fields||{}).filter(([o,s])=>s&&H(s)&&s.type!==void 0).map(([o])=>X(o));this.curlyBlock([`export const attach_${r}_to_${t} =`,`(resource: ${t}, profile: ${r}): ${t}`,"=>"],()=>{this.curlyBlock(["return"],()=>{this.line("...resource,"),this.curlyBlock(["meta:"],()=>{this.line(`profile: ['${e.identifier.url}']`);},[","]),n.forEach(o=>{this.line(`${o}: ${q("profile",o)},`);});});}),this.line();}generateExtractProfile(e,t){let r=R(t.base),n=R(t.identifier),o=Object.entries(t.fields||{}).filter(([c,l])=>H(l)&&l.type!==void 0).map(([c])=>c),s=e.findLastSpecialization(t);if(!B(s))throw new Error(`Specialization not found for ${t.identifier.url}`);let a={};this.curlyBlock([`export const extract_${n}_from_${r} =`,`(resource: ${r}): ${n}`,"=>"],()=>{o.forEach(c=>{let l=X(c),p=t.fields?.[c],f=s.fields?.[c];if(!H(p)||!H(f))return;p.required&&!f.required&&this.curlyBlock([`if (${q("resource",l)} === undefined)`],()=>this.lineSM(`throw new Error("'${l}' is required for ${t.identifier.url}")`));let y=p?.reference?.map(g=>g.name),d=f?.reference?.map(g=>g.name);if(y&&d&&y.length!==d.length){let g=`reference_is_valid_${l}`;this.curlyBlock(["const",g,"=","(ref?: Reference)","=>"],()=>{this.line("return !ref"),this.indentBlock(()=>{d.forEach(u=>{this.line(`|| ref.reference?.startsWith('${u}/')`);}),this.line(";");});});let h=p?.required?"":`!${q("resource",l)} || `;p.array?h+=`${q("resource",l)}.every( (ref) => ${g}(ref) )`:h+=`!${g}(${q("resource",l)})`,this.curlyBlock(["if (",h,")"],()=>{this.lineSM(`throw new Error("'${c}' has different references in profile and specialization")`);}),this.line(),a[c]=true;}}),this.curlyBlock(["return"],()=>{this.line(`__profileUrl: '${t.identifier.url}',`),o.forEach(c=>{let l=X(c);a[c]?this.line(`${l}:`,`${q("resource",l)} as ${n}['${l}'],`):this.line(`${l}:`,`${q("resource",l)},`);});});});}generateResourceModule(e,t){this.cat(`${oi(t.identifier)}`,()=>{if(this.generateDisclaimer(),["complex-type","resource","logical"].includes(t.identifier.kind))this.generateDependenciesImports(e,t),this.generateComplexTypeReexports(t),this.generateNestedTypes(e,t),this.comment("CanonicalURL:",t.identifier.url),this.generateType(e,t),this.generateResourceTypePredicate(t);else if(he(t)){let r=e.flatProfile(t);this.generateDependenciesImports(e,r),this.comment("CanonicalURL:",t.identifier.url),this.generateProfileType(e,r),this.generateAttachProfile(r),this.generateExtractProfile(e,r);}else throw new Error(`Profile generation not implemented for kind: ${t.identifier.kind}`)});}async generate(e){let t=[...e.collectComplexTypes(),...e.collectResources(),...e.collectLogicalModels(),...this.opts.generateProfile?e.collectProfiles().filter(n=>e.isWithMetaField(n)):[]],r=z(t);this.cd("/",()=>{for(let[n,o]of Object.entries(r)){let s=ir(n);this.cd(s,()=>{for(let a of o)this.generateResourceModule(e,a);this.generateFhirPackageIndexFile(o);});}});}};var or=i=>{let e=i.replace(/[^a-zA-Z0-9\-_.@#()]/g,"");return e.length===0?"unknown":e},ai=async(i,e)=>{e.info("Cleaning outputs...");try{e.info(`Clean ${i.outputDir}`),x.rmSync(i.outputDir,{recursive:!0,force:!0}),i.typeSchemaOutputDir&&(e.info(`Clean ${i.typeSchemaOutputDir}`),x.rmSync(i.typeSchemaOutputDir,{recursive:!0,force:!0})),i.exportTypeTree&&(e.info(`Clean ${i.exportTypeTree}`),x.rmSync(i.exportTypeTree,{recursive:!0,force:!0}));}catch(t){e.warn(`Error cleaning output directory: ${t instanceof Error?t.message:String(t)}`);}},ci=async(i,e,t)=>{await U.mkdir(e,{recursive:true}),t.info(`Writing TypeSchema files to ${e}/...`);let r={};for(let n of i){let o={name:n.identifier.package,version:n.identifier.version},s=or(b(o)),a=or(`${n.identifier.name}(${ge(n.identifier.url)})`),c=JSON.stringify(n,null,2),l=N.join(e,s,a);r[l]||(r[l]=[]),r[l]?.some(p=>p===c)||r[l].push(c);}for(let[n,o]of Object.entries(r))await Promise.all(o.map(async(s,a)=>{let c;a===0?c=`${n}.typeschema.json`:c=`${n}-${a}.typeschema.json`,await U.mkdir(N.dirname(c),{recursive:true}),await U.writeFile(c,s);}));},li=async(i,e,t)=>{t.info(`Writing TypeSchema files to: ${e}`),await U.mkdir(N.dirname(e),{recursive:true}),t.info(`Writing TypeSchemas to one file ${e}...`);for(let r of i){let n=JSON.stringify(r,null,2);await U.appendFile(e,`${n}
|
|
7
|
-
`);}},pi=async(i,e,t)=>{if(e.typeSchemaOutputDir)try{N.extname(e.typeSchemaOutputDir)===".ndjson"?await li(i,e.typeSchemaOutputDir,t):await ci(i,e.typeSchemaOutputDir,t),t.info("Writing TypeSchema - DONE");}catch(r){if(t.error("Failed to write TypeSchema output",r instanceof Error?r:new Error(String(r))),e.throwException)throw r}},ce=class{schemas=[];options;generators=new Map;logger;packages=[];localStructurePackages=[];localTgzArchives=[];progressCallback;typeSchemaConfig;constructor(e={}){this.options={outputDir:e.outputDir||"./generated",overwrite:e.overwrite??true,cache:e.cache??true,cleanOutput:e.cleanOutput??true,typeSchemaConfig:e.typeSchemaConfig,manager:e.manager||null,throwException:e.throwException||false,typeSchemaOutputDir:e.typeSchemaOutputDir,exportTypeTree:e.exportTypeTree,treeShake:e.treeShake,registry:e.registry},this.typeSchemaConfig=e.typeSchemaConfig,this.logger=e.logger||L({prefix:"API",level:e.logLevel});}fromPackage(e,t){let r=fe({name:e,version:t||"latest"});return this.packages.push(r),this}fromPackageRef(e){return this.packages.push(e),this}registry(e){return this.options.registry=e,this}localStructureDefinitions(e){return this.localStructurePackages.push(e),this}localTgzPackage(e){return this.localTgzArchives.push(N.resolve(e)),this}fromSchemas(e){return this.logger.debug(`Adding ${e.length} TypeSchemas to generation`),this.schemas=[...this.schemas,...e],this}typescript(e){let n={...{...{logger:this.logger,outputDir:N.join(this.options.outputDir,"/types"),tabSize:4,withDebugComment:false,commentLinePrefix:"//",generateProfile:true},openResourceTypeSet:false,primitiveTypeExtension:true},...Object.fromEntries(Object.entries(e).filter(([s,a])=>a!==void 0))},o=new Be(n);return this.generators.set("typescript",o),this.logger.debug(`Configured TypeScript generator (${JSON.stringify(n,void 0,2)})`),this}python(e){let n={...{...{logger:this.logger,outputDir:this.options.outputDir,tabSize:4,withDebugComment:false,commentLinePrefix:"#"},rootPackageName:"fhir_types",fieldFormat:"snake_case"},...Object.fromEntries(Object.entries(e).filter(([s,a])=>a!==void 0))},o=new Ce(n);return this.generators.set("python",o),this.logger.debug("Configured python generator"),this}mustache(e,t){let r={logger:this.logger,outputDir:this.options.outputDir},n={meta:{timestamp:new Date().toISOString(),generator:"atomic-codegen"}},o={...r,...n,...t},s=er(e,o);return this.generators.set(`mustache[${e}]`,s),this.logger.debug(`Configured TypeScript generator (${JSON.stringify(o,void 0,2)})`),this}csharp(e){let n={...{...{logger:this.logger,outputDir:N.join(this.options.outputDir,"/types"),tabSize:4,withDebugComment:false,commentLinePrefix:"//"},rootNamespace:"Fhir.Types"},...Object.fromEntries(Object.entries(e).filter(([s,a])=>a!==void 0))},o=new Se(n);return this.generators.set("csharp",o),this.logger.debug("Configured C# generator"),this}onProgress(e){return this.progressCallback=e,this}outputTo(e){this.logger.debug(`Setting output directory: ${e}`),this.options.outputDir=e;for(let t of this.generators.values())t.setOutputDir(e);return this}setLogLevel(e){return this.logger?.setLevel(typeof e=="string"?gt(e):e),this}throwException(e=true){return this.options.throwException=e,this}cleanOutput(e=true){return this.options.cleanOutput=e,this}writeTypeTree(e){return this.options.exportTypeTree=e,this}treeShake(e){return this.options.treeShake=e,this}writeTypeSchemas(e){return this.options.typeSchemaOutputDir=e,this}async generate(){let e=performance.now(),t={success:false,outputDir:this.options.outputDir,filesGenerated:{},errors:[],warnings:[],duration:0};this.logger.debug(`Starting generation with ${this.generators.size} generators`);try{this.options.cleanOutput&&ai(this.options,this.logger),this.logger.info("Initialize Canonical Manager");let r=this.options.manager||CanonicalManager({packages:this.packages,workingDir:".codegen-cache/canonical-manager-cache",registry:this.options.registry||void 0});if(this.localStructurePackages.length>0)for(let p of this.localStructurePackages)this.logger.info(`Registering local StructureDefinitions for ${p.package.name}@${p.package.version}`),await r.addLocalPackage({name:p.package.name,version:p.package.version,path:p.path,dependencies:p.dependencies?.map(f=>fe(f))});for(let p of this.localTgzArchives)this.logger.info(`Registering local tgz package: ${p}`),await r.addTgzPackage({archivePath:p});let n=await r.init(),o=Object.values(n),s=await ie(r,{logger:this.logger,focusedPackages:o}),a=await Kt(s,this.logger);await pi(a,this.options,this.logger);let c={resolutionTree:s.resolutionTree(),logger:this.logger},l=be(a,c);this.options.treeShake&&(l=Yt(l,this.options.treeShake,c)),this.options.exportTypeTree&&await l.exportTree(this.options.exportTypeTree),this.logger.debug(`Executing ${this.generators.size} generators`),await this.executeGenerators(t,l),this.logger.info("Generation completed successfully"),t.success=t.errors.length===0,this.logger.debug(`Generation completed: ${t.filesGenerated.length} files`);}catch(r){if(this.logger.error("Code generation failed",r instanceof Error?r:new Error(String(r))),t.errors.push(r instanceof Error?r.message:String(r)),this.options.throwException)throw r}return {...t,success:t.errors.length===0,duration:performance.now()-e}}reset(){return this.schemas=[],this.generators.clear(),this.progressCallback=void 0,this.packages=[],this.localStructurePackages=[],this.localTgzArchives=[],this}getSchemas(){return [...this.schemas]}getGenerators(){return Array.from(this.generators.keys())}async executeGenerators(e,t){for(let[r,n]of this.generators.entries()){this.logger.info(`Generating ${r}...`);try{await n.generate(t),n.writtenFiles().forEach(s=>{e.filesGenerated[s.relPath]=s.content;}),this.logger.info(`Generating ${r} finished successfully`);}catch(o){if(e.errors.push(`${r} generator failed: ${o instanceof Error?o.message:String(o)}`),this.options.throwException)throw o}}}};var lt={outputDir:"./generated",verbose:false,overwrite:true,validate:true,cache:true,cleanOutput:true,registry:"",typescript:{moduleFormat:"esm",generateIndex:true,includeDocuments:false,namingConvention:"PascalCase",strictMode:true,includeProfiles:true,includeExtensions:false,includeCodeSystems:false,includeOperations:false,generateValueSets:false,valueSetDirectory:"valuesets",valueSetMode:"required-only",valueSetStrengths:["required"],includeValueSetHelpers:false,fhirVersion:"R4",resourceTypes:[],maxDepth:10,profileOptions:{generateKind:"interface",includeConstraints:true,includeDocumentation:true,strictMode:false,subfolder:"profiles"},generateBuilders:false,builderOptions:{includeValidation:true,includeFactoryMethods:true,includeInterfaces:true,generateNestedBuilders:true,includeHelperMethods:true,supportPartialBuild:true,includeJSDoc:true,generateFactories:true,includeTypeGuards:true,handleChoiceTypes:true,generateArrayHelpers:true},validatorOptions:{includeCardinality:true,includeTypes:true,includeConstraints:true,includeInvariants:false,validateRequired:true,allowAdditional:false,strictValidation:false,collectMetrics:false,generateAssertions:true,generatePartialValidators:true,optimizePerformance:true,includeJSDoc:true,generateCompositeValidators:true},guardOptions:{includeRuntimeValidation:true,includeErrorMessages:true,treeShakeable:true,targetTSVersion:"5.0",strictGuards:false,includeNullChecks:true,verbose:false}},typeSchema:{enablePersistence:true,cacheDir:".typeschema-cache",maxAge:1440*60*1e3,validateCached:true,forceRegenerate:false,shareCache:true,cacheKeyPrefix:"",treeshake:[],singleFile:false,profiles:{autoDetect:true}},packages:[],files:[],$schema:""},Ue=["atomic-codegen.config.ts","atomic-codegen.config","atomic-codegen.config.json",".atomic-codegenrc","atomic-codegen.json",".atomic-codegen.json","codegen.config.json","codegen.json"],pt=class{validate(e){let t={valid:true,errors:[],warnings:[]};if(!e||typeof e!="object")return t.valid=false,t.errors.push({path:"root",message:"Configuration must be an object",value:e}),t;let r=e;r.outputDir!==void 0&&typeof r.outputDir!="string"&&t.errors.push({path:"outputDir",message:"outputDir must be a string",value:r.outputDir});let n=["verbose","overwrite","validate","cache"];for(let o of n)r[o]!==void 0&&typeof r[o]!="boolean"&&t.errors.push({path:o,message:`${o} must be a boolean`,value:r[o]});if(r.typescript!==void 0){let o=this.validateTypeScriptConfig(r.typescript);t.errors.push(...o);}if(r.typeSchema!==void 0){let o=this.validateTypeSchemaConfig(r.typeSchema);t.errors.push(...o);}return r.packages!==void 0&&(Array.isArray(r.packages)?r.packages.forEach((o,s)=>{typeof o!="string"&&t.errors.push({path:`packages[${s}]`,message:"package name must be a string",value:o});}):t.errors.push({path:"packages",message:"packages must be an array",value:r.packages})),r.files!==void 0&&(Array.isArray(r.files)?r.files.forEach((o,s)=>{typeof o!="string"&&t.errors.push({path:`files[${s}]`,message:"file path must be a string",value:o});}):t.errors.push({path:"files",message:"files must be an array",value:r.files})),t.valid=t.errors.length===0,t.valid&&(t.config=r),t}validateTypeScriptConfig(e){let t=[];if(typeof e!="object"||e===null)return t.push({path:"typescript",message:"typescript config must be an object",value:e}),t;let r=e;r.moduleFormat!==void 0&&(["esm","cjs"].includes(r.moduleFormat)||t.push({path:"typescript.moduleFormat",message:'moduleFormat must be "esm" or "cjs"',value:r.moduleFormat})),r.namingConvention!==void 0&&(["PascalCase","camelCase"].includes(r.namingConvention)||t.push({path:"typescript.namingConvention",message:'namingConvention must be "PascalCase" or "camelCase"',value:r.namingConvention}));let n=["generateIndex","includeDocuments","strictMode","includeProfiles","includeExtensions","includeCodeSystems","includeOperations","generateValueSets","includeValueSetHelpers"];for(let o of n)r[o]!==void 0&&typeof r[o]!="boolean"&&t.push({path:`typescript.${o}`,message:`${o} must be a boolean`,value:r[o]});if(r.validatorOptions!==void 0){let o=this.validateValidatorOptions(r.validatorOptions);t.push(...o);}if(r.guardOptions!==void 0){let o=this.validateGuardOptions(r.guardOptions);t.push(...o);}if(r.profileOptions!==void 0){let o=this.validateProfileOptions(r.profileOptions);t.push(...o);}return t}validateValidatorOptions(e){let t=[];if(typeof e!="object"||e===null)return t.push({path:"typescript.validatorOptions",message:"validatorOptions must be an object",value:e}),t;let r=e,n=["includeCardinality","includeTypes","includeConstraints","includeInvariants","validateRequired","allowAdditional","strictValidation","collectMetrics","generateAssertions","generatePartialValidators","optimizePerformance","includeJSDoc","generateCompositeValidators"];for(let o of n)r[o]!==void 0&&typeof r[o]!="boolean"&&t.push({path:`typescript.validatorOptions.${o}`,message:`${o} must be a boolean`,value:r[o]});return t}validateGuardOptions(e){let t=[];if(typeof e!="object"||e===null)return t.push({path:"typescript.guardOptions",message:"guardOptions must be an object",value:e}),t;let r=e;r.targetTSVersion!==void 0&&(["3.8","4.0","4.5","5.0"].includes(r.targetTSVersion)||t.push({path:"typescript.guardOptions.targetTSVersion",message:'targetTSVersion must be one of: "3.8", "4.0", "4.5", "5.0"',value:r.targetTSVersion}));let n=["includeRuntimeValidation","includeErrorMessages","treeShakeable","strictGuards","includeNullChecks","verbose"];for(let o of n)r[o]!==void 0&&typeof r[o]!="boolean"&&t.push({path:`typescript.guardOptions.${o}`,message:`${o} must be a boolean`,value:r[o]});return t}validateProfileOptions(e){let t=[];if(typeof e!="object"||e===null)return t.push({path:"typescript.profileOptions",message:"profileOptions must be an object",value:e}),t;let r=e;r.generateKind!==void 0&&(["interface","type","both"].includes(r.generateKind)||t.push({path:"typescript.profileOptions.generateKind",message:'generateKind must be "interface", "type", or "both"',value:r.generateKind})),r.subfolder!==void 0&&typeof r.subfolder!="string"&&t.push({path:"typescript.profileOptions.subfolder",message:"subfolder must be a string",value:r.subfolder});let n=["includeConstraints","includeDocumentation","strictMode"];for(let o of n)r[o]!==void 0&&typeof r[o]!="boolean"&&t.push({path:`typescript.profileOptions.${o}`,message:`${o} must be a boolean`,value:r[o]});return t}validateTypeSchemaConfig(e){let t=[];if(typeof e!="object"||e===null)return t.push({path:"typeSchema",message:"typeSchema config must be an object",value:e}),t;let r=e,n=["enablePersistence","validateCached","forceRegenerate","shareCache"];for(let s of n)r[s]!==void 0&&typeof r[s]!="boolean"&&t.push({path:`typeSchema.${s}`,message:`${s} must be a boolean`,value:r[s]});let o=["cacheDir","cacheKeyPrefix"];for(let s of o)r[s]!==void 0&&typeof r[s]!="string"&&t.push({path:`typeSchema.${s}`,message:`${s} must be a string`,value:r[s]});if(r.maxAge!==void 0&&(typeof r.maxAge!="number"||r.maxAge<=0)&&t.push({path:"typeSchema.maxAge",message:"maxAge must be a positive number",value:r.maxAge}),r.profiles!==void 0)if(typeof r.profiles!="object"||r.profiles===null)t.push({path:"typeSchema.profiles",message:"profiles must be an object",value:r.profiles});else {let s=r.profiles;s.autoDetect!==void 0&&typeof s.autoDetect!="boolean"&&t.push({path:"typeSchema.profiles.autoDetect",message:"autoDetect must be a boolean",value:s.autoDetect});}return t}},dt=class{validator=new pt;async autoload(e=process.cwd()){let t=await this.findConfigFile(e);return t?this.loadFromFile(t):{...lt}}async loadFromFile(e){try{let t;if(e.endsWith(".ts")||e.endsWith("")){let o=await import(resolve(e));t=o.default||o;}else {let n=await readFile(e,"utf-8");t=JSON.parse(n);}let r=this.validator.validate(t);if(!r.valid){let n=r.errors.map(o=>`${o.path}: ${o.message}`).join(`
|
|
8
|
-
`);throw new Error(`Configuration validation failed:
|
|
9
|
-
${n}`)}if(!r.config)throw new Error("Invalid configuration");return this.mergeWithDefaults(r.config)}catch(t){throw t instanceof Error?new Error(`Failed to load config from ${e}: ${t.message}`):t}}async findConfigFile(e){for(let t of Ue){let r=resolve(e,t);if(existsSync(r))return r}return null}mergeWithDefaults(e){return {...lt,...e,typescript:{...lt.typescript,...e.typescript}}}},gi=new dt;async function Ae(i){return gi.autoload(i)}var ar={command:"generate",describe:"Generate code based on configuration file settings",builder:i=>i.option("verbose",{alias:"v",type:"boolean",default:false,description:"Enable verbose output"}).example("$0 generate","Generate code using settings from config file").example("$0 generate --verbose","Generate with verbose output"),handler:async i=>{if(i._.length>1){let s=i._.slice(1).join(" ");w(`Invalid syntax: 'atomic-codegen generate ${s}'
|
|
10
|
-
|
|
11
|
-
The CLI has been simplified and no longer uses subcommands.
|
|
12
|
-
|
|
13
|
-
\u2705 Use: atomic-codegen generate
|
|
14
|
-
\u274C Old: atomic-codegen generate typescript
|
|
15
|
-
|
|
16
|
-
All generation settings are now configured in your config file.
|
|
17
|
-
Create an atomic-codegen.config.ts file to get started.`),process.exit(1);}let e=process.cwd(),t=await yi(e);if(!t){let s=Ue.map(a=>` - ${a}`).join(`
|
|
18
|
-
`);w(`No configuration file found. Please create one of the following files in your project root:
|
|
19
|
-
${s}
|
|
20
|
-
|
|
21
|
-
Example atomic-codegen.config.ts:
|
|
22
|
-
|
|
23
|
-
import { defineConfig } from '@atomic-ehr/codegen';
|
|
24
|
-
|
|
25
|
-
export default defineConfig({
|
|
26
|
-
packages: ['hl7.fhir.r4.core@4.0.1'],
|
|
27
|
-
typescript: {
|
|
28
|
-
generateIndex: true
|
|
29
|
-
}
|
|
30
|
-
});`),process.exit(1);}let r=await Ae(e),n=i.verbose??r.verbose??false,o=L({prefix:"Generate"});try{ht("Starting generation from config"),n&&(o.info(`Config file: ${t}`),o.info(`Output directory: ${r.outputDir||"./generated"}`),o.info(`Packages: ${r.packages?.length||0}`),o.info(`Files: ${r.files?.length||0}`),o.info(`TypeScript generation: ${r.typescript?"enabled":"disabled"}`));let s=new ce({outputDir:r.outputDir||"./generated",overwrite:r.overwrite??!0,cache:r.cache??!0,typeSchemaConfig:r.typeSchema,logger:o});if(r.packages&&r.packages.length>0){o.info(`Loading packages from config: ${r.packages.join(", ")}`);for(let c of r.packages){let[l,p]=c.includes("@")?c.split("@"):[c,void 0];s.fromPackage(l,p);}}else throw r.files&&r.files.length>0?(o.info(`Loading files from config: ${r.files.join(", ")}`),new Error("Not Implemented")):new Error("No data source specified in config. Please configure 'packages' or 'files' in your config file.");if(r.typescript)throw new Error("Not Implemented");if(!r.typescript)throw new Error("No generators configured. Please enable 'typescript' in your config file.");n&&s.onProgress((c,l,p,f)=>{let y=Math.round(l/p*100);o.progress(`[${c}] ${y}% - ${f||"Processing..."}`);}),o.step("Executing generation...");let a=await s.generate();if(a.success){if(Ge(`Generated ${a.filesGenerated.length} files in ${a.duration.toFixed(2)}ms`),o.dim(`Output directory: ${a.outputDir}`),a.warnings.length>0)for(let c of a.warnings)ft(c);}else {w(`Generation failed with ${a.errors.length} errors`);for(let c of a.errors)o.dim(` ${c}`);process.exit(1);}}catch(s){w("Generation failed with unexpected error",s instanceof Error?s:new Error(String(s))),process.exit(1);}}};async function yi(i){for(let e of Ue){let t=resolve(i,e);if(existsSync(t))return t}return null}var cr={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 i=>{let e=L({prefix:"TypeSchema"});try{let t=await Ae(process.cwd());e.step("Generating TypeSchema from FHIR packages"),e.info(`Packages: ${i.packages.join(", ")}`),e.info(`Output: ${i.output}`);let r=i.singleFile!==void 0?i.singleFile:t.typeSchema?.singleFile??!1,n=r?"ndjson":i.format;e.debug(`Format: ${n}${r&&i.format==="json"?" (forced from json due to singleFile)":""}`);let o=i.treeshake&&i.treeshake.length>0?i.treeshake:t.typeSchema?.treeshake;o&&o.length>0&&e.info(`Treeshaking enabled for ResourceTypes: ${o.join(", ")}`),r&&e.info("Single file output enabled (NDJSON format)");let s=i.registry||t.registry;s&&e.info(`Using custom registry: ${s}`);let a=Date.now(),c=new ne({treeshake:o,registry:s,manager:CanonicalManager({packages:[],workingDir:".codegen-cache/canonical-manager-cache",registry:s})}),l=[];for(let d of i.packages){let[g,h]=d.includes("@")?d.split("@"):[d,void 0];e.progress(`Processing package: ${g}${h?`@${h}`:""}`);let u=await c.generateFromPackage(g,h,e);l.push(...u);}if(l.length===0)throw new Error("No schemas were generated from the specified packages");let p=i.output;if(!p)throw new Error("Output format not specified");await mkdir(dirname(p),{recursive:!0});let f;n==="json"?f=JSON.stringify(l,null,2):f=l.map(d=>JSON.stringify(d)).join(`
|
|
31
|
-
`),await writeFile(p,f,"utf-8");let y=Date.now()-a;if(Tt(`Generated ${l.length} TypeSchema definitions`,y,{schemas:l.length}),e.dim(`Output: ${p}`),i.verbose){e.debug("Generated schemas:");let d=l.map(g=>`${g.identifier?.name||"Unknown"} (${g.identifier?.kind||"unknown"})`);J(d);}}catch(t){e.error("Failed to generate TypeSchema",t instanceof Error?t:new Error(String(t))),process.exit(1);}}};var lr={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:i=>i.command(cr).help().example("$0 typeschema generate hl7.fhir.r4.core@4.0.1","Generate TypeSchema from FHIR R4 core package"),handler:i=>{if(!i.subcommand&&i._.length===1){He("Available typeschema subcommands:"),J(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
|
|
2
|
+
import x from'picocolors';import Ke from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as re from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';import Ue from'assert';var L=class t{options;dryWarnSet=new Set;constructor(e={}){this.options={timestamp:false,level:1,...e};}shouldLog(e){let n=this.options.level??1;return e>=n}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(e,n,i){let r=this.options.timestamp?`${x.gray(new Date().toLocaleTimeString())} `:"",o=this.options.prefix?`${x.cyan(`[${this.options.prefix}]`)} `:"";return `${r}${i(e)} ${o}${n}`}isSuppressed(e){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(e)||false}tryWriteToConsole(e,n){if(this.isSuppressed(e)||!this.shouldLog(e))return;(t.consoleLevelsMap[e]||console.log)(n);}success(e){this.tryWriteToConsole(1,this.formatMessage("",e,x.green));}error(e,n){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",e,x.red));let i=this.options.level===0;n&&i&&(console.error(x.red(` ${n.message}`)),n.stack&&console.error(x.gray(n.stack)));}warn(e){this.tryWriteToConsole(2,this.formatMessage("!",e,x.yellow));}dry_warn(e){this.dryWarnSet.has(e)||(this.warn(e),this.dryWarnSet.add(e));}info(e){this.tryWriteToConsole(1,this.formatMessage("i",e,x.blue));}debug(e){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",e,x.magenta));}step(e){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",e,x.cyan));}progress(e){this.tryWriteToConsole(1,this.formatMessage("\u23F3",e,x.blue));}plain(e,n=i=>i){let i=this.options.timestamp?`${x.gray(new Date().toLocaleTimeString())} `:"",r=this.options.prefix?`${x.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${i}${r}${n(e)}`);}dim(e){this.plain(e,x.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;}},F=new L;function Re(t){F.success(t);}function b(t,e){F.error(t,e);}function O(t){F.info(t);}function Ce(t){F.dim(t);}function X(t){F.configure(t);}function w(t={}){return new L(t)}function Z(t){console.log(),console.log(x.cyan(x.bold(`\u2501\u2501\u2501 ${t} \u2501\u2501\u2501`)));}function Y(t,e,n){let i=t;e&&(i+=` ${x.gray(`(${e}ms)`)}`),Re(i),n&&Object.entries(n).forEach(([r,o])=>{Ce(` ${r}: ${o}`);});}function I(t,e="\u2022"){t.forEach(n=>{console.log(x.gray(` ${e} ${n}`));});}var B=t=>t!==null&&typeof t=="object"&&t.resourceType==="CodeSystem";var P=t=>t!==null&&typeof t=="object"&&t.resourceType==="ValueSet";var S=t=>`${t.name}#${t.version}`;var j=(t,e)=>(e||(e={name:"undefined",version:"undefined"}),{...t,package_meta:t.package_meta||e,name:t.name,url:t.url,base:t.base});var ee=t=>t?.kind==="nested",te=t=>t?.kind==="profile";var ne=(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}};var ke=async(t,e)=>{let i=(await t.packageJson(e.name)).dependencies;return i!==void 0?Object.entries(i).map(([r,o])=>({name:r,version:o})):[]},oe=t=>({pkg:t,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),ae=async(t,e,n,i,r)=>{let o=S(e);if(r?.info(`${" ".repeat(n*2)}+ ${o}`),i[o])return i[o];let a=oe(e);for(let s of await t.search({package:e})){let c=s.url;if(!c||!(isStructureDefinition(s)||P(s)||B(s)))continue;let u=c;a.canonicalResolution[u]&&r?.dry_warn(`Duplicate canonical URL: ${u} at ${o}.`),a.canonicalResolution[u]=[{deep:n,pkg:e,pkgId:o,resource:s}];}let l=await ke(t,e);for(let s of l){let{canonicalResolution:c}=await ae(t,s,n+1,i,r);for(let[u,m]of Object.entries(c)){let f=u;a.canonicalResolution[f]=[...a.canonicalResolution[f]||[],...m];}}for(let s of Object.values(a.canonicalResolution))s.sort((c,u)=>c.deep-u.deep);return i[o]=a,a},ie=(t,e)=>{for(let{pkg:n,canonicalResolution:i}of Object.values(t)){let r=S(n);if(!t[r])throw new Error(`Package ${r} not found`);for(let[a,l]of Object.entries(i)){let s=l[0];if(!s)throw new Error("Resource not found");let c=s.resource,u=s.pkg;if(isStructureDefinition(c)){let m=re.translate(c),f=j(m,u);t[r].fhirSchemas[f.url]=f;}if(P(c)){let m=ne(c,u);t[r].valueSets[m.url]=m;}}}},be=(t,e,n)=>{let i=Object.values(t).flatMap(r=>r.canonicalResolution[e]);if(!i)throw new Error(`No canonical resolution found for ${e} in any package`);return i[0]?.resource},_=async(t,{logger:e,fallbackPackageForNameResolution:n,focusedPackages:i})=>{let r=i??await t.packages(),o={};for(let p of r)await ae(t,p,0,o,e);ie(o);let a=(p,d)=>o[S(p)]?.fhirSchemas[d]||n&&o[S(n)]?.fhirSchemas[d],l=(p,d)=>o[S(p)]?.valueSets[d]||n&&o[S(n)]?.valueSets[d],s=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),c=(p,d)=>{let g=a(p,d);if(g===void 0)throw new Error(`Failed to resolve FHIR Schema: '${d}'`);let y=[g];for(;g?.base;){let R=g.package_meta,C=s(g.base);if(g=a(R,C),g===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${d}'. Problem: '${C}' from '${S(R)}'`);y.push(g);}return y},u=(p,d)=>c(p,d).filter(g=>g.derivation==="specialization"),m=(p,d)=>{let g=c(p.package_meta,p.url),y=Ie(g,d);return ve(y)},f=p=>{let d=new Set;for(let[g,y]of Object.entries(p)){d.add(g);for(let R of y?.choices||[])p[R]||d.add(R);}return Array.from(d)},h;return {testAppendFs(p){let d=j(p),g=S(d.package_meta);o[g]||(o[g]=oe(d.package_meta)),o[g].fhirSchemas[d.url]=d,h=void 0;},resolveFs:a,resolveFsGenealogy:c,resolveFsSpecializations:u,ensureSpecializationCanonicalUrl:s,resolveSd:(p,d)=>{let g=o[S(p)]?.canonicalResolution[d]?.[0]?.resource;if(isStructureDefinition(g))return g},allSd:()=>Object.values(o).flatMap(p=>Object.values(p.canonicalResolution).flatMap(d=>d.map(g=>{let y=g.resource;return y.package_name?y:{...y,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(o).flatMap(d=>Object.values(d.canonicalResolution).forEach(g=>{g.forEach(y=>{if(isStructureDefinition(y.resource)){let R=y.resource,C=p(d.pkg,R);if(R.url!==C.url)throw new Error(`Patch update StructureDefinition URL: ${R.url} !== ${C.url}`);y.resource=C;}});})),ie(o),h=void 0;},allFs:()=>Object.values(o).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(o).flatMap(p=>Object.values(p.valueSets)),resolveVs:l,resolveAny:p=>be(o,p),resolveElementSnapshot:m,getAllElementKeys:f,resolver:o,resolutionTree:()=>{if(h)return h;let p={};for(let[d,g]of Object.entries(o)){let y=g.pkg.name;p[y]={};for(let[R,C]of Object.entries(g.canonicalResolution)){let J=R;p[y][J]=[];for(let Q of C)p[y][J].push({deep:Q.deep,pkg:Q.pkg});}}return h=p,p}}};var Ie=(t,e)=>{let[n,...i]=e;return n===void 0?[]:t.map(r=>{if(!r.elements)return;let o=r.elements?.[n];for(let a of i)o=o?.elements?.[a];return o}).filter(r=>r!==void 0)};function ve(t){let e=t.reverse(),n=Object.assign({},...e);return n.elements=void 0,n}var T="Use CodeableReference which is not provided by FHIR R4.",Fe="Use Availability which is not provided by FHIR R4.",se={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":Fe,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":T,"http://hl7.org/fhir/StructureDefinition/specimen-additive":T,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":T,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":T,"http://hl7.org/fhir/StructureDefinition/workflow-reason":T},"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 A(t,e){let n=`${t.name}#${t.version}`,i=se[n]?.[e];if(i)return {shouldSkip:true,reason:i};let r=se[t.name]?.[e];return r?{shouldSkip:true,reason:r}:{shouldSkip:false}}function G(t){let e=t.split("|")[0];return e||t}function Ee(t){return t.split("|")[1]}function Te(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 k(t){return {kind:Te(t),package:t.package_meta.name,version:t.package_meta.version,name:t.name,url:t.url}}var De=t=>{let e=t.split("/"),n=e[e.length-1];return n&&n.length>0?n.split(/[-_]/).map(i=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join(""):t};function U(t,e,n){let i=G(n),r=De(i),o={package_meta:{name:"missing_valuesets",version:Ee(i)||"0.0.0"},id:n},a=t.resolveVs(e,i)||o,l=a?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(a.id)?a.id:r;return {kind:"value-set",package:a.package_meta.name,version:a.package_meta.version,name:l,url:i}}function N(t,e,n){let i=e.join("."),[r,o,a]=n?[{name:"shared",version:"1.0.0"},n,`urn:fhir:binding:${n}`]:[t.package_meta,`${t.name}.${i}_binding`,`${t.url}#${i}_binding`];return {kind:"binding",package:r.name,version:r.version,name:o,url:a}}function $(t,e,n,i){let r={};if(e.derivation==="constraint"){let m=t.resolveFsSpecializations(e.package_meta,e.url).map(f=>q(t,f,i)).filter(f=>f!==void 0).flat();for(let f of m.reverse())r[f.identifier.name]=f.identifier.url;}let o=n.join("."),a=r[o]??`${e.url}#${o}`,l=a.split("#")[0],c=t.resolveFs(e.package_meta,l)?.package_meta??e.package_meta;return {kind:"nested",package:c.name,version:c.version,name:o,url:a}}function ce(t,e,n){let i=[];for(let[r,o]of Object.entries(n)){let a=[...e,r];D(o)&&i.push([a,o]),o.elements&&i.push(...ce(t,a,o.elements));}return i}function Le(t,e,n,i,r){let o={};for(let[a,l]of Object.entries(i)){let s=[...n,a],c=t.resolveElementSnapshot(e,s);D(c)?o[a]=H(t,e,s,c,r):o[a]=V(t,e,s,c,r);}return o}function q(t,e,n){if(!e.elements)return;let i=ce(e,[],e.elements).filter(([o,a])=>a.elements&&Object.keys(a.elements).length>0),r=[];for(let[o,a]of i){let l=$(t,e,o,n),s;a.type==="BackboneElement"||!a.type?s="BackboneElement":s=a.type;let c=t.ensureSpecializationCanonicalUrl(s),u=t.resolveFs(e.package_meta,c);if(!u)throw new Error(`Could not resolve base type ${s}`);let m={kind:"complex-type",package:u.package_meta.name,version:u.package_meta.version,name:s,url:c},f=Le(t,e,o,a.elements??{},n),h={identifier:l,base:m,fields:f};r.push(h);}return r.sort((o,a)=>o.identifier.url.localeCompare(a.identifier.url)),r.length===0?void 0:r}function le(t){let e=[];for(let n of t){n.base&&e.push(n.base);for(let i of Object.values(n.fields||{}))"type"in i&&i.type&&e.push(i.type),"binding"in i&&i.binding&&e.push(i.binding);}return e}function pe(t,e,n){let i=n[n.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${n.join("/")}`);let r=n.slice(0,-1),o=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(a=>{if(r.length===0)return a.required||[];if(!a.elements)return [];let l=a;for(let s of r)l=l?.elements?.[s];return l?.required||[]});return new Set(o).has(i)}function de(t,e,n){let i=n[n.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${n.join("/")}`);let r=n.slice(0,-1),o=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(a=>{if(r.length===0)return a.excluded||[];if(!a.elements)return [];let l=a;for(let s of r)l=l?.elements?.[s];return l?.excluded||[]});return new Set(o).has(i)}var we=(t,e,n)=>{if(n.refers)return n.refers.map(i=>{let r=t.ensureSpecializationCanonicalUrl(i),o=t.resolveFs(e.package_meta,r);if(!o)throw new Error(`Failed to resolve fs for ${r}`);return k(o)})},Pe=t=>{let e=new Set,n=new Set;if(t.required)for(let i of t.required)e.add(i);if(t.excluded)for(let i of t.excluded)n.add(i);if(t.elements)for(let[i,r]of Object.entries(t.elements))r.min!==void 0&&r.min>0&&e.add(i);return {required:e.size>0?Array.from(e):void 0,excluded:n.size>0?Array.from(n):void 0}},ue=t=>{let e=t.slicing;if(!e)return;let n={};for(let[i,r]of Object.entries(e.slices??{})){if(!r)continue;let{required:o,excluded:a}=r.schema?Pe(r.schema):{};n[i]={min:r.min,max:r.max,match:r.match,required:o,excluded:a};}return {discriminator:e.discriminator,rules:e.rules,ordered:e.ordered,slices:Object.keys(n).length>0?n:void 0}};function v(t,e,n,i,r){if(i.elementReference){let o=i.elementReference.slice(1).filter((a,l)=>l%2===1);return $(t,e,o,r)}else if(i.type){let o=t.ensureSpecializationCanonicalUrl(i.type),a=t.resolveFs(e.package_meta,o);if(!a)throw new Error(`Could not resolve field type: <${e.url}>.${n.join(".")}: <${i.type}> (pkg: '${S(e.package_meta)}'))`);return k(a)}else {if(i.choices)return;if(e.derivation==="constraint")return;throw r?.error(`Can't recognize element type: <${e.url}>.${n.join(".")} (pkg: '${S(e.package_meta)}'): ${JSON.stringify(i,void 0,2)}`),new Error("Unrecognized element type")}}var V=(t,e,n,i,r)=>{let o,a;i.binding&&(o=N(e,n,i.binding.bindingName),i.binding.strength==="required"&&i.type==="code"&&(a=z(t,e,i,r)));let l=v(t,e,n,i,r);return l||r?.dry_warn(`Field type not found for '${e.url}#${n.join(".")}' (${e.derivation})`),{type:l,required:pe(t,e,n),excluded:de(t,e,n),reference:we(t,e,i),array:i.array||false,min:i.min,max:i.max,slicing:ue(i),choices:i.choices,choiceOf:i.choiceOf,binding:o,enum:a}};function D(t){let e=t.type==="BackboneElement",n=t.type==="Element"&&t.elements!==void 0&&Object.keys(t.elements).length>0,i=t.type===void 0&&t.choiceOf===void 0&&t.elements!==void 0&&Object.keys(t.elements).length>0;return e||n||i}function H(t,e,n,i,r){return {type:$(t,e,n,r),array:i.array||false,required:pe(t,e,n),excluded:de(t,e,n),slicing:ue(i)}}function W(t,e,n,i){let r=G(n)||n,o=t.resolveVs(e,r);if(o)return Ne(t,o)}function Ne(t,e,n){if(e.expansion?.contains)return e.expansion.contains.filter(r=>r.code!==void 0).map(r=>(Ue(r.code),{code:r.code,display:r.display,system:r.system}));let i=[];if(e.compose?.include){for(let r of e.compose.include)if(r.concept)for(let o of r.concept)i.push({system:r.system,code:o.code,display:o.display});else if(r.system&&!r.filter)try{let o=t.resolveAny(r.system);if(o?.concept){let a=(l,s)=>{for(let c of l)i.push({system:s,code:c.code,display:c.display}),c.concept&&a(c.concept,s);};a(o.concept,r.system);}}catch{}}return i.length>0?i:void 0}var me=100;function z(t,e,n,i){if(!n.binding)return;let r=n.binding.strength,o=n.binding.valueSet;if(!o||!(r==="required"||r==="extensible"&&(n.type==="code"||n.type==="Coding")||r==="preferred"&&(n.type==="code"||n.type==="Coding")))return;let l=W(t,e.package_meta,o);if(!l||l.length===0)return;let s=l.map(c=>c.code).filter(c=>c&&typeof c=="string"&&c.trim().length>0);if(s.length>me){i?.dry_warn(`Value set ${o} has ${s.length} which is more than ${me} codes, which may cause issues with code generation.`);return}return s.length>0?s:void 0}function $e(t,e,n,i,r){if(!i.binding?.valueSet)return;let o=N(e,n,i.binding.bindingName),a=v(t,e,n,i,r),l=U(t,e.package_meta,i.binding.valueSet),s=[];a&&s.push(a),s.push(l);let c=z(t,e,i,r);return {identifier:o,type:a,valueset:l,strength:i.binding.strength,enum:c,dependencies:s}}function fe(t,e,n){let i=new Set;if(!e.elements)return [];let r=[];function o(s,c){for(let[u,m]of Object.entries(s)){let f=[...c,u],h=f.join("."),p=t.resolveElementSnapshot(e,f);if(!i.has(h)){if(i.add(h),p.binding){let d=$e(t,e,f,p,n);d&&r.push(d);}m.elements&&o(m.elements,f);}}}o(e.elements,[]),r.sort((s,c)=>s.identifier.name.localeCompare(c.identifier.name));let a=[],l=new Set;for(let s of r)l.has(s.identifier.url)||(l.add(s.identifier.url),a.push(s));return a}function Ve(t,e,n,i,r){if(!i)return;let o={};for(let a of t.getAllElementKeys(i)){let l=[...n,a],s=t.resolveElementSnapshot(e,l),c=s.type?t.ensureSpecializationCanonicalUrl(s.type):void 0;if(c&&A(e.package_meta,c).shouldSkip){r?.warn(`Skipping field ${l} for ${c} due to skip hack ${A(e.package_meta,c).reason}`);continue}D(s)?o[a]=H(t,e,l,s,r):o[a]=V(t,e,l,s,r);}return o}function He(t){let e=[];for(let n of Object.values(t))"type"in n&&n.type&&e.push(n.type),"binding"in n&&n.binding&&e.push(n.binding);return e}function Me(t,e){return !!(t.base==="Extension"||t.base==="http://hl7.org/fhir/StructureDefinition/Extension"||t.url?.includes("/extension/")||t.url?.includes("-extension")||t.name?.toLowerCase().includes("extension")||t.type==="Extension")}async function ge(t,e,n){if(!e.url)throw new Error("ValueSet URL is required");let i=U(t,e.package_meta,e.url),r=W(t,e.package_meta,e.url);return {identifier:i,description:e.description,concept:r,compose:r?void 0:e.compose}}function Oe(t,e,n,i){let r=[];e&&r.push(e),n&&r.push(...He(n)),i&&r.push(...le(i));let o={};for(let s of r)s.url!==t.url&&(o[s.url]=s);let a=new Set(i?.map(s=>s.identifier.url)),l=Object.values(o).filter(s=>te(t)||!ee(s)?true:!a.has(s.url)).sort((s,c)=>s.url.localeCompare(c.url));return l.length>0?l:void 0}function Be(t,e,n){let i=k(e),r;if(e.base&&e.type!=="Element"){let h=t.resolveFs(e.package_meta,t.ensureSpecializationCanonicalUrl(e.base));if(!h)throw new Error(`Base resource not found '${e.base}' for <${e.url}> from ${S(e.package_meta)}`);r=k(h);}let o=Ve(t,e,[],e.elements,n),a=q(t,e,n),l=e.derivation==="constraint"?Ae(t,e,n):void 0,s=Oe(i,r,o,a),c=l?.flatMap(h=>h.valueTypes??[])??[],u=(()=>{if(!s&&c.length===0)return s;let h={};for(let p of s??[])h[p.url]=p;for(let p of c)h[p.url]=p;return Object.values(h)})(),m={identifier:i,base:r,fields:o,nested:a,description:e.description,dependencies:u,...l&&l.length>0?{extensions:l}:{}},f=fe(t,e,n);return [m,...f]}function je(t,e,n,i){let r=t.resolveFs(e.package_meta,n);if(!r?.elements)return;let o=[];for(let[l,s]of Object.entries(r.elements)){if(s.choiceOf!=="value"&&!l.startsWith("value"))continue;let c=v(t,r,[l],s,i);c&&o.push(c);}if(o.length===0)return;let a=new Map(o.map(l=>[l.url,l]));return Array.from(a.values())}function _e(t,e,n,i){let r=t.resolveFs(e.package_meta,n);if(!r?.elements)return;let o=[];for(let[s,c]of Object.entries(r.elements)){if(!s.startsWith("extension:"))continue;let u=s.split(":")[1];if(!u)continue;let m=c.url??u,f;for(let[h,p]of Object.entries(c.elements??{}))if(!(p.choiceOf!=="value"&&!h.startsWith("value"))&&(f=v(t,r,[s,h],p,i),f))break;o.push({name:u,url:m,valueType:f,min:c.min,max:c.max!==void 0?String(c.max):void 0});}let l=r.elements.extension?.slicing?.slices;if(l&&typeof l=="object")for(let[s,c]of Object.entries(l)){let u=c,m=u.schema;if(!m)continue;let f=u.match?.url??s,h,p=m.elements??{};for(let[d,g]of Object.entries(p)){let y=g;if(!(y.choiceOf!=="value"&&!d.startsWith("value"))&&y.type){h={kind:"complex-type",package:r.package_meta.name,version:r.package_meta.version,name:y.type,url:`http://hl7.org/fhir/StructureDefinition/${y.type}`};break}}o.push({name:s,url:f,valueType:h,min:m._required?1:m.min??0,max:m.max!==void 0?String(m.max):m.array?"*":"1"});}return o.length>0?o:void 0}function Ae(t,e,n){let i=[],r=(a,l,s)=>{let c=s.url,u=c?je(t,e,c,n):void 0,m=c?_e(t,e,c,n):void 0,f=m!==void 0&&m.length>0;i.push({name:l,path:[...a,"extension"].join("."),url:c,min:s.min,max:s.max!==void 0?String(s.max):void 0,mustSupport:s.mustSupport,valueTypes:u,subExtensions:m,isComplex:f});},o=(a,l)=>{if(l.extensions)for(let[s,c]of Object.entries(l.extensions))r(a,s,c);if(l.elements)for(let[s,c]of Object.entries(l.elements))o([...a,s],c);};if(e.extensions)for(let[a,l]of Object.entries(e.extensions))r([],a,l);if(e.elements)for(let[a,l]of Object.entries(e.elements))o([a],l);return i}async function he(t,e,n){let i=Be(t,e,n);if(Me(e,k(e))){let r=i[0];if(!r)throw new Error("Expected schema to be defined");r.metadata={isExtension:true};}return i}var M=class{manager;options;logger;constructor(e){this.options={...e},this.manager=e.manager,this.logger=e.logger||w({prefix:"TypeSchema"});}async registerFromPackageMetas(e){let n=e.map(S);return this.logger?.step(`Loading FHIR packages: ${n.join(", ")}`),await this.manager.init(),_(this.manager,{focusedPackages:e})}generateFhirSchemas(e){this.logger?.progress(`Converting ${e.length} StructureDefinitions to FHIRSchemas`);let n=[],i=0,r=0;for(let o of e)try{let a=re.translate(o);n.push(a),i++,this.logger?.debug(`Converted StructureDefinition: ${o.name||o.id} (${o.resourceType})`);}catch(a){r++,this.logger?.warn(`Failed to convert StructureDefinition ${o.name||o.id}: ${a instanceof Error?a.message:String(a)}`);}return this.logger?.success(`FHIR Schema conversion completed: ${i}/${e.length} successful, ${r} failed`),n}async generateValueSetSchemas(e,n){e.length>0&&this.logger?.debug(`${e.length} ValueSets available for enum extraction`);let i=await _(this.manager,{logger:this.logger}),r=[];if(e.length>0){this.logger?.progress(`Converting ${e.length} ValueSets to TypeSchema`);let o=0,a=0;for(let l of e)try{let s=await ge(i,l,n);s&&(r.push(s),o++,this.logger?.debug(`Converted ValueSet: ${l.name||l.id}`));}catch(s){a++,this.logger?.warn(`Failed to convert ValueSet ${l.name||l.id}: ${s instanceof Error?s.message:String(s)}`);}this.logger?.success(`ValueSet conversion completed: ${o}/${e.length} successful, ${a} failed`);}return r}async generateFromPackage(e,n,i){let r={name:e,version:n||"latest"},o=await this.registerFromPackageMetas([r]),a=await this.generateValueSetSchemas(o.allVs(),i);return [...(await Promise.all(o.allFs().map(async c=>await he(o,c,i)))).flat(),...a]}};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 t=>{let e=w({prefix:"TypeSchema"});try{e.step("Generating TypeSchema from FHIR packages"),e.info(`Packages: ${t.packages.join(", ")}`),e.info(`Output: ${t.output}`);let n=t.singleFile?"ndjson":t.format;e.debug(`Format: ${n}${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 i=Date.now(),r=new M({treeshake:t.treeshake,registry:t.registry,manager:CanonicalManager({packages:[],workingDir:".codegen-cache/canonical-manager-cache",registry:t.registry})}),o=[];for(let c of t.packages){let[u,m]=c.includes("@")?c.split("@"):[c,void 0];e.progress(`Processing package: ${u}${m?`@${m}`:""}`);let f=await r.generateFromPackage(u,m,e);o.push(...f);}if(o.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 l;n==="json"?l=JSON.stringify(o,null,2):l=o.map(c=>JSON.stringify(c)).join(`
|
|
3
|
+
`),await writeFile(a,l,"utf-8");let s=Date.now()-i;if(Y(`Generated ${o.length} TypeSchema definitions`,s,{schemas:o.length}),e.dim(`Output: ${a}`),t.verbose){e.debug("Generated schemas:");let c=o.map(u=>`${u.identifier?.name||"Unknown"} (${u.identifier?.kind||"unknown"})`);I(c);}}catch(n){e.error("Failed to generate TypeSchema",n instanceof Error?n:new Error(String(n))),process.exit(1);}}};var xe={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:t=>t.command(Se).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){O("Available typeschema subcommands:"),I(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
|
|
32
4
|
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),console.log(`
|
|
33
|
-
Examples:`),
|
|
34
|
-
`),
|
|
35
|
-
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};function
|
|
5
|
+
Examples:`),I(["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)&&(b(`Unknown typeschema subcommand: ${t.subcommand}
|
|
6
|
+
`),O("Available typeschema subcommands:"),I(["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 Qe(t){return t?{debug:0,info:1,warn:2,error:3,silent:4}[t.toLowerCase()]:void 0}async function Xe(t){let e=Qe(t.logLevel);e===void 0&&(t.debug||t.verbose?e=0:e=1),X({timestamp:t.debug,level:e});}function Ze(){return Ke(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(Xe).command(xe).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&&(Z("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
|
|
36
8
|
Use 'atomic-codegen <command> --help' for more information about a command.`),console.log(`
|
|
37
|
-
Quick examples:`),console.log(" atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson"),console.log(
|
|
38
|
-
Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0
|
|
39
|
-
Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function
|
|
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((t,e,n)=>{e?b(e.message,e):b(t),b(`
|
|
11
|
+
Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function K(){await Ze().parseAsync();}import.meta.main&&K().catch(t=>{t("Unexpected error:",t),process.exit(1);});K().catch(t=>{console.error("CLI Error:",t instanceof Error?t.message:t),process.exit(1);});
|