@atomic-ehr/codegen 0.0.11 → 0.0.12-canary.20260416151931.b4c1a6f
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 +120 -90
- 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
|
@@ -1984,6 +1984,92 @@ function collectBindingSchemas(register, fhirSchema, logger) {
|
|
|
1984
1984
|
return uniqueBindings;
|
|
1985
1985
|
}
|
|
1986
1986
|
|
|
1987
|
+
// src/typeschema/core/name-candidates.ts
|
|
1988
|
+
var normalizeName = (s) => {
|
|
1989
|
+
const cleaned = s.replace(/\[x\]/g, "").replace(/[- :.]/g, "_");
|
|
1990
|
+
if (!cleaned) return "";
|
|
1991
|
+
return uppercaseFirstLetter(cleaned);
|
|
1992
|
+
};
|
|
1993
|
+
var normalizeCamelName = (s) => {
|
|
1994
|
+
const cleaned = s.replace(/\[x\]/g, "").replace(/:/g, "_");
|
|
1995
|
+
if (!cleaned) return "";
|
|
1996
|
+
return uppercaseFirstLetter(camelCase(cleaned));
|
|
1997
|
+
};
|
|
1998
|
+
var extensionCandidates = (name, path) => {
|
|
1999
|
+
const base = normalizeCamelName(name) || "Extension";
|
|
2000
|
+
const pathParts = path.split(".").filter((p) => p && p !== "extension").join("_");
|
|
2001
|
+
const pathPart = pathParts ? normalizeCamelName(pathParts) : "";
|
|
2002
|
+
const qualified = `${pathPart}${base}`;
|
|
2003
|
+
return [base, qualified, `${qualified}Extension`];
|
|
2004
|
+
};
|
|
2005
|
+
var sliceCandidates = (fieldName, sliceName) => {
|
|
2006
|
+
const base = normalizeName(sliceName) || "Slice";
|
|
2007
|
+
const fieldPart = normalizeCamelName(fieldName) || "Field";
|
|
2008
|
+
const qualified = `${fieldPart}${base}`;
|
|
2009
|
+
return [base, qualified, `${qualified}Slice`];
|
|
2010
|
+
};
|
|
2011
|
+
var countBy = (entries, level, reserved) => entries.reduce(
|
|
2012
|
+
(counts, e) => {
|
|
2013
|
+
const name = e.candidates[level] ?? "";
|
|
2014
|
+
counts[name] = (counts[name] ?? 0) + 1;
|
|
2015
|
+
if (reserved.has(name)) counts[name] = (counts[name] ?? 0) + 1;
|
|
2016
|
+
return counts;
|
|
2017
|
+
},
|
|
2018
|
+
{}
|
|
2019
|
+
);
|
|
2020
|
+
var resolveNameCollisions = (entries, reserved) => {
|
|
2021
|
+
const levels = entries[0]?.candidates.length ?? 0;
|
|
2022
|
+
const resolve6 = (unresolved, level) => {
|
|
2023
|
+
if (unresolved.length === 0 || level >= levels) return {};
|
|
2024
|
+
const counts = countBy(unresolved, level, reserved);
|
|
2025
|
+
const isLastLevel = level >= levels - 1;
|
|
2026
|
+
const [resolved, colliding] = unresolved.reduce(
|
|
2027
|
+
([res, col], e) => {
|
|
2028
|
+
const name = e.candidates[level] ?? "";
|
|
2029
|
+
return (counts[name] ?? 0) > 1 && !isLastLevel ? [res, [...col, e]] : [{ ...res, [e.key]: name }, col];
|
|
2030
|
+
},
|
|
2031
|
+
[{}, []]
|
|
2032
|
+
);
|
|
2033
|
+
return { ...resolved, ...resolve6(colliding, level + 1) };
|
|
2034
|
+
};
|
|
2035
|
+
return resolve6(entries, 0);
|
|
2036
|
+
};
|
|
2037
|
+
var mkExtensionNameCandidates = (ext) => {
|
|
2038
|
+
return { candidates: extensionCandidates(ext.name, ext.path), recommended: "" };
|
|
2039
|
+
};
|
|
2040
|
+
var mkSliceNameCandidates = (fieldName, sliceName) => {
|
|
2041
|
+
return { candidates: sliceCandidates(fieldName, sliceName), recommended: "" };
|
|
2042
|
+
};
|
|
2043
|
+
var assignRecommendedBaseNames = (profile) => {
|
|
2044
|
+
const extensionEntries = (profile.extensions ?? []).filter((ext) => ext.url).map((ext) => ({
|
|
2045
|
+
key: `ext:${ext.url}:${ext.path}`,
|
|
2046
|
+
candidates: ext.nameCandidates.candidates
|
|
2047
|
+
}));
|
|
2048
|
+
const sliceEntries = Object.entries(profile.fields ?? {}).flatMap(([fieldName, field]) => {
|
|
2049
|
+
if (!("slicing" in field) || !field.slicing?.slices) return [];
|
|
2050
|
+
return Object.entries(field.slicing.slices).map(([sliceName, slice]) => ({
|
|
2051
|
+
key: `slice:${fieldName}:${sliceName}`,
|
|
2052
|
+
candidates: slice.nameCandidates.candidates
|
|
2053
|
+
}));
|
|
2054
|
+
});
|
|
2055
|
+
const reservedNames = new Set(Object.keys(profile.fields ?? {}).map(normalizeCamelName));
|
|
2056
|
+
const allEntries = [...extensionEntries, ...sliceEntries];
|
|
2057
|
+
if (allEntries.length === 0) return;
|
|
2058
|
+
const resolved = resolveNameCollisions(allEntries, reservedNames);
|
|
2059
|
+
for (const ext of profile.extensions ?? []) {
|
|
2060
|
+
if (!ext.url) continue;
|
|
2061
|
+
const key = `ext:${ext.url}:${ext.path}`;
|
|
2062
|
+
if (resolved[key]) ext.nameCandidates.recommended = resolved[key];
|
|
2063
|
+
}
|
|
2064
|
+
for (const [fieldName, field] of Object.entries(profile.fields ?? {})) {
|
|
2065
|
+
if (!("slicing" in field) || !field.slicing?.slices) continue;
|
|
2066
|
+
for (const [sliceName, slice] of Object.entries(field.slicing.slices)) {
|
|
2067
|
+
const key = `slice:${fieldName}:${sliceName}`;
|
|
2068
|
+
if (resolved[key]) slice.nameCandidates.recommended = resolved[key];
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
|
|
1987
2073
|
// src/fhir-types/hl7-fhir-r4-core/CodeSystem.ts
|
|
1988
2074
|
var isCodeSystem = (resource) => {
|
|
1989
2075
|
return resource !== null && typeof resource === "object" && resource.resourceType === "CodeSystem";
|
|
@@ -2550,7 +2636,7 @@ var computeMatchFromSchema = (discriminators, schema) => {
|
|
|
2550
2636
|
}
|
|
2551
2637
|
return result;
|
|
2552
2638
|
};
|
|
2553
|
-
var buildSlicing = (element) => {
|
|
2639
|
+
var buildSlicing = (fieldName, element) => {
|
|
2554
2640
|
const slicing = element.slicing;
|
|
2555
2641
|
if (!slicing) return void 0;
|
|
2556
2642
|
const slices = {};
|
|
@@ -2563,7 +2649,8 @@ var buildSlicing = (element) => {
|
|
|
2563
2649
|
match: isEmptyMatch(slice.match) ? computeMatchFromSchema(slicing.discriminator ?? [], slice.schema) : slice.match,
|
|
2564
2650
|
required,
|
|
2565
2651
|
excluded,
|
|
2566
|
-
elements
|
|
2652
|
+
elements,
|
|
2653
|
+
nameCandidates: mkSliceNameCandidates(fieldName, name)
|
|
2567
2654
|
};
|
|
2568
2655
|
}
|
|
2569
2656
|
return {
|
|
@@ -2626,12 +2713,12 @@ var mkField = (register, fhirSchema, path, element, logger, rawElement) => {
|
|
|
2626
2713
|
(s) => s.min !== void 0 && s.min >= 1 && s.match && typeof s.match === "object" && Object.keys(s.match).length > 0
|
|
2627
2714
|
);
|
|
2628
2715
|
if (allRequired) {
|
|
2629
|
-
const codingValues = allSliceValues.
|
|
2716
|
+
const codingValues = allSliceValues.flatMap((s) => s.match ? [s.match] : []);
|
|
2630
2717
|
valueConstraint = {
|
|
2631
2718
|
kind: "fixed",
|
|
2632
2719
|
type: "CodeableConcept",
|
|
2633
2720
|
value: {
|
|
2634
|
-
coding: codingValues
|
|
2721
|
+
coding: codingValues
|
|
2635
2722
|
}
|
|
2636
2723
|
};
|
|
2637
2724
|
}
|
|
@@ -2644,7 +2731,7 @@ var mkField = (register, fhirSchema, path, element, logger, rawElement) => {
|
|
|
2644
2731
|
array: element.array || false,
|
|
2645
2732
|
min: element.min,
|
|
2646
2733
|
max: element.max,
|
|
2647
|
-
slicing: buildSlicing(element),
|
|
2734
|
+
slicing: buildSlicing(path[path.length - 1] ?? "", element),
|
|
2648
2735
|
choices: element.choices,
|
|
2649
2736
|
choiceOf: element.choiceOf,
|
|
2650
2737
|
binding,
|
|
@@ -2660,7 +2747,7 @@ function mkNestedField(register, fhirSchema, path, element) {
|
|
|
2660
2747
|
array: element.array || false,
|
|
2661
2748
|
required: isRequired(register, fhirSchema, path),
|
|
2662
2749
|
excluded: isExcluded(register, fhirSchema, path),
|
|
2663
|
-
slicing: buildSlicing(element)
|
|
2750
|
+
slicing: buildSlicing(path[path.length - 1] ?? "", element)
|
|
2664
2751
|
};
|
|
2665
2752
|
}
|
|
2666
2753
|
|
|
@@ -2759,9 +2846,10 @@ var extractProfileExtensions = (register, fhirSchema, logger) => {
|
|
|
2759
2846
|
const isComplex = subExtensions && subExtensions.length > 0;
|
|
2760
2847
|
const extFs = url ? register.resolveFs(fhirSchema.package_meta, url) : void 0;
|
|
2761
2848
|
const profile = extFs ? mkIdentifier(extFs) : void 0;
|
|
2849
|
+
const extPath = [...path, "extension"].join(".");
|
|
2762
2850
|
extensions.push({
|
|
2763
2851
|
name,
|
|
2764
|
-
path:
|
|
2852
|
+
path: extPath,
|
|
2765
2853
|
url,
|
|
2766
2854
|
profile,
|
|
2767
2855
|
min: schema.min,
|
|
@@ -2769,7 +2857,8 @@ var extractProfileExtensions = (register, fhirSchema, logger) => {
|
|
|
2769
2857
|
mustSupport: schema.mustSupport,
|
|
2770
2858
|
valueFieldTypes,
|
|
2771
2859
|
subExtensions,
|
|
2772
|
-
isComplex
|
|
2860
|
+
isComplex,
|
|
2861
|
+
nameCandidates: mkExtensionNameCandidates({ name, path: extPath })
|
|
2773
2862
|
});
|
|
2774
2863
|
};
|
|
2775
2864
|
const walkElement = (path, element) => {
|
|
@@ -2886,18 +2975,17 @@ function transformFhirSchema(register, fhirSchema, logger) {
|
|
|
2886
2975
|
const extensions = extractProfileExtensions(register, fhirSchema, logger);
|
|
2887
2976
|
const extensionDeps = extensions?.flatMap(extractExtensionDeps);
|
|
2888
2977
|
const rawDeps = extractProfileDependencies(identifier2, base, fields, nested);
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
];
|
|
2978
|
+
const profileSchema = {
|
|
2979
|
+
identifier: identifier2,
|
|
2980
|
+
base,
|
|
2981
|
+
fields,
|
|
2982
|
+
nested,
|
|
2983
|
+
description: fhirSchema.description,
|
|
2984
|
+
dependencies: concatIdentifiers(rawDeps, extensionDeps),
|
|
2985
|
+
extensions
|
|
2986
|
+
};
|
|
2987
|
+
assignRecommendedBaseNames(profileSchema);
|
|
2988
|
+
return [profileSchema, ...bindingSchemas];
|
|
2901
2989
|
}
|
|
2902
2990
|
if (fhirSchema.kind === "primitive-type") {
|
|
2903
2991
|
const identifier2 = mkIdentifier(fhirSchema);
|
|
@@ -4276,20 +4364,6 @@ var tsExtensionFlatTypeName = (profileName, extensionName) => {
|
|
|
4276
4364
|
return `${uppercaseFirstLetter(profileName)}_${uppercaseFirstLetter(normalizeTsName(extensionName))}Flat`;
|
|
4277
4365
|
};
|
|
4278
4366
|
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
4367
|
var tsValueFieldName = (id) => `value${uppercaseFirstLetter(id.name)}`;
|
|
4294
4368
|
|
|
4295
4369
|
// src/api/writer-generator/typescript/utils.ts
|
|
@@ -4640,10 +4714,10 @@ var generateGenericExtensionGetter = (w, info) => {
|
|
|
4640
4714
|
}
|
|
4641
4715
|
});
|
|
4642
4716
|
};
|
|
4643
|
-
var generateExtensionMethods = (w, tsIndex, flatProfile
|
|
4717
|
+
var generateExtensionMethods = (w, tsIndex, flatProfile) => {
|
|
4644
4718
|
for (const ext of flatProfile.extensions ?? []) {
|
|
4645
4719
|
if (!ext.url) continue;
|
|
4646
|
-
const baseName =
|
|
4720
|
+
const baseName = ext.nameCandidates.recommended;
|
|
4647
4721
|
const targetPath = ext.path.split(".").filter((segment) => segment !== "extension");
|
|
4648
4722
|
const extProfileInfo = resolveExtensionProfile(tsIndex, flatProfile.identifier.package, ext.url);
|
|
4649
4723
|
const info = {
|
|
@@ -4786,6 +4860,7 @@ var collectSliceDefs = (tsIndex, flatProfile) => Object.entries(flatProfile.fiel
|
|
|
4786
4860
|
baseType,
|
|
4787
4861
|
typedBaseType,
|
|
4788
4862
|
sliceName,
|
|
4863
|
+
baseName: slice.nameCandidates.recommended,
|
|
4789
4864
|
match: slice.match ?? {},
|
|
4790
4865
|
required,
|
|
4791
4866
|
excluded: slice.excluded ?? [],
|
|
@@ -4796,11 +4871,11 @@ var collectSliceDefs = (tsIndex, flatProfile) => Object.entries(flatProfile.fiel
|
|
|
4796
4871
|
};
|
|
4797
4872
|
});
|
|
4798
4873
|
});
|
|
4799
|
-
var generateSliceSetters = (w, sliceDefs, flatProfile
|
|
4874
|
+
var generateSliceSetters = (w, sliceDefs, flatProfile) => {
|
|
4800
4875
|
const profileClassName = tsProfileClassName(flatProfile);
|
|
4801
4876
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
4802
4877
|
for (const sliceDef of sliceDefs) {
|
|
4803
|
-
const baseName =
|
|
4878
|
+
const baseName = sliceDef.baseName;
|
|
4804
4879
|
const methodName = `set${baseName}`;
|
|
4805
4880
|
const inputTypeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
|
|
4806
4881
|
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
|
|
@@ -4860,12 +4935,12 @@ var generateSliceSetters = (w, sliceDefs, flatProfile, sliceBaseNames) => {
|
|
|
4860
4935
|
w.line();
|
|
4861
4936
|
}
|
|
4862
4937
|
};
|
|
4863
|
-
var generateSliceGetters = (w, sliceDefs, flatProfile
|
|
4938
|
+
var generateSliceGetters = (w, sliceDefs, flatProfile) => {
|
|
4864
4939
|
const profileClassName = tsProfileClassName(flatProfile);
|
|
4865
4940
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
4866
4941
|
const defaultMode = w.opts.sliceGetterDefault ?? "flat";
|
|
4867
4942
|
for (const sliceDef of sliceDefs) {
|
|
4868
|
-
const baseName =
|
|
4943
|
+
const baseName = sliceDef.baseName;
|
|
4869
4944
|
const getMethodName = `get${baseName}`;
|
|
4870
4945
|
const flatTypeName = tsSliceFlatAllTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
|
|
4871
4946
|
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
|
|
@@ -5460,7 +5535,7 @@ var generateFactoryMethods = (w, tsIndex, flatProfile, factoryInfo) => {
|
|
|
5460
5535
|
});
|
|
5461
5536
|
w.line();
|
|
5462
5537
|
};
|
|
5463
|
-
var generateFieldAccessors = (w, factoryInfo
|
|
5538
|
+
var generateFieldAccessors = (w, factoryInfo) => {
|
|
5464
5539
|
w.line("// Field accessors");
|
|
5465
5540
|
for (const p of factoryInfo.params) {
|
|
5466
5541
|
const methodBaseName = uppercaseFirstLetter(p.name);
|
|
@@ -5476,7 +5551,6 @@ var generateFieldAccessors = (w, factoryInfo, extSliceMethodBaseNames) => {
|
|
|
5476
5551
|
}
|
|
5477
5552
|
for (const a of factoryInfo.accessors) {
|
|
5478
5553
|
const methodBaseName = uppercaseFirstLetter(tsCamelCase(a.name));
|
|
5479
|
-
if (extSliceMethodBaseNames.has(methodBaseName)) continue;
|
|
5480
5554
|
const fieldAccess = tsFieldName(a.name);
|
|
5481
5555
|
w.curlyBlock([`get${methodBaseName}`, "()", `: ${a.tsType} | undefined`], () => {
|
|
5482
5556
|
w.lineSM(`return ${tsGet("this.resource", fieldAccess)} as ${a.tsType} | undefined`);
|
|
@@ -5599,49 +5673,6 @@ var generateFlatInputType = (w, flatProfile) => {
|
|
|
5599
5673
|
});
|
|
5600
5674
|
w.line();
|
|
5601
5675
|
};
|
|
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
5676
|
var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
5646
5677
|
const tsBaseResourceName = tsTypeFromIdentifier(flatProfile.base);
|
|
5647
5678
|
const profileClassName = tsProfileClassName(flatProfile);
|
|
@@ -5654,7 +5685,6 @@ var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
|
5654
5685
|
generateFlatInputType(w, flatProfile);
|
|
5655
5686
|
const canonicalUrl = flatProfile.identifier.url;
|
|
5656
5687
|
w.comment("CanonicalURL:", canonicalUrl, `(pkg: ${packageMetaToFhir(packageMeta(flatProfile))})`);
|
|
5657
|
-
const resolvedMethodNames = resolveProfileMethodBaseNames(flatProfile.extensions ?? [], sliceDefs);
|
|
5658
5688
|
w.curlyBlock(["export", "class", profileClassName], () => {
|
|
5659
5689
|
w.lineSM(`static readonly canonicalUrl = ${JSON.stringify(canonicalUrl)}`);
|
|
5660
5690
|
w.line();
|
|
@@ -5662,12 +5692,12 @@ var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
|
5662
5692
|
w.lineSM(`private resource: ${tsBaseResourceName}`);
|
|
5663
5693
|
w.line();
|
|
5664
5694
|
generateFactoryMethods(w, tsIndex, flatProfile, factoryInfo);
|
|
5665
|
-
generateFieldAccessors(w, factoryInfo
|
|
5695
|
+
generateFieldAccessors(w, factoryInfo);
|
|
5666
5696
|
w.line("// Extensions");
|
|
5667
|
-
generateExtensionMethods(w, tsIndex, flatProfile
|
|
5697
|
+
generateExtensionMethods(w, tsIndex, flatProfile);
|
|
5668
5698
|
w.line("// Slices");
|
|
5669
|
-
generateSliceSetters(w, sliceDefs, flatProfile
|
|
5670
|
-
generateSliceGetters(w, sliceDefs, flatProfile
|
|
5699
|
+
generateSliceSetters(w, sliceDefs, flatProfile);
|
|
5700
|
+
generateSliceGetters(w, sliceDefs, flatProfile);
|
|
5671
5701
|
w.line("// Validation");
|
|
5672
5702
|
generateValidateMethod(w, tsIndex, flatProfile);
|
|
5673
5703
|
});
|