@atomic-ehr/codegen 0.0.6 → 0.0.7-canary.20260224101452.ccac84d
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/dist/cli/index.js +7 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +910 -689
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
package/dist/cli/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import x from'picocolors';import Ke from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as re from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';import Ue from'assert';var L=class t{options;dryWarnSet=new Set;constructor(e={}){this.options={timestamp:false,level:1,...e};}shouldLog(e){let n=this.options.level??1;return e>=n}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(e,n,i){let r=this.options.timestamp?`${x.gray(new Date().toLocaleTimeString())} `:"",o=this.options.prefix?`${x.cyan(`[${this.options.prefix}]`)} `:"";return `${r}${i(e)} ${o}${n}`}isSuppressed(e){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(e)||false}tryWriteToConsole(e,n){if(this.isSuppressed(e)||!this.shouldLog(e))return;(t.consoleLevelsMap[e]||console.log)(n);}success(e){this.tryWriteToConsole(1,this.formatMessage("",e,x.green));}error(e,n){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",e,x.red));let i=this.options.level===0;n&&i&&(console.error(x.red(` ${n.message}`)),n.stack&&console.error(x.gray(n.stack)));}warn(e){this.tryWriteToConsole(2,this.formatMessage("!",e,x.yellow));}dry_warn(e){this.dryWarnSet.has(e)||(this.warn(e),this.dryWarnSet.add(e));}info(e){this.tryWriteToConsole(1,this.formatMessage("i",e,x.blue));}debug(e){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",e,x.magenta));}step(e){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",e,x.cyan));}progress(e){this.tryWriteToConsole(1,this.formatMessage("\u23F3",e,x.blue));}plain(e,n=i=>i){let i=this.options.timestamp?`${x.gray(new Date().toLocaleTimeString())} `:"",r=this.options.prefix?`${x.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${i}${r}${n(e)}`);}dim(e){this.plain(e,x.gray);}child(e){return new t({...this.options,prefix:this.options.prefix?`${this.options.prefix}:${e}`:e})}configure(e){this.options={...this.options,...e};}getLevel(){return this.options.level??1}setLevel(e){this.options.level=e;}},F=new L;function Re(t){F.success(t);}function b(t,e){F.error(t,e);}function O(t){F.info(t);}function Ce(t){F.dim(t);}function X(t){F.configure(t);}function w(t={}){return new L(t)}function Z(t){console.log(),console.log(x.cyan(x.bold(`\u2501\u2501\u2501 ${t} \u2501\u2501\u2501`)));}function Y(t,e,n){let i=t;e&&(i+=` ${x.gray(`(${e}ms)`)}`),Re(i),n&&Object.entries(n).forEach(([r,o])=>{Ce(` ${r}: ${o}`);});}function I(t,e="\u2022"){t.forEach(n=>{console.log(x.gray(` ${e} ${n}`));});}var B=t=>t!==null&&typeof t=="object"&&t.resourceType==="CodeSystem";var P=t=>t!==null&&typeof t=="object"&&t.resourceType==="ValueSet";var S=t=>`${t.name}#${t.version}`;var j=(t,e)=>(e||(e={name:"undefined",version:"undefined"}),{...t,package_meta:t.package_meta||e,name:t.name,url:t.url,base:t.base});var ee=t=>t?.kind==="nested",te=t=>t?.kind==="profile";var ne=(t,e)=>{if(!t.url)throw new Error("ValueSet must have a URL");if(!t.name)throw new Error("ValueSet must have a name");return {...t,package_meta:t.package_meta||e,name:t.name,url:t.url}};var ke=async(t,e)=>{let i=(await t.packageJson(e.name)).dependencies;return i!==void 0?Object.entries(i).map(([r,o])=>({name:r,version:o})):[]},oe=t=>({pkg:t,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),ae=async(t,e,n,i,r)=>{let o=S(e);if(r?.info(`${" ".repeat(n*2)}+ ${o}`),i[o])return i[o];let a=oe(e);for(let s of await t.search({package:e})){let c=s.url;if(!c||!(isStructureDefinition(s)||P(s)||B(s)))continue;let u=c;a.canonicalResolution[u]&&r?.dry_warn(`Duplicate canonical URL: ${u} at ${o}.`),a.canonicalResolution[u]=[{deep:n,pkg:e,pkgId:o,resource:s}];}let l=await ke(t,e);for(let s of l){let{canonicalResolution:c}=await ae(t,s,n+1,i,r);for(let[u,m]of Object.entries(c)){let f=u;a.canonicalResolution[f]=[...a.canonicalResolution[f]||[],...m];}}for(let s of Object.values(a.canonicalResolution))s.sort((c,u)=>c.deep-u.deep);return i[o]=a,a},ie=(t,e)=>{for(let{pkg:n,canonicalResolution:i}of Object.values(t)){let r=S(n);if(!t[r])throw new Error(`Package ${r} not found`);for(let[a,l]of Object.entries(i)){let s=l[0];if(!s)throw new Error("Resource not found");let c=s.resource,u=s.pkg;if(isStructureDefinition(c)){let m=re.translate(c),f=j(m,u);t[r].fhirSchemas[f.url]=f;}if(P(c)){let m=ne(c,u);t[r].valueSets[m.url]=m;}}}},be=(t,e,n)=>{let i=Object.values(t).flatMap(r=>r.canonicalResolution[e]);if(!i)throw new Error(`No canonical resolution found for ${e} in any package`);return i[0]?.resource},_=async(t,{logger:e,fallbackPackageForNameResolution:n,focusedPackages:i})=>{let r=i??await t.packages(),o={};for(let p of r)await ae(t,p,0,o,e);ie(o);let a=(p,d)=>o[S(p)]?.fhirSchemas[d]||n&&o[S(n)]?.fhirSchemas[d],l=(p,d)=>o[S(p)]?.valueSets[d]||n&&o[S(n)]?.valueSets[d],s=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),c=(p,d)=>{let g=a(p,d);if(g===void 0)throw new Error(`Failed to resolve FHIR Schema: '${d}'`);let y=[g];for(;g?.base;){let R=g.package_meta,C=s(g.base);if(g=a(R,C),g===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${d}'. Problem: '${C}' from '${S(R)}'`);y.push(g);}return y},u=(p,d)=>c(p,d).filter(g=>g.derivation==="specialization"),m=(p,d)=>{let g=c(p.package_meta,p.url),y=Ie(g,d);return ve(y)},f=p=>{let d=new Set;for(let[g,y]of Object.entries(p)){d.add(g);for(let R of y?.choices||[])p[R]||d.add(R);}return Array.from(d)},h;return {testAppendFs(p){let d=j(p),g=S(d.package_meta);o[g]||(o[g]=oe(d.package_meta)),o[g].fhirSchemas[d.url]=d,h=void 0;},resolveFs:a,resolveFsGenealogy:c,resolveFsSpecializations:u,ensureSpecializationCanonicalUrl:s,resolveSd:(p,d)=>{let g=o[S(p)]?.canonicalResolution[d]?.[0]?.resource;if(isStructureDefinition(g))return g},allSd:()=>Object.values(o).flatMap(p=>Object.values(p.canonicalResolution).flatMap(d=>d.map(g=>{let y=g.resource;return y.package_name?y:{...y,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,d)=>p.url.localeCompare(d.url)),patchSd:p=>{Object.values(o).flatMap(d=>Object.values(d.canonicalResolution).forEach(g=>{g.forEach(y=>{if(isStructureDefinition(y.resource)){let R=y.resource,C=p(d.pkg,R);if(R.url!==C.url)throw new Error(`Patch update StructureDefinition URL: ${R.url} !== ${C.url}`);y.resource=C;}});})),ie(o),h=void 0;},allFs:()=>Object.values(o).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(o).flatMap(p=>Object.values(p.valueSets)),resolveVs:l,resolveAny:p=>be(o,p),resolveElementSnapshot:m,getAllElementKeys:f,resolver:o,resolutionTree:()=>{if(h)return h;let p={};for(let[d,g]of Object.entries(o)){let y=g.pkg.name;p[y]={};for(let[R,C]of Object.entries(g.canonicalResolution)){let J=R;p[y][J]=[];for(let Q of C)p[y][J].push({deep:Q.deep,pkg:Q.pkg});}}return h=p,p}}};var Ie=(t,e)=>{let[n,...i]=e;return n===void 0?[]:t.map(r=>{if(!r.elements)return;let o=r.elements?.[n];for(let a of i)o=o?.elements?.[a];return o}).filter(r=>r!==void 0)};function ve(t){let e=t.reverse(),n=Object.assign({},...e);return n.elements=void 0,n}var T="Use CodeableReference which is not provided by FHIR R4.",Fe="Use Availability which is not provided by FHIR R4.",se={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":Fe,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":T,"http://hl7.org/fhir/StructureDefinition/specimen-additive":T,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":T,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":T,"http://hl7.org/fhir/StructureDefinition/workflow-reason":T},"hl7.fhir.r5.core#5.0.0":{"http://hl7.org/fhir/StructureDefinition/shareablecodesystem":"FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now.","http://hl7.org/fhir/StructureDefinition/publishablecodesystem":"Uses R5-only base types not available in R4 generation."}};function A(t,e){let n=`${t.name}#${t.version}`,i=se[n]?.[e];if(i)return {shouldSkip:true,reason:i};let r=se[t.name]?.[e];return r?{shouldSkip:true,reason:r}:{shouldSkip:false}}function G(t){let e=t.split("|")[0];return e||t}function Ee(t){return t.split("|")[1]}function Te(t){return t.derivation==="constraint"?"profile":t.kind==="primitive-type"?"primitive-type":t.kind==="complex-type"?"complex-type":t.kind==="resource"?"resource":t.kind==="logical"?"logical":"resource"}function k(t){return {kind:Te(t),package:t.package_meta.name,version:t.package_meta.version,name:t.name,url:t.url}}var De=t=>{let e=t.split("/"),n=e[e.length-1];return n&&n.length>0?n.split(/[-_]/).map(i=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join(""):t};function U(t,e,n){let i=G(n),r=De(i),o={package_meta:{name:"missing_valuesets",version:Ee(i)||"0.0.0"},id:n},a=t.resolveVs(e,i)||o,l=a?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(a.id)?a.id:r;return {kind:"value-set",package:a.package_meta.name,version:a.package_meta.version,name:l,url:i}}function N(t,e,n){let i=e.join("."),[r,o,a]=n?[{name:"shared",version:"1.0.0"},n,`urn:fhir:binding:${n}`]:[t.package_meta,`${t.name}.${i}_binding`,`${t.url}#${i}_binding`];return {kind:"binding",package:r.name,version:r.version,name:o,url:a}}function $(t,e,n,i){let r={};if(e.derivation==="constraint"){let m=t.resolveFsSpecializations(e.package_meta,e.url).map(f=>q(t,f,i)).filter(f=>f!==void 0).flat();for(let f of m.reverse())r[f.identifier.name]=f.identifier.url;}let o=n.join("."),a=r[o]??`${e.url}#${o}`,l=a.split("#")[0],c=t.resolveFs(e.package_meta,l)?.package_meta??e.package_meta;return {kind:"nested",package:c.name,version:c.version,name:o,url:a}}function ce(t,e,n){let i=[];for(let[r,o]of Object.entries(n)){let a=[...e,r];D(o)&&i.push([a,o]),o.elements&&i.push(...ce(t,a,o.elements));}return i}function Le(t,e,n,i,r){let o={};for(let[a,l]of Object.entries(i)){let s=[...n,a],c=t.resolveElementSnapshot(e,s);D(c)?o[a]=H(t,e,s,c,r):o[a]=V(t,e,s,c,r);}return o}function q(t,e,n){if(!e.elements)return;let i=ce(e,[],e.elements).filter(([o,a])=>a.elements&&Object.keys(a.elements).length>0),r=[];for(let[o,a]of i){let l=$(t,e,o,n),s;a.type==="BackboneElement"||!a.type?s="BackboneElement":s=a.type;let c=t.ensureSpecializationCanonicalUrl(s),u=t.resolveFs(e.package_meta,c);if(!u)throw new Error(`Could not resolve base type ${s}`);let m={kind:"complex-type",package:u.package_meta.name,version:u.package_meta.version,name:s,url:c},f=Le(t,e,o,a.elements??{},n),h={identifier:l,base:m,fields:f};r.push(h);}return r.sort((o,a)=>o.identifier.url.localeCompare(a.identifier.url)),r.length===0?void 0:r}function le(t){let e=[];for(let n of t){n.base&&e.push(n.base);for(let i of Object.values(n.fields||{}))"type"in i&&i.type&&e.push(i.type),"binding"in i&&i.binding&&e.push(i.binding);}return e}function pe(t,e,n){let i=n[n.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${n.join("/")}`);let r=n.slice(0,-1),o=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(a=>{if(r.length===0)return a.required||[];if(!a.elements)return [];let l=a;for(let s of r)l=l?.elements?.[s];return l?.required||[]});return new Set(o).has(i)}function de(t,e,n){let i=n[n.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${n.join("/")}`);let r=n.slice(0,-1),o=t.resolveFsGenealogy(e.package_meta,e.url).flatMap(a=>{if(r.length===0)return a.excluded||[];if(!a.elements)return [];let l=a;for(let s of r)l=l?.elements?.[s];return l?.excluded||[]});return new Set(o).has(i)}var we=(t,e,n)=>{if(n.refers)return n.refers.map(i=>{let r=t.ensureSpecializationCanonicalUrl(i),o=t.resolveFs(e.package_meta,r);if(!o)throw new Error(`Failed to resolve fs for ${r}`);return k(o)})},Pe=t=>{let e=new Set,n=new Set;if(t.required)for(let i of t.required)e.add(i);if(t.excluded)for(let i of t.excluded)n.add(i);if(t.elements)for(let[i,r]of Object.entries(t.elements))r.min!==void 0&&r.min>0&&e.add(i);return {required:e.size>0?Array.from(e):void 0,excluded:n.size>0?Array.from(n):void 0}},ue=t=>{let e=t.slicing;if(!e)return;let n={};for(let[i,r]of Object.entries(e.slices??{})){if(!r)continue;let{required:o,excluded:a}=r.schema?Pe(r.schema):{};n[i]={min:r.min,max:r.max,match:r.match,required:o,excluded:a};}return {discriminator:e.discriminator,rules:e.rules,ordered:e.ordered,slices:Object.keys(n).length>0?n:void 0}};function v(t,e,n,i,r){if(i.elementReference){let o=i.elementReference.slice(1).filter((a,l)=>l%2===1);return $(t,e,o,r)}else if(i.type){let o=t.ensureSpecializationCanonicalUrl(i.type),a=t.resolveFs(e.package_meta,o);if(!a)throw new Error(`Could not resolve field type: <${e.url}>.${n.join(".")}: <${i.type}> (pkg: '${S(e.package_meta)}'))`);return k(a)}else {if(i.choices)return;if(e.derivation==="constraint")return;throw r?.error(`Can't recognize element type: <${e.url}>.${n.join(".")} (pkg: '${S(e.package_meta)}'): ${JSON.stringify(i,void 0,2)}`),new Error("Unrecognized element type")}}var V=(t,e,n,i,r)=>{let o,a;i.binding&&(o=N(e,n,i.binding.bindingName),i.binding.strength==="required"&&i.type==="code"&&(a=z(t,e,i,r)));let l=v(t,e,n,i,r);return l||r?.dry_warn(`Field type not found for '${e.url}#${n.join(".")}' (${e.derivation})`),{type:l,required:pe(t,e,n),excluded:de(t,e,n),reference:we(t,e,i),array:i.array||false,min:i.min,max:i.max,slicing:ue(i),choices:i.choices,choiceOf:i.choiceOf,binding:o,enum:a}};function D(t){let e=t.type==="BackboneElement",n=t.type==="Element"&&t.elements!==void 0&&Object.keys(t.elements).length>0,i=t.type===void 0&&t.choiceOf===void 0&&t.elements!==void 0&&Object.keys(t.elements).length>0;return e||n||i}function H(t,e,n,i,r){return {type:$(t,e,n,r),array:i.array||false,required:pe(t,e,n),excluded:de(t,e,n),slicing:ue(i)}}function W(t,e,n,i){let r=G(n)||n,o=t.resolveVs(e,r);if(o)return Ne(t,o)}function Ne(t,e,n){if(e.expansion?.contains)return e.expansion.contains.filter(r=>r.code!==void 0).map(r=>(Ue(r.code),{code:r.code,display:r.display,system:r.system}));let i=[];if(e.compose?.include){for(let r of e.compose.include)if(r.concept)for(let o of r.concept)i.push({system:r.system,code:o.code,display:o.display});else if(r.system&&!r.filter)try{let o=t.resolveAny(r.system);if(o?.concept){let a=(l,s)=>{for(let c of l)i.push({system:s,code:c.code,display:c.display}),c.concept&&a(c.concept,s);};a(o.concept,r.system);}}catch{}}return i.length>0?i:void 0}var me=100;function z(t,e,n,i){if(!n.binding)return;let r=n.binding.strength,o=n.binding.valueSet;if(!o||!(r==="required"||r==="extensible"&&(n.type==="code"||n.type==="Coding")||r==="preferred"&&(n.type==="code"||n.type==="Coding")))return;let l=W(t,e.package_meta,o);if(!l||l.length===0)return;let s=l.map(c=>c.code).filter(c=>c&&typeof c=="string"&&c.trim().length>0);if(s.length>me){i?.dry_warn(`Value set ${o} has ${s.length} which is more than ${me} codes, which may cause issues with code generation.`);return}return s.length>0?s:void 0}function $e(t,e,n,i,r){if(!i.binding?.valueSet)return;let o=N(e,n,i.binding.bindingName),a=v(t,e,n,i,r),l=U(t,e.package_meta,i.binding.valueSet),s=[];a&&s.push(a),s.push(l);let c=z(t,e,i,r);return {identifier:o,type:a,valueset:l,strength:i.binding.strength,enum:c,dependencies:s}}function fe(t,e,n){let i=new Set;if(!e.elements)return [];let r=[];function o(s,c){for(let[u,m]of Object.entries(s)){let f=[...c,u],h=f.join("."),p=t.resolveElementSnapshot(e,f);if(!i.has(h)){if(i.add(h),p.binding){let d=$e(t,e,f,p,n);d&&r.push(d);}m.elements&&o(m.elements,f);}}}o(e.elements,[]),r.sort((s,c)=>s.identifier.name.localeCompare(c.identifier.name));let a=[],l=new Set;for(let s of r)l.has(s.identifier.url)||(l.add(s.identifier.url),a.push(s));return a}function Ve(t,e,n,i,r){if(!i)return;let o={};for(let a of t.getAllElementKeys(i)){let l=[...n,a],s=t.resolveElementSnapshot(e,l),c=s.type?t.ensureSpecializationCanonicalUrl(s.type):void 0;if(c&&A(e.package_meta,c).shouldSkip){r?.warn(`Skipping field ${l} for ${c} due to skip hack ${A(e.package_meta,c).reason}`);continue}D(s)?o[a]=H(t,e,l,s,r):o[a]=V(t,e,l,s,r);}return o}function He(t){let e=[];for(let n of Object.values(t))"type"in n&&n.type&&e.push(n.type),"binding"in n&&n.binding&&e.push(n.binding);return e}function Me(t,e){return !!(t.base==="Extension"||t.base==="http://hl7.org/fhir/StructureDefinition/Extension"||t.url?.includes("/extension/")||t.url?.includes("-extension")||t.name?.toLowerCase().includes("extension")||t.type==="Extension")}async function ge(t,e,n){if(!e.url)throw new Error("ValueSet URL is required");let i=U(t,e.package_meta,e.url),r=W(t,e.package_meta,e.url);return {identifier:i,description:e.description,concept:r,compose:r?void 0:e.compose}}function Oe(t,e,n,i){let r=[];e&&r.push(e),n&&r.push(...He(n)),i&&r.push(...le(i));let o={};for(let s of r)s.url!==t.url&&(o[s.url]=s);let a=new Set(i?.map(s=>s.identifier.url)),l=Object.values(o).filter(s=>te(t)||!ee(s)?true:!a.has(s.url)).sort((s,c)=>s.url.localeCompare(c.url));return l.length>0?l:void 0}function Be(t,e,n){let i=k(e),r;if(e.base&&e.type!=="Element"){let h=t.resolveFs(e.package_meta,t.ensureSpecializationCanonicalUrl(e.base));if(!h)throw new Error(`Base resource not found '${e.base}' for <${e.url}> from ${S(e.package_meta)}`);r=k(h);}let o=Ve(t,e,[],e.elements,n),a=q(t,e,n),l=e.derivation==="constraint"?Ae(t,e,n):void 0,s=Oe(i,r,o,a),c=l?.flatMap(h=>h.valueTypes??[])??[],u=(()=>{if(!s&&c.length===0)return s;let h={};for(let p of s??[])h[p.url]=p;for(let p of c)h[p.url]=p;return Object.values(h)})(),m={identifier:i,base:r,fields:o,nested:a,description:e.description,dependencies:u,...l&&l.length>0?{extensions:l}:{}},f=fe(t,e,n);return [m,...f]}function je(t,e,n,i){let r=t.resolveFs(e.package_meta,n);if(!r?.elements)return;let o=[];for(let[l,s]of Object.entries(r.elements)){if(s.choiceOf!=="value"&&!l.startsWith("value"))continue;let c=v(t,r,[l],s,i);c&&o.push(c);}if(o.length===0)return;let a=new Map(o.map(l=>[l.url,l]));return Array.from(a.values())}function _e(t,e,n,i){let r=t.resolveFs(e.package_meta,n);if(!r?.elements)return;let o=[];for(let[s,c]of Object.entries(r.elements)){if(!s.startsWith("extension:"))continue;let u=s.split(":")[1];if(!u)continue;let m=c.url??u,f;for(let[h,p]of Object.entries(c.elements??{}))if(!(p.choiceOf!=="value"&&!h.startsWith("value"))&&(f=v(t,r,[s,h],p,i),f))break;o.push({name:u,url:m,valueType:f,min:c.min,max:c.max!==void 0?String(c.max):void 0});}let l=r.elements.extension?.slicing?.slices;if(l&&typeof l=="object")for(let[s,c]of Object.entries(l)){let u=c,m=u.schema;if(!m)continue;let f=u.match?.url??s,h,p=m.elements??{};for(let[d,g]of Object.entries(p)){let y=g;if(!(y.choiceOf!=="value"&&!d.startsWith("value"))&&y.type){h={kind:"complex-type",package:r.package_meta.name,version:r.package_meta.version,name:y.type,url:`http://hl7.org/fhir/StructureDefinition/${y.type}`};break}}o.push({name:s,url:f,valueType:h,min:m._required?1:m.min??0,max:m.max!==void 0?String(m.max):m.array?"*":"1"});}return o.length>0?o:void 0}function Ae(t,e,n){let i=[],r=(a,l,s)=>{let c=s.url,u=c?je(t,e,c,n):void 0,m=c?_e(t,e,c,n):void 0,f=m!==void 0&&m.length>0;i.push({name:l,path:[...a,"extension"].join("."),url:c,min:s.min,max:s.max!==void 0?String(s.max):void 0,mustSupport:s.mustSupport,valueTypes:u,subExtensions:m,isComplex:f});},o=(a,l)=>{if(l.extensions)for(let[s,c]of Object.entries(l.extensions))r(a,s,c);if(l.elements)for(let[s,c]of Object.entries(l.elements))o([...a,s],c);};if(e.extensions)for(let[a,l]of Object.entries(e.extensions))r([],a,l);if(e.elements)for(let[a,l]of Object.entries(e.elements))o([a],l);return i}async function he(t,e,n){let i=Be(t,e,n);if(Me(e,k(e))){let r=i[0];if(!r)throw new Error("Expected schema to be defined");r.metadata={isExtension:true};}return i}var M=class{manager;options;logger;constructor(e){this.options={...e},this.manager=e.manager,this.logger=e.logger||w({prefix:"TypeSchema"});}async registerFromPackageMetas(e){let n=e.map(S);return this.logger?.step(`Loading FHIR packages: ${n.join(", ")}`),await this.manager.init(),_(this.manager,{focusedPackages:e})}generateFhirSchemas(e){this.logger?.progress(`Converting ${e.length} StructureDefinitions to FHIRSchemas`);let n=[],i=0,r=0;for(let o of e)try{let a=re.translate(o);n.push(a),i++,this.logger?.debug(`Converted StructureDefinition: ${o.name||o.id} (${o.resourceType})`);}catch(a){r++,this.logger?.warn(`Failed to convert StructureDefinition ${o.name||o.id}: ${a instanceof Error?a.message:String(a)}`);}return this.logger?.success(`FHIR Schema conversion completed: ${i}/${e.length} successful, ${r} failed`),n}async generateValueSetSchemas(e,n){e.length>0&&this.logger?.debug(`${e.length} ValueSets available for enum extraction`);let i=await _(this.manager,{logger:this.logger}),r=[];if(e.length>0){this.logger?.progress(`Converting ${e.length} ValueSets to TypeSchema`);let o=0,a=0;for(let l of e)try{let s=await ge(i,l,n);s&&(r.push(s),o++,this.logger?.debug(`Converted ValueSet: ${l.name||l.id}`));}catch(s){a++,this.logger?.warn(`Failed to convert ValueSet ${l.name||l.id}: ${s instanceof Error?s.message:String(s)}`);}this.logger?.success(`ValueSet conversion completed: ${o}/${e.length} successful, ${a} failed`);}return r}async generateFromPackage(e,n,i){let r={name:e,version:n||"latest"},o=await this.registerFromPackageMetas([r]),a=await this.generateValueSetSchemas(o.allVs(),i);return [...(await Promise.all(o.allFs().map(async c=>await he(o,c,i)))).flat(),...a]}};var Se={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async t=>{let e=w({prefix:"TypeSchema"});try{e.step("Generating TypeSchema from FHIR packages"),e.info(`Packages: ${t.packages.join(", ")}`),e.info(`Output: ${t.output}`);let n=t.singleFile?"ndjson":t.format;e.debug(`Format: ${n}${t.singleFile&&t.format==="json"?" (forced from json due to singleFile)":""}`),t.treeshake&&t.treeshake.length>0&&e.info(`Treeshaking enabled for ResourceTypes: ${t.treeshake.join(", ")}`),t.singleFile&&e.info("Single file output enabled (NDJSON format)"),t.registry&&e.info(`Using custom registry: ${t.registry}`);let i=Date.now(),r=new M({treeshake:t.treeshake,registry:t.registry,manager:CanonicalManager({packages:[],workingDir:".codegen-cache/canonical-manager-cache",registry:t.registry})}),o=[];for(let c of t.packages){let[u,m]=c.includes("@")?c.split("@"):[c,void 0];e.progress(`Processing package: ${u}${m?`@${m}`:""}`);let f=await r.generateFromPackage(u,m,e);o.push(...f);}if(o.length===0)throw new Error("No schemas were generated from the specified packages");let a=t.output;if(!a)throw new Error("Output format not specified");await mkdir(dirname(a),{recursive:!0});let l;n==="json"?l=JSON.stringify(o,null,2):l=o.map(c=>JSON.stringify(c)).join(`
|
|
3
|
-
`),await writeFile(a,
|
|
2
|
+
import S from'picocolors';import Ze from'yargs';import {hideBin}from'yargs/helpers';import {mkdir,writeFile}from'fs/promises';import {dirname}from'path';import {createHash}from'crypto';import Te from'assert';import {CanonicalManager}from'@atomic-ehr/fhir-canonical-manager';import*as ge from'@atomic-ehr/fhirschema';import {isStructureDefinition}from'@atomic-ehr/fhirschema';var D=class e{options;dryWarnSet=new Set;constructor(t={}){this.options={timestamp:false,level:1,...t};}shouldLog(t){let o=this.options.level??1;return t>=o}static consoleLevelsMap={1:console.log,2:console.warn,3:console.error,0:console.log,4:()=>{}};formatMessage(t,o,i){let n=this.options.timestamp?`${S.gray(new Date().toLocaleTimeString())} `:"",r=this.options.prefix?`${S.cyan(`[${this.options.prefix}]`)} `:"";return `${n}${i(t)} ${r}${o}`}isSuppressed(t){return this.options.suppressLoggingLevel==="all"||this.options.suppressLoggingLevel?.includes(t)||false}tryWriteToConsole(t,o){if(this.isSuppressed(t)||!this.shouldLog(t))return;(e.consoleLevelsMap[t]||console.log)(o);}success(t){this.tryWriteToConsole(1,this.formatMessage("",t,S.green));}error(t,o){if(this.isSuppressed(3)||!this.shouldLog(3))return;console.error(this.formatMessage("X",t,S.red));let i=this.options.level===0;o&&i&&(console.error(S.red(` ${o.message}`)),o.stack&&console.error(S.gray(o.stack)));}warn(t){this.tryWriteToConsole(2,this.formatMessage("!",t,S.yellow));}dryWarn(t){this.dryWarnSet.has(t)||(this.warn(t),this.dryWarnSet.add(t));}info(t){this.tryWriteToConsole(1,this.formatMessage("i",t,S.blue));}debug(t){this.shouldLog(0)&&this.tryWriteToConsole(0,this.formatMessage("\u{1F41B}",t,S.magenta));}step(t){this.tryWriteToConsole(1,this.formatMessage("\u{1F680}",t,S.cyan));}progress(t){this.tryWriteToConsole(1,this.formatMessage("\u23F3",t,S.blue));}plain(t,o=i=>i){let i=this.options.timestamp?`${S.gray(new Date().toLocaleTimeString())} `:"",n=this.options.prefix?`${S.cyan(`[${this.options.prefix}]`)} `:"";this.tryWriteToConsole(1,`${i}${n}${o(t)}`);}dim(t){this.plain(t,S.gray);}child(t){return new e({...this.options,prefix:this.options.prefix?`${this.options.prefix}:${t}`:t})}configure(t){this.options={...this.options,...t};}getLevel(){return this.options.level??1}setLevel(t){this.options.level=t;}},v=new D;function Ce(e){v.success(e);}function C(e,t){v.error(e,t);}function H(e){v.info(e);}function ke(e){v.dim(e);}function K(e){v.configure(e);}function J(e={}){return new D(e)}function Q(e){console.log(),console.log(S.cyan(S.bold(`\u2501\u2501\u2501 ${e} \u2501\u2501\u2501`)));}function X(e,t,o){let i=e;t&&(i+=` ${S.gray(`(${t}ms)`)}`),Ce(i),o&&Object.entries(o).forEach(([n,r])=>{ke(` ${n}: ${r}`);});}function k(e,t="\u2022"){e.forEach(o=>{console.log(S.gray(` ${t} ${o}`));});}var F="Use CodeableReference which is not provided by FHIR R4.",be="Use Availability which is not provided by FHIR R4.",O={"hl7.fhir.uv.extensions.r4":{"http://hl7.org/fhir/StructureDefinition/extended-contact-availability":be,"http://hl7.org/fhir/StructureDefinition/immunization-procedure":F,"http://hl7.org/fhir/StructureDefinition/specimen-additive":F,"http://hl7.org/fhir/StructureDefinition/workflow-barrier":F,"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor":F,"http://hl7.org/fhir/StructureDefinition/workflow-reason":F},"hl7.fhir.r5.core#5.0.0":{"http://hl7.org/fhir/StructureDefinition/shareablecodesystem":"FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now.","http://hl7.org/fhir/StructureDefinition/publishablecodesystem":"Uses R5-only base types not available in R4 generation."}};function b(e,t){let o=`${e.name}#${e.version}`,i=O[o]?.[t];if(i)return {shouldSkip:true,reason:i};let n=O[e.name]?.[t];return n?{shouldSkip:true,reason:n}:{shouldSkip:false}}var x=e=>`${e.name}#${e.version}`,Y=e=>`${e.name}@${e.version}`;var Z=e=>{let t=JSON.stringify(e);return createHash("sha256").update(t).digest("hex").slice(0,16)},ee=(e,t)=>({...e,package_meta:e.package_meta||t,name:e.name,url:e.url,base:e.base});var te=e=>e?.kind==="nested",ne=e=>e?.kind==="profile";var ie=(e,t)=>{if(!e.url)throw new Error("ValueSet must have a URL");if(!e.name)throw new Error("ValueSet must have a name");return {...e,package_meta:e.package_meta||t,name:e.name,url:e.url}};function M(e){let t=e.split("|")[0];return t||e}function ve(e){return e.split("|")[1]}function Fe(e){return e.derivation==="constraint"?"profile":e.kind==="primitive-type"?"primitive-type":e.kind==="complex-type"?"complex-type":e.kind==="resource"?"resource":e.kind==="logical"?"logical":"resource"}function I(e){return {kind:Fe(e),package:e.package_meta.name,version:e.package_meta.version,name:e.name,url:e.url}}var Ee=e=>{let t=e.split("/"),o=t[t.length-1];return o&&o.length>0?o.split(/[-_]/).map(i=>i.charAt(0).toUpperCase()+i.slice(1).toLowerCase()).join(""):e};function L(e,t,o){let i=M(o),n=Ee(i),r={package_meta:{name:"missing_valuesets",version:ve(i)||"0.0.0"},id:o},s=e.resolveVs(t,i)||r,c=s?.id&&!/^[a-zA-Z0-9_-]{20,}$/.test(s.id)?s.id:n;return {kind:"value-set",package:s.package_meta.name,version:s.package_meta.version,name:c,url:i}}function P(e,t,o){let i=o.binding?.bindingName,n=t.join("."),[r,s,c]=i?[{name:"shared",version:"1.0.0"},i,`urn:fhir:binding:${i}`]:[e.package_meta,`${e.name}.${n}_binding`,`${e.url}#${n}_binding`];return {kind:"binding",package:r.name,version:r.version,name:s,url:c}}function B(e,t,o,i){let n=M(o)||o,r=e.resolveVs(t,n);if(r)return De(e,r)}function De(e,t,o){if(t.expansion?.contains)return t.expansion.contains.filter(n=>n.code!==void 0).map(n=>(Te(n.code),{code:n.code,display:n.display,system:n.system}));let i=[];if(t.compose?.include){for(let n of t.compose.include)if(n.concept)for(let r of n.concept)i.push({system:n.system,code:r.code,display:r.display});else if(n.system&&!n.filter)try{let r=e.resolveAny(n.system);if(r?.concept){let s=(c,a)=>{for(let l of c)i.push({system:a,code:l.code,display:l.display}),l.concept&&s(l.concept,a);};s(r.concept,n.system);}}catch{}}return i.length>0?i:void 0}var oe=100,j=new Set(["code","Coding","CodeableConcept","CodeableReference","Quantity","string","uri","Duration"]);function _(e,t,o,i){if(!o.binding)return;let n=o.binding.strength,r=o.binding.valueSet;if(!r)return;if(!j.has(o.type??"")){i?.dryWarn(`eld-11: Binding on non-bindable type '${o.type}' (valueSet: ${r})`);return}if(!(n==="required"||n==="extensible"||n==="preferred"))return;let c=B(e,t.package_meta,r);if(!c||c.length===0)return;let a=c.map(l=>l.code).filter(l=>l&&typeof l=="string"&&l.trim().length>0);if(a.length>oe){i?.dryWarn(`Value set ${r} has ${a.length} which is more than ${oe} codes, which may cause issues with code generation.`);return}if(a.length!==0)return {isOpen:n!=="required",values:a}}function Le(e,t,o,i,n){if(!i.binding?.valueSet)return;let r=P(t,o,i),s=L(e,t.package_meta,i.binding.valueSet),c=_(e,t,i,n);return {identifier:r,valueset:s,strength:i.binding.strength,enum:c,dependencies:[s]}}function re(e,t,o){let i=new Set;if(!t.elements)return [];let n=[];function r(a,l){for(let[u,m]of Object.entries(a)){let h=[...l,u],p=h.join("."),d=e.resolveElementSnapshot(t,h);if(!i.has(p)){if(i.add(p),d.binding){let f=Le(e,t,h,d,o);f&&n.push(f);}m.elements&&r(m.elements,h);}}}r(t.elements,[]),n.sort((a,l)=>a.identifier.name.localeCompare(l.identifier.name));let s=[],c=new Set;for(let a of n)c.has(a.identifier.url)||(c.add(a.identifier.url),s.push(a));return s}function N(e,t,o,i){let n={};if(t.derivation==="constraint"){let m=e.resolveFsSpecializations(t.package_meta,t.url).map(h=>A(e,h,i)).filter(h=>h!==void 0).flat();for(let h of m.reverse())n[h.identifier.name]=h.identifier.url;}let r=o.join("."),s=n[r]??`${t.url}#${r}`,c=s.split("#")[0],l=e.resolveFs(t.package_meta,c)?.package_meta??t.package_meta;return {kind:"nested",package:l.name,version:l.version,name:r,url:s}}function se(e,t,o){let i=[];for(let[n,r]of Object.entries(o)){let s=[...t,n];E(r)&&i.push([s,r]),r.elements&&i.push(...se(e,s,r.elements));}return i}function Pe(e,t,o,i,n){let r={};for(let[s,c]of Object.entries(i)){let a=[...o,s],l=e.resolveElementSnapshot(t,a);E(l)?r[s]=U(e,t,a,l,n):r[s]=w(e,t,a,l,n);}return r}function A(e,t,o){if(!t.elements)return;let i=se(t,[],t.elements).filter(([r,s])=>s.elements&&Object.keys(s.elements).length>0),n=[];for(let[r,s]of i){let c=N(e,t,r,o),a;s.type==="BackboneElement"||!s.type?a="BackboneElement":a=s.type;let l=e.ensureSpecializationCanonicalUrl(a),u=e.resolveFs(t.package_meta,l);if(!u)throw new Error(`Could not resolve base type ${a}`);let m={kind:"complex-type",package:u.package_meta.name,version:u.package_meta.version,name:a,url:l},h=Pe(e,t,r,s.elements??{},o),p={identifier:c,base:m,fields:h};n.push(p);}return n.sort((r,s)=>r.identifier.url.localeCompare(s.identifier.url)),n.length===0?void 0:n}function ae(e){let t=[];for(let o of e){o.base&&t.push(o.base);for(let i of Object.values(o.fields||{}))"type"in i&&i.type&&t.push(i.type),"binding"in i&&i.binding&&t.push(i.binding);}return t}function ce(e,t,o){let i=o[o.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${o.join("/")}`);let n=o.slice(0,-1),r=e.resolveFsGenealogy(t.package_meta,t.url).flatMap(s=>{if(n.length===0)return s.required||[];if(!s.elements)return [];let c=s;for(let a of n)c=c?.elements?.[a];return c?.required||[]});return new Set(r).has(i)}function le(e,t,o){let i=o[o.length-1];if(!i)throw new Error(`Internal error: fieldName is missing for path ${o.join("/")}`);let n=o.slice(0,-1),r=e.resolveFsGenealogy(t.package_meta,t.url).flatMap(s=>{if(n.length===0)return s.excluded||[];if(!s.elements)return [];let c=s;for(let a of n)c=c?.elements?.[a];return c?.excluded||[]});return new Set(r).has(i)}var Ne=(e,t,o)=>{if(o.refers)return o.refers.map(i=>{let n=e.ensureSpecializationCanonicalUrl(i),r=e.resolveFs(t.package_meta,n);if(!r)throw new Error(`Failed to resolve fs for ${n}`);return I(r)})},we=e=>{let t=new Set,o=new Set;if(e.required)for(let i of e.required)t.add(i);if(e.excluded)for(let i of e.excluded)o.add(i);if(e.elements)for(let[i,n]of Object.entries(e.elements))n.min!==void 0&&n.min>0&&t.add(i);return {required:t.size>0?Array.from(t):void 0,excluded:o.size>0?Array.from(o):void 0}},pe=e=>{let t=e.slicing;if(!t)return;let o={};for(let[i,n]of Object.entries(t.slices??{})){if(!n)continue;let{required:r,excluded:s}=n.schema?we(n.schema):{};o[i]={min:n.min,max:n.max,match:n.match,required:r,excluded:s};}return {discriminator:t.discriminator,rules:t.rules,ordered:t.ordered,slices:Object.keys(o).length>0?o:void 0}};function $(e,t,o,i,n){if(i.elementReference){let r=i.elementReference.slice(1).filter((s,c)=>c%2===1);return N(e,t,r,n)}else if(i.type){let r=e.ensureSpecializationCanonicalUrl(i.type),s=e.resolveFs(t.package_meta,r);if(!s)throw new Error(`Could not resolve field type: <${t.url}>.${o.join(".")}: <${i.type}> (pkg: '${x(t.package_meta)}'))`);return I(s)}else {if(i.choices)return;if(t.derivation==="constraint")return;n?.dryWarn(`Can't recognize element type: <${t.url}>.${o.join(".")} (pkg: '${x(t.package_meta)}'): missing type info`);return}}var w=(e,t,o,i,n)=>{let r,s;i.binding&&(r=P(t,o,i),j.has(i.type??"")&&(s=_(e,t,i,n)));let c=$(e,t,o,i,n);return c||n?.dryWarn(`Field type not found for '${t.url}#${o.join(".")}' (${t.derivation})`),{type:c,required:ce(e,t,o),excluded:le(e,t,o),reference:Ne(e,t,i),array:i.array||false,min:i.min,max:i.max,slicing:pe(i),choices:i.choices,choiceOf:i.choiceOf,binding:r,enum:s}};function E(e){let t=e.type==="BackboneElement",o=e.type==="Element"&&e.elements!==void 0&&Object.keys(e.elements).length>0,i=e.type===void 0&&e.choiceOf===void 0&&e.elements!==void 0&&Object.keys(e.elements).length>0;return t||o||i}function U(e,t,o,i,n){return {type:N(e,t,o,n),array:i.array||false,required:ce(e,t,o),excluded:le(e,t,o),slicing:pe(i)}}function Ue(e,t,o,i,n){if(!i)return;let r={};for(let s of e.getAllElementKeys(i)){let c=[...o,s],a=e.resolveElementSnapshot(t,c),l=a.type?e.ensureSpecializationCanonicalUrl(a.type):void 0;if(l&&b(t.package_meta,l).shouldSkip){n?.warn(`Skipping field ${c} for ${l} due to skip hack ${b(t.package_meta,l).reason}`);continue}E(a)?r[s]=U(e,t,c,a,n):r[s]=w(e,t,c,a,n);}return r}function $e(e){let t=[];for(let o of Object.values(e))"type"in o&&o.type&&t.push(o.type),"binding"in o&&o.binding&&t.push(o.binding);return t}async function de(e,t,o){if(!t.url)throw new Error("ValueSet URL is required");let i=L(e,t.package_meta,t.url),n=B(e,t.package_meta,t.url);return {identifier:i,description:t.description,concept:n,compose:n?void 0:t.compose}}function Ve(e,t,o,i){let n=[];t&&n.push(t),o&&n.push(...$e(o)),i&&n.push(...ae(i));let r={};for(let a of n)a.url!==e.url&&(r[a.url]=a);let s=new Set(i?.map(a=>a.identifier.url)),c=Object.values(r).filter(a=>ne(e)||!te(a)?true:!s.has(a.url)).sort((a,l)=>a.url.localeCompare(l.url));return c.length>0?c:void 0}function He(e,t,o){let i=I(t),n;if(t.base&&t.type!=="Element"){let p=e.resolveFs(t.package_meta,e.ensureSpecializationCanonicalUrl(t.base));if(!p)throw new Error(`Base resource not found '${t.base}' for <${t.url}> from ${x(t.package_meta)}`);n=I(p);}let r=Ue(e,t,[],t.elements,o),s=A(e,t,o),c=t.derivation==="constraint"?_e(e,t,o):void 0,a=Ve(i,n,r,s),l=c?.flatMap(p=>p.valueTypes??[])??[],u=(()=>{if(!a&&l.length===0)return a;let p={};for(let d of a??[])p[d.url]=d;for(let d of l)p[d.url]=d;return Object.values(p)})(),m={identifier:i,base:n,fields:r,nested:s,description:t.description,dependencies:u,...c&&c.length>0?{extensions:c}:{}},h=re(e,t,o);return [m,...h]}function Oe(e,t,o,i){let n=e.resolveFs(t.package_meta,o);if(!n?.elements)return;let r=[];for(let[c,a]of Object.entries(n.elements)){if(a.choiceOf!=="value"&&!c.startsWith("value"))continue;let l=$(e,n,[c],a,i);l&&r.push(l);}if(r.length===0)return;let s=new Map(r.map(c=>[c.url,c]));return Array.from(s.values())}var Me=(e,t,o)=>{let i=[];if(!t.elements)return i;for(let[n,r]of Object.entries(t.elements)){if(!n.startsWith("extension:"))continue;let s=n.split(":")[1];if(!s)continue;let c;for(let[a,l]of Object.entries(r.elements??{}))if(!(l.choiceOf!=="value"&&!a.startsWith("value"))&&(c=$(e,t,[n,a],l,o),c))break;i.push({name:s,url:r.url??s,valueType:c,min:r.min,max:r.max!==void 0?String(r.max):void 0});}return i},Be=e=>{let t=[],i=e.elements?.extension?.slicing?.slices;if(!i||typeof i!="object")return t;for(let[n,r]of Object.entries(i)){let s=r,c=s.schema;if(!c)continue;let a;for(let[l,u]of Object.entries(c.elements??{})){let m=u;if(!(m.choiceOf!=="value"&&!l.startsWith("value"))&&m.type){a={kind:"complex-type",package:e.package_meta.name,version:e.package_meta.version,name:m.type,url:`http://hl7.org/fhir/StructureDefinition/${m.type}`};break}}t.push({name:n,url:s.match?.url??n,valueType:a,min:c._required?1:c.min??0,max:c.max!==void 0?String(c.max):c.array?"*":"1"});}return t},je=(e,t,o,i)=>{let n=e.resolveFs(t.package_meta,o);if(!n?.elements)return;let r=Me(e,n,i),s=Be(n),c=[...r,...s];return c.length>0?c:void 0};function _e(e,t,o){let i=[],n=(s,c,a)=>{let l=a.url,u=l?Oe(e,t,l,o):void 0,m=l?je(e,t,l,o):void 0,h=m!==void 0&&m.length>0;i.push({name:c,path:[...s,"extension"].join("."),url:l,min:a.min,max:a.max!==void 0?String(a.max):void 0,mustSupport:a.mustSupport,valueTypes:u,subExtensions:m,isComplex:h});},r=(s,c)=>{if(c.extensions)for(let[a,l]of Object.entries(c.extensions))n(s,a,l);if(c.elements)for(let[a,l]of Object.entries(c.elements))r([...s,a],l);};if(t.extensions)for(let[s,c]of Object.entries(t.extensions))n([],s,c);if(t.elements)for(let[s,c]of Object.entries(t.elements))r([s],c);return i}async function ue(e,t,o){return He(e,t,o)}var Ae=(e,t)=>{let o={};for(let r of e){let s=`${r.schema.identifier.url}|${r.schema.identifier.package}`,c=Z(r.schema);o[s]??={},o[s][c]??={typeSchema:r.schema,sources:[]},o[s][c].sources.push(r);}let i=[],n={};for(let r of Object.values(o)){let s=Object.values(r).sort((a,l)=>l.sources.length-a.sources.length),c=s[0];if(c&&(i.push(c.typeSchema),s.length>1)){let a=c.typeSchema.identifier.package,l=c.typeSchema.identifier.url;t?.dryWarn(`'${l}' from '${a}'' has ${s.length} versions`),n[a]??={},n[a][l]=s.flatMap(u=>u.sources.map(m=>({typeSchema:u.typeSchema,sourcePackage:m.sourcePackage,sourceCanonical:m.sourceCanonical})));}}return {schemas:i,collisions:n}},me=async(e,t)=>{let o=[];for(let i of e.allFs()){let n=x(i.package_meta),r=b(i.package_meta,i.url);if(r.shouldSkip){t?.dryWarn(`Skip ${i.url} from ${n}. Reason: ${r.reason}`);continue}for(let s of await ue(e,i,t))o.push({schema:s,sourcePackage:n,sourceCanonical:i.url});}for(let i of e.allVs())o.push({schema:await de(e,i),sourcePackage:x(i.package_meta),sourceCanonical:i.url});return Ae(o,t)};var G=e=>e!==null&&typeof e=="object"&&e.resourceType==="CodeSystem";var V=e=>e!==null&&typeof e=="object"&&e.resourceType==="ValueSet";var We=async(e,t)=>{let o=await e.packageJson(t.name);if(!o)return [];let i=o.dependencies;return i!==void 0?Object.entries(i).map(([n,r])=>({name:n,version:r})):[]},he=e=>({pkg:e,canonicalResolution:{},fhirSchemas:{},valueSets:{}}),ye=async(e,t,o,i,n)=>{let r=x(t);if(n?.info(`${" ".repeat(o*2)}+ ${r}`),i[r])return i[r];let s=he(t);for(let a of await e.search({package:t})){let l=a.url;if(!l||!(isStructureDefinition(a)||V(a)||G(a)))continue;let u=l;s.canonicalResolution[u]&&n?.dryWarn(`Duplicate canonical URL: ${u} at ${r}.`),s.canonicalResolution[u]=[{deep:o,pkg:t,pkgId:r,resource:a}];}let c=await We(e,t);for(let a of c){let{canonicalResolution:l}=await ye(e,a,o+1,i,n);for(let[u,m]of Object.entries(l)){let h=u;s.canonicalResolution[h]=[...s.canonicalResolution[h]||[],...m];}}for(let a of Object.values(s.canonicalResolution))a.sort((l,u)=>l.deep-u.deep);return i[r]=s,s},fe=(e,t)=>{for(let{pkg:o,canonicalResolution:i}of Object.values(e)){let n=x(o);if(!e[n])throw new Error(`Package ${n} not found`);for(let[s,c]of Object.entries(i)){let a=c[0];if(!a)throw new Error("Resource not found");let l=a.resource,u=a.pkg;if(isStructureDefinition(l)){let m=ge.translate(l),h=ee(m,u);e[n].fhirSchemas[h.url]=h;}if(V(l)){let m=ie(l,u);e[n].valueSets[m.url]=m;}}}},qe=(e,t,o)=>{let i=Object.values(e).flatMap(n=>n.canonicalResolution[t]);if(!i)throw new Error(`No canonical resolution found for ${t} in any package`);return i[0]?.resource},ze=async(e,{logger:t,focusedPackages:o})=>{let i=o??await e.packages(),n={};for(let p of i)await ye(e,p,0,n,t);fe(n);let r=(p,d)=>{let f=n[x(p)];if(f){let g=f.canonicalResolution[d]?.[0];if(g)return n[g.pkgId]?.fhirSchemas[d]}for(let g of Object.values(n)){let y=g.fhirSchemas[d];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(n)){let y=g.fhirSchemas[d];if(y)return y}},s=(p,d)=>{let f=n[x(p)];if(f){let g=f.canonicalResolution[d]?.[0];if(g)return n[g.pkgId]?.valueSets[d]}for(let g of Object.values(n)){let y=g.valueSets[d];if(y&&y.package_meta.name===p.name)return y}for(let g of Object.values(n)){let y=g.valueSets[d];if(y)return y}},c=p=>(p.includes("|")&&(p=p.split("|")[0]),p.match(/^[a-zA-Z0-9]+$/)?`http://hl7.org/fhir/StructureDefinition/${p}`:p),a=(p,d)=>{let f=r(p,d);if(f===void 0)throw new Error(`Failed to resolve FHIR Schema: '${d}'`);let g=[f];for(;f?.base;){let y=f.package_meta,R=c(f.base);if(f=r(y,R),f===void 0)throw new Error(`Failed to resolve FHIR Schema base for '${d}'. Problem: '${R}' from '${x(y)}'`);g.push(f);}return g},l=(p,d)=>a(p,d).filter(f=>f.derivation==="specialization"),u=(p,d)=>{let f=a(p.package_meta,p.url),g=Ke(f,d);return Je(g)},m=p=>{let d=new Set;for(let[f,g]of Object.entries(p)){d.add(f);for(let y of g?.choices||[])p[y]||d.add(y);}return Array.from(d)},h;return {testAppendFs(p){let d=x(p.package_meta);n[d]||(n[d]=he(p.package_meta)),n[d].fhirSchemas[p.url]=p,h=void 0;},resolveFs:r,resolveFsGenealogy:a,resolveFsSpecializations:l,ensureSpecializationCanonicalUrl:c,resolveSd:(p,d)=>{let f=n[x(p)]?.canonicalResolution[d]?.[0]?.resource;if(isStructureDefinition(f))return f},allSd:()=>Object.values(n).flatMap(p=>Object.values(p.canonicalResolution).flatMap(d=>d.map(f=>{let g=f.resource;return g.package_name?g:{...g,package_name:p.pkg.name,package_version:p.pkg.version}}))).filter(p=>isStructureDefinition(p)).sort((p,d)=>p.url.localeCompare(d.url)),patchSd:p=>{Object.values(n).flatMap(d=>Object.values(d.canonicalResolution).forEach(f=>{f.forEach(g=>{if(isStructureDefinition(g.resource)){let y=g.resource,R=p(d.pkg,y);if(y.url!==R.url)throw new Error(`Patch update StructureDefinition URL: ${y.url} !== ${R.url}`);g.resource=R;}});})),fe(n),h=void 0;},allFs:()=>Object.values(n).flatMap(p=>Object.values(p.fhirSchemas)),allVs:()=>Object.values(n).flatMap(p=>Object.values(p.valueSets)),resolveVs:s,resolveAny:p=>qe(n,p),resolveElementSnapshot:u,getAllElementKeys:m,resolver:n,resolutionTree:()=>{if(h)return h;let p={};for(let[d,f]of Object.entries(n)){let g=f.pkg.name;p[g]={};for(let[y,R]of Object.entries(f.canonicalResolution)){let q=y;p[g][q]=[];for(let z of R)p[g][q].push({deep:z.deep,pkg:z.pkg});}}return h=p,p}}},Se=async(e,t)=>{let o=e.map(Y);t?.logger?.step(`Loading FHIR packages: ${o.join(", ")}`);let i=CanonicalManager({packages:o,workingDir:"tmp/fhir",registry:t.registry||void 0});return await i.init(),await ze(i,{...t,focusedPackages:e})},Ke=(e,t)=>{let[o,...i]=t;return o===void 0?[]:e.map(n=>{if(!n.elements)return;let r=n.elements?.[o];for(let s of i)r=r?.elements?.[s];return r}).filter(n=>n!==void 0)};function Je(e){let t=e.reverse(),o=Object.assign({},...t);return o.elements=void 0,o}var xe={command:"generate <packages..>",describe:"Generate TypeSchema files from FHIR packages",builder:{packages:{type:"string",array:true,demandOption:true,describe:"FHIR packages to process (e.g., hl7.fhir.r4.core@4.0.1)"},output:{alias:"o",type:"string",describe:"Output file or directory",default:"./schemas.ndjson"},format:{alias:"f",type:"string",choices:["ndjson","json"],default:"ndjson",describe:"Output format for TypeSchema files"},treeshake:{alias:"t",type:"string",array:true,describe:"Only generate TypeSchemas for specific ResourceTypes (treeshaking)"},singleFile:{alias:"s",type:"boolean",default:false,describe:"Generate single TypeSchema file instead of multiple files (NDJSON format)"},verbose:{alias:"v",type:"boolean",default:false,describe:"Enable verbose output"},registry:{alias:"r",type:"string",describe:"Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/)"}},handler:async e=>{let t=J({prefix:"TypeSchema"});try{t.step("Generating TypeSchema from FHIR packages"),t.info(`Packages: ${e.packages.join(", ")}`),t.info(`Output: ${e.output}`);let o=e.singleFile?"ndjson":e.format;t.debug(`Format: ${o}${e.singleFile&&e.format==="json"?" (forced from json due to singleFile)":""}`),e.treeshake&&e.treeshake.length>0&&t.info(`Treeshaking enabled for ResourceTypes: ${e.treeshake.join(", ")}`),e.singleFile&&t.info("Single file output enabled (NDJSON format)"),e.registry&&t.info(`Using custom registry: ${e.registry}`);let i=Date.now(),n=e.packages.map(u=>{if(u.includes("@")){let m=u.lastIndexOf("@");return {name:u.slice(0,m),version:u.slice(m+1)||"latest"}}return {name:u,version:"latest"}});t.progress(`Processing packages: ${n.map(u=>`${u.name}@${u.version}`).join(", ")}`);let r=await Se(n,{logger:t,registry:e.registry,focusedPackages:n}),{schemas:s}=await me(r,t);if(s.length===0)throw new Error("No schemas were generated from the specified packages");let c=e.output;if(!c)throw new Error("Output format not specified");await mkdir(dirname(c),{recursive:!0});let a;o==="json"?a=JSON.stringify(s,null,2):a=s.map(u=>JSON.stringify(u)).join(`
|
|
3
|
+
`),await writeFile(c,a,"utf-8");let l=Date.now()-i;if(X(`Generated ${s.length} TypeSchema definitions`,l,{schemas:s.length}),t.dim(`Output: ${c}`),e.verbose){t.debug("Generated schemas:");let u=s.map(m=>`${m.identifier?.name||"Unknown"} (${m.identifier?.kind||"unknown"})`);k(u);}}catch(o){t.error("Failed to generate TypeSchema",o instanceof Error?o:new Error(String(o))),process.exit(1);}}};var Re={command:"typeschema [subcommand]",describe:"TypeSchema operations - generate, validate and merge schemas",builder:e=>e.command(xe).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){H("Available typeschema subcommands:"),k(["generate Generate TypeSchema files from FHIR packages"]),console.log(`
|
|
4
4
|
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),console.log(`
|
|
5
|
-
Examples:`),
|
|
6
|
-
`),
|
|
7
|
-
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};function
|
|
5
|
+
Examples:`),k(["atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","atomic-codegen typeschema validate schemas.ndjson","atomic-codegen typeschema merge schema1.ndjson schema2.ndjson -o merged.ndjson"]);return}e.subcommand&&!["generate","validate","merge"].includes(e.subcommand)&&(C(`Unknown typeschema subcommand: ${e.subcommand}
|
|
6
|
+
`),H("Available typeschema subcommands:"),k(["generate Generate TypeSchema files from FHIR packages","validate Validate TypeSchema files for correctness and consistency","merge Merge multiple TypeSchema files into a single file"]),console.log(`
|
|
7
|
+
Use 'atomic-codegen typeschema <subcommand> --help' for more information about a subcommand.`),process.exit(1));}};function tt(e){return e?{debug:0,info:1,warn:2,error:3,silent:4}[e.toLowerCase()]:void 0}async function nt(e){let t=tt(e.logLevel);t===void 0&&(e.debug||e.verbose?t=0:t=1),K({timestamp:e.debug,level:t});}function it(){return Ze(hideBin(process.argv)).scriptName("atomic-codegen").usage("$0 <command> [options]").middleware(nt).command(Re).option("verbose",{alias:"v",type:"boolean",description:"Enable verbose output",default:false,global:true}).option("debug",{alias:"d",type:"boolean",description:"Enable debug output with detailed logging",default:false,global:true}).option("log-level",{alias:"l",type:"string",choices:["debug","info","warn","error","silent"],description:"Set the log level (default: info)",global:true}).demandCommand(0).middleware(e=>{e._.length===0&&(Q("Welcome to Atomic Codegen!"),console.log("Available commands:"),console.log(" typeschema Generate, validate and merge TypeSchema files"),console.log(`
|
|
8
8
|
Use 'atomic-codegen <command> --help' for more information about a command.`),console.log(`
|
|
9
9
|
Quick examples:`),console.log(" atomic-codegen typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson"),console.log(`
|
|
10
|
-
Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((t,
|
|
11
|
-
Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function
|
|
10
|
+
Use 'atomic-codegen --help' to see all options.`),process.exit(0));}).help().version("0.1.0").example("$0 typeschema generate hl7.fhir.r4.core@4.0.1 -o schemas.ndjson","Generate TypeSchemas from FHIR package").fail((e,t,o)=>{t?C(t.message,t):C(e),C(`
|
|
11
|
+
Use --help for usage information`),process.exit(1);}).wrap(Math.min(120,process.stdout.columns||80))}async function W(){await it().parseAsync();}import.meta.main&&W().catch(e=>{e("Unexpected error:",e),process.exit(1);});W().catch(e=>{console.error("CLI Error:",e instanceof Error?e.message:e),process.exit(1);});
|
package/dist/index.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ declare class CodegenLogger {
|
|
|
49
49
|
* Warning message with warning sign
|
|
50
50
|
*/
|
|
51
51
|
warn(message: string): void;
|
|
52
|
-
|
|
52
|
+
dryWarn(message: string): void;
|
|
53
53
|
/**
|
|
54
54
|
* Info message with info icon
|
|
55
55
|
*/
|
|
@@ -801,7 +801,9 @@ type Register = {
|
|
|
801
801
|
resolveFsSpecializations(pkg: PackageMeta, canonicalUrl: CanonicalUrl): RichFHIRSchema[];
|
|
802
802
|
allSd(): RichStructureDefinition[];
|
|
803
803
|
patchSd(fn: (pkg: PackageMeta, sd: StructureDefinition$1) => StructureDefinition$1): void;
|
|
804
|
+
/** Returns all FHIRSchemas from all packages in the resolver */
|
|
804
805
|
allFs(): RichFHIRSchema[];
|
|
806
|
+
/** Returns all ValueSets from all packages in the resolver */
|
|
805
807
|
allVs(): RichValueSet[];
|
|
806
808
|
resolveVs(_pkg: PackageMeta, canonicalUrl: CanonicalUrl): RichValueSet | undefined;
|
|
807
809
|
resolveAny(canonicalUrl: CanonicalUrl): any | undefined;
|
|
@@ -830,6 +832,13 @@ type ResolutionTree = Record<PkgName, Record<CanonicalUrl, {
|
|
|
830
832
|
deep: number;
|
|
831
833
|
pkg: PackageMeta;
|
|
832
834
|
}[]>>;
|
|
835
|
+
type RegisterConfig = {
|
|
836
|
+
logger?: CodegenLogger;
|
|
837
|
+
focusedPackages?: PackageMeta[];
|
|
838
|
+
/** Custom FHIR package registry URL */
|
|
839
|
+
registry?: string;
|
|
840
|
+
};
|
|
841
|
+
declare const registerFromPackageMetas: (packageMetas: PackageMeta[], conf: RegisterConfig) => Promise<Register>;
|
|
833
842
|
|
|
834
843
|
type FileSystemWriterOptions = {
|
|
835
844
|
outputDir: string;
|
|
@@ -949,6 +958,8 @@ interface APIBuilderOptions {
|
|
|
949
958
|
logLevel: LogLevel;
|
|
950
959
|
/** Custom FHIR package registry URL (default: https://fs.get-ig.org/pkgs/) */
|
|
951
960
|
registry: string | undefined;
|
|
961
|
+
/** Drop the canonical manager cache */
|
|
962
|
+
dropCanonicalManagerCache: boolean;
|
|
952
963
|
}
|
|
953
964
|
type GenerationReport = {
|
|
954
965
|
success: boolean;
|
|
@@ -984,11 +995,6 @@ declare class APIBuilder {
|
|
|
984
995
|
});
|
|
985
996
|
fromPackage(packageName: string, version?: string): APIBuilder;
|
|
986
997
|
fromPackageRef(packageRef: string): APIBuilder;
|
|
987
|
-
/**
|
|
988
|
-
* Set a custom FHIR package registry URL
|
|
989
|
-
* @param url The registry URL (default: https://fs.get-ig.org/pkgs/)
|
|
990
|
-
*/
|
|
991
|
-
registry(url: string): APIBuilder;
|
|
992
998
|
localStructureDefinitions(config: LocalStructureDefinitionConfig): APIBuilder;
|
|
993
999
|
localTgzPackage(archivePath: string): APIBuilder;
|
|
994
1000
|
introspection(userOpts?: Partial<IntrospectionWriterOptions>): APIBuilder;
|
|
@@ -1017,4 +1023,4 @@ declare class APIBuilder {
|
|
|
1017
1023
|
private executeGenerators;
|
|
1018
1024
|
}
|
|
1019
1025
|
|
|
1020
|
-
export { APIBuilder, type APIBuilderOptions, type CSharpGeneratorOptions, type IrConf, type LocalStructureDefinitionConfig, LogLevel, type LogicalPromotionConf, type TreeShakeConf, type TypeScriptOptions, prettyReport };
|
|
1026
|
+
export { APIBuilder, type APIBuilderOptions, type CSharpGeneratorOptions, type IrConf, type LocalStructureDefinitionConfig, LogLevel, type LogicalPromotionConf, type TreeShakeConf, type TypeScriptOptions, prettyReport, registerFromPackageMetas };
|