@atomic-ehr/codegen 0.0.11 → 0.0.12-canary.20260420080923.373dc66
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 +8 -7
- package/dist/cli/index.js +5 -5
- package/dist/index.js +124 -91
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -53,13 +53,14 @@ A powerful, extensible code generation toolkit for FHIR ([Fast Healthcare Intero
|
|
|
53
53
|
- [ ] **Search Builders** — type-safe FHIR search query construction
|
|
54
54
|
- [ ] **Operation Generation** — type-safe FHIR operation calls
|
|
55
55
|
|
|
56
|
-
| Feature
|
|
57
|
-
|
|
58
|
-
| Resources & Complex Types
|
|
59
|
-
|
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
56
|
+
| Feature | TypeScript | Python | C# | Mustache |
|
|
57
|
+
|-----------------------------------|------------|---------|------|----------|
|
|
58
|
+
| Resources & Complex Types | yes | yes | yes | template |
|
|
59
|
+
| Polymorphic container `Bundle<T>` | yes | yes | no | no |
|
|
60
|
+
| Value Set Bindings | inline | limited | enum | template |
|
|
61
|
+
| Primitive Extensions | yes | no | no | no |
|
|
62
|
+
| Profiles | yes | no | no | no |
|
|
63
|
+
| Profile Validation | yes | no | no | no |
|
|
63
64
|
|
|
64
65
|
## Guides
|
|
65
66
|
|
package/dist/cli/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import b from'picocolors';import ln from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import Ce from'assert';import {createHash}from'crypto';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as pe from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var ee=e=>{console.log(),console.log(b.cyan(b.bold(`\u2501\u2501\u2501 ${e} \u2501\u2501\u2501`)));},ne=(e,n,o)=>{let t=e;if(n&&(t+=` ${b.gray(`(${n}ms)`)}`),console.log(`${b.green("")} ${t}`),o)for(let[i,r]of Object.entries(o))console.log(b.gray(` ${i}: ${r}`));},F=(e,n="\u2022")=>{for(let o of e)console.log(b.gray(` ${n} ${o}`));};var te={DEBUG:0,INFO:1,WARN:2,ERROR:3,SILENT:4};function C(e={}){let n=e.prefix??"",o=new Set(e.suppressTags??[]),t={},i=[],r=new Set,a=e.level??"INFO",l=p=>te[p]>=te[a],c={DEBUG:p=>p,INFO:p=>p,WARN:b.yellow,ERROR:b.red,SILENT:p=>p},s=(p,m,f,g)=>{let y=n?`${n}: `:"",S=g?` ${b.dim(`(${g})`)}`:"";return c[p](`${m} ${y}${f}`)+S},d=(p,m,f,g=false)=>{i.push({level:p,tag:f,message:m,suppressed:g,prefix:n,timestamp:Date.now()});},u=(p,m,f,g=false)=>(...y)=>{let S=y.length===2?y[0]:void 0,x=y.length===2?y[1]:y[0];S&&(t[S]=(t[S]??0)+1);let k=S!==void 0&&o.has(S);if(d(p,x,S,k),!k&&l(p)){if(g){let D=`${p}::${S??""}::${x}`;if(r.has(D))return;r.add(D);}f(s(p,m,x,S));}},h={warn:u("WARN","!",console.warn),dryWarn:u("WARN","!",console.warn,true),info:u("INFO","i",console.log),error:u("ERROR","X",console.error),debug:u("DEBUG","D",console.log),fork(p,m){let f=n?`${n}/${p}`:p,g=[...o,...m?.suppressTags??[]];return C({prefix:f,suppressTags:g,level:m?.level??a})},as(){return h},tagCounts(){return t},printTagSummary(){let p=Object.entries(t);if(p.length===0)return;let m=n?`${n}: `:"",f=p.filter(([y])=>!o.has(y)),g=p.filter(([y])=>o.has(y));if(f.length>0){let y=f.reduce((x,[,k])=>x+k,0),S=f.map(([x,k])=>`${x}: ${k}`).join(", ");console.warn(b.yellow(`! ${m}${y} warnings (${S})`));}if(g.length>0){let y=g.reduce((x,[,k])=>x+k,0),S=g.map(([x,k])=>`${x}: ${k}`).join(", ");console.log(b.dim(`i ${m}${y} suppressed (${S})`));}},buffer(){return i},bufferClear(){i.length=0;}};return h}var P="Use CodeableReference which is not provided by FHIR R4.",He="Use Availability which is not provided by FHIR R4.",_={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":He,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":P,"http://hl7.org/fhir/StructureDefinition/specimen-additive":P,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":P,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":P,"http://hl7.org/fhir/StructureDefinition/workflow-reason":P},"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 T(e,n){let o=`${e.name}#${e.version}`,t=_[o]?.[n];if(t)return {shouldSkip:true,reason:t};let i=_[e.name]?.[n];return i?{shouldSkip:true,reason:i}:{shouldSkip:false}}var R=e=>`${e.name}#${e.version}`,ie=e=>`${e.name}@${e.version}`,oe=e=>{let n=JSON.stringify(e);return createHash("sha256").update(n).digest("hex").slice(0,16)},re=(e,n)=>{let o=e.derivation==="constraint"?"constraint":"specialization";return {...e,derivation:o,kind:e.kind,package_meta:e.package_meta||n,name:e.name,url:e.url,base:e.base}};var A=e=>e?.kind==="nested";var v=(...e)=>{let n=e.filter(t=>t!==void 0).flatMap(t=>t.map(i=>[i.url,i]));return n.length===0?void 0:Object.values(Object.fromEntries(n)).sort((t,i)=>t.url.localeCompare(i.url))};var ae=e=>[...e.valueFieldTypes??[],...e.profile?[e.profile]:[],...e.subExtensions?.flatMap(n=>n.valueFieldType?[n.valueFieldType]:[])??[]];var se=(e,n)=>{if(!e.url)throw new Error("ValueSet must have a URL");if(!e.name)throw new Error("ValueSet must have a name");return {...e,package_meta:e.package_meta||n,name:e.name,url:e.url}};function G(e){let n=e.split("|")[0];return n||e}function Ne(e){return e.split("|")[1]}var Le=e=>({package:e.package_meta.name,version:e.package_meta.version,name:e.name,url:e.url});function I(e){let n=Le(e);return e.derivation==="constraint"?{kind:"profile",...n}:e.kind==="primitive-type"?{kind:"primitive-type",...n}:e.kind==="complex-type"?{kind:"complex-type",...n}:e.kind==="resource"?{kind:"resource",...n}:e.kind==="logical"?{kind:"logical",...n}:{kind:"resource",...n}}var we=e=>{let n=e.split("/"),o=n[n.length-1];return o&&o.length>0?o.split(/[-_]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join(""):e};function N(e,n,o){let t=G(o),i=we(t),r={package_meta:{name:"missing_valuesets",version:Ne(t)||"0.0.0"},id:o},a=e.resolveVs(n,t)||r,l=a?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(a.id)?a.id:i;return {kind:"value-set",package:a.package_meta.name,version:a.package_meta.version,name:l,url:t}}function L(e,n,o){let t=o.binding?.bindingName,i=n.join("."),[r,a,l]=t?[{name:"shared",version:"1.0.0"},t,`urn:fhir:binding:${t}`]:[e.package_meta,`${e.name}.${i}_binding`,`${e.url}#${i}_binding`];return {kind:"binding",package:r.name,version:r.version,name:a,url:l}}function z(e,n,o,t){let i=G(o)||o,r=e.resolveVs(n,i);if(r)return $e(e,r)}function $e(e,n,o){if(n.expansion?.contains)return n.expansion.contains.filter(i=>i.code!==void 0).map(i=>(Ce(i.code),{code:i.code,display:i.display,system:i.system}));let t=[];if(n.compose?.include){for(let i of n.compose.include)if(i.concept)for(let r of i.concept)t.push({system:i.system,code:r.code,display:r.display});else if(i.system&&!i.filter)try{let r=e.resolveAny(i.system);if(r?.concept){let a=(l,c)=>{for(let s of l)t.push({system:c,code:s.code,display:s.display}),s.concept&&a(s.concept,c);};a(r.concept,i.system);}}catch{}}return t.length>0?t:void 0}var ce=100,W=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function q(e,n,o,t){if(!o.binding)return;let i=o.binding.strength,r=o.binding.valueSet;if(!r)return;if(!W.has(o.type??"")){t?.dryWarn("#binding",`eld-11: Binding on non-bindable type '${o.type}' (valueSet: ${r})`);return}if(!(i==="required"||i==="extensible"||i==="preferred"))return;let l=z(e,n.package_meta,r);if(!l||l.length===0)return;let c=l.map(s=>s.code).filter(s=>s&&typeof s=="string"&&s.trim().length>0);if(c.length>ce){t?.dryWarn("#largeValueSet",`Value set ${r} has ${c.length} which is more than ${ce} codes, which may cause issues with code generation.`);return}if(c.length!==0)return {isOpen:i!=="required",values:c}}function Ve(e,n,o,t,i){if(!t.binding?.valueSet)return;let r=L(n,o,t),a=N(e,n.package_meta,t.binding.valueSet),l=q(e,n,t,i);return {identifier:r,valueset:a,strength:t.binding.strength,enum:l,dependencies:[a]}}function le(e,n,o){let t=new Set;if(!n.elements)return [];let i=[];function r(c,s){for(let[d,u]of Object.entries(c)){let h=[...s,d],p=h.join("."),m=e.resolveElementSnapshot(n,h);if(!t.has(p)){if(t.add(p),m.binding){let f=Ve(e,n,h,m,o);f&&i.push(f);}u.elements&&r(u.elements,h);}}}r(n.elements,[]),i.sort((c,s)=>c.identifier.name.localeCompare(s.identifier.name));let a=[],l=new Set;for(let c of i)l.has(c.identifier.url)||(l.add(c.identifier.url),a.push(c));return a}var K=e=>e!==null&&typeof e=="object"&&e.resourceType==="CodeSystem";var w=e=>e!==null&&typeof e=="object"&&e.resourceType==="ValueSet";var je=async(e,n)=>{let o=await e.packageJson(n.name);if(!o)return [];let t=o.dependencies;return t!==void 0?Object.entries(t).map(([i,r])=>({name:i,version:r})):[]},de=e=>({pkg:e,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),me=async(e,n,o,t,i)=>{let r=R(n);if(i?.info(`${" ".repeat(o*2)}+ ${r}`),t[r])return t[r];let a=de(n);for(let c of await e.search({package:n})){let s=c.url;if(!s||!(isStructureDefinition(c)||w(c)||K(c)))continue;let d=s;a.canonicalResolution[d]&&i?.dryWarn("#duplicateCanonical",`Duplicate canonical URL: ${d} at ${r}.`),a.canonicalResolution[d]=[{deep:o,pkg:n,pkgId:r,resource:c}];}let l=await je(e,n);for(let c of l){let{canonicalResolution:s}=await me(e,c,o+1,t,i);for(let[d,u]of Object.entries(s)){let h=d;a.canonicalResolution[h]=[...a.canonicalResolution[h]||[],...u];}}for(let c of Object.values(a.canonicalResolution))c.sort((s,d)=>s.deep-d.deep);return t[r]=a,a},Oe=(e,n)=>{for(let{pkg:o,canonicalResolution:t}of Object.values(e)){let i=R(o);if(!e[i])throw new Error(`Package ${i} not found`);let r=0;n?.info(`FHIR Schema conversion for '${R(o)}' begins...`);for(let[a,l]of Object.entries(t)){let c=l[0];if(!c)throw new Error("Resource not found");let s=c.resource,d=c.pkg;if(isStructureDefinition(s)){let u=pe.translate(s),h=re(u,d);r++,e[i].fhirSchemas[h.url]=h;}if(w(s)){let u=se(s,d);e[i].valueSets[u.url]=u;}}n?.info(`FHIR Schema conversion for '${R(o)}' completed: ${r} successful`);}},Me=(e,n,o)=>{let t=Object.values(e).flatMap(i=>i.canonicalResolution[n]);if(!t)throw new Error(`No canonical resolution found for ${n} in any package`);return t[0]?.resource},_e=async(e,{logger:n,focusedPackages:o})=>{let t=o??await e.packages(),i={};for(let p of t)await me(e,p,0,i,n);Oe(i,n);let r=(p,m)=>{let f=i[R(p)];if(f){let g=f.canonicalResolution[m]?.[0];if(g)return i[g.pkgId]?.fhirSchemas[m]}for(let g of Object.values(i)){let y=g.fhirSchemas[m];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(i)){let y=g.fhirSchemas[m];if(y)return y}},a=(p,m)=>{let f=i[R(p)];if(f){let g=f.canonicalResolution[m]?.[0];if(g)return i[g.pkgId]?.valueSets[m]}for(let g of Object.values(i)){let y=g.valueSets[m];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(i)){let y=g.valueSets[m];if(y)return y}},l=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),c=(p,m)=>{let f=r(p,m);if(f===void 0)throw new Error(`Failed to resolve FHIR Schema: '${m}'`);let g=[f];for(;f?.base;){let y=f.package_meta,S=l(f.base);if(f=r(y,S),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${m}'. Problem: '${S}' from '${R(y)}'`);g.push(f);}return g},s=(p,m)=>c(p,m).filter(f=>f.derivation==="specialization"),d=(p,m)=>{let f=c(p.package_meta,p.url),g=$(f,m);return J(g)},u=p=>{let m=new Set;for(let[f,g]of Object.entries(p)){m.add(f);for(let y of g?.choices||[])p[y]||m.add(y);}return Array.from(m)},h;return {testAppendFs(p){let m=R(p.package_meta);i[m]||(i[m]=de(p.package_meta)),i[m].fhirSchemas[p.url]=p,h=void 0;},resolveFs:r,resolveFsGenealogy:c,resolveFsSpecializations:s,ensureSpecializationCanonicalUrl:l,resolveSd:(p,m)=>{let f=i[R(p)]?.canonicalResolution[m]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(i).flatMap(p=>Object.values(p.canonicalResolution).flatMap(m=>m.map(f=>{let g=f.resource;return g.package_name?g:{...g,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,m)=>p.url.localeCompare(m.url)),allFs:()=>Object.values(i).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(i).flatMap(p=>Object.values(p.valueSets)),resolveVs:a,resolveAny:p=>Me(i,p),resolveElementSnapshot:d,getAllElementKeys:u,resolver:i,resolutionTree:()=>{if(h)return h;let p={};for(let[m,f]of Object.entries(i)){let g=f.pkg.name;p[g]={};for(let[y,S]of Object.entries(f.canonicalResolution)){let x=y;p[g][x]=[];for(let k of S)p[g][x].push({deep:k.deep,pkg:k.pkg});}}return h=p,p}}},ue=async(e,n)=>{let o=e.map(ie);n?.logger?.info(`Loading FHIR packages: ${o.join(", ")}`);let t=CanonicalManager({packages:o,workingDir:".codegen-cache/canonical-manager-cache",registry:n.registry||void 0});return await t.init(),await _e(t,{...n,focusedPackages:e})},$=(e,n)=>{let[o,...t]=n;return o===void 0?[]:e.map(i=>{if(!i.elements)return;let r=i.elements?.[o];for(let a of t)r=r?.elements?.[a];return r}).filter(i=>i!==void 0)};function J(e){let n=e.reverse(),o=Object.assign({},...n);return o.elements=void 0,o}var fe=(e,n,o)=>{let t=e.resolveFsSpecializations(n.package_meta,n.url),i=$(t,o),r=J(i).type,a;if(r){let l=e.ensureSpecializationCanonicalUrl(r),s=e.resolveFsGenealogy(n.package_meta,l).flatMap(d=>Object.keys(d.elements??{}));s.length>0&&(a=new Set(s));}for(let l of i)if(!(!l.elements||Object.keys(l.elements).length===0)&&!(a&&!Object.keys(l.elements).some(c=>!a.has(c))))return true;return false},Y=(e,n,o,t,i)=>t.type==="BackboneElement"?true:!i?.elements||i.choiceOf!==void 0?false:fe(e,n,o),Ae=e=>e.elements?new Set(Z(e,[],e.elements).filter(([n,o])=>o.elements&&Object.keys(o.elements).length>0).map(([n])=>n.join("."))):new Set;function V(e,n,o){let t={},i=n.derivation==="constraint"?e.resolveFsSpecializations(n.package_meta,n.url):e.resolveFsGenealogy(n.package_meta,n.url);for(let d of [...i].reverse()){let u=Ae(d);for(let h of u)t[h]=`${d.url}#${h}`;}let r=o.join("."),a=t[r]??`${n.url}#${r}`,l=a.split("#")[0],s=e.resolveFs(n.package_meta,l)?.package_meta??n.package_meta;return {kind:"nested",package:s.name,version:s.version,name:r,url:a}}function Z(e,n,o){let t=[];for(let[i,r]of Object.entries(o)){let a=[...n,i];r.elements&&r.choiceOf===void 0&&t.push([a,r]),r.elements&&t.push(...Z(e,a,r.elements));}return t}function Ge(e,n,o,t,i){let r={},a=e.resolveFsGenealogy(n.package_meta,n.url),l=$(a,o),c=new Set;for(let s of l)if(s.elements)for(let d of Object.keys(s.elements))c.add(d);for(let s of c){let d=[...o,s],u=e.resolveElementSnapshot(n,d);Y(e,n,d,u,t[s])?r[s]=j(e,n,d,u):r[s]=B(e,n,d,u,i);}return r}function ge(e,n,o){if(!n.elements)return;let t=Z(n,[],n.elements).filter(([r,a])=>!a.elements||Object.keys(a.elements).length===0?false:a.type!=="BackboneElement"?fe(e,n,r):true),i=[];for(let[r,a]of t){let l=V(e,n,r),c;a.type==="BackboneElement"||!a.type?c="BackboneElement":c=a.type;let s=e.ensureSpecializationCanonicalUrl(c),d=e.resolveFs(n.package_meta,s);if(!d)throw new Error(`Could not resolve base type ${c}`);let u={kind:"complex-type",package:d.package_meta.name,version:d.package_meta.version,name:c,url:s},h=Ge(e,n,r,a.elements??{},o),p={identifier:l,base:u,fields:h};i.push(p);}return i.sort((r,a)=>r.identifier.url.localeCompare(a.identifier.url)),i.length===0?void 0:i}function ye(e){let n=[];for(let o of e){o.base&&n.push(o.base);for(let t of Object.values(o.fields||{}))"type"in t&&t.type&&n.push(t.type),"binding"in t&&t.binding&&n.push(t.binding);}return n}function he(e,n,o){let t=o[o.length-1];if(!t)throw new Error(`Internal error: fieldName is missing for path ${o.join("/")}`);let i=o.slice(0,-1),r=e.resolveFsGenealogy(n.package_meta,n.url).flatMap(a=>{if(i.length===0)return a.required||[];if(!a.elements)return [];let l=a;for(let c of i)l=l?.elements?.[c];return l?.required||[]});return new Set(r).has(t)}function Se(e,n,o){let t=o[o.length-1];if(!t)throw new Error(`Internal error: fieldName is missing for path ${o.join("/")}`);let i=o.slice(0,-1),r=e.resolveFsGenealogy(n.package_meta,n.url).flatMap(a=>{if(i.length===0)return a.excluded||[];if(!a.elements)return [];let l=a;for(let c of i)l=l?.elements?.[c];return l?.excluded||[]});return new Set(r).has(t)}var ze=(e,n,o)=>{if(o.refers)return o.refers.map(t=>{let i=e.ensureSpecializationCanonicalUrl(t),r=e.resolveFs(n.package_meta,i);if(!r)throw new Error(`Failed to resolve fs for ${i}`);return I(r)})},We=e=>{let n=new Set,o=new Set;if(e.required)for(let i of e.required)n.add(i);if(e.excluded)for(let i of e.excluded)o.add(i);if(e.elements)for(let[i,r]of Object.entries(e.elements))r.min!==void 0&&r.min>0&&n.add(i);let t=e.elements?Object.keys(e.elements):void 0;return {required:n.size>0?Array.from(n):void 0,excluded:o.size>0?Array.from(o):void 0,elements:t&&t.length>0?t:void 0}},qe=e=>!e||typeof e=="object"&&Object.keys(e).length===0,O=(e,n,o)=>{let t=e;for(let r=0;r<n.length-1;r++){let a=n[r];(!t[a]||typeof t[a]!="object")&&(t[a]={}),t=t[a];}let i=n[n.length-1];t[i]=o;},Ke=(e,n)=>{let o=e;for(let t of n)if(o&&typeof o=="object"&&!Array.isArray(o))o=o[t];else return;return o},Re=(e,n,o,t,i)=>{if(o>=n.length||!e.elements)return;let r=n[o],a=e.elements[r];if(a){if(o===n.length-1&&a.fixed?.value!==void 0){O(t,n,a.fixed.value);return}if(a.slicing?.slices){i.add(n.slice(0,o+1).join("."));let l=n.slice(o+1);for(let c of Object.values(a.slicing.slices)){if(!c.min||c.min<1||!c.match||typeof c.match!="object")continue;let s=c.match;if(Object.keys(s).length!==0)if(l.length>0){let d=Ke(s,l);d!==void 0&&O(t,n,d);}else O(t,n.slice(0,o+1),s);}return}Re(a,n,o+1,t,i);}},Je=(e,n,o)=>{if(e==="$this")return;let t=e.split("."),i=n;for(let a of t)if(i=i?.elements?.[a],!i)return;let r=i.type;!r||r.includes("/")||O(o,t,{resourceType:r});},Ye=(e,n)=>{if(!n||!e||e.length===0)return;let o={},t=new Set;for(let i of e)if(i.type==="type")Je(i.path,n,o);else {if(!n.elements)continue;let r=i.path.split(".");Re(n,r,0,o,t);}if(Object.keys(o).length!==0){for(let i of t){let r=i.split("."),a=o;for(let c=0;c<r.length-1;c++){let s=a[r[c]];if(!s||typeof s!="object"||Array.isArray(s))break;a=s;}let l=r[r.length-1];a[l]&&typeof a[l]=="object"&&!Array.isArray(a[l])&&(a[l]=[a[l]]);}return o}},xe=e=>{let n=e.slicing;if(!n)return;let o={};for(let[t,i]of Object.entries(n.slices??{})){if(!i)continue;let{required:r,excluded:a,elements:l}=i.schema?We(i.schema):{};o[t]={min:i.min,max:i.max,match:qe(i.match)?Ye(n.discriminator??[],i.schema):i.match,required:r,excluded:a,elements:l};}return {discriminator:n.discriminator??[],rules:n.rules,ordered:n.ordered,slices:Object.keys(o).length>0?o:void 0}};function E(e,n,o,t,i){if(t.elementReference){let r=t.elementReference.slice(1).filter((a,l)=>l%2===1);return V(e,n,r)}else if(t.type){let r=e.ensureSpecializationCanonicalUrl(t.type),a=e.resolveFs(n.package_meta,r);if(!a)throw new Error(`Could not resolve field type: <${n.url}>.${o.join(".")}: <${t.type}> (pkg: '${R(n.package_meta)}'))`);return I(a)}else {if(t.choices)return;if(n.derivation==="constraint")return;i?.dryWarn("#fieldTypeNotFound",`Can't recognize element type: <${n.url}>.${o.join(".")} (pkg: '${R(n.package_meta)}'): missing type info`);return}}var B=(e,n,o,t,i,r)=>{let a,l;t.binding&&(a=L(n,o,t),W.has(t.type??"")&&(l=q(e,n,t,i)));let c=E(e,n,o,t,i);c||i?.dryWarn("#fieldTypeNotFound",`Field type not found for '${n.url}#${o.join(".")}' (${n.derivation})`);let s;t.pattern?s={kind:"pattern",type:t.pattern.type,value:t.pattern.value}:t.fixed&&(s={kind:"fixed",type:t.fixed.type,value:t.fixed.value});let d=r??t;if(!s&&d.elements?.coding?.slicing?.slices){let u=d.elements.coding.slicing.slices,h=Object.values(u);if(h.length>0&&h.every(m=>m.min!==void 0&&m.min>=1&&m.match&&typeof m.match=="object"&&Object.keys(m.match).length>0)){let m=h.map(f=>f.match);s={kind:"fixed",type:"CodeableConcept",value:{coding:m.length===1?[m[0]]:m}};}}return {type:c,required:he(e,n,o),excluded:Se(e,n,o),reference:ze(e,n,t),array:t.array||false,min:t.min,max:t.max,slicing:xe(t),choices:t.choices,choiceOf:t.choiceOf,binding:a,enum:l,valueConstraint:s,mustSupport:t.mustSupport}};function j(e,n,o,t){return {type:V(e,n,o),array:t.array||false,required:he(e,n,o),excluded:Se(e,n,o),slicing:xe(t)}}var Ze=(e,n,o,t)=>{let i=e.resolveFs(n.package_meta,o);if(!i?.elements)return;let r=[];for(let[a,l]of Object.entries(i.elements)){if(l.choiceOf!=="value"&&!a.startsWith("value"))continue;let c=E(e,i,[a],l,t);c&&r.push(c);}return v(r)},Qe=(e,n,o)=>{let t=[];if(!n.elements)return t;for(let[i,r]of Object.entries(n.elements)){if(!i.startsWith("extension:"))continue;let a=i.split(":")[1];if(!a)continue;let l;for(let[c,s]of Object.entries(r.elements??{}))if(!(s.choiceOf!=="value"&&!c.startsWith("value"))&&(l=E(e,n,[i,c],s,o),l))break;t.push({name:a,url:r.url??a,valueFieldType:l,min:r.min,max:r.max!==void 0?String(r.max):void 0});}return t},Xe=(e,n,o)=>{let t=[],r=n.elements?.extension?.slicing?.slices;if(!r||typeof r!="object")return t;for(let[a,l]of Object.entries(r)){let c=l,s=c.schema;if(!s)continue;let d;for(let[u,h]of Object.entries(s.elements??{})){let p=h;if(!(p.choiceOf!=="value"&&!u.startsWith("value"))&&(d=E(e,n,[u],p,o),d))break}t.push({name:a,url:c.match?.url??a,valueFieldType:d,min:s._required?1:s.min??0,max:s.max!==void 0?String(s.max):s.array?"*":"1"});}return t},en=(e,n,o,t)=>{let i=e.resolveFs(n.package_meta,o);if(!i?.elements)return;let r=Qe(e,i,t),a=Xe(e,i,t),l=[...r,...a];return l.length>0?l:void 0},ke=(e,n,o)=>{let t=[],i=(c,s,d)=>{let u=d.url,h=u?Ze(e,n,u,o):void 0,p=u?en(e,n,u,o):void 0;if(!u){let y=n.elements?.extension?.slicing?.slices?.[s]?.schema;if(y){u=y.elements?.url?.fixed?.value??s;for(let[S,x]of Object.entries(y.elements??{})){let k=x;if(k.choiceOf==="value"||S.startsWith("value")){let D=E(e,n,[S],k,o);if(D){h=[D];break}}}}}let m=p&&p.length>0,f=u?e.resolveFs(n.package_meta,u):void 0,g=f?I(f):void 0;t.push({name:s,path:[...c,"extension"].join("."),url:u,profile:g,min:d.min,max:d.max!==void 0?String(d.max):void 0,mustSupport:d.mustSupport,valueFieldTypes:h,subExtensions:p,isComplex:m});},r=(c,s)=>{if(s.extensions)for(let[d,u]of Object.entries(s.extensions))i(c,d,u);if(s.elements)for(let[d,u]of Object.entries(s.elements))r([...c,d],u);};r([],n);let a=new Set,l=t.filter(c=>{let s=`${c.url}:${c.path}`;return a.has(s)?false:(a.add(s),true)});return l.length===0?void 0:l};function nn(e,n,o,t,i){if(!t)return;let r={};for(let a of e.getAllElementKeys(t)){let l=[...o,a],c=e.resolveElementSnapshot(n,l),s=c.type?e.ensureSpecializationCanonicalUrl(c.type):void 0;if(s&&T(n.package_meta,s).shouldSkip){i?.warn("#skipCanonical",`Skipping field ${l} for ${s} due to skip hack ${T(n.package_meta,s).reason}`);continue}Y(e,n,l,c,t[a])?r[a]=j(e,n,l,c):r[a]=B(e,n,l,c,i,t[a]);}return r}function tn(e){let n=[];for(let o of Object.values(e))"type"in o&&o.type&&n.push(o.type),"binding"in o&&o.binding&&n.push(o.binding);return n}async function be(e,n,o){if(!n.url)throw new Error("ValueSet URL is required");let t=N(e,n.package_meta,n.url),i=z(e,n.package_meta,n.url);return {identifier:t,description:n.description,concept:i,compose:i?void 0:n.compose}}var Fe=(e,n,o)=>{let t=[];return e&&t.push(e),n&&t.push(...tn(n)),o&&t.push(...ye(o)),t},Ie=(e,n,o,t)=>{let r=Fe(n,o,t).filter(a=>!(a.url===e.url||A(a)));return v(r)},on=(e,n,o,t)=>{let r=Fe(n,o,t).filter(a=>a.url!==e.url);return v(r)};function Te(e,n,o){let t;if(n.base){let s=e.resolveFs(n.package_meta,e.ensureSpecializationCanonicalUrl(n.base));if(!s)throw new Error(`Base resource not found '${n.base}' for <${n.url}> from ${R(n.package_meta)}`);let d=I(s);Ce(!A(d),`Unexpected nested base for ${n.url}`),t=d;}let i=nn(e,n,[],n.elements,o),r=ge(e,n,o),a=le(e,n,o);if(n.derivation==="constraint"){let s=I(n);if(!t)throw new Error(`Profile ${n.url} must have a base type`);let d=ke(e,n,o),u=d?.flatMap(ae),h=on(s,t,i,r);return [{identifier:s,base:t,fields:i,nested:r,description:n.description,dependencies:v(h,u),extensions:d},...a]}if(n.kind==="primitive-type"){let s=I(n);return Ce(t,`Primitive type ${n.url} must have a base type`),[{identifier:s,description:n.description,base:t,dependencies:Ie(s,t,i,r)},...a]}let l=I(n);return [{identifier:l,base:t,fields:i,nested:r,description:n.description,dependencies:Ie(l,t,i,r),typeFamily:void 0},...a]}var rn=(e,n,o)=>{let t={};for(let a of e){let l=`${a.schema.identifier.url}|${a.schema.identifier.package}`,c=oe(a.schema);t[l]??={},t[l][c]??={typeSchema:a.schema,sources:[]},t[l][c].sources.push(a);}let i=[],r={};for(let a of Object.values(t)){let l=Object.values(a).sort((s,d)=>d.sources.length-s.sources.length),c=l[0];if(c)if(l.length>1){let s=c.typeSchema.identifier.url,d=c.typeSchema.identifier.package;o?.dryWarn("#duplicateSchema",`'${s}' from '${d}' has ${l.length} versions`),i.push(c.typeSchema);r[d]??={},r[d][s]=l.flatMap(h=>h.sources.map(p=>({typeSchema:h.typeSchema,sourcePackage:p.sourcePackage,sourceCanonical:p.sourceCanonical})));}else i.push(c.typeSchema);}return {schemas:i,collisions:r}},ve=async(e,n,o)=>{let t=[];for(let i of e.allFs()){let r=R(i.package_meta),a=T(i.package_meta,i.url);if(a.shouldSkip){o?.dryWarn("#skipCanonical",`Skip ${i.url} from ${r}. Reason: ${a.reason}`);continue}for(let l of Te(e,i,o))t.push({schema:l,sourcePackage:r,sourceCanonical:i.url});}for(let i of e.allVs())t.push({schema:await be(e,i),sourcePackage:R(i.package_meta),sourceCanonical:i.url});return rn(t,n,o)};var Ee={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async e=>{let n=C({prefix:"TypeSchema"});try{n.info("Generating TypeSchema from FHIR packages"),n.info(`Packages: ${e.packages.join(", ")}`),n.info(`Output: ${e.output}`);let o=e.singleFile?"ndjson":e.format;n.debug(`Format: ${o}${e.singleFile&&e.format==="json"?" (forced from json due to singleFile)":""}`),e.treeshake&&e.treeshake.length>0&&n.info(`Treeshaking enabled for ResourceTypes: ${e.treeshake.join(", ")}`),e.singleFile&&n.info("Single file output enabled (NDJSON format)"),e.registry&&n.info(`Using custom registry: ${e.registry}`);let t=Date.now(),i=e.packages.map(d=>{if(d.includes("@")){let u=d.lastIndexOf("@");return {name:d.slice(0,u),version:d.slice(u+1)||"latest"}}return {name:d,version:"latest"}});n.info(`Processing packages: ${i.map(d=>`${d.name}@${d.version}`).join(", ")}`);let r=await ue(i,{logger:n,registry:e.registry,focusedPackages:i}),{schemas:a}=await ve(r,void 0,n);if(a.length===0)throw new Error("No schemas were generated from the specified packages");let l=e.output;if(!l)throw new Error("Output format not specified");await mkdir(dirname(l),{recursive:!0});let c;o==="json"?c=JSON.stringify(a,null,2):c=a.map(d=>JSON.stringify(d)).join(`
|
|
3
|
-
`),await writeFile(l,
|
|
2
|
+
import b from'picocolors';import In from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import Ne from'assert';import {createHash}from'crypto';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as he from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var ie=e=>{console.log(),console.log(b.cyan(b.bold(`\u2501\u2501\u2501 ${e} \u2501\u2501\u2501`)));},re=(e,n,i)=>{let t=e;if(n&&(t+=` ${b.gray(`(${n}ms)`)}`),console.log(`${b.green("")} ${t}`),i)for(let[r,o]of Object.entries(i))console.log(b.gray(` ${r}: ${o}`));},F=(e,n="\u2022")=>{for(let i of e)console.log(b.gray(` ${n} ${i}`));};var oe={DEBUG:0,INFO:1,WARN:2,ERROR:3,SILENT:4};function k(e={}){let n=e.prefix??"",i=new Set(e.suppressTags??[]),t={},r=[],o=new Set,a=e.level??"INFO",c=p=>oe[p]>=oe[a],l={DEBUG:p=>p,INFO:p=>p,WARN:b.yellow,ERROR:b.red,SILENT:p=>p},s=(p,m,f,y)=>{let h=n?`${n}: `:"",S=y?` ${b.dim(`(${y})`)}`:"";return l[p](`${m} ${h}${f}`)+S},d=(p,m,f,y=false)=>{r.push({level:p,tag:f,message:m,suppressed:y,prefix:n,timestamp:Date.now()});},u=(p,m,f,y=false)=>(...h)=>{let S=h.length===2?h[0]:void 0,x=h.length===2?h[1]:h[0];S&&(t[S]=(t[S]??0)+1);let C=S!==void 0&&i.has(S);if(d(p,x,S,C),!C&&c(p)){if(y){let N=`${p}::${S??""}::${x}`;if(o.has(N))return;o.add(N);}f(s(p,m,x,S));}},g={warn:u("WARN","!",console.warn),dryWarn:u("WARN","!",console.warn,true),info:u("INFO","i",console.log),error:u("ERROR","X",console.error),debug:u("DEBUG","D",console.log),fork(p,m){let f=n?`${n}/${p}`:p,y=[...i,...m?.suppressTags??[]];return k({prefix:f,suppressTags:y,level:m?.level??a})},as(){return g},tagCounts(){return t},printTagSummary(){let p=Object.entries(t);if(p.length===0)return;let m=n?`${n}: `:"",f=p.filter(([h])=>!i.has(h)),y=p.filter(([h])=>i.has(h));if(f.length>0){let h=f.reduce((x,[,C])=>x+C,0),S=f.map(([x,C])=>`${x}: ${C}`).join(", ");console.warn(b.yellow(`! ${m}${h} warnings (${S})`));}if(y.length>0){let h=y.reduce((x,[,C])=>x+C,0),S=y.map(([x,C])=>`${x}: ${C}`).join(", ");console.log(b.dim(`i ${m}${h} suppressed (${S})`));}},buffer(){return r},bufferClear(){r.length=0;}};return g}var D="Use CodeableReference which is not provided by FHIR R4.",Be="Use Availability which is not provided by FHIR R4.",A={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":Be,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":D,"http://hl7.org/fhir/StructureDefinition/specimen-additive":D,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":D,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":D,"http://hl7.org/fhir/StructureDefinition/workflow-reason":D},"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 T(e,n){let i=`${e.name}#${e.version}`,t=A[i]?.[n];if(t)return {shouldSkip:true,reason:t};let r=A[e.name]?.[n];return r?{shouldSkip:true,reason:r}:{shouldSkip:false}}var R=e=>`${e.name}#${e.version}`,ae=e=>`${e.name}@${e.version}`,se=e=>{let n=JSON.stringify(e);return createHash("sha256").update(n).digest("hex").slice(0,16)},ce=(e,n)=>{let i=e.derivation==="constraint"?"constraint":"specialization";return {...e,derivation:i,kind:e.kind,package_meta:e.package_meta||n,name:e.name,url:e.url,base:e.base}};var z=e=>e?.kind==="nested";var v=(...e)=>{let n=e.filter(t=>t!==void 0).flatMap(t=>t.map(r=>[r.url,r]));return n.length===0?void 0:Object.values(Object.fromEntries(n)).sort((t,r)=>t.url.localeCompare(r.url))};var le=e=>[...e.valueFieldTypes??[],...e.profile?[e.profile]:[],...e.subExtensions?.flatMap(n=>n.valueFieldType?[n.valueFieldType]:[])??[]];var pe=(e,n)=>{if(!e.url)throw new Error("ValueSet must have a URL");if(!e.name)throw new Error("ValueSet must have a name");return {...e,package_meta:e.package_meta||n,name:e.name,url:e.url}};function G(e){let n=e.split("|")[0];return n||e}function Oe(e){return e.split("|")[1]}var je=e=>({package:e.package_meta.name,version:e.package_meta.version,name:e.name,url:e.url});function I(e){let n=je(e);return e.derivation==="constraint"?{kind:"profile",...n}:e.kind==="primitive-type"?{kind:"primitive-type",...n}:e.kind==="complex-type"?{kind:"complex-type",...n}:e.kind==="resource"?{kind:"resource",...n}:e.kind==="logical"?{kind:"logical",...n}:{kind:"resource",...n}}var Me=e=>{let n=e.split("/"),i=n[n.length-1];return i&&i.length>0?i.split(/[-_]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join(""):e};function H(e,n,i){let t=G(i),r=Me(t),o={package_meta:{name:"missing_valuesets",version:Oe(t)||"0.0.0"},id:i},a=e.resolveVs(n,t)||o,c=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:c,url:t}}function L(e,n,i){let t=i.binding?.bindingName,r=n.join("."),[o,a,c]=t?[{name:"shared",version:"1.0.0"},t,`urn:fhir:binding:${t}`]:[e.package_meta,`${e.name}.${r}_binding`,`${e.url}#${r}_binding`];return {kind:"binding",package:o.name,version:o.version,name:a,url:c}}function q(e,n,i,t){let r=G(i)||i,o=e.resolveVs(n,r);if(o)return Ae(e,o)}function Ae(e,n,i){if(n.expansion?.contains)return n.expansion.contains.filter(r=>r.code!==void 0).map(r=>(Ne(r.code),{code:r.code,display:r.display,system:r.system}));let t=[];if(n.compose?.include){for(let r of n.compose.include)if(r.concept)for(let o of r.concept)t.push({system:r.system,code:o.code,display:o.display});else if(r.system&&!r.filter)try{let o=e.resolveAny(r.system);if(o?.concept){let a=(c,l)=>{for(let s of c)t.push({system:l,code:s.code,display:s.display}),s.concept&&a(s.concept,l);};a(o.concept,r.system);}}catch{}}return t.length>0?t:void 0}var de=100,W=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function K(e,n,i,t){if(!i.binding)return;let r=i.binding.strength,o=i.binding.valueSet;if(!o)return;if(!W.has(i.type??"")){t?.dryWarn("#binding",`eld-11: Binding on non-bindable type '${i.type}' (valueSet: ${o})`);return}if(!(r==="required"||r==="extensible"||r==="preferred"))return;let c=q(e,n.package_meta,o);if(!c||c.length===0)return;let l=c.map(s=>s.code).filter(s=>s&&typeof s=="string"&&s.trim().length>0);if(l.length>de){t?.dryWarn("#largeValueSet",`Value set ${o} has ${l.length} which is more than ${de} codes, which may cause issues with code generation.`);return}if(l.length!==0)return {isOpen:r!=="required",values:l}}function ze(e,n,i,t,r){if(!t.binding?.valueSet)return;let o=L(n,i,t),a=H(e,n.package_meta,t.binding.valueSet),c=K(e,n,t,r);return {identifier:o,valueset:a,strength:t.binding.strength,enum:c,dependencies:[a]}}function me(e,n,i){let t=new Set;if(!n.elements)return [];let r=[];function o(l,s){for(let[d,u]of Object.entries(l)){let g=[...s,d],p=g.join("."),m=e.resolveElementSnapshot(n,g);if(!t.has(p)){if(t.add(p),m.binding){let f=ze(e,n,g,m,i);f&&r.push(f);}u.elements&&o(u.elements,g);}}}o(n.elements,[]),r.sort((l,s)=>l.identifier.name.localeCompare(s.identifier.name));let a=[],c=new Set;for(let l of r)c.has(l.identifier.url)||(c.add(l.identifier.url),a.push(l));return a}var Ge=e=>e.split(/(?<=[a-z])(?=[A-Z])|[-_.\s]/).filter(Boolean);var qe=e=>{if(e.length===0)throw new Error("Empty string");return e[0]?.toUpperCase()+e.substring(1).toLowerCase()},ue=e=>{if(e.length===0)throw new Error("Empty string");let[n,...i]=Ge(e);return [n?.toLowerCase(),...i.map(qe)].join("")};var J=e=>!e||e.length===0?e:e.charAt(0).toUpperCase()+e.slice(1);var We=e=>{let n=e.replace(/\[x\]/g,"").replace(/[- :.]/g,"_");return n?J(n):""},w=e=>{let n=e.replace(/\[x\]/g,"").replace(/:/g,"_");return n?J(ue(n)):""},Ke=(e,n)=>{let i=w(e)||"Extension",t=n.split(".").filter(a=>a&&a!=="extension").join("_"),o=`${t?w(t):""}${i}`;return [i,o,`${o}Extension`]},Je=(e,n)=>{let i=We(n)||"Slice",r=`${w(e)||"Field"}${i}`;return [i,r,`${r}Slice`]},Ye=(e,n,i)=>e.reduce((t,r)=>{let o=r.candidates[n]??"";return t[o]=(t[o]??0)+1,i.has(o)&&(t[o]=(t[o]??0)+1),t},{}),Ze=(e,n)=>{let i=e[0]?.candidates.length??0,t=(r,o)=>{if(r.length===0||o>=i)return {};let a=Ye(r,o,n),c=o>=i-1,[l,s]=r.reduce(([d,u],g)=>{let p=g.candidates[o]??"";return (a[p]??0)>1&&!c?[d,[...u,g]]:[{...d,[g.key]:p},u]},[{},[]]);return {...l,...t(s,o+1)}};return t(e,0)},fe=e=>({candidates:Ke(e.name,e.path),recommended:""}),ge=(e,n)=>({candidates:Je(e,n),recommended:""}),ye=e=>{let n=(e.extensions??[]).filter(a=>a.url).map(a=>({key:`ext:${a.url}:${a.path}`,candidates:a.nameCandidates.candidates})),i=Object.entries(e.fields??{}).flatMap(([a,c])=>!("slicing"in c)||!c.slicing?.slices?[]:Object.entries(c.slicing.slices).map(([l,s])=>({key:`slice:${a}:${l}`,candidates:s.nameCandidates.candidates}))),t=new Set(Object.keys(e.fields??{}).map(w)),r=[...n,...i];if(r.length===0)return;let o=Ze(r,t);for(let a of e.extensions??[]){if(!a.url)continue;let c=`ext:${a.url}:${a.path}`;o[c]&&(a.nameCandidates.recommended=o[c]);}for(let[a,c]of Object.entries(e.fields??{}))if(!(!("slicing"in c)||!c.slicing?.slices))for(let[l,s]of Object.entries(c.slicing.slices)){let d=`slice:${a}:${l}`;o[d]&&(s.nameCandidates.recommended=o[d]);}};var Y=e=>e!==null&&typeof e=="object"&&e.resourceType==="CodeSystem";var U=e=>e!==null&&typeof e=="object"&&e.resourceType==="ValueSet";var Xe=async(e,n)=>{let i=await e.packageJson(n.name);if(!i)return [];let t=i.dependencies;return t!==void 0?Object.entries(t).map(([r,o])=>({name:r,version:o})):[]},Se=e=>({pkg:e,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),Re=async(e,n,i,t,r)=>{let o=R(n);if(r?.info(`${" ".repeat(i*2)}+ ${o}`),t[o])return t[o];let a=Se(n);for(let l of await e.search({package:n})){let s=l.url;if(!s||!(isStructureDefinition(l)||U(l)||Y(l)))continue;let d=s;a.canonicalResolution[d]&&r?.dryWarn("#duplicateCanonical",`Duplicate canonical URL: ${d} at ${o}.`),a.canonicalResolution[d]=[{deep:i,pkg:n,pkgId:o,resource:l}];}let c=await Xe(e,n);for(let l of c){let{canonicalResolution:s}=await Re(e,l,i+1,t,r);for(let[d,u]of Object.entries(s)){let g=d;a.canonicalResolution[g]=[...a.canonicalResolution[g]||[],...u];}}for(let l of Object.values(a.canonicalResolution))l.sort((s,d)=>s.deep-d.deep);return t[o]=a,a},en=(e,n)=>{for(let{pkg:i,canonicalResolution:t}of Object.values(e)){let r=R(i);if(!e[r])throw new Error(`Package ${r} not found`);let o=0;n?.info(`FHIR Schema conversion for '${R(i)}' begins...`);for(let[a,c]of Object.entries(t)){let l=c[0];if(!l)throw new Error("Resource not found");let s=l.resource,d=l.pkg;if(isStructureDefinition(s)){let u=he.translate(s),g=ce(u,d);o++,e[r].fhirSchemas[g.url]=g;}if(U(s)){let u=pe(s,d);e[r].valueSets[u.url]=u;}}n?.info(`FHIR Schema conversion for '${R(i)}' completed: ${o} successful`);}},nn=(e,n,i)=>{let t=Object.values(e).flatMap(r=>r.canonicalResolution[n]);if(!t)throw new Error(`No canonical resolution found for ${n} in any package`);return t[0]?.resource},tn=async(e,{logger:n,focusedPackages:i})=>{let t=i??await e.packages(),r={};for(let p of t)await Re(e,p,0,r,n);en(r,n);let o=(p,m)=>{let f=r[R(p)];if(f){let y=f.canonicalResolution[m]?.[0];if(y)return r[y.pkgId]?.fhirSchemas[m]}for(let y of Object.values(r)){let h=y.fhirSchemas[m];if(h&&h.package_meta.name===p.name)return h}for(let y of Object.values(r)){let h=y.fhirSchemas[m];if(h)return h}},a=(p,m)=>{let f=r[R(p)];if(f){let y=f.canonicalResolution[m]?.[0];if(y)return r[y.pkgId]?.valueSets[m]}for(let y of Object.values(r)){let h=y.valueSets[m];if(h&&h.package_meta.name===p.name)return h}for(let y of Object.values(r)){let h=y.valueSets[m];if(h)return h}},c=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),l=(p,m)=>{let f=o(p,m);if(f===void 0)throw new Error(`Failed to resolve FHIR Schema: '${m}'`);let y=[f];for(;f?.base;){let h=f.package_meta,S=c(f.base);if(f=o(h,S),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${m}'. Problem: '${S}' from '${R(h)}'`);y.push(f);}return y},s=(p,m)=>l(p,m).filter(f=>f.derivation==="specialization"),d=(p,m)=>{let f=l(p.package_meta,p.url),y=B(f,m);return Z(y)},u=p=>{let m=new Set;for(let[f,y]of Object.entries(p)){m.add(f);for(let h of y?.choices||[])p[h]||m.add(h);}return Array.from(m)},g;return {testAppendFs(p){let m=R(p.package_meta);r[m]||(r[m]=Se(p.package_meta)),r[m].fhirSchemas[p.url]=p,g=void 0;},resolveFs:o,resolveFsGenealogy:l,resolveFsSpecializations:s,ensureSpecializationCanonicalUrl:c,resolveSd:(p,m)=>{let f=r[R(p)]?.canonicalResolution[m]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(r).flatMap(p=>Object.values(p.canonicalResolution).flatMap(m=>m.map(f=>{let y=f.resource;return y.package_name?y:{...y,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,m)=>p.url.localeCompare(m.url)),allFs:()=>Object.values(r).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(r).flatMap(p=>Object.values(p.valueSets)),resolveVs:a,resolveAny:p=>nn(r,p),resolveElementSnapshot:d,getAllElementKeys:u,resolver:r,resolutionTree:()=>{if(g)return g;let p={};for(let[m,f]of Object.entries(r)){let y=f.pkg.name;p[y]={};for(let[h,S]of Object.entries(f.canonicalResolution)){let x=h;p[y][x]=[];for(let C of S)p[y][x].push({deep:C.deep,pkg:C.pkg});}}return g=p,p}}},xe=async(e,n)=>{let i=e.map(ae);n?.logger?.info(`Loading FHIR packages: ${i.join(", ")}`);let t=CanonicalManager({packages:i,workingDir:".codegen-cache/canonical-manager-cache",registry:n.registry||void 0});return await t.init(),await tn(t,{...n,focusedPackages:e})},B=(e,n)=>{let[i,...t]=n;return i===void 0?[]:e.map(r=>{if(!r.elements)return;let o=r.elements?.[i];for(let a of t)o=o?.elements?.[a];return o}).filter(r=>r!==void 0)};function Z(e){let n=e.reverse(),i=Object.assign({},...n);return i.elements=void 0,i}var Ce=(e,n,i)=>{let t=e.resolveFsSpecializations(n.package_meta,n.url),r=B(t,i),o=Z(r).type,a;if(o){let c=e.ensureSpecializationCanonicalUrl(o),s=e.resolveFsGenealogy(n.package_meta,c).flatMap(d=>Object.keys(d.elements??{}));s.length>0&&(a=new Set(s));}for(let c of r)if(!(!c.elements||Object.keys(c.elements).length===0)&&!(a&&!Object.keys(c.elements).some(l=>!a.has(l))))return true;return false},Q=(e,n,i,t,r)=>t.type==="BackboneElement"?true:!r?.elements||r.choiceOf!==void 0?false:Ce(e,n,i),rn=e=>e.elements?new Set(X(e,[],e.elements).filter(([n,i])=>i.elements&&Object.keys(i.elements).length>0).map(([n])=>n.join("."))):new Set;function V(e,n,i){let t={},r=n.derivation==="constraint"?e.resolveFsSpecializations(n.package_meta,n.url):e.resolveFsGenealogy(n.package_meta,n.url);for(let d of [...r].reverse()){let u=rn(d);for(let g of u)t[g]=`${d.url}#${g}`;}let o=i.join("."),a=t[o]??`${n.url}#${o}`,c=a.split("#")[0],s=e.resolveFs(n.package_meta,c)?.package_meta??n.package_meta;return {kind:"nested",package:s.name,version:s.version,name:o,url:a}}function X(e,n,i){let t=[];for(let[r,o]of Object.entries(i)){let a=[...n,r];o.elements&&o.choiceOf===void 0&&t.push([a,o]),o.elements&&t.push(...X(e,a,o.elements));}return t}function on(e,n,i,t,r){let o={},a=e.resolveFsGenealogy(n.package_meta,n.url),c=B(a,i),l=new Set;for(let s of c)if(s.elements)for(let d of Object.keys(s.elements))l.add(d);for(let s of l){let d=[...i,s],u=e.resolveElementSnapshot(n,d);Q(e,n,d,u,t[s])?o[s]=j(e,n,d,u):o[s]=O(e,n,d,u,r);}return o}function ke(e,n,i){if(!n.elements)return;let t=X(n,[],n.elements).filter(([o,a])=>!a.elements||Object.keys(a.elements).length===0?false:a.type!=="BackboneElement"?Ce(e,n,o):true),r=[];for(let[o,a]of t){let c=V(e,n,o),l;a.type==="BackboneElement"||!a.type?l="BackboneElement":l=a.type;let s=e.ensureSpecializationCanonicalUrl(l),d=e.resolveFs(n.package_meta,s);if(!d)throw new Error(`Could not resolve base type ${l}`);let u={kind:"complex-type",package:d.package_meta.name,version:d.package_meta.version,name:l,url:s},g=on(e,n,o,a.elements??{},i),p={identifier:c,base:u,fields:g};r.push(p);}return r.sort((o,a)=>o.identifier.url.localeCompare(a.identifier.url)),r.length===0?void 0:r}function Ie(e){let n=[];for(let i of e){i.base&&n.push(i.base);for(let t of Object.values(i.fields||{}))"type"in t&&t.type&&n.push(t.type),"binding"in t&&t.binding&&n.push(t.binding);}return n}function be(e,n,i){let t=i[i.length-1];if(!t)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let r=i.slice(0,-1),o=e.resolveFsGenealogy(n.package_meta,n.url).flatMap(a=>{if(r.length===0)return a.required||[];if(!a.elements)return [];let c=a;for(let l of r)c=c?.elements?.[l];return c?.required||[]});return new Set(o).has(t)}function Fe(e,n,i){let t=i[i.length-1];if(!t)throw new Error(`Internal error: fieldName is missing for path ${i.join("/")}`);let r=i.slice(0,-1),o=e.resolveFsGenealogy(n.package_meta,n.url).flatMap(a=>{if(r.length===0)return a.excluded||[];if(!a.elements)return [];let c=a;for(let l of r)c=c?.elements?.[l];return c?.excluded||[]});return new Set(o).has(t)}var an=(e,n,i)=>{if(i.refers)return i.refers.map(t=>{let r=e.ensureSpecializationCanonicalUrl(t),o=e.resolveFs(n.package_meta,r);if(!o)throw new Error(`Failed to resolve fs for ${r}`);return I(o)})},sn=e=>{let n=new Set,i=new Set;if(e.required)for(let r of e.required)n.add(r);if(e.excluded)for(let r of e.excluded)i.add(r);if(e.elements)for(let[r,o]of Object.entries(e.elements))o.min!==void 0&&o.min>0&&n.add(r);let t=e.elements?Object.keys(e.elements):void 0;return {required:n.size>0?Array.from(n):void 0,excluded:i.size>0?Array.from(i):void 0,elements:t&&t.length>0?t:void 0}},cn=e=>!e||typeof e=="object"&&Object.keys(e).length===0,M=(e,n,i)=>{let t=e;for(let o=0;o<n.length-1;o++){let a=n[o];(!t[a]||typeof t[a]!="object")&&(t[a]={}),t=t[a];}let r=n[n.length-1];t[r]=i;},ln=(e,n)=>{let i=e;for(let t of n)if(i&&typeof i=="object"&&!Array.isArray(i))i=i[t];else return;return i},Te=(e,n,i,t,r)=>{if(i>=n.length||!e.elements)return;let o=n[i],a=e.elements[o];if(a){if(i===n.length-1&&a.fixed?.value!==void 0){M(t,n,a.fixed.value);return}if(a.slicing?.slices){r.add(n.slice(0,i+1).join("."));let c=n.slice(i+1);for(let l of Object.values(a.slicing.slices)){if(!l.min||l.min<1||!l.match||typeof l.match!="object")continue;let s=l.match;if(Object.keys(s).length!==0)if(c.length>0){let d=ln(s,c);d!==void 0&&M(t,n,d);}else M(t,n.slice(0,i+1),s);}return}Te(a,n,i+1,t,r);}},pn=(e,n,i)=>{if(e==="$this")return;let t=e.split("."),r=n;for(let a of t)if(r=r?.elements?.[a],!r)return;let o=r.type;!o||o.includes("/")||M(i,t,{resourceType:o});},dn=(e,n)=>{if(!n||!e||e.length===0)return;let i={},t=new Set;for(let r of e)if(r.type==="type")pn(r.path,n,i);else {if(!n.elements)continue;let o=r.path.split(".");Te(n,o,0,i,t);}if(Object.keys(i).length!==0){for(let r of t){let o=r.split("."),a=i;for(let l=0;l<o.length-1;l++){let s=a[o[l]];if(!s||typeof s!="object"||Array.isArray(s))break;a=s;}let c=o[o.length-1];a[c]&&typeof a[c]=="object"&&!Array.isArray(a[c])&&(a[c]=[a[c]]);}return i}},ve=(e,n)=>{let i=n.slicing;if(!i)return;let t={};for(let[r,o]of Object.entries(i.slices??{})){if(!o)continue;let{required:a,excluded:c,elements:l}=o.schema?sn(o.schema):{};t[r]={min:o.min,max:o.max,match:cn(o.match)?dn(i.discriminator??[],o.schema):o.match,required:a,excluded:c,elements:l,nameCandidates:ge(e,r)};}return {discriminator:i.discriminator??[],rules:i.rules,ordered:i.ordered,slices:Object.keys(t).length>0?t:void 0}};function E(e,n,i,t,r){if(t.elementReference){let o=t.elementReference.slice(1).filter((a,c)=>c%2===1);return V(e,n,o)}else if(t.type){let o=e.ensureSpecializationCanonicalUrl(t.type),a=e.resolveFs(n.package_meta,o);if(!a)throw new Error(`Could not resolve field type: <${n.url}>.${i.join(".")}: <${t.type}> (pkg: '${R(n.package_meta)}'))`);return I(a)}else {if(t.choices)return;if(n.derivation==="constraint")return;r?.dryWarn("#fieldTypeNotFound",`Can't recognize element type: <${n.url}>.${i.join(".")} (pkg: '${R(n.package_meta)}'): missing type info`);return}}var O=(e,n,i,t,r,o)=>{let a,c;t.binding&&(a=L(n,i,t),W.has(t.type??"")&&(c=K(e,n,t,r)));let l=E(e,n,i,t,r);l||r?.dryWarn("#fieldTypeNotFound",`Field type not found for '${n.url}#${i.join(".")}' (${n.derivation})`);let s;t.pattern?s={kind:"pattern",type:t.pattern.type,value:t.pattern.value}:t.fixed&&(s={kind:"fixed",type:t.fixed.type,value:t.fixed.value});let d=o??t;if(!s&&d.elements?.coding?.slicing?.slices){let u=d.elements.coding.slicing.slices,g=Object.values(u);g.length>0&&g.every(m=>m.min!==void 0&&m.min>=1&&m.match&&typeof m.match=="object"&&Object.keys(m.match).length>0)&&(s={kind:"fixed",type:"CodeableConcept",value:{coding:g.flatMap(f=>f.match?[f.match]:[])}});}return {type:l,required:be(e,n,i),excluded:Fe(e,n,i),reference:an(e,n,t),array:t.array||false,min:t.min,max:t.max,slicing:ve(i[i.length-1]??"",t),choices:t.choices,choiceOf:t.choiceOf,binding:a,enum:c,valueConstraint:s,mustSupport:t.mustSupport}};function j(e,n,i,t){return {type:V(e,n,i),array:t.array||false,required:be(e,n,i),excluded:Fe(e,n,i),slicing:ve(i[i.length-1]??"",t)}}var mn=(e,n,i,t)=>{let r=e.resolveFs(n.package_meta,i);if(!r?.elements)return;let o=[];for(let[a,c]of Object.entries(r.elements)){if(c.choiceOf!=="value"&&!a.startsWith("value"))continue;let l=E(e,r,[a],c,t);l&&o.push(l);}return v(o)},un=(e,n,i)=>{let t=[];if(!n.elements)return t;for(let[r,o]of Object.entries(n.elements)){if(!r.startsWith("extension:"))continue;let a=r.split(":")[1];if(!a)continue;let c;for(let[l,s]of Object.entries(o.elements??{}))if(!(s.choiceOf!=="value"&&!l.startsWith("value"))&&(c=E(e,n,[r,l],s,i),c))break;t.push({name:a,url:o.url??a,valueFieldType:c,min:o.min,max:o.max!==void 0?String(o.max):void 0});}return t},fn=(e,n,i)=>{let t=[],o=n.elements?.extension?.slicing?.slices;if(!o||typeof o!="object")return t;for(let[a,c]of Object.entries(o)){let l=c,s=l.schema;if(!s)continue;let d;for(let[u,g]of Object.entries(s.elements??{})){let p=g;if(!(p.choiceOf!=="value"&&!u.startsWith("value"))&&(d=E(e,n,[u],p,i),d))break}t.push({name:a,url:l.match?.url??a,valueFieldType:d,min:s._required?1:s.min??0,max:s.max!==void 0?String(s.max):s.array?"*":"1"});}return t},gn=(e,n,i,t)=>{let r=e.resolveFs(n.package_meta,i);if(!r?.elements)return;let o=un(e,r,t),a=fn(e,r,t),c=[...o,...a];return c.length>0?c:void 0},Ee=(e,n,i)=>{let t=[],r=(l,s,d)=>{let u=d.url,g=u?mn(e,n,u,i):void 0,p=u?gn(e,n,u,i):void 0;if(!u){let S=n.elements?.extension?.slicing?.slices?.[s]?.schema;if(S){u=S.elements?.url?.fixed?.value??s;for(let[x,C]of Object.entries(S.elements??{})){let N=C;if(N.choiceOf==="value"||x.startsWith("value")){let te=E(e,n,[x],N,i);if(te){g=[te];break}}}}}let m=p&&p.length>0,f=u?e.resolveFs(n.package_meta,u):void 0,y=f?I(f):void 0,h=[...l,"extension"].join(".");t.push({name:s,path:h,url:u,profile:y,min:d.min,max:d.max!==void 0?String(d.max):void 0,mustSupport:d.mustSupport,valueFieldTypes:g,subExtensions:p,isComplex:m,nameCandidates:fe({name:s,path:h})});},o=(l,s)=>{if(s.extensions)for(let[d,u]of Object.entries(s.extensions))r(l,d,u);if(s.elements)for(let[d,u]of Object.entries(s.elements))o([...l,d],u);};o([],n);let a=new Set,c=t.filter(l=>{let s=`${l.url}:${l.path}`;return a.has(s)?false:(a.add(s),true)});return c.length===0?void 0:c};function yn(e,n,i,t,r){if(!t)return;let o={};for(let a of e.getAllElementKeys(t)){let c=[...i,a],l=e.resolveElementSnapshot(n,c),s=l.type?e.ensureSpecializationCanonicalUrl(l.type):void 0;if(s&&T(n.package_meta,s).shouldSkip){r?.warn("#skipCanonical",`Skipping field ${c} for ${s} due to skip hack ${T(n.package_meta,s).reason}`);continue}Q(e,n,c,l,t[a])?o[a]=j(e,n,c,l):o[a]=O(e,n,c,l,r,t[a]);}return o}function hn(e){let n=[];for(let i of Object.values(e))"type"in i&&i.type&&n.push(i.type),"binding"in i&&i.binding&&n.push(i.binding);return n}async function De(e,n,i){if(!n.url)throw new Error("ValueSet URL is required");let t=H(e,n.package_meta,n.url),r=q(e,n.package_meta,n.url);return {identifier:t,description:n.description,concept:r,compose:r?void 0:n.compose}}var He=(e,n,i)=>{let t=[];return e&&t.push(e),n&&t.push(...hn(n)),i&&t.push(...Ie(i)),t},Pe=(e,n,i,t)=>{let o=He(n,i,t).filter(a=>!(a.url===e.url||z(a)));return v(o)},Sn=(e,n,i,t)=>{let o=He(n,i,t).filter(a=>a.url!==e.url);return v(o)};function Le(e,n,i){let t;if(n.base){let s=e.resolveFs(n.package_meta,e.ensureSpecializationCanonicalUrl(n.base));if(!s)throw new Error(`Base resource not found '${n.base}' for <${n.url}> from ${R(n.package_meta)}`);let d=I(s);Ne(!z(d),`Unexpected nested base for ${n.url}`),t=d;}let r=yn(e,n,[],n.elements,i),o=ke(e,n,i),a=me(e,n,i);if(n.derivation==="constraint"){let s=I(n);if(!t)throw new Error(`Profile ${n.url} must have a base type`);let d=Ee(e,n,i),u=d?.flatMap(le),g=Sn(s,t,r,o),p={identifier:s,base:t,fields:r,nested:o,description:n.description,dependencies:v(g,u),extensions:d};return ye(p),[p,...a]}if(n.kind==="primitive-type"){let s=I(n);return Ne(t,`Primitive type ${n.url} must have a base type`),[{identifier:s,description:n.description,base:t,dependencies:Pe(s,t,r,o)},...a]}let c=I(n);return [{identifier:c,base:t,fields:r,nested:o,description:n.description,dependencies:Pe(c,t,r,o),typeFamily:void 0},...a]}var Rn=(e,n,i)=>{let t={};for(let a of e){let c=`${a.schema.identifier.url}|${a.schema.identifier.package}`,l=se(a.schema);t[c]??={},t[c][l]??={typeSchema:a.schema,sources:[]},t[c][l].sources.push(a);}let r=[],o={};for(let a of Object.values(t)){let c=Object.values(a).sort((s,d)=>d.sources.length-s.sources.length),l=c[0];if(l)if(c.length>1){let s=l.typeSchema.identifier.url,d=l.typeSchema.identifier.package;i?.dryWarn("#duplicateSchema",`'${s}' from '${d}' has ${c.length} versions`),r.push(l.typeSchema);o[d]??={},o[d][s]=c.flatMap(g=>g.sources.map(p=>({typeSchema:g.typeSchema,sourcePackage:p.sourcePackage,sourceCanonical:p.sourceCanonical})));}else r.push(l.typeSchema);}return {schemas:r,collisions:o}},we=async(e,n,i)=>{let t=[];for(let r of e.allFs()){let o=R(r.package_meta),a=T(r.package_meta,r.url);if(a.shouldSkip){i?.dryWarn("#skipCanonical",`Skip ${r.url} from ${o}. Reason: ${a.reason}`);continue}for(let c of Le(e,r,i))t.push({schema:c,sourcePackage:o,sourceCanonical:r.url});}for(let r of e.allVs())t.push({schema:await De(e,r),sourcePackage:R(r.package_meta),sourceCanonical:r.url});return Rn(t,n,i)};var Ue={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async e=>{let n=k({prefix:"TypeSchema"});try{n.info("Generating TypeSchema from FHIR packages"),n.info(`Packages: ${e.packages.join(", ")}`),n.info(`Output: ${e.output}`);let i=e.singleFile?"ndjson":e.format;n.debug(`Format: ${i}${e.singleFile&&e.format==="json"?" (forced from json due to singleFile)":""}`),e.treeshake&&e.treeshake.length>0&&n.info(`Treeshaking enabled for ResourceTypes: ${e.treeshake.join(", ")}`),e.singleFile&&n.info("Single file output enabled (NDJSON format)"),e.registry&&n.info(`Using custom registry: ${e.registry}`);let t=Date.now(),r=e.packages.map(d=>{if(d.includes("@")){let u=d.lastIndexOf("@");return {name:d.slice(0,u),version:d.slice(u+1)||"latest"}}return {name:d,version:"latest"}});n.info(`Processing packages: ${r.map(d=>`${d.name}@${d.version}`).join(", ")}`);let o=await xe(r,{logger:n,registry:e.registry,focusedPackages:r}),{schemas:a}=await we(o,void 0,n);if(a.length===0)throw new Error("No schemas were generated from the specified packages");let c=e.output;if(!c)throw new Error("Output format not specified");await mkdir(dirname(c),{recursive:!0});let l;i==="json"?l=JSON.stringify(a,null,2):l=a.map(d=>JSON.stringify(d)).join(`
|
|
3
|
+
`),await writeFile(c,l,"utf-8");let s=Date.now()-t;if(re(`Generated ${a.length} TypeSchema definitions`,s,{schemas:a.length}),n.info(`Output: ${c}`),e.verbose){n.debug("Generated schemas:");let d=a.map(u=>`${u.identifier?.name||"Unknown"} (${u.identifier?.kind||"unknown"})`);F(d);}}catch(i){n.error(`Failed to generate TypeSchema: ${i instanceof Error?i.message:String(i)}`),process.exit(1);}}};var ee=k({prefix:"typeschema"}),$e={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:e=>e.command(Ue).help().example("$0 typeschema generate hl7.fhir.r4.core@4.0.1","Generate TypeSchema from FHIR R4 core package"),handler:e=>{if(!e.subcommand&&e._.length===1){ee.info("Available typeschema subcommands:"),F(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
|
|
4
4
|
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),console.log(`
|
|
5
|
-
Examples:`),F(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}e.subcommand&&!["generate","validate","merge"].includes(e.subcommand)&&(
|
|
6
|
-
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};var
|
|
5
|
+
Examples:`),F(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}e.subcommand&&!["generate","validate","merge"].includes(e.subcommand)&&(ee.error(`Unknown typeschema subcommand: ${e.subcommand}`),ee.info("Available typeschema subcommands:"),F(["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(`
|
|
6
|
+
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};var _=k({prefix:"cli"});async function Fn(e){let n=e.logLevel??(e.debug||e.verbose?"DEBUG":"INFO");_=k({prefix:"cli",level:n});}function Tn(){return In(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(Fn).command($e).option("verbose",{alias:"v",type:"boolean",description:"Enable verbose output",default:false,global:true}).option("debug",{alias:"d",type:"boolean",description:"Enable debug output with detailed logging",default:false,global:true}).option("log-level",{alias:"l",type:"string",choices:["DEBUG","INFO","WARN","ERROR","SILENT"],description:"Set the log level (default: INFO)",global:true}).demandCommand(0).middleware(e=>{e._.length===0&&(ie("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
|
|
7
7
|
Use 'atomic-codegen <command> --help' for more information about a command.`),console.log(`
|
|
8
8
|
Quick examples:`),console.log(" atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson"),console.log(`
|
|
9
|
-
Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((e,n,
|
|
9
|
+
Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((e,n,i)=>{_.error(n?n.message:e),_.error("Use --help for usage information"),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function ne(){await Tn().parseAsync();}import.meta.main&&ne().catch(e=>{_.error(String(e)),process.exit(1);});ne().catch(e=>{console.error("CLI Error:",e instanceof Error?e.message:e),process.exit(1);});
|
package/dist/index.js
CHANGED
|
@@ -1561,6 +1561,9 @@ var Python = class extends Writer {
|
|
|
1561
1561
|
generateResourceMethods(schema) {
|
|
1562
1562
|
const className = schema.identifier.name.toString();
|
|
1563
1563
|
this.line();
|
|
1564
|
+
this.line("def model_post_init(self, __context: Any) -> None:");
|
|
1565
|
+
this.line(' self.__pydantic_fields_set__.add("resource_type")');
|
|
1566
|
+
this.line();
|
|
1564
1567
|
this.line("def to_json(self, indent: int | None = None) -> str:");
|
|
1565
1568
|
this.line(" return self.model_dump_json(exclude_unset=True, exclude_none=True, indent=indent)");
|
|
1566
1569
|
this.line();
|
|
@@ -1578,7 +1581,7 @@ var Python = class extends Writer {
|
|
|
1578
1581
|
generateDefaultImports(includeGenericImports) {
|
|
1579
1582
|
this.pyImportFrom("__future__", "annotations");
|
|
1580
1583
|
this.pyImportFrom("pydantic", "BaseModel", "ConfigDict", "Field", "PositiveInt");
|
|
1581
|
-
const typingImports = ["List as PyList", "Literal"];
|
|
1584
|
+
const typingImports = ["Any", "List as PyList", "Literal"];
|
|
1582
1585
|
if (includeGenericImports) {
|
|
1583
1586
|
typingImports.push("Generic");
|
|
1584
1587
|
}
|
|
@@ -1984,6 +1987,92 @@ function collectBindingSchemas(register, fhirSchema, logger) {
|
|
|
1984
1987
|
return uniqueBindings;
|
|
1985
1988
|
}
|
|
1986
1989
|
|
|
1990
|
+
// src/typeschema/core/name-candidates.ts
|
|
1991
|
+
var normalizeName = (s) => {
|
|
1992
|
+
const cleaned = s.replace(/\[x\]/g, "").replace(/[- :.]/g, "_");
|
|
1993
|
+
if (!cleaned) return "";
|
|
1994
|
+
return uppercaseFirstLetter(cleaned);
|
|
1995
|
+
};
|
|
1996
|
+
var normalizeCamelName = (s) => {
|
|
1997
|
+
const cleaned = s.replace(/\[x\]/g, "").replace(/:/g, "_");
|
|
1998
|
+
if (!cleaned) return "";
|
|
1999
|
+
return uppercaseFirstLetter(camelCase(cleaned));
|
|
2000
|
+
};
|
|
2001
|
+
var extensionCandidates = (name, path) => {
|
|
2002
|
+
const base = normalizeCamelName(name) || "Extension";
|
|
2003
|
+
const pathParts = path.split(".").filter((p) => p && p !== "extension").join("_");
|
|
2004
|
+
const pathPart = pathParts ? normalizeCamelName(pathParts) : "";
|
|
2005
|
+
const qualified = `${pathPart}${base}`;
|
|
2006
|
+
return [base, qualified, `${qualified}Extension`];
|
|
2007
|
+
};
|
|
2008
|
+
var sliceCandidates = (fieldName, sliceName) => {
|
|
2009
|
+
const base = normalizeName(sliceName) || "Slice";
|
|
2010
|
+
const fieldPart = normalizeCamelName(fieldName) || "Field";
|
|
2011
|
+
const qualified = `${fieldPart}${base}`;
|
|
2012
|
+
return [base, qualified, `${qualified}Slice`];
|
|
2013
|
+
};
|
|
2014
|
+
var countBy = (entries, level, reserved) => entries.reduce(
|
|
2015
|
+
(counts, e) => {
|
|
2016
|
+
const name = e.candidates[level] ?? "";
|
|
2017
|
+
counts[name] = (counts[name] ?? 0) + 1;
|
|
2018
|
+
if (reserved.has(name)) counts[name] = (counts[name] ?? 0) + 1;
|
|
2019
|
+
return counts;
|
|
2020
|
+
},
|
|
2021
|
+
{}
|
|
2022
|
+
);
|
|
2023
|
+
var resolveNameCollisions = (entries, reserved) => {
|
|
2024
|
+
const levels = entries[0]?.candidates.length ?? 0;
|
|
2025
|
+
const resolve6 = (unresolved, level) => {
|
|
2026
|
+
if (unresolved.length === 0 || level >= levels) return {};
|
|
2027
|
+
const counts = countBy(unresolved, level, reserved);
|
|
2028
|
+
const isLastLevel = level >= levels - 1;
|
|
2029
|
+
const [resolved, colliding] = unresolved.reduce(
|
|
2030
|
+
([res, col], e) => {
|
|
2031
|
+
const name = e.candidates[level] ?? "";
|
|
2032
|
+
return (counts[name] ?? 0) > 1 && !isLastLevel ? [res, [...col, e]] : [{ ...res, [e.key]: name }, col];
|
|
2033
|
+
},
|
|
2034
|
+
[{}, []]
|
|
2035
|
+
);
|
|
2036
|
+
return { ...resolved, ...resolve6(colliding, level + 1) };
|
|
2037
|
+
};
|
|
2038
|
+
return resolve6(entries, 0);
|
|
2039
|
+
};
|
|
2040
|
+
var mkExtensionNameCandidates = (ext) => {
|
|
2041
|
+
return { candidates: extensionCandidates(ext.name, ext.path), recommended: "" };
|
|
2042
|
+
};
|
|
2043
|
+
var mkSliceNameCandidates = (fieldName, sliceName) => {
|
|
2044
|
+
return { candidates: sliceCandidates(fieldName, sliceName), recommended: "" };
|
|
2045
|
+
};
|
|
2046
|
+
var assignRecommendedBaseNames = (profile) => {
|
|
2047
|
+
const extensionEntries = (profile.extensions ?? []).filter((ext) => ext.url).map((ext) => ({
|
|
2048
|
+
key: `ext:${ext.url}:${ext.path}`,
|
|
2049
|
+
candidates: ext.nameCandidates.candidates
|
|
2050
|
+
}));
|
|
2051
|
+
const sliceEntries = Object.entries(profile.fields ?? {}).flatMap(([fieldName, field]) => {
|
|
2052
|
+
if (!("slicing" in field) || !field.slicing?.slices) return [];
|
|
2053
|
+
return Object.entries(field.slicing.slices).map(([sliceName, slice]) => ({
|
|
2054
|
+
key: `slice:${fieldName}:${sliceName}`,
|
|
2055
|
+
candidates: slice.nameCandidates.candidates
|
|
2056
|
+
}));
|
|
2057
|
+
});
|
|
2058
|
+
const reservedNames = new Set(Object.keys(profile.fields ?? {}).map(normalizeCamelName));
|
|
2059
|
+
const allEntries = [...extensionEntries, ...sliceEntries];
|
|
2060
|
+
if (allEntries.length === 0) return;
|
|
2061
|
+
const resolved = resolveNameCollisions(allEntries, reservedNames);
|
|
2062
|
+
for (const ext of profile.extensions ?? []) {
|
|
2063
|
+
if (!ext.url) continue;
|
|
2064
|
+
const key = `ext:${ext.url}:${ext.path}`;
|
|
2065
|
+
if (resolved[key]) ext.nameCandidates.recommended = resolved[key];
|
|
2066
|
+
}
|
|
2067
|
+
for (const [fieldName, field] of Object.entries(profile.fields ?? {})) {
|
|
2068
|
+
if (!("slicing" in field) || !field.slicing?.slices) continue;
|
|
2069
|
+
for (const [sliceName, slice] of Object.entries(field.slicing.slices)) {
|
|
2070
|
+
const key = `slice:${fieldName}:${sliceName}`;
|
|
2071
|
+
if (resolved[key]) slice.nameCandidates.recommended = resolved[key];
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
};
|
|
2075
|
+
|
|
1987
2076
|
// src/fhir-types/hl7-fhir-r4-core/CodeSystem.ts
|
|
1988
2077
|
var isCodeSystem = (resource) => {
|
|
1989
2078
|
return resource !== null && typeof resource === "object" && resource.resourceType === "CodeSystem";
|
|
@@ -2550,7 +2639,7 @@ var computeMatchFromSchema = (discriminators, schema) => {
|
|
|
2550
2639
|
}
|
|
2551
2640
|
return result;
|
|
2552
2641
|
};
|
|
2553
|
-
var buildSlicing = (element) => {
|
|
2642
|
+
var buildSlicing = (fieldName, element) => {
|
|
2554
2643
|
const slicing = element.slicing;
|
|
2555
2644
|
if (!slicing) return void 0;
|
|
2556
2645
|
const slices = {};
|
|
@@ -2563,7 +2652,8 @@ var buildSlicing = (element) => {
|
|
|
2563
2652
|
match: isEmptyMatch(slice.match) ? computeMatchFromSchema(slicing.discriminator ?? [], slice.schema) : slice.match,
|
|
2564
2653
|
required,
|
|
2565
2654
|
excluded,
|
|
2566
|
-
elements
|
|
2655
|
+
elements,
|
|
2656
|
+
nameCandidates: mkSliceNameCandidates(fieldName, name)
|
|
2567
2657
|
};
|
|
2568
2658
|
}
|
|
2569
2659
|
return {
|
|
@@ -2626,12 +2716,12 @@ var mkField = (register, fhirSchema, path, element, logger, rawElement) => {
|
|
|
2626
2716
|
(s) => s.min !== void 0 && s.min >= 1 && s.match && typeof s.match === "object" && Object.keys(s.match).length > 0
|
|
2627
2717
|
);
|
|
2628
2718
|
if (allRequired) {
|
|
2629
|
-
const codingValues = allSliceValues.
|
|
2719
|
+
const codingValues = allSliceValues.flatMap((s) => s.match ? [s.match] : []);
|
|
2630
2720
|
valueConstraint = {
|
|
2631
2721
|
kind: "fixed",
|
|
2632
2722
|
type: "CodeableConcept",
|
|
2633
2723
|
value: {
|
|
2634
|
-
coding: codingValues
|
|
2724
|
+
coding: codingValues
|
|
2635
2725
|
}
|
|
2636
2726
|
};
|
|
2637
2727
|
}
|
|
@@ -2644,7 +2734,7 @@ var mkField = (register, fhirSchema, path, element, logger, rawElement) => {
|
|
|
2644
2734
|
array: element.array || false,
|
|
2645
2735
|
min: element.min,
|
|
2646
2736
|
max: element.max,
|
|
2647
|
-
slicing: buildSlicing(element),
|
|
2737
|
+
slicing: buildSlicing(path[path.length - 1] ?? "", element),
|
|
2648
2738
|
choices: element.choices,
|
|
2649
2739
|
choiceOf: element.choiceOf,
|
|
2650
2740
|
binding,
|
|
@@ -2660,7 +2750,7 @@ function mkNestedField(register, fhirSchema, path, element) {
|
|
|
2660
2750
|
array: element.array || false,
|
|
2661
2751
|
required: isRequired(register, fhirSchema, path),
|
|
2662
2752
|
excluded: isExcluded(register, fhirSchema, path),
|
|
2663
|
-
slicing: buildSlicing(element)
|
|
2753
|
+
slicing: buildSlicing(path[path.length - 1] ?? "", element)
|
|
2664
2754
|
};
|
|
2665
2755
|
}
|
|
2666
2756
|
|
|
@@ -2759,9 +2849,10 @@ var extractProfileExtensions = (register, fhirSchema, logger) => {
|
|
|
2759
2849
|
const isComplex = subExtensions && subExtensions.length > 0;
|
|
2760
2850
|
const extFs = url ? register.resolveFs(fhirSchema.package_meta, url) : void 0;
|
|
2761
2851
|
const profile = extFs ? mkIdentifier(extFs) : void 0;
|
|
2852
|
+
const extPath = [...path, "extension"].join(".");
|
|
2762
2853
|
extensions.push({
|
|
2763
2854
|
name,
|
|
2764
|
-
path:
|
|
2855
|
+
path: extPath,
|
|
2765
2856
|
url,
|
|
2766
2857
|
profile,
|
|
2767
2858
|
min: schema.min,
|
|
@@ -2769,7 +2860,8 @@ var extractProfileExtensions = (register, fhirSchema, logger) => {
|
|
|
2769
2860
|
mustSupport: schema.mustSupport,
|
|
2770
2861
|
valueFieldTypes,
|
|
2771
2862
|
subExtensions,
|
|
2772
|
-
isComplex
|
|
2863
|
+
isComplex,
|
|
2864
|
+
nameCandidates: mkExtensionNameCandidates({ name, path: extPath })
|
|
2773
2865
|
});
|
|
2774
2866
|
};
|
|
2775
2867
|
const walkElement = (path, element) => {
|
|
@@ -2886,18 +2978,17 @@ function transformFhirSchema(register, fhirSchema, logger) {
|
|
|
2886
2978
|
const extensions = extractProfileExtensions(register, fhirSchema, logger);
|
|
2887
2979
|
const extensionDeps = extensions?.flatMap(extractExtensionDeps);
|
|
2888
2980
|
const rawDeps = extractProfileDependencies(identifier2, base, fields, nested);
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
];
|
|
2981
|
+
const profileSchema = {
|
|
2982
|
+
identifier: identifier2,
|
|
2983
|
+
base,
|
|
2984
|
+
fields,
|
|
2985
|
+
nested,
|
|
2986
|
+
description: fhirSchema.description,
|
|
2987
|
+
dependencies: concatIdentifiers(rawDeps, extensionDeps),
|
|
2988
|
+
extensions
|
|
2989
|
+
};
|
|
2990
|
+
assignRecommendedBaseNames(profileSchema);
|
|
2991
|
+
return [profileSchema, ...bindingSchemas];
|
|
2901
2992
|
}
|
|
2902
2993
|
if (fhirSchema.kind === "primitive-type") {
|
|
2903
2994
|
const identifier2 = mkIdentifier(fhirSchema);
|
|
@@ -4276,20 +4367,6 @@ var tsExtensionFlatTypeName = (profileName, extensionName) => {
|
|
|
4276
4367
|
return `${uppercaseFirstLetter(profileName)}_${uppercaseFirstLetter(normalizeTsName(extensionName))}Flat`;
|
|
4277
4368
|
};
|
|
4278
4369
|
var tsSliceStaticName = (name) => name.replace(/\[x\]/g, "").replace(/[^a-zA-Z0-9_$]/g, "_");
|
|
4279
|
-
var tsSliceMethodBaseName = (sliceName) => uppercaseFirstLetter(normalizeTsName(sliceName) || "Slice");
|
|
4280
|
-
var tsExtensionMethodBaseName = (name) => uppercaseFirstLetter(tsCamelCase(name) || "Extension");
|
|
4281
|
-
var tsQualifiedExtensionMethodBaseName = (name, path) => {
|
|
4282
|
-
const rawPath = path?.split(".").filter((p) => p && p !== "extension").join("_") ?? "";
|
|
4283
|
-
const pathPart = rawPath ? uppercaseFirstLetter(tsCamelCase(rawPath)) : "";
|
|
4284
|
-
return `${pathPart}${uppercaseFirstLetter(tsCamelCase(name) || "Extension")}`;
|
|
4285
|
-
};
|
|
4286
|
-
var tsQualifiedSliceMethodBaseName = (fieldName, sliceName) => {
|
|
4287
|
-
const fieldPart = uppercaseFirstLetter(tsCamelCase(fieldName) || "Field");
|
|
4288
|
-
const slicePart = uppercaseFirstLetter(normalizeTsName(sliceName) || "Slice");
|
|
4289
|
-
return `${fieldPart}${slicePart}`;
|
|
4290
|
-
};
|
|
4291
|
-
var tsResolvedExtensionBaseName = (extensionBaseNames, url, path, fallbackName) => extensionBaseNames[`${url}:${path}`] ?? fallbackName;
|
|
4292
|
-
var tsResolvedSliceBaseName = (sliceBaseNames, fieldName, sliceName) => sliceBaseNames[`${fieldName}:${sliceName}`] ?? sliceName;
|
|
4293
4370
|
var tsValueFieldName = (id) => `value${uppercaseFirstLetter(id.name)}`;
|
|
4294
4371
|
|
|
4295
4372
|
// src/api/writer-generator/typescript/utils.ts
|
|
@@ -4640,10 +4717,10 @@ var generateGenericExtensionGetter = (w, info) => {
|
|
|
4640
4717
|
}
|
|
4641
4718
|
});
|
|
4642
4719
|
};
|
|
4643
|
-
var generateExtensionMethods = (w, tsIndex, flatProfile
|
|
4720
|
+
var generateExtensionMethods = (w, tsIndex, flatProfile) => {
|
|
4644
4721
|
for (const ext of flatProfile.extensions ?? []) {
|
|
4645
4722
|
if (!ext.url) continue;
|
|
4646
|
-
const baseName =
|
|
4723
|
+
const baseName = ext.nameCandidates.recommended;
|
|
4647
4724
|
const targetPath = ext.path.split(".").filter((segment) => segment !== "extension");
|
|
4648
4725
|
const extProfileInfo = resolveExtensionProfile(tsIndex, flatProfile.identifier.package, ext.url);
|
|
4649
4726
|
const info = {
|
|
@@ -4786,6 +4863,7 @@ var collectSliceDefs = (tsIndex, flatProfile) => Object.entries(flatProfile.fiel
|
|
|
4786
4863
|
baseType,
|
|
4787
4864
|
typedBaseType,
|
|
4788
4865
|
sliceName,
|
|
4866
|
+
baseName: slice.nameCandidates.recommended,
|
|
4789
4867
|
match: slice.match ?? {},
|
|
4790
4868
|
required,
|
|
4791
4869
|
excluded: slice.excluded ?? [],
|
|
@@ -4796,11 +4874,11 @@ var collectSliceDefs = (tsIndex, flatProfile) => Object.entries(flatProfile.fiel
|
|
|
4796
4874
|
};
|
|
4797
4875
|
});
|
|
4798
4876
|
});
|
|
4799
|
-
var generateSliceSetters = (w, sliceDefs, flatProfile
|
|
4877
|
+
var generateSliceSetters = (w, sliceDefs, flatProfile) => {
|
|
4800
4878
|
const profileClassName = tsProfileClassName(flatProfile);
|
|
4801
4879
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
4802
4880
|
for (const sliceDef of sliceDefs) {
|
|
4803
|
-
const baseName =
|
|
4881
|
+
const baseName = sliceDef.baseName;
|
|
4804
4882
|
const methodName = `set${baseName}`;
|
|
4805
4883
|
const inputTypeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
|
|
4806
4884
|
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
|
|
@@ -4860,12 +4938,12 @@ var generateSliceSetters = (w, sliceDefs, flatProfile, sliceBaseNames) => {
|
|
|
4860
4938
|
w.line();
|
|
4861
4939
|
}
|
|
4862
4940
|
};
|
|
4863
|
-
var generateSliceGetters = (w, sliceDefs, flatProfile
|
|
4941
|
+
var generateSliceGetters = (w, sliceDefs, flatProfile) => {
|
|
4864
4942
|
const profileClassName = tsProfileClassName(flatProfile);
|
|
4865
4943
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
4866
4944
|
const defaultMode = w.opts.sliceGetterDefault ?? "flat";
|
|
4867
4945
|
for (const sliceDef of sliceDefs) {
|
|
4868
|
-
const baseName =
|
|
4946
|
+
const baseName = sliceDef.baseName;
|
|
4869
4947
|
const getMethodName = `get${baseName}`;
|
|
4870
4948
|
const flatTypeName = tsSliceFlatAllTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
|
|
4871
4949
|
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
|
|
@@ -5460,7 +5538,7 @@ var generateFactoryMethods = (w, tsIndex, flatProfile, factoryInfo) => {
|
|
|
5460
5538
|
});
|
|
5461
5539
|
w.line();
|
|
5462
5540
|
};
|
|
5463
|
-
var generateFieldAccessors = (w, factoryInfo
|
|
5541
|
+
var generateFieldAccessors = (w, factoryInfo) => {
|
|
5464
5542
|
w.line("// Field accessors");
|
|
5465
5543
|
for (const p of factoryInfo.params) {
|
|
5466
5544
|
const methodBaseName = uppercaseFirstLetter(p.name);
|
|
@@ -5476,7 +5554,6 @@ var generateFieldAccessors = (w, factoryInfo, extSliceMethodBaseNames) => {
|
|
|
5476
5554
|
}
|
|
5477
5555
|
for (const a of factoryInfo.accessors) {
|
|
5478
5556
|
const methodBaseName = uppercaseFirstLetter(tsCamelCase(a.name));
|
|
5479
|
-
if (extSliceMethodBaseNames.has(methodBaseName)) continue;
|
|
5480
5557
|
const fieldAccess = tsFieldName(a.name);
|
|
5481
5558
|
w.curlyBlock([`get${methodBaseName}`, "()", `: ${a.tsType} | undefined`], () => {
|
|
5482
5559
|
w.lineSM(`return ${tsGet("this.resource", fieldAccess)} as ${a.tsType} | undefined`);
|
|
@@ -5599,49 +5676,6 @@ var generateFlatInputType = (w, flatProfile) => {
|
|
|
5599
5676
|
});
|
|
5600
5677
|
w.line();
|
|
5601
5678
|
};
|
|
5602
|
-
var countBy = (entries, level) => entries.reduce(
|
|
5603
|
-
(counts, e) => {
|
|
5604
|
-
const name = e.candidates[level] ?? "";
|
|
5605
|
-
counts[name] = (counts[name] ?? 0) + 1;
|
|
5606
|
-
return counts;
|
|
5607
|
-
},
|
|
5608
|
-
{}
|
|
5609
|
-
);
|
|
5610
|
-
var resolveNameCollisions = (entries) => {
|
|
5611
|
-
const levels = entries[0]?.candidates.length ?? 0;
|
|
5612
|
-
const resolve6 = (unresolved, level) => {
|
|
5613
|
-
if (unresolved.length === 0 || level >= levels) return {};
|
|
5614
|
-
const counts = countBy(unresolved, level);
|
|
5615
|
-
const isLastLevel = level >= levels - 1;
|
|
5616
|
-
const [resolved, colliding] = unresolved.reduce(
|
|
5617
|
-
([res, col], e) => {
|
|
5618
|
-
const name = e.candidates[level] ?? "";
|
|
5619
|
-
return (counts[name] ?? 0) > 1 && !isLastLevel ? [res, [...col, e]] : [{ ...res, [e.key]: name }, col];
|
|
5620
|
-
},
|
|
5621
|
-
[{}, []]
|
|
5622
|
-
);
|
|
5623
|
-
return { ...resolved, ...resolve6(colliding, level + 1) };
|
|
5624
|
-
};
|
|
5625
|
-
return resolve6(entries, 0);
|
|
5626
|
-
};
|
|
5627
|
-
var toRecord = (entries, resolved) => Object.fromEntries(entries.map((e) => [e.key, resolved[e.key] ?? e.candidates[0] ?? ""]));
|
|
5628
|
-
var resolveProfileMethodBaseNames = (extensions, sliceDefs) => {
|
|
5629
|
-
const extensionEntries = extensions.filter((ext) => ext.url).map((ext) => {
|
|
5630
|
-
const base = tsExtensionMethodBaseName(ext.name);
|
|
5631
|
-
const qualified = tsQualifiedExtensionMethodBaseName(ext.name, ext.path);
|
|
5632
|
-
return { key: `${ext.url}:${ext.path}`, candidates: [base, qualified, `${qualified}Extension`] };
|
|
5633
|
-
});
|
|
5634
|
-
const sliceEntries = sliceDefs.map((slice) => {
|
|
5635
|
-
const base = tsSliceMethodBaseName(slice.sliceName);
|
|
5636
|
-
const qualified = tsQualifiedSliceMethodBaseName(slice.fieldName, slice.sliceName);
|
|
5637
|
-
return { key: `${slice.fieldName}:${slice.sliceName}`, candidates: [base, qualified, `${qualified}Slice`] };
|
|
5638
|
-
});
|
|
5639
|
-
const resolved = resolveNameCollisions([...extensionEntries, ...sliceEntries]);
|
|
5640
|
-
const extensionsRecords = toRecord(extensionEntries, resolved);
|
|
5641
|
-
const slicesRecords = toRecord(sliceEntries, resolved);
|
|
5642
|
-
const allBaseNames = /* @__PURE__ */ new Set([...Object.values(extensionsRecords), ...Object.values(slicesRecords)]);
|
|
5643
|
-
return { extensions: extensionsRecords, slices: slicesRecords, allBaseNames };
|
|
5644
|
-
};
|
|
5645
5679
|
var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
5646
5680
|
const tsBaseResourceName = tsTypeFromIdentifier(flatProfile.base);
|
|
5647
5681
|
const profileClassName = tsProfileClassName(flatProfile);
|
|
@@ -5654,7 +5688,6 @@ var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
|
5654
5688
|
generateFlatInputType(w, flatProfile);
|
|
5655
5689
|
const canonicalUrl = flatProfile.identifier.url;
|
|
5656
5690
|
w.comment("CanonicalURL:", canonicalUrl, `(pkg: ${packageMetaToFhir(packageMeta(flatProfile))})`);
|
|
5657
|
-
const resolvedMethodNames = resolveProfileMethodBaseNames(flatProfile.extensions ?? [], sliceDefs);
|
|
5658
5691
|
w.curlyBlock(["export", "class", profileClassName], () => {
|
|
5659
5692
|
w.lineSM(`static readonly canonicalUrl = ${JSON.stringify(canonicalUrl)}`);
|
|
5660
5693
|
w.line();
|
|
@@ -5662,12 +5695,12 @@ var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
|
5662
5695
|
w.lineSM(`private resource: ${tsBaseResourceName}`);
|
|
5663
5696
|
w.line();
|
|
5664
5697
|
generateFactoryMethods(w, tsIndex, flatProfile, factoryInfo);
|
|
5665
|
-
generateFieldAccessors(w, factoryInfo
|
|
5698
|
+
generateFieldAccessors(w, factoryInfo);
|
|
5666
5699
|
w.line("// Extensions");
|
|
5667
|
-
generateExtensionMethods(w, tsIndex, flatProfile
|
|
5700
|
+
generateExtensionMethods(w, tsIndex, flatProfile);
|
|
5668
5701
|
w.line("// Slices");
|
|
5669
|
-
generateSliceSetters(w, sliceDefs, flatProfile
|
|
5670
|
-
generateSliceGetters(w, sliceDefs, flatProfile
|
|
5702
|
+
generateSliceSetters(w, sliceDefs, flatProfile);
|
|
5703
|
+
generateSliceGetters(w, sliceDefs, flatProfile);
|
|
5671
5704
|
w.line("// Validation");
|
|
5672
5705
|
generateValidateMethod(w, tsIndex, flatProfile);
|
|
5673
5706
|
});
|